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:
parent
a619bc4906
commit
ba3923495e
5 changed files with 69 additions and 51 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
34
src/server.c
34
src/server.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
44
src/timer.c
44
src/timer.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue