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:
parent
36f98bf7f0
commit
4d47b62f5f
3 changed files with 28 additions and 9 deletions
|
@ -58,6 +58,11 @@ enum patty_ax25_sock_mode {
|
||||||
PATTY_AX25_SOCK_SABME
|
PATTY_AX25_SOCK_SABME
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum patty_ax25_sock_flow {
|
||||||
|
PATTY_AX25_SOCK_WAIT,
|
||||||
|
PATTY_AX25_SOCK_READY
|
||||||
|
};
|
||||||
|
|
||||||
enum patty_ax25_sock_opt {
|
enum patty_ax25_sock_opt {
|
||||||
PATTY_AX25_SOCK_IF
|
PATTY_AX25_SOCK_IF
|
||||||
};
|
};
|
||||||
|
@ -68,6 +73,7 @@ typedef struct _patty_ax25_sock {
|
||||||
enum patty_ax25_version version;
|
enum patty_ax25_version version;
|
||||||
enum patty_ax25_sock_status status;
|
enum patty_ax25_sock_status status;
|
||||||
enum patty_ax25_sock_mode mode;
|
enum patty_ax25_sock_mode mode;
|
||||||
|
enum patty_ax25_sock_flow flow;
|
||||||
|
|
||||||
size_t n_maxlen_tx,
|
size_t n_maxlen_tx,
|
||||||
n_maxlen_rx,
|
n_maxlen_rx,
|
||||||
|
|
27
src/server.c
27
src/server.c
|
@ -1416,6 +1416,7 @@ static int handle_rr(patty_ax25_server *server,
|
||||||
|
|
||||||
case PATTY_AX25_FRAME_RESPONSE:
|
case PATTY_AX25_FRAME_RESPONSE:
|
||||||
sock->vs = frame->nr;
|
sock->vs = frame->nr;
|
||||||
|
|
||||||
fd_watch(server, sock->fd);
|
fd_watch(server, sock->fd);
|
||||||
|
|
||||||
patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE);
|
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);
|
patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_RESPONSE, 1);
|
||||||
|
|
||||||
case PATTY_AX25_FRAME_RESPONSE:
|
case PATTY_AX25_FRAME_RESPONSE:
|
||||||
sock->vs = frame->nr;
|
sock->flow = PATTY_AX25_SOCK_WAIT;
|
||||||
|
sock->vs = frame->nr;
|
||||||
|
|
||||||
fd_clear(server, sock->fd);
|
fd_clear(server, sock->fd);
|
||||||
|
|
||||||
patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE);
|
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)) {
|
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)?
|
int ret = FD_ISSET(sock->fd, &server->fds_watch)?
|
||||||
patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_COMMAND, 1):
|
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) {
|
if (sock->flow == PATTY_AX25_SOCK_READY) {
|
||||||
fd_clear(server, sock->fd);
|
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);
|
fd_clear(server, sock->fd);
|
||||||
goto done;
|
|
||||||
|
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) {
|
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);
|
patty_timer_start(&sock->timer_t1, sock->n_ack);
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,7 @@ void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
|
||||||
void patty_ax25_sock_init(patty_ax25_sock *sock) {
|
void patty_ax25_sock_init(patty_ax25_sock *sock) {
|
||||||
sock->status = PATTY_AX25_SOCK_CLOSED;
|
sock->status = PATTY_AX25_SOCK_CLOSED;
|
||||||
sock->mode = PATTY_AX25_SOCK_DM;
|
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_tx = PATTY_AX25_SOCK_DEFAULT_I_LEN;
|
||||||
sock->n_maxlen_rx = 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;
|
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) {
|
void patty_ax25_sock_reset(patty_ax25_sock *sock) {
|
||||||
|
sock->flow = PATTY_AX25_SOCK_READY;
|
||||||
sock->vs = 0;
|
sock->vs = 0;
|
||||||
sock->vr = 0;
|
sock->vr = 0;
|
||||||
sock->va = 0;
|
sock->va = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue