From a08a70151ca9d0d70c1297eb5377bdea7e613594 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Sat, 1 Aug 2020 16:41:57 -0400 Subject: [PATCH] Better implementations of Timers T1, T2 and T3 More strictly adhere to the behaviors of Timers T1, T2 and T3 as prescribed in the AX.25 v2.2 Specification, Section 4.4.5 "Timeout Error Recovery" descriptions for Timer T1 and T3, as well as Section 6.7.1.2 "Response Delay Timer T2" --- include/patty/ax25/sock.h | 2 +- src/server.c | 67 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index 54840b4..79e0dcf 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -3,7 +3,7 @@ #include -#define PATTY_AX25_SOCK_DEFAULT_KEEPALIVE (1000 * 5) +#define PATTY_AX25_SOCK_DEFAULT_KEEPALIVE (1000 * 30) #define PATTY_AX25_SOCK_DEFAULT_DELAY 3000 #define PATTY_AX25_SOCK_DEFAULT_CLASSES \ diff --git a/src/server.c b/src/server.c index 2d67140..5adbb5a 100644 --- a/src/server.c +++ b/src/server.c @@ -1214,6 +1214,8 @@ static int handle_sabm(patty_ax25_server *server, goto error_respond_accept; } + patty_timer_start(&remote->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + return reply_ua(iface, frame, PATTY_AX25_FRAME_FINAL); error_respond_accept: @@ -1251,6 +1253,8 @@ static int handle_ua(patty_ax25_server *server, patty_timer_stop(&sock->timer_t1); + patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + sock->status = PATTY_AX25_SOCK_ESTABLISHED; if ((client = client_by_sock(server, sock)) < 0) { @@ -1317,10 +1321,11 @@ static int handle_i(patty_ax25_server *server, patty_timer_stop(&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); } + patty_timer_start(&sock->timer_t2, PATTY_AX25_SOCK_DEFAULT_DELAY); + patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + return 0; error_write: @@ -1352,6 +1357,29 @@ reply_dm: return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); } +static int handle_rr(patty_ax25_server *server, + patty_ax25_sock *sock, + patty_ax25_frame *frame) { + if (sock == NULL || frame->pf == 0) { + return 0; + } + + patty_timer_stop(&sock->timer_t1); + + switch (frame->cr) { + case PATTY_AX25_FRAME_COMMAND: + return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1); + + case PATTY_AX25_FRAME_RESPONSE: + patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + + default: + break; + } + + return 0; +} + static int handle_rej(patty_ax25_server *server, patty_ax25_sock *sock, patty_ax25_frame *frame) { @@ -1552,6 +1580,7 @@ static int handle_frame(patty_ax25_server *server, switch (frame.type) { case PATTY_AX25_FRAME_I: return handle_i(server, iface, sock, &frame); + case PATTY_AX25_FRAME_RR: return handle_rr(server, sock, &frame); case PATTY_AX25_FRAME_REJ: return handle_rej(server, sock, &frame); case PATTY_AX25_FRAME_SREJ: return handle_srej(server, sock, &frame); case PATTY_AX25_FRAME_XID: return handle_xid(server, iface, &frame, buf, offset, len); @@ -1657,15 +1686,47 @@ static int handle_sock(uint32_t key, case PATTY_AX25_SOCK_ESTABLISHED: patty_timer_tick(&sock->timer_t2, &server->elapsed); + patty_timer_tick(&sock->timer_t3, &server->elapsed); + + if (patty_timer_expired(&sock->timer_t1)) { + if (sock->retries) { + int ret = patty_ax25_sock_send_rr(sock, + PATTY_AX25_FRAME_COMMAND, + 1); + + sock->retries--; + patty_timer_start(&sock->timer_t1, sock->n_ack); + + return ret; + } else { + (void)sock_shutdown(server, sock); + + return sock_close(server, sock); + } + } if (patty_timer_expired(&sock->timer_t2)) { + patty_timer_stop(&sock->timer_t2); + if (sock->pending) { sock->pending = 0; - return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0); + return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 0); } } + if (patty_timer_expired(&sock->timer_t3)) { + /* + * AX.25 v.2.2 Section 6.7.1.3 "Inactive Link Timer T3" + */ + int ret = patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1); + + patty_timer_stop(&sock->timer_t3); + patty_timer_start(&sock->timer_t1, sock->n_ack); + + return ret; + } + default: break; }