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
This commit is contained in:
XANTRONIX Development 2020-07-15 23:13:41 -04:00 committed by XANTRONIX Industrial
parent 6df612b910
commit c26c7509f4
3 changed files with 85 additions and 20 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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: