Implement patty_ax25_aprs_is_send()

Implement patty_ax25_aprs_is_send() to be able to encode any outbound UI
frames in TNC2 format, and to send them to a remote APRS-IS server

Other changes:

    * Remove unimplemented patty_ax25_aprs_is_printf() declaration

    * Remove unimplemented patty_ax25_aprs_is_readline() declaration
This commit is contained in:
XANTRONIX Development 2020-09-19 14:08:21 -05:00 committed by XANTRONIX Industrial
parent 34e5629bc9
commit 70d112eb91
2 changed files with 112 additions and 62 deletions

View file

@ -33,12 +33,6 @@ patty_ax25_aprs_is *patty_ax25_aprs_is_new(patty_ax25_aprs_is_info *info);
void patty_ax25_aprs_is_destroy(patty_ax25_aprs_is *aprs);
ssize_t patty_ax25_aprs_is_readline(patty_ax25_aprs_is *aprs,
void *buf,
size_t len);
int patty_ax25_aprs_is_printf(patty_ax25_aprs_is *aprs, const char *fmt, ...);
int patty_ax25_aprs_is_fd(patty_ax25_aprs_is *aprs);
ssize_t patty_ax25_aprs_is_pending(patty_ax25_aprs_is *aprs);

View file

@ -41,51 +41,39 @@ struct _patty_ax25_aprs_is {
encoded;
};
static ssize_t send_line(patty_ax25_aprs_is *aprs, char *buf, size_t len) {
if (len > PATTY_AX25_APRS_IS_PACKET_MAX - 2) {
len = PATTY_AX25_APRS_IS_PACKET_MAX - 2;
}
static ssize_t aprs_is_vprintf(patty_ax25_aprs_is *aprs,
const char *fmt,
va_list args) {
int len;
buf[len] = '\r';
buf[len+1] = '\n';
return write(aprs->fd, buf, len+2);
}
static int send_va(patty_ax25_aprs_is *aprs, const char *fmt, va_list args) {
size_t len;
if (vsnprintf(aprs->tx_buf, PATTY_AX25_APRS_IS_PACKET_MAX, fmt, args) < 0) {
if ((len = vsnprintf(aprs->tx_buf,
PATTY_AX25_APRS_IS_PACKET_MAX,
fmt,
args)) < 0) {
goto error_vsnprintf;
}
len = strnlen(aprs->tx_buf, PATTY_AX25_APRS_IS_PACKET_MAX);
return write(aprs->fd, aprs->tx_buf, (size_t)len);
if (send_line(aprs, aprs->tx_buf, len) < 0) {
goto error_send_line;
}
return 0;
error_send_line:
error_vsnprintf:
return -1;
}
static int send_fmt(patty_ax25_aprs_is *aprs, const char *fmt, ...) {
static ssize_t aprs_is_printf(patty_ax25_aprs_is *aprs, const char *fmt, ...) {
ssize_t len;
va_list args;
va_start(args, fmt);
if (send_va(aprs, fmt, args) < 0) {
goto error_send_va;
if ((len = aprs_is_vprintf(aprs, fmt, args)) < 0) {
goto error_aprs_is_vprintf;
}
va_end(args);
return 0;
return len;
error_send_va:
error_aprs_is_vprintf:
return -1;
}
@ -113,20 +101,20 @@ static int aprs_is_connect(patty_ax25_aprs_is *aprs,
freeaddrinfo(ai0);
if (send_fmt(aprs,
"user %s pass %s vers %s %s filter %s",
if (aprs_is_printf(aprs,
"user %s pass %s vers %s %s filter %s\r\n",
info->user,
info->pass,
info->appname,
info->version,
info->filter) < 0) {
goto error_send_fmt;
goto error_aprs_is_printf;
}
return 0;
}
error_send_fmt:
error_aprs_is_printf:
close(aprs->fd);
error_getaddrinfo:
@ -322,31 +310,99 @@ ssize_t patty_ax25_aprs_is_flush(patty_ax25_aprs_is *aprs) {
return ret;
}
int patty_ax25_aprs_is_printf(patty_ax25_aprs_is *aprs, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
if (send_va(aprs, fmt, args) < 0) {
goto error_send_va;
}
va_end(args);
return 0;
error_send_va:
va_end(args);
return -1;
}
ssize_t patty_ax25_aprs_is_send(patty_ax25_aprs_is *aprs,
const void *buf,
size_t len) {
patty_ax25_frame frame;
size_t offset = 0;
ssize_t decoded;
int formatted,
i;
char station[PATTY_AX25_ADDRSTRLEN+1];
if ((decoded = patty_ax25_frame_decode_address(&frame, buf, len)) < 0) {
goto error;
}
if (patty_ax25_frame_decode_control(&frame,
PATTY_AX25_FRAME_NORMAL,
buf,
decoded,
len) < 0) {
goto error;
}
if (!PATTY_AX25_FRAME_CONTROL_UI(frame.control)) {
return 0;
}
if (patty_ax25_ntop(&frame.src, station, sizeof(station)) < 0) {
goto error;
}
if ((formatted = snprintf(aprs->tx_buf,
aprs->tx_bufsz,
"%s>",
station)) < 0) {
goto error;
} else {
offset += formatted;
}
if (patty_ax25_ntop(&frame.dest, station, sizeof(station)) < 0) {
goto error;
}
if ((formatted = snprintf(aprs->tx_buf + offset,
aprs->tx_bufsz - offset,
"%s",
station)) < 0) {
goto error;
} else {
offset += formatted;
}
for (i=0; i<frame.hops; i++) {
if (patty_ax25_ntop(&frame.repeaters[i],
station,
sizeof(station)) < 0) {
goto error;
}
if ((formatted = snprintf(aprs->tx_buf + offset,
aprs->tx_bufsz - offset,
",%s",
station)) < 0) {
goto error;
} else {
offset += formatted;
}
}
if (aprs->tx_bufsz - offset < frame.infolen + 3) {
errno = EOVERFLOW;
goto error;
}
aprs->tx_buf[offset++] = ':';
memcpy(aprs->tx_buf + offset, frame.info, frame.infolen);
offset += frame.infolen;
aprs->tx_buf[offset++] = '\r';
aprs->tx_buf[offset++] = '\n';
return write(aprs->fd, aprs->tx_buf, offset);
error:
return -1;
}
patty_ax25_if_driver *patty_ax25_aprs_is_driver() {
static patty_ax25_if_driver driver = {
.create = (patty_ax25_if_driver_create *)patty_ax25_aprs_is_new,