From aa2fd9b06d1a5014c27dde7aa7bc6191d4b71360 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Fri, 31 Jul 2020 01:14:11 -0400 Subject: [PATCH] Implement Response Delay Timer T2 Implement AX.25 v2.2 Section 6.7.1.2 "Response Delay Timer T2" as per specification; do not acknowledge several sequential I frames until a certain period of time has passed since the receipt of the most recent I frame --- include/patty/ax25/sock.h | 3 +- src/server.c | 60 +++++++++++++++++++++++++++------------ src/sock.c | 1 + 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index d22d37d..6acb477 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -72,7 +72,8 @@ typedef struct _patty_ax25_sock { unsigned int seq_send, seq_recv; - size_t retries; + size_t retries, + pending; int fd; char pty[PATTY_AX25_SOCK_PATH_SIZE]; diff --git a/src/server.c b/src/server.c index 2908b03..977766c 100644 --- a/src/server.c +++ b/src/server.c @@ -1314,8 +1314,16 @@ static int handle_i(patty_ax25_server *server, goto error_write; } - return frame->pf? - patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0): 0; + if (++sock->pending == sock->n_window_rx / 2) { + sock->pending = 0; + patty_timer_cancel(&sock->timer_t2); + + return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0); + } else { + patty_timer_start(&sock->timer_t2, &server->timer, 3000); + } + + return 0; error_write: return -1; @@ -1628,24 +1636,40 @@ static int handle_sock(uint32_t key, ssize_t len; - if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) { - if (patty_timer_expired(&sock->timer_t1)) { - if (sock->retries) { - int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL); - - patty_timer_start(&sock->timer_t1, &server->timer, sock->n_ack); - - return ret; - } else { - (void)sock_shutdown(server, sock); - - return sock_close(server, sock); - } - } else { + switch (sock->status) { + case PATTY_AX25_SOCK_PENDING_CONNECT: patty_timer_tick(&sock->timer_t1, &server->elapsed); - } - goto done; + if (patty_timer_expired(&sock->timer_t1)) { + if (sock->retries) { + int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL); + + sock->retries--; + patty_timer_start(&sock->timer_t1, &server->timer, sock->n_ack); + + return ret; + } else { + (void)sock_shutdown(server, sock); + + return sock_close(server, sock); + } + } + + goto done; + + case PATTY_AX25_SOCK_ESTABLISHED: + patty_timer_tick(&sock->timer_t2, &server->elapsed); + + if (patty_timer_expired(&sock->timer_t2)) { + if (sock->pending) { + sock->pending = 0; + + return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0); + } + } + + default: + break; } if (!FD_ISSET(sock->fd, &server->fds_r)) { diff --git a/src/sock.c b/src/sock.c index 869885b..72c9282 100644 --- a/src/sock.c +++ b/src/sock.c @@ -180,6 +180,7 @@ int patty_ax25_sock_reset(patty_ax25_sock *sock) { sock->seq_send = 0; sock->seq_recv = 0; sock->retries = sock->n_retry; + sock->pending = 0; timerclear(&sock->timer_t1); timerclear(&sock->timer_t2);