diff --git a/include/patty/ax25/sock.h b/include/patty/ax25/sock.h index 0caf556..75f41c8 100644 --- a/include/patty/ax25/sock.h +++ b/include/patty/ax25/sock.h @@ -234,7 +234,9 @@ ssize_t patty_ax25_sock_recv_pending(patty_ax25_sock *sock); ssize_t patty_ax25_sock_resend(patty_ax25_sock *sock, int seq); -void patty_ax25_sock_ack(patty_ax25_sock *sock, int seq); +int patty_ax25_sock_ack(patty_ax25_sock *sock, int seq); + +int patty_ax25_sock_ack_pending(patty_ax25_sock *sock); ssize_t patty_ax25_sock_send_rr(patty_ax25_sock *sock, enum patty_ax25_frame_cr cr, diff --git a/src/server.c b/src/server.c index 8b858df..9b3b55a 100644 --- a/src/server.c +++ b/src/server.c @@ -1503,6 +1503,17 @@ static int handle_i(patty_ax25_server *server, patty_ax25_sock_ack(sock, frame->nr - 1); + if (patty_ax25_sock_ack_pending(sock) == 0) { + patty_timer_stop(&sock->timer_t1); + } else { + sock->retries = sock->n_retry; + sock->flow = PATTY_AX25_SOCK_WAIT; + + fd_clear(server, sock->fd); + + patty_timer_start(&sock->timer_t1, sock->n_ack); + } + if (frame->ns == sock->vr) { patty_ax25_sock_vr_incr(sock); } else if (frame->ns == sock->vr + 1) { @@ -1588,6 +1599,22 @@ reply_dm: return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); } +static int frame_ack(patty_ax25_server *server, + patty_ax25_sock *sock, + patty_ax25_frame *frame) { + if (sock == NULL) { + return 0; + } + + if (patty_ax25_sock_ack(sock, frame->nr - 1) > 0) { + patty_timer_stop(&sock->timer_t1); + } + + if (patty_ax25_sock_ack_pending(sock) > 0) { + patty_timer_start(&sock->timer_t1, sock->n_ack); + } +} + static int handle_rr(patty_ax25_server *server, patty_ax25_sock *sock, patty_ax25_frame *frame) { @@ -1595,9 +1622,13 @@ static int handle_rr(patty_ax25_server *server, return 0; } - patty_ax25_sock_ack(sock, frame->nr - 1); + if (patty_ax25_sock_ack(sock, frame->nr - 1) > 0) { - patty_timer_stop(&sock->timer_t1); + } + + if (patty_ax25_sock_ack_pending(sock) == 0) { + patty_timer_stop(&sock->timer_t1); + } switch (frame->cr) { case PATTY_AX25_FRAME_COMMAND: @@ -1610,11 +1641,20 @@ static int handle_rr(patty_ax25_server *server, patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_RESPONSE, 1); case PATTY_AX25_FRAME_RESPONSE: - sock->retries = sock->n_retry; + if (patty_ax25_sock_ack_pending(sock) == 0) { + sock->retries = sock->n_retry; - 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); + } else { + sock->retries = sock->n_retry; + sock->flow = PATTY_AX25_SOCK_WAIT; + + fd_clear(server, sock->fd); + + patty_timer_start(&sock->timer_t1, sock->n_ack); + } default: break; @@ -1630,17 +1670,19 @@ static int handle_rnr(patty_ax25_server *server, return 0; } - patty_timer_stop(&sock->timer_t1); - patty_ax25_sock_ack(sock, frame->nr - 1); + if (patty_ax25_sock_ack_pending(sock) == 0) { + patty_timer_stop(&sock->timer_t1); + } + switch (frame->cr) { case PATTY_AX25_FRAME_COMMAND: if (frame->pf == 0) { break; } - return FD_ISSET(sock->fd, &server->fds_watch)? + return sock->flow == PATTY_AX25_SOCK_READY? patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 1): patty_ax25_sock_send_rnr(sock, PATTY_AX25_FRAME_RESPONSE, 1); @@ -1650,7 +1692,11 @@ static int handle_rnr(patty_ax25_server *server, fd_clear(server, sock->fd); - patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + if (patty_ax25_sock_ack_pending(sock) == 0) { + patty_timer_start(&sock->timer_t3, PATTY_AX25_SOCK_DEFAULT_KEEPALIVE); + } else { + patty_timer_start(&sock->timer_t1, sock->n_ack); + } default: break; diff --git a/src/sock.c b/src/sock.c index e8a8579..666d014 100644 --- a/src/sock.c +++ b/src/sock.c @@ -71,8 +71,7 @@ static inline int tx_seq(patty_ax25_sock *sock, int seq) { } static inline struct slot *tx_slot(patty_ax25_sock *sock, int seq) { - size_t win = sock->n_window_tx, - i = tx_seq(sock, seq) % win; + int i = tx_seq(sock, seq) % sock->n_window_tx; return (struct slot *) ((uint8_t *)sock->tx_slots + (i * tx_slot_size(sock))); @@ -653,17 +652,19 @@ static ssize_t frame_send(patty_ax25_sock *sock, if (info && infolen) { if (PATTY_AX25_FRAME_CONTROL_I(control)) { - struct slot *slot = tx_slot(sock, sock->vs); - buf[offset++] = proto; - - slot->len = offset; - slot->ack = 0; } memcpy(buf + offset, info, infolen); offset += infolen; + + if (PATTY_AX25_FRAME_CONTROL_I(control)) { + struct slot *slot = tx_slot(sock, sock->vs); + + slot->len = offset; + slot->ack = 0; + } } return patty_ax25_if_send(sock->iface, buf, offset); @@ -682,18 +683,37 @@ ssize_t patty_ax25_sock_resend(patty_ax25_sock *sock, int seq) { return slot->len > 0? patty_ax25_if_send(sock->iface, buf, slot->len): 0; } -void patty_ax25_sock_ack(patty_ax25_sock *sock, int seq) { - int i; +int patty_ax25_sock_ack(patty_ax25_sock *sock, int seq) { + int ret = 0, + i; for (i=0; in_window_tx; i++) { struct slot *slot = tx_slot(sock, seq - i); if (slot->len > 0) { slot->ack = 1; + ret++; } } sock->va = seq; + + return ret; +} + +int patty_ax25_sock_ack_pending(patty_ax25_sock *sock) { + int ret = 0, + i; + + for (i=0; in_window_tx; i++) { + struct slot *slot = tx_slot(sock, i); + + if (slot->len > 0 && slot->ack == 0) { + ret++; + } + } + + return ret; } static uint16_t control_i(patty_ax25_sock *sock, int flag) {