Re-establish broken APRS-IS connections

Re-establish broken APRS-IS connections in src/aprs_is.c; when read() or
write() sets errno to EIO, attempt at most 3 times to re-establish the
APRS-IS connection per read()/write() failure; if the maximum number of
attempts is met, the I/O operation is considered a total failure
This commit is contained in:
XANTRONIX 2020-10-01 15:41:43 -04:00 committed by XANTRONIX Industrial
parent 88743a5754
commit 65ae821342
2 changed files with 39 additions and 15 deletions

View file

@ -12,7 +12,7 @@
#define PATTY_AX25_APRS_IS_PACKET_MAX 512 #define PATTY_AX25_APRS_IS_PACKET_MAX 512
#define PATTY_AX25_APRS_IS_FRAME_MAX PATTY_AX25_APRS_IS_PACKET_MAX #define PATTY_AX25_APRS_IS_FRAME_MAX PATTY_AX25_APRS_IS_PACKET_MAX
typedef struct _patty_ax25_aprs_is patty_ax25_aprs_is; #define PATTY_AX25_APRS_IS_ATTEMPTS_MAX 3
typedef struct _patty_ax25_aprs_is_info { typedef struct _patty_ax25_aprs_is_info {
const char *host, const char *host,
@ -24,6 +24,8 @@ typedef struct _patty_ax25_aprs_is_info {
*filter; *filter;
} patty_ax25_aprs_is_info; } patty_ax25_aprs_is_info;
typedef struct _patty_ax25_aprs_is patty_ax25_aprs_is;
ssize_t patty_ax25_aprs_is_encode(void *dest, ssize_t patty_ax25_aprs_is_encode(void *dest,
const char *src, const char *src,
size_t len, size_t len,

View file

@ -19,25 +19,26 @@ enum state {
struct _patty_ax25_aprs_is { struct _patty_ax25_aprs_is {
patty_ax25_if_stats stats; patty_ax25_if_stats stats;
patty_ax25_aprs_is_info info;
int fd; int fd;
char rx_buf[PATTY_AX25_APRS_IS_PACKET_MAX], char rx_buf[PATTY_AX25_APRS_IS_PACKET_MAX],
tx_buf[PATTY_AX25_APRS_IS_FRAME_MAX], tx_buf[PATTY_AX25_APRS_IS_FRAME_MAX],
call[PATTY_AX25_ADDRSTRLEN+1], call[PATTY_AX25_ADDRSTRLEN+1],
info[PATTY_AX25_APRS_IS_PAYLOAD_MAX]; body[PATTY_AX25_APRS_IS_PAYLOAD_MAX];
patty_ax25_frame frame; patty_ax25_frame frame;
size_t rx_bufsz, size_t rx_bufsz,
tx_bufsz, tx_bufsz,
infosz; bodysz;
enum state state; enum state state;
size_t offset_i, size_t offset_i,
offset_call, offset_call,
offset_info; offset_body;
ssize_t readlen, ssize_t readlen,
encoded; encoded;
@ -138,13 +139,15 @@ patty_ax25_aprs_is *patty_ax25_aprs_is_new(patty_ax25_aprs_is_info *info) {
aprs->rx_bufsz = PATTY_AX25_APRS_IS_PACKET_MAX; aprs->rx_bufsz = PATTY_AX25_APRS_IS_PACKET_MAX;
aprs->tx_bufsz = PATTY_AX25_APRS_IS_FRAME_MAX; aprs->tx_bufsz = PATTY_AX25_APRS_IS_FRAME_MAX;
aprs->infosz = PATTY_AX25_APRS_IS_PAYLOAD_MAX; aprs->bodysz = PATTY_AX25_APRS_IS_PAYLOAD_MAX;
aprs->state = APRS_IS_HEADER; aprs->state = APRS_IS_HEADER;
if (aprs_is_connect(aprs, info) < 0) { if (aprs_is_connect(aprs, info) < 0) {
goto error_connect; goto error_connect;
} }
memcpy(&aprs->info, info, sizeof(aprs->info));
return aprs; return aprs;
error_connect: error_connect:
@ -175,9 +178,17 @@ ssize_t patty_ax25_aprs_is_pending(patty_ax25_aprs_is *aprs) {
} }
ssize_t patty_ax25_aprs_is_fill(patty_ax25_aprs_is *aprs) { ssize_t patty_ax25_aprs_is_fill(patty_ax25_aprs_is *aprs) {
if ((aprs->readlen = read(aprs->fd, aprs->rx_buf, aprs->rx_bufsz)) < 0) { int attempt = 0;
while ((aprs->readlen = read(aprs->fd, aprs->rx_buf, aprs->rx_bufsz)) < 0) {
if (errno == EIO) {
if (++attempt == PATTY_AX25_APRS_IS_ATTEMPTS_MAX) {
(void)aprs_is_connect(aprs, &aprs->info);
}
} else {
goto error_read; goto error_read;
} }
}
aprs->offset_i = 0; aprs->offset_i = 0;
@ -260,8 +271,8 @@ ssize_t patty_ax25_aprs_is_drain(patty_ax25_aprs_is *aprs,
aprs->frame.control = PATTY_AX25_FRAME_UI; aprs->frame.control = PATTY_AX25_FRAME_UI;
aprs->frame.cr = PATTY_AX25_FRAME_COMMAND; aprs->frame.cr = PATTY_AX25_FRAME_COMMAND;
aprs->frame.proto = PATTY_AX25_PROTO_NONE; aprs->frame.proto = PATTY_AX25_PROTO_NONE;
aprs->frame.info = aprs->info; aprs->frame.info = aprs->body;
aprs->frame.infolen = aprs->offset_info; aprs->frame.infolen = aprs->offset_body;
if ((aprs->encoded = patty_ax25_frame_encode(&aprs->frame, if ((aprs->encoded = patty_ax25_frame_encode(&aprs->frame,
buf, buf,
@ -271,11 +282,11 @@ ssize_t patty_ax25_aprs_is_drain(patty_ax25_aprs_is *aprs,
goto done; goto done;
} else { } else {
if (aprs->offset_info == aprs->infosz) { if (aprs->offset_body == aprs->bodysz) {
goto drop; goto drop;
} }
aprs->info[aprs->offset_info++] = c; aprs->body[aprs->offset_body++] = c;
} }
break; break;
@ -307,7 +318,7 @@ ssize_t patty_ax25_aprs_is_flush(patty_ax25_aprs_is *aprs) {
aprs->state = APRS_IS_HEADER; aprs->state = APRS_IS_HEADER;
aprs->offset_i = aprs->readlen; aprs->offset_i = aprs->readlen;
aprs->offset_call = 0; aprs->offset_call = 0;
aprs->offset_info = 0; aprs->offset_body = 0;
aprs->encoded = 0; aprs->encoded = 0;
memset(&aprs->frame, '\0', sizeof(aprs->frame)); memset(&aprs->frame, '\0', sizeof(aprs->frame));
@ -326,7 +337,8 @@ ssize_t patty_ax25_aprs_is_send(patty_ax25_aprs_is *aprs,
ssize_t decoded; ssize_t decoded;
int formatted; int formatted,
attempt;
char call[PATTY_AX25_ADDRSTRLEN+1]; char call[PATTY_AX25_ADDRSTRLEN+1];
@ -408,10 +420,20 @@ ssize_t patty_ax25_aprs_is_send(patty_ax25_aprs_is *aprs,
aprs->tx_buf[o++] = '\r'; aprs->tx_buf[o++] = '\r';
aprs->tx_buf[o++] = '\n'; aprs->tx_buf[o++] = '\n';
if (write(aprs->fd, aprs->tx_buf, o) < 0) { attempt = 0;
while (write(aprs->fd, aprs->tx_buf, o) < 0) {
if (++attempt == PATTY_AX25_APRS_IS_ATTEMPTS_MAX) {
goto error; goto error;
} }
if (errno == EIO) {
(void)aprs_is_connect(aprs, &aprs->info);
} else {
goto error;
}
}
return i; return i;
error: error: