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
This commit is contained in:
XANTRONIX Development 2020-07-31 01:14:11 -04:00 committed by XANTRONIX Industrial
parent 05cac588f2
commit aa2fd9b06d
3 changed files with 45 additions and 19 deletions

View file

@ -72,7 +72,8 @@ typedef struct _patty_ax25_sock {
unsigned int seq_send, unsigned int seq_send,
seq_recv; seq_recv;
size_t retries; size_t retries,
pending;
int fd; int fd;
char pty[PATTY_AX25_SOCK_PATH_SIZE]; char pty[PATTY_AX25_SOCK_PATH_SIZE];

View file

@ -1314,8 +1314,16 @@ static int handle_i(patty_ax25_server *server,
goto error_write; goto error_write;
} }
return frame->pf? if (++sock->pending == sock->n_window_rx / 2) {
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0): 0; 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: error_write:
return -1; return -1;
@ -1628,24 +1636,40 @@ static int handle_sock(uint32_t key,
ssize_t len; ssize_t len;
if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) { switch (sock->status) {
if (patty_timer_expired(&sock->timer_t1)) { case PATTY_AX25_SOCK_PENDING_CONNECT:
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 {
patty_timer_tick(&sock->timer_t1, &server->elapsed); 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)) { if (!FD_ISSET(sock->fd, &server->fds_r)) {

View file

@ -180,6 +180,7 @@ int patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->seq_send = 0; sock->seq_send = 0;
sock->seq_recv = 0; sock->seq_recv = 0;
sock->retries = sock->n_retry; sock->retries = sock->n_retry;
sock->pending = 0;
timerclear(&sock->timer_t1); timerclear(&sock->timer_t1);
timerclear(&sock->timer_t2); timerclear(&sock->timer_t2);