Issue 186 - Copy KISS frames between TCP KISS clients.

This commit is contained in:
wb2osz 2019-01-01 19:59:58 -05:00
parent c13375a9ab
commit ecf5fd1d59
5 changed files with 140 additions and 2 deletions

View File

@ -854,6 +854,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_misc_config->agwpe_port = DEFAULT_AGWPE_PORT;
p_misc_config->kiss_port = DEFAULT_KISS_PORT;
p_misc_config->enable_kiss_pt = 0; /* -p option */
p_misc_config->kiss_copy = 0;
/* Defaults from http://info.aprs.net/index.php?title=SmartBeaconing */
@ -4332,6 +4333,16 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}
}
/*
* KISSCOPY - Data from network KISS client is copied to all others.
*/
else if (strcasecmp(t, "KISSCOPY") == 0) {
p_misc_config->kiss_copy = 1;
}
/*
* GPSNMEA - Device name for reading from GPS receiver.
*/
@ -4712,6 +4723,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_misc_config->maxframe_basic = n;
}
else {
p_misc_config->maxframe_basic = AX25_K_MAXFRAME_BASIC_DEFAULT;
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Invalid MAXFRAME value outside range of %d to %d. Using default %d.\n",
line, AX25_K_MAXFRAME_BASIC_MIN, AX25_K_MAXFRAME_BASIC_MAX, p_misc_config->maxframe_basic);
@ -4737,6 +4749,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_misc_config->maxframe_extended = n;
}
else {
p_misc_config->maxframe_extended = AX25_K_MAXFRAME_EXTENDED_DEFAULT;
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Invalid EMAXFRAME value outside of range %d to %d. Using default %d.\n",
line, AX25_K_MAXFRAME_EXTENDED_MIN, AX25_K_MAXFRAME_EXTENDED_MAX, p_misc_config->maxframe_extended);

View File

@ -35,6 +35,7 @@ struct misc_config_s {
int agwpe_port; /* Port number for the "AGW TCPIP Socket Interface" */
int kiss_port; /* Port number for the "TCP KISS" protocol. */
int kiss_copy; /* Data from network KISS client is copied to all others. */
int enable_kiss_pt; /* Enable pseudo terminal for KISS. */
/* Want this to be off by default because it hangs */
/* after a while if nothing is reading from other end. */

View File

@ -93,6 +93,7 @@
#include "tq.h"
#include "xmit.h"
#include "version.h"
#include "kissnet.h"
/* In server.c. Should probably move to some misc. function file. */
@ -506,7 +507,7 @@ void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, v
* debug - Debug option is selected.
*
* client - Client app number for TCP KISS.
* Ignored for pseudo termal and serial port.
* Should be -1 for pseudo termal and serial port.
*
* sendfun - Function to send something to the client application.
* "Set Hardware" can send a response.
@ -522,7 +523,7 @@ void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, v
void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int client, void (*sendfun)(int,int,unsigned char*,int,int))
{
int port;
int port; // Should rename to chan because that's what we use everywhere else.
int cmd;
packet_t pp;
alevel_t alevel;
@ -534,6 +535,10 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
{
case KISS_CMD_DATA_FRAME: /* 0 = Data Frame */
if (client >= 0) {
kissnet_copy (kiss_msg, kiss_len, port, cmd, client);
}
/* Special hack - Discard apparently bad data from Linux AX25. */
/* Note July 2017: There is a variant of of KISS, called SMACK, that assumes */
@ -545,6 +550,36 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
/* Our current default is a maximum of 6 channels but it is easily */
/* increased by changing one number and recompiling. */
// Additional information, from Mike Playle, December 2018, for Issue #42
//
// I came across this the other day with Xastir, and took a quick look.
// The problem is fixable without the kiss_frame.c hack, which doesn't help with Xastir anyway.
//
// Workaround
//
// After the kissattach command, put the interface into CRC mode "none" with a command like this:
//
// # kissparms -c 1 -p radio
//
// Analysis
//
// The source of this behaviour is the kernel's KISS implementation:
//
// https://elixir.bootlin.com/linux/v4.9/source/drivers/net/hamradio/mkiss.c#L489
//
// It defaults to starting in state CRC_MODE_SMACK_TEST and ending up in mode CRC_NONE
// after the first two packets, which have their framing byte modified by this code in the process.
// It looks to me like deliberate behaviour on the kernel's part.
//
// Setting the CRC mode explicitly before sending any packets stops this state machine from running.
//
// Is this a bug? I don't know - that's up to you! Maybe it would make sense for Direwolf to set
// the CRC mode itself, or to expect this behaviour and ignore these flags on the first packets
// received from the Linux pty.
//
// This workaround seems sound to me, though, so perhaps this is just a documentation issue.
if (kiss_len > 16 &&
(port == 2 || port == 8) &&
kiss_msg[1] == 'Q' << 1 &&

View File

@ -159,6 +159,7 @@ static THREAD_F connect_listen_thread (void *arg);
static THREAD_F kissnet_listen_thread (void *arg);
static struct misc_config_s *s_misc_config_p;
static int kiss_debug = 0; /* Print information flowing from and to client. */
@ -204,6 +205,8 @@ void kissnet_init (struct misc_config_s *mc)
pthread_t cmd_listen_tid[MAX_NET_CLIENTS];
int e;
#endif
s_misc_config_p = mc;
int kiss_port = mc->kiss_port; /* default 8001 but easily changed. */
@ -650,6 +653,90 @@ void kissnet_send_rec_packet (int chan, int kiss_cmd, unsigned char *fbuf, int f
} /* end kissnet_send_rec_packet */
/*-------------------------------------------------------------------
*
* Name: kissnet_copy
*
* Purpose: Send data from one network KISS client to all others.
*
* Inputs: in_msg - KISS frame data without the framing or escapes.
* The first byte is channel (port) and command (should be data).
*
* in_len - Number of bytes in above.
*
* chan - Channel. Redundant because it is also in first byte of kiss_msg.
* Not currently used.
*
* cmd - KISS command nybble. Redundant because it is in first byte.
* Should be 0 because I'm expecting this only for data.
*
* from_client - Number of network (TCP) client instance.
* Should be 0, 1, 2, ...
*
*
* Global In: kiss_copy - From misc. configuration.
* This enables the feature.
*
*
* Description: Send message to any attached network KISS clients, other than the one where it came from.
* Enable this by putting KISSCOPY in the configuration file.
* Note that this applies only to network (TCP) KISS clients, not serial port, or pseudo terminal.
*
*
*--------------------------------------------------------------------*/
void kissnet_copy (unsigned char *in_msg, int in_len, int chan, int cmd, int from_client)
{
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN];
int kiss_len;
int err;
int send_to;
(void) chan;
(void) cmd;
if (s_misc_config_p->kiss_copy) {
for (send_to = 0; send_to < MAX_NET_CLIENTS; send_to++) {
if (send_to != from_client && client_sock[send_to] != -1) {
kiss_len = kiss_encapsulate (in_msg, in_len, kiss_buff);
/* This has the escapes and the surrounding FENDs. */
if (kiss_debug) {
kiss_debug_print (TO_CLIENT, NULL, kiss_buff, kiss_len);
}
#if __WIN32__
err = SOCK_SEND(client_sock[send_to], (char*)kiss_buff, kiss_len);
if (err == SOCKET_ERROR)
{
text_color_set(DW_COLOR_ERROR);
dw_printf ("\nError %d copying message to KISS client %d application. Closing connection.\n\n", WSAGetLastError(), send_to);
closesocket (client_sock[send_to]);
client_sock[send_to] = -1;
WSACleanup();
}
#else
err = SOCK_SEND (client_sock[send_to], kiss_buff, kiss_len);
if (err <= 0)
{
text_color_set(DW_COLOR_ERROR);
dw_printf ("\nError copying message to KISS client %d application. Closing connection.\n\n", send_to);
close (client_sock[send_to]);
client_sock[send_to] = -1;
}
#endif
} // if origin and destination different.
} // loop over all KISS network clients.
} // Feature enabled.
} /* end kissnet_copy */
/*-------------------------------------------------------------------
*

View File

@ -17,5 +17,7 @@ void kissnet_send_rec_packet (int chan, int kiss_cmd, unsigned char *fbuf, int
void kiss_net_set_debug (int n);
void kissnet_copy (unsigned char *kiss_msg, int kiss_len, int chan, int cmd, int from_client);
/* end kissnet.h */