kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit d6ab1d74450cbe17ea0e7b12d05d6bb827c6a783
parent cf028f20b6b9c526ad792a08b21b04e3eac8c254
Author: Joris Vink <joris@coders.se>
Date:   Mon,  6 Apr 2015 18:54:35 +0200

Add rudimentary timers to Kore.

Timers are in ms resolution and are added using
kore_timer_add(cb, interval, flags).

Both oneshot timers and continious timers are supported.

Diffstat:
Makefile | 4++--
includes/kore.h | 7+++++++
src/bsd.c | 4++--
src/timer.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/worker.c | 6++++--
5 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,8 +8,8 @@ INCLUDE_DIR=$(PREFIX)/include/kore S_SRC= src/kore.c src/accesslog.c src/auth.c src/buf.c src/cli.c src/config.c \ src/connection.c src/domain.c src/http.c src/mem.c src/module.c \ - src/net.c src/pool.c src/spdy.c src/validator.c src/utils.c \ - src/websocket.c src/worker.c src/zlib_dict.c + src/net.c src/pool.c src/spdy.c src/timer.c src/validator.c \ + src/utils.c src/websocket.c src/worker.c src/zlib_dict.c S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes diff --git a/includes/kore.h b/includes/kore.h @@ -164,6 +164,8 @@ LIST_HEAD(listener_head, listener); #define WEBSOCKET_BROADCAST_LOCAL 1 #define WEBSOCKET_BROADCAST_GLOBAL 2 +#define KORE_TIMER_ONESHOT 0x01 + struct connection { u_int8_t type; int fd; @@ -407,6 +409,11 @@ void kore_auth_init(void); int kore_auth_new(const char *); struct kore_auth *kore_auth_lookup(const char *); +void kore_timer_init(void); +u_int64_t kore_timer_run(u_int64_t); +void kore_timer_add(void (*cb)(u_int64_t, u_int64_t), + u_int64_t, int); + int kore_ssl_sni_cb(SSL *, int *, void *); int kore_server_bind(const char *, const char *); int kore_ssl_npn_cb(SSL *, const u_char **, unsigned int *, void *); diff --git a/src/bsd.c b/src/bsd.c @@ -102,8 +102,8 @@ kore_platform_event_wait(u_int64_t timer) struct timespec timeo; int n, i; - timeo.tv_sec = 0; - timeo.tv_nsec = timer * 1000000; + timeo.tv_sec = timer / 1000; + timeo.tv_nsec = (timer % 1000) * 1000000; n = kevent(kfd, changelist, nchanges, events, event_count, &timeo); if (n == -1) { if (errno == EINTR) diff --git a/src/timer.c b/src/timer.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 Joris Vink <joris@coders.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/queue.h> + +#include "kore.h" + +struct timer { + u_int64_t nextrun; + u_int64_t interval; + int flags; + void (*cb)(u_int64_t, u_int64_t); + TAILQ_ENTRY(timer) list; +}; + +TAILQ_HEAD(timerlist, timer) kore_timers; + +void +kore_timer_init(void) +{ + TAILQ_INIT(&kore_timers); +} + +void +kore_timer_add(void (*cb)(u_int64_t, u_int64_t), u_int64_t interval, int flags) +{ + struct timer *timer, *t; + + timer = kore_malloc(sizeof(*timer)); + + timer->cb = cb; + timer->flags = flags; + timer->interval = interval; + timer->nextrun = kore_time_ms() + timer->interval; + + TAILQ_FOREACH(t, &kore_timers, list) { + if (t->nextrun > timer->nextrun) { + TAILQ_INSERT_BEFORE(t, timer, list); + return; + } + } + + TAILQ_INSERT_TAIL(&kore_timers, timer, list); +} + +u_int64_t +kore_timer_run(u_int64_t now) +{ + struct timer *timer, *t; + u_int64_t next_timer, delta; + + next_timer = 100; + + while ((timer = TAILQ_FIRST(&kore_timers)) != NULL) { + if (timer->nextrun > now) { + next_timer = timer->nextrun - now; + break; + } + + TAILQ_REMOVE(&kore_timers, timer, list); + delta = now - timer->nextrun; + timer->cb(now, delta); + + if (timer->flags & KORE_TIMER_ONESHOT) { + kore_mem_free(timer); + } else { + timer->nextrun += timer->interval - delta; + TAILQ_FOREACH(t, &kore_timers, list) { + if (t->nextrun > timer->nextrun) { + TAILQ_INSERT_BEFORE(t, timer, list); + break; + } + } + + if (t == NULL) + TAILQ_INSERT_TAIL(&kore_timers, timer, list); + } + } + + if (next_timer > 1) + next_timer -= 1; + + return (next_timer); +} diff --git a/src/worker.c b/src/worker.c @@ -186,7 +186,7 @@ kore_worker_entry(struct kore_worker *kw) char buf[16]; struct connection *c, *cnext; int quit, had_lock, r; - u_int64_t now, idle_check, next_lock; + u_int64_t now, idle_check, next_lock, netwait; worker = kw; @@ -234,6 +234,7 @@ kore_worker_entry(struct kore_worker *kw) net_init(); http_init(); + kore_timer_init(); kore_connection_init(); kore_domain_load_crl(); TAILQ_INIT(&disconnected); @@ -273,6 +274,7 @@ kore_worker_entry(struct kore_worker *kw) } now = kore_time_ms(); + netwait = kore_timer_run(now); if (now > next_lock) { if (kore_worker_acceptlock_obtain()) { @@ -290,7 +292,7 @@ kore_worker_entry(struct kore_worker *kw) } } - r = kore_platform_event_wait(100); + r = kore_platform_event_wait(netwait); if (worker->has_lock && r > 0) { kore_worker_acceptlock_release(); next_lock = now + WORKER_LOCK_TIMEOUT;