Implement patty_timer type

Changes:

    * Implement patty_timer type to store both a struct timeval and a
      bitfield for indicating timer state; currently, this only holds
      the PATTY_TIMER_RUNNING flag to indicate whether a timer has been
      stopped (irrespective of its "expired" status)

    * Remove 'target' argument from patty_timer_start(); instead, rely
      on select() polling every 1s to cause events to trigger at a
      regular interval

    * Make patty_timer_expired() return false if PATTY_TIMER_RUNNING is
      not set

    * Implement patty_timer_stop() to clear the PATTY_TIMER_RUNNING flag
      of a timer

    * Make patty_timer_clear() set all fields to zero, including
      clearing the PATTY_TIMER_RUNNING flag
This commit is contained in:
XANTRONIX Development 2020-08-01 16:37:39 -04:00 committed by XANTRONIX Industrial
parent a619bc4906
commit ba3923495e
5 changed files with 69 additions and 51 deletions

View file

@ -1,6 +1,11 @@
#ifndef _PATTY_AX25_SOCK_H #ifndef _PATTY_AX25_SOCK_H
#define _PATTY_AX25_SOCK_H #define _PATTY_AX25_SOCK_H
#include <patty/timer.h>
#define PATTY_AX25_SOCK_DEFAULT_KEEPALIVE (1000 * 5)
#define PATTY_AX25_SOCK_DEFAULT_DELAY 3000
#define PATTY_AX25_SOCK_DEFAULT_CLASSES \ #define PATTY_AX25_SOCK_DEFAULT_CLASSES \
(PATTY_AX25_PARAM_CLASSES_ABM) (PATTY_AX25_PARAM_CLASSES_ABM)
@ -62,13 +67,13 @@ typedef struct _patty_ax25_sock {
n_ack, n_ack,
n_retry; n_retry;
struct timeval timer_t1,
timer_t2,
timer_t3;
uint32_t flags_classes, uint32_t flags_classes,
flags_hdlc; flags_hdlc;
patty_timer timer_t1,
timer_t2,
timer_t3;
unsigned int seq_send, unsigned int seq_send,
seq_recv; seq_recv;

View file

@ -1,17 +1,30 @@
#ifndef _PATTY_TIMER_H #ifndef _PATTY_TIMER_H
#define _PATTY_TIMER_H #define _PATTY_TIMER_H
#include <stdint.h>
#include <sys/time.h> #include <sys/time.h>
int patty_timer_expired(struct timeval *timer); enum patty_timer_flags {
PATTY_TIMER_RUNNING = (1 << 0)
};
void patty_timer_cancel(struct timeval *timer); typedef struct _patty_timer {
struct timeval t;
uint32_t flags;
} patty_timer;
void patty_timer_start(struct timeval *timer, int patty_timer_running(patty_timer *timer);
struct timeval *target,
int patty_timer_expired(patty_timer *timer);
void patty_timer_clear(patty_timer *timer);
void patty_timer_start(patty_timer *timer,
time_t ms); time_t ms);
void patty_timer_tick(struct timeval *timer, void patty_timer_stop(patty_timer *timer);
void patty_timer_tick(patty_timer *timer,
struct timeval *elapsed); struct timeval *elapsed);
#endif /* _PATTY_TIMER_H */ #endif /* _PATTY_TIMER_H */

View file

@ -11,7 +11,6 @@
#include <patty/ax25.h> #include <patty/ax25.h>
#include <patty/hash.h> #include <patty/hash.h>
#include <patty/timer.h>
typedef int (*patty_ax25_server_call)(patty_ax25_server *, int); typedef int (*patty_ax25_server_call)(patty_ax25_server *, int);
@ -21,8 +20,7 @@ struct _patty_ax25_server {
int fd, /* fd of UNIX domain socket */ int fd, /* fd of UNIX domain socket */
fd_max; fd_max;
struct timeval timer, struct timeval elapsed;
elapsed;
fd_set fds_watch, /* fds to monitor with select() */ fd_set fds_watch, /* fds to monitor with select() */
fds_r; /* fds select()ed for reading */ fds_r; /* fds select()ed for reading */
@ -830,7 +828,7 @@ static int server_connect(patty_ax25_server *server,
return respond_connect(client, -1, errno); return respond_connect(client, -1, errno);
} }
patty_timer_start(&sock->timer_t1, &server->timer, sock->n_ack); patty_timer_start(&sock->timer_t1, sock->n_ack);
/* /*
* At this point, we will wait for a DM, FRMR or XID response, which * At this point, we will wait for a DM, FRMR or XID response, which
@ -1153,7 +1151,7 @@ static int handle_frmr(patty_ax25_server *server,
if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) { if (sock->status == PATTY_AX25_SOCK_PENDING_CONNECT) {
int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL); int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
patty_timer_start(&sock->timer_t1, &server->timer, sock->n_ack); patty_timer_start(&sock->timer_t1, sock->n_ack);
return ret; return ret;
} }
@ -1251,7 +1249,7 @@ static int handle_ua(patty_ax25_server *server,
return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL); return reply_dm(iface, frame, PATTY_AX25_FRAME_FINAL);
} }
patty_timer_cancel(&sock->timer_t1); patty_timer_stop(&sock->timer_t1);
sock->status = PATTY_AX25_SOCK_ESTABLISHED; sock->status = PATTY_AX25_SOCK_ESTABLISHED;
@ -1316,7 +1314,7 @@ static int handle_i(patty_ax25_server *server,
if (++sock->pending == sock->n_window_rx / 2) { if (++sock->pending == sock->n_window_rx / 2) {
sock->pending = 0; sock->pending = 0;
patty_timer_cancel(&sock->timer_t2); patty_timer_stop(&sock->timer_t2);
return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0); return patty_ax25_sock_send_rr(sock, PATTY_AX25_FRAME_RESPONSE, 0);
} else { } else {
@ -1460,7 +1458,7 @@ static int handle_xid(patty_ax25_server *server,
ret = patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL); ret = patty_ax25_sock_send_sabm(remote, PATTY_AX25_FRAME_POLL);
patty_timer_start(&remote->timer_t1, &server->timer, remote->n_ack); patty_timer_start(&remote->timer_t1, remote->n_ack);
return ret; return ret;
} }
@ -1645,7 +1643,7 @@ static int handle_sock(uint32_t key,
int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL); int ret = patty_ax25_sock_send_sabm(sock, PATTY_AX25_FRAME_POLL);
sock->retries--; sock->retries--;
patty_timer_start(&sock->timer_t1, &server->timer, sock->n_ack); patty_timer_start(&sock->timer_t1, sock->n_ack);
return ret; return ret;
} else { } else {
@ -1704,7 +1702,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, &server->timer, sock->n_ack); patty_timer_start(&sock->timer_t1, sock->n_ack);
done: done:
return 0; return 0;
@ -1726,28 +1724,20 @@ int patty_ax25_server_run(patty_ax25_server *server) {
while (1) { while (1) {
int nready; int nready;
struct timeval remaining, struct timeval timer = { 1, 0 },
*timer; remaining = { 1, 0 };
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r)); memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
memcpy(&remaining, &server->timer, sizeof(remaining));
timer = timerisset(&remaining)? &remaining: NULL;
if ((nready = select( server->fd_max, if ((nready = select( server->fd_max,
&server->fds_r, &server->fds_r,
NULL, NULL,
NULL, NULL,
timer)) < 0) { &remaining)) < 0) {
goto error_io; goto error_io;
} }
if (timer) { timersub(&timer, &remaining, &server->elapsed);
timersub(&server->timer, &remaining, &server->elapsed);
memcpy(&server->timer, &remaining, sizeof(server->timer));
} else {
timerclear(&server->elapsed);
}
if (handle_clients(server) < 0) { if (handle_clients(server) < 0) {
goto error_io; goto error_io;

View file

@ -182,9 +182,9 @@ int patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->retries = sock->n_retry; sock->retries = sock->n_retry;
sock->pending = 0; sock->pending = 0;
timerclear(&sock->timer_t1); patty_timer_clear(&sock->timer_t1);
timerclear(&sock->timer_t2); patty_timer_clear(&sock->timer_t2);
timerclear(&sock->timer_t3); patty_timer_clear(&sock->timer_t3);
return 0; return 0;
} }

View file

@ -1,32 +1,42 @@
#include <patty/timer.h> #include <patty/timer.h>
int patty_timer_expired(struct timeval *timer) { int patty_timer_running(patty_timer *timer) {
return timer->tv_sec <= 0? 1: 0; return (timer->flags & PATTY_TIMER_RUNNING)? 1: 0;
} }
void patty_timer_cancel(struct timeval *timer) { int patty_timer_expired(patty_timer *timer) {
timer->tv_sec = 0; return (timer->flags & PATTY_TIMER_RUNNING) && timer->t.tv_sec <= 0? 1: 0;
timer->tv_usec = 0;
} }
void patty_timer_start(struct timeval *timer, void patty_timer_clear(patty_timer *timer) {
struct timeval *target, timer->t.tv_sec = 0;
timer->t.tv_usec = 0;
timer->flags &= ~PATTY_TIMER_RUNNING;
}
void patty_timer_start(patty_timer *timer,
time_t ms) { time_t ms) {
timer->tv_sec = ms / 1000; timer->t.tv_sec = ms / 1000;
timer->tv_usec = (ms % 1000) * 1000; timer->t.tv_usec = (ms % 1000) * 1000;
if (timercmp(timer, target, >)) { timer->flags |= PATTY_TIMER_RUNNING;
target->tv_sec = timer->tv_sec;
target->tv_usec = timer->tv_usec;
}
} }
void patty_timer_tick(struct timeval *timer, void patty_timer_stop(patty_timer *timer) {
timer->flags &= ~PATTY_TIMER_RUNNING;
}
void patty_timer_tick(patty_timer *timer,
struct timeval *elapsed) { struct timeval *elapsed) {
struct timeval res; struct timeval res;
timersub(timer, elapsed, &res); if (!(timer->flags & PATTY_TIMER_RUNNING)) {
return;
}
timer->tv_sec = res.tv_sec; timersub(&timer->t, elapsed, &res);
timer->tv_usec = res.tv_usec;
timer->t.tv_sec = res.tv_sec;
timer->t.tv_usec = res.tv_usec;
} }