From c26c7509f4904c1810223ab55287fc6be062a6b0 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Wed, 15 Jul 2020 23:13:41 -0400 Subject: [PATCH] Implement ring buffer for sock sent frames Implement ring buffer for frames sent in a SABM or SABME session, facilitating the ability to retransmit select frames upon request, retaining a copy of the full frame and its transmitted size --- include/patty/ax25/sock.h | 19 +++++++++-- src/server.c | 17 +++++++--- src/sock.c | 69 ++++++++++++++++++++++++++++++++------- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index e97c04b..cc89a66 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -1,7 +1,9 @@ #ifndef _PATTY_AX25_SOCK_H #define _PATTY_AX25_SOCK_H -#define PATTY_AX25_SOCK_BUFSZ 4096 +#define PATTY_AX25_SOCK_BUFSZ 4096 +#define PATTY_AX25_SOCK_SLOTS_SABM 8 +#define PATTY_AX25_SOCK_SLOTS_SABME 128 enum patty_ax25_sock_type { PATTY_AX25_SOCK_STREAM, @@ -26,6 +28,11 @@ enum patty_ax25_sock_opt { PATTY_AX25_SOCK_IF }; +typedef struct _patty_ax25_sock_tx_slot { + size_t len; + uint8_t buf[PATTY_AX25_SOCK_BUFSZ]; +} patty_ax25_sock_tx_slot; + typedef struct _patty_ax25_sock { enum patty_ax25_proto proto; enum patty_ax25_sock_type type; @@ -46,8 +53,8 @@ typedef struct _patty_ax25_sock { int fd; char path[PATTY_AX25_SOCK_PATH_SIZE]; - void *buf; - size_t bufsz; + void *rx_buf; + patty_ax25_sock_tx_slot *tx_slots; patty_ax25_if *iface; @@ -65,6 +72,9 @@ void patty_ax25_sock_reset(patty_ax25_sock *sock); void patty_ax25_sock_destroy(patty_ax25_sock *sock); +int patty_ax25_sock_mode_set(patty_ax25_sock *sock, + enum patty_ax25_sock_mode mode); + char *patty_ax25_sock_pty(patty_ax25_sock *sock); int patty_ax25_sock_bind_if(patty_ax25_sock *sock, @@ -80,6 +90,9 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, void *info, size_t infolen); +ssize_t patty_ax25_sock_resend(patty_ax25_sock *sock, + unsigned int seq); + ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock, enum patty_ax25_frame_cr cr); diff --git a/src/server.c b/src/server.c index eb020a8..5a7d06d 100644 --- a/src/server.c +++ b/src/server.c @@ -1047,6 +1047,8 @@ static int handle_sabm(patty_ax25_server *server, patty_ax25_sock *local, *remote; patty_ax25_call_accept_response response; + enum patty_ax25_sock_mode mode; + if ((local = sock_by_addr(server->socks_pending_accept, &frame->dest)) == NULL) { return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); @@ -1060,11 +1062,15 @@ static int handle_sabm(patty_ax25_server *server, goto error_sock_new; } + mode = (frame->type == PATTY_AX25_FRAME_SABM)? + PATTY_AX25_SOCK_SABM: PATTY_AX25_SOCK_SABME; + remote->status = PATTY_AX25_SOCK_ESTABLISHED; remote->iface = iface; - remote->mode = (frame->type == PATTY_AX25_FRAME_SABM)? - PATTY_AX25_SOCK_SABM: PATTY_AX25_SOCK_SABME; + if (patty_ax25_sock_mode_set(remote, mode) < 0) { + goto error_sock_set_mode; + } save_reply_addr(remote, frame); @@ -1111,6 +1117,7 @@ error_reply_ua: error_sock_delete_by_addr: error_sock_save_by_addrpair: error_sock_save_by_fd: +error_sock_set_mode: patty_ax25_sock_destroy(remote); error_sock_new: @@ -1307,7 +1314,7 @@ static int handle_frame(patty_ax25_server *server, case PATTY_AX25_FRAME_SABME: return handle_sabm(server, iface, &frame); case PATTY_AX25_FRAME_DISC: return handle_disc(server, iface, &frame); case PATTY_AX25_FRAME_FRMR: return 0; - + default: break; } @@ -1380,7 +1387,7 @@ static int handle_sock(uint32_t key, goto done; } - if ((len = read(sock->fd, sock->buf, sock->bufsz)) < 0) { + if ((len = read(sock->fd, sock->rx_buf, PATTY_AX25_SOCK_BUFSZ)) < 0) { if (errno == EIO) { (void)sock_close(server, sock); @@ -1394,7 +1401,7 @@ static int handle_sock(uint32_t key, goto done; } - if (patty_ax25_sock_write(sock, sock->buf, len) < 0) { + if (patty_ax25_sock_write(sock, sock->rx_buf, len) < 0) { goto error_sock_write; } diff --git a/src/sock.c b/src/sock.c index f77ee57..e329cd2 100644 --- a/src/sock.c +++ b/src/sock.c @@ -64,15 +64,18 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, memset(sock, '\0', sizeof(*sock)); - if ((sock->buf = malloc(PATTY_AX25_SOCK_BUFSZ)) == NULL) { - goto error_malloc_buf; + if ((sock->rx_buf = malloc(PATTY_AX25_SOCK_BUFSZ)) == NULL) { + goto error_malloc_rx_buf; + } + + if ((sock->tx_slots = malloc(PATTY_AX25_SOCK_SLOTS_SABM * sizeof(patty_ax25_sock_tx_slot))) == NULL) { + goto error_malloc_tx_slots; } if (bind_pty(sock) < 0) { goto error_bind_pty; } - sock->bufsz = PATTY_AX25_SOCK_BUFSZ; sock->proto = proto; sock->type = type; sock->status = PATTY_AX25_SOCK_CLOSED; @@ -83,9 +86,12 @@ patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto, return sock; error_bind_pty: - free(sock->buf); + free(sock->tx_slots); -error_malloc_buf: +error_malloc_tx_slots: + free(sock->rx_buf); + +error_malloc_rx_buf: free(sock); error_malloc_sock: @@ -114,10 +120,39 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) { close(sock->fd); } - free(sock->buf); + free(sock->rx_buf); + free(sock->tx_slots); free(sock); } +int patty_ax25_sock_mode_set(patty_ax25_sock *sock, + enum patty_ax25_sock_mode mode) { + size_t slots = 0; + + if (sock->mode == mode) { + return 0; + } + + switch (mode) { + case PATTY_AX25_SOCK_SABM: slots = PATTY_AX25_SOCK_SLOTS_SABM; break; + case PATTY_AX25_SOCK_SABME: slots = PATTY_AX25_SOCK_SLOTS_SABME; break; + case PATTY_AX25_SOCK_DM: goto done; + } + + if ((sock->tx_slots = realloc(sock->tx_slots, + slots * sizeof(patty_ax25_sock_tx_slot))) == NULL) { + goto error_malloc_tx_slots; + } + +done: + sock->mode = mode; + + return 0; + +error_malloc_tx_slots: + return -1; +} + char *patty_ax25_sock_pty(patty_ax25_sock *sock) { return sock->path; } @@ -154,9 +189,10 @@ void patty_ax25_sock_seq_recv_incr(patty_ax25_sock *sock) { } } -static size_t addr_copy_to_tx_buf(patty_ax25_sock *sock, - enum patty_ax25_frame_cr cr) { - uint8_t *buf = sock->iface->tx_buf; +static size_t addr_copy_to_buf(void *dest, + patty_ax25_sock *sock, + enum patty_ax25_frame_cr cr) { + uint8_t *buf = (uint8_t *)dest; size_t offset = 0; uint8_t flags_remote = 0x00, @@ -190,7 +226,7 @@ static inline int toobig(patty_ax25_sock *sock, PATTY_AX25_FRAME_NORMAL, sock->hops, control, - infolen) > sock->iface->tx_bufsz? 1: 0; + infolen) > PATTY_AX25_SOCK_BUFSZ? 1: 0; } ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, @@ -199,13 +235,13 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, void *info, size_t infolen) { size_t offset; - uint8_t *buf = (uint8_t *)sock->iface->tx_buf; + uint8_t *buf = sock->tx_slots[sock->seq_send].buf; if (toobig(sock, control, infolen)) { goto error_toobig; } - offset = addr_copy_to_tx_buf(sock, cr); + offset = addr_copy_to_buf(buf, sock, cr); if (sock->mode == PATTY_AX25_SOCK_SABME) { buf[offset++] = (control & 0xff00) >> 8; @@ -221,12 +257,21 @@ ssize_t patty_ax25_sock_send(patty_ax25_sock *sock, offset += infolen; } + sock->tx_slots[sock->seq_send].len = offset; + return patty_ax25_if_send(sock->iface, buf, offset); error_toobig: return -1; } +ssize_t patty_ax25_sock_resend(patty_ax25_sock *sock, + unsigned int seq) { + patty_ax25_sock_tx_slot *slot = &sock->tx_slots[seq]; + + return patty_ax25_if_send(sock->iface, slot->buf, slot->len); +} + static uint16_t control_i(patty_ax25_sock *sock, int flag) { switch (sock->mode) { case PATTY_AX25_SOCK_SABM: