diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index b9b6a677d..62a8cf08b 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -12,8 +12,6 @@ #include #include -static struct timeout topology_timeout; - struct block { int height; @@ -65,6 +63,14 @@ struct topology { struct block_map block_map; }; +static void start_poll_chaintips(struct lightningd_state *dstate); + +static void next_topology_timer(struct lightningd_state *dstate) +{ + new_reltimer(dstate, dstate, time_from_sec(dstate->config.poll_seconds), + start_poll_chaintips, dstate); +} + static int cmp_times(const u32 *a, const u32 *b, void *unused) { if (*a > *b) @@ -371,7 +377,7 @@ static void gather_blocks(struct lightningd_state *dstate, /* All done. */ topology_changed(dstate, prev, b); - refresh_timeout(dstate, &topology_timeout); + next_topology_timer(dstate); } static void check_chaintips(struct lightningd_state *dstate, @@ -385,7 +391,8 @@ static void check_chaintips(struct lightningd_state *dstate, bitcoind_getrawblock(dstate, &blockids[0], gather_blocks, (struct block *)NULL); else - refresh_timeout(dstate, &topology_timeout); + /* Next! */ + next_topology_timer(dstate); } static void start_poll_chaintips(struct lightningd_state *dstate) @@ -393,10 +400,10 @@ static void start_poll_chaintips(struct lightningd_state *dstate) if (!list_empty(&dstate->bitcoin_req)) { log_unusual(dstate->base_log, "Delaying start poll: commands in progress"); - refresh_timeout(dstate, &topology_timeout); + next_topology_timer(dstate); } else bitcoind_get_chaintips(dstate, check_chaintips, NULL); -} + } static void init_topo(struct lightningd_state *dstate, struct bitcoin_block *blk, @@ -457,7 +464,5 @@ void setup_topology(struct lightningd_state *dstate) dstate->topology->tip = NULL; block_map_init(&dstate->topology->block_map); - init_timeout(&topology_timeout, dstate->config.poll_seconds, - start_poll_chaintips, dstate); bitcoind_getblockcount(dstate, get_init_blockhash, NULL); } diff --git a/daemon/lightningd.c b/daemon/lightningd.c index 6cf0f7d38..28afb8b33 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -307,11 +307,8 @@ int main(int argc, char *argv[]) * NULL if we only broke out due to timer). */ tal_free(v); - if (expired) { - struct timeout *to; - to = container_of(expired, struct timeout, timer); - to->cb(to->arg); - } + if (expired) + timer_expired(dstate, expired); } tal_free(dstate); diff --git a/daemon/peer.c b/daemon/peer.c index 8273e8f69..bb601a90e 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -1559,9 +1559,10 @@ void peer_watch_anchor(struct peer *peer, * So, our formula of 12 + N*2 holds for N <= 20 at least. */ if (w->timeout != INPUT_NONE) { - w->timer = oneshot_timeout(peer->dstate, w, - 7200 + 20*peer->us.mindepth, - anchor_timeout, w); + w->timer = new_reltimer(peer->dstate, w, + time_from_sec(7200 + + 20*peer->us.mindepth), + anchor_timeout, w); } else w->timer = NULL; } @@ -2063,13 +2064,13 @@ static void htlc_expiry_timeout(struct peer *peer) void peer_add_htlc_expiry(struct peer *peer, const struct abs_locktime *expiry) { - time_t when; + struct timeabs absexpiry; /* Add 30 seconds to be sure peers agree on timeout. */ - when = abs_locktime_to_seconds(expiry) - controlled_time().ts.tv_sec; - when += 30; + absexpiry.ts.tv_sec = abs_locktime_to_seconds(expiry) + 30; + absexpiry.ts.tv_nsec = 0; - oneshot_timeout(peer->dstate, peer, when, htlc_expiry_timeout, peer); + new_abstimer(peer->dstate, peer, absexpiry, htlc_expiry_timeout, peer); } struct newhtlc { diff --git a/daemon/timeout.c b/daemon/timeout.c index 81f179150..8f842cd73 100644 --- a/daemon/timeout.c +++ b/daemon/timeout.c @@ -2,54 +2,51 @@ #include "lightningd.h" #include "timeout.h" -void init_timeout_(struct timeout *t, unsigned int interval, - void (*cb)(void *), void *arg) -{ - timer_init(&t->timer); - t->interval = time_from_sec(interval); - t->cb = cb; - t->arg = arg; -} - -void refresh_timeout(struct lightningd_state *dstate, struct timeout *t) -{ - timer_del(&dstate->timers, &t->timer); - timer_add(&dstate->timers, &t->timer, - timeabs_add(controlled_time(), t->interval)); -} - -/* FIXME: Make all timers one-shot! */ struct oneshot { - struct timeout timeout; struct lightningd_state *dstate; + struct timer timer; void (*cb)(void *); void *arg; }; -static void remove_timer(struct oneshot *o) +static void remove_timer(struct oneshot *t) { - timer_del(&o->dstate->timers, &o->timeout.timer); + timer_del(&t->dstate->timers, &t->timer); } -static void oneshot_done(struct oneshot *o) +struct oneshot *new_abstimer_(struct lightningd_state *dstate, + const tal_t *ctx, + struct timeabs expiry, + void (*cb)(void *), void *arg) { - o->cb(o->arg); - tal_free(o); + struct oneshot *t = tal(ctx, struct oneshot); + + t->cb = cb; + t->arg = arg; + t->dstate = dstate; + timer_init(&t->timer); + timer_add(&dstate->timers, &t->timer, expiry); + tal_add_destructor(t, remove_timer); + + return t; } -struct oneshot *oneshot_timeout_(struct lightningd_state *dstate, - const tal_t *ctx, unsigned int seconds, - void (*cb)(void *), void *arg) +struct oneshot *new_reltimer_(struct lightningd_state *dstate, + const tal_t *ctx, + struct timerel relexpiry, + void (*cb)(void *), void *arg) { - struct oneshot *o = tal(ctx, struct oneshot); - - o->dstate = dstate; - o->cb = cb; - o->arg = arg; - - init_timeout(&o->timeout, seconds, oneshot_done, o); - refresh_timeout(dstate, &o->timeout); - tal_add_destructor(o, remove_timer); - - return o; + return new_abstimer_(dstate, ctx, + timeabs_add(controlled_time(), relexpiry), + cb, arg); +} + +void timer_expired(struct lightningd_state *dstate, struct timer *timer) +{ + struct oneshot *t = container_of(timer, struct oneshot, timer); + tal_t *tmpctx = tal(dstate, char); + + /* If it doesn't free itself, freeing tmpctx will do it */ + tal_steal(tmpctx, t); + t->cb(t->arg); } diff --git a/daemon/timeout.h b/daemon/timeout.h index 12c0cdcd9..a272e4c9d 100644 --- a/daemon/timeout.h +++ b/daemon/timeout.h @@ -7,31 +7,25 @@ #include #include -struct timeout { - struct timer timer; - struct timerel interval; - void (*cb)(void *); - void *arg; -}; - -struct lightningd_state; - -void init_timeout_(struct timeout *t, unsigned int interval, - void (*cb)(void *), void *arg); - -void refresh_timeout(struct lightningd_state *dstate, struct timeout *t); - -#define init_timeout(t, interval, func, arg) \ - init_timeout_((t), (interval), \ - typesafe_cb(void, void *, (func), (arg)), (arg)) - /* tal_free this to disable timer. */ -struct oneshot *oneshot_timeout_(struct lightningd_state *dstate, - const tal_t *ctx, unsigned int seconds, - void (*cb)(void *), void *arg); +struct oneshot *new_reltimer_(struct lightningd_state *dstate, + const tal_t *ctx, + struct timerel expire, + void (*cb)(void *), void *arg); -#define oneshot_timeout(dstate, ctx, interval, func, arg) \ - oneshot_timeout_((dstate), (ctx), (interval), \ - typesafe_cb(void, void *, (func), (arg)), (arg)) +#define new_reltimer(dstate, ctx, relexpire, func, arg) \ + new_reltimer_((dstate), (ctx), (relexpire), \ + typesafe_cb(void, void *, (func), (arg)), (arg)) + +struct oneshot *new_abstimer_(struct lightningd_state *dstate, + const tal_t *ctx, + struct timeabs expire, + void (*cb)(void *), void *arg); + +#define new_abstimer(dstate, ctx, absexpire, func, arg) \ + new_abstimer_((dstate), (ctx), (absexpire), \ + typesafe_cb(void, void *, (func), (arg)), (arg)) + +void timer_expired(struct lightningd_state *dstate, struct timer *timer); #endif /* LIGHTNING_DAEMON_TIMEOUT_H */