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"
This commit is contained in:
XANTRONIX Development 2020-08-01 16:41:57 -04:00 committed by XANTRONIX Industrial
parent ba3923495e
commit a08a70151c
2 changed files with 65 additions and 4 deletions

View file

@ -3,7 +3,7 @@
#include <patty/timer.h>
#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 \

View file

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