Implement additional socket flow control

Implement the SOCK_WAIT and SOCK_READY socket flow control states to
indicate a Receive Ready or Receive Not Ready state on the remote end

Other changes:

    * Fix issue wherein flow control was never halted when the remote
      end has received k (window) number of frames without the sending
      station asking for acknowledgment
This commit is contained in:
XANTRONIX Development 2020-08-05 21:51:51 -04:00 committed by XANTRONIX Industrial
parent 36f98bf7f0
commit 4d47b62f5f
3 changed files with 28 additions and 9 deletions

View file

@ -58,6 +58,11 @@ enum patty_ax25_sock_mode {
PATTY_AX25_SOCK_SABME
};
enum patty_ax25_sock_flow {
PATTY_AX25_SOCK_WAIT,
PATTY_AX25_SOCK_READY
};
enum patty_ax25_sock_opt {
PATTY_AX25_SOCK_IF
};
@ -68,6 +73,7 @@ typedef struct _patty_ax25_sock {
enum patty_ax25_version version;
enum patty_ax25_sock_status status;
enum patty_ax25_sock_mode mode;
enum patty_ax25_sock_flow flow;
size_t n_maxlen_tx,
n_maxlen_rx,

View file

@ -1416,6 +1416,7 @@ static int handle_rr(patty_ax25_server *server,
case PATTY_AX25_FRAME_RESPONSE:
sock->vs = frame->nr;
fd_watch(server, sock->fd);
patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE);
@ -1447,7 +1448,9 @@ static int handle_rnr(patty_ax25_server *server,
patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_RESPONSE, 1);
case PATTY_AX25_FRAME_RESPONSE:
sock->vs = frame->nr;
sock->flow = PATTY_AX25_SOCK_WAIT;
sock->vs = frame->nr;
fd_clear(server, sock->fd);
patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE);
@ -1833,7 +1836,7 @@ static int handle_sock(uint32_t key,
if (patty_timer_expired(&sock->timer_t3)) {
/*
* AX.25 v.2.2 Section 6.7.1.3 "Inactive Link Timer T3"
* AX.25 v.2.2 Section 6.7.1.3, "Inactive Link Timer T3"
*/
int ret = FD_ISSET(sock->fd, &server->fds_watch)?
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1):
@ -1854,13 +1857,21 @@ static int handle_sock(uint32_t key,
}
/*
* NOTE: See AX.25 2.2, Section 6.4.1, "Sending I Frames"
* AX.25 v2.2, Section 6.4.1, "Sending I Frames"
*/
if (sock->vs + sock->n_window_tx == sock->vs) {
fd_clear(server, sock->fd);
if (sock->flow == PATTY_AX25_SOCK_READY) {
if (sock->vs % sock->n_window_tx == sock->n_window_tx - 1) {
sock->flow = PATTY_AX25_SOCK_WAIT;
return patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_COMMAND, 1);
goto done;
fd_clear(server, sock->fd);
patty_timer_start(&sock->timer_t1, sock->n_ack);
patty_timer_stop(&sock->timer_t3);
return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1);
}
} else if (sock->flow == PATTY_AX25_SOCK_WAIT) {
sock->flow = PATTY_AX25_SOCK_READY;
}
if ((len = read(sock->fd, sock->rx_buf, sock->n_maxlen_rx)) < 0) {
@ -1882,7 +1893,7 @@ static int handle_sock(uint32_t key,
}
/*
* AX.25 v2.2, Section 6.4.1 "Sending I Frames"
* AX.25 v2.2, Section 6.4.1, "Sending I Frames"
*/
patty_timer_start(&sock->timer_t1, sock->n_ack);

View file

@ -200,6 +200,7 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
void patty_ax25_sock_init(patty_ax25_sock *sock) {
sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM;
sock->flow = PATTY_AX25_SOCK_WAIT;
sock->n_maxlen_tx = PATTY_AX25_SOCK_DEFAULT_I_LEN;
sock->n_maxlen_rx = PATTY_AX25_SOCK_DEFAULT_I_LEN;
sock->n_window_tx = PATTY_AX25_SOCK_DEFAULT_WINDOW;
@ -211,9 +212,10 @@ void patty_ax25_sock_init(patty_ax25_sock *sock) {
}
/*
* AX.25 v2.2 Specification, Section 6.5 "Resetting Procedure"
* AX.25 v2.2, Section 6.5 "Resetting Procedure"
*/
void patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->flow = PATTY_AX25_SOCK_READY;
sock->vs = 0;
sock->vr = 0;
sock->va = 0;