diff --git a/examples/client.c b/examples/client.c index d134758d63..0f7fe5d031 100644 --- a/examples/client.c +++ b/examples/client.c @@ -1030,7 +1030,6 @@ main(int argc, char **argv) { struct timeval tv; int result; coap_tick_t now; - coap_queue_t *nextpdu; coap_pdu_t *pdu; static str server; unsigned short port = COAP_DEFAULT_PORT; @@ -1210,32 +1209,8 @@ main(int argc, char **argv) { FD_ZERO(&readfds); FD_SET( ctx->sockfd, &readfds ); - nextpdu = coap_peek_next( ctx ); - -// coap_ticks(&now); -// while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { -// coap_retransmit( ctx, coap_pop_next( ctx )); -// nextpdu = coap_peek_next( ctx ); -// } - - if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait, max_wait) - now) { - /* set timeout if there is a pdu to send */ - tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; - } else { - /* check if obs_wait fires before max_wait */ - if (obs_wait && obs_wait < max_wait) { - tv.tv_usec = ((obs_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (obs_wait - now) / COAP_TICKS_PER_SECOND; - } else { - tv.tv_usec = ((max_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (max_wait - now) / COAP_TICKS_PER_SECOND; - } - } - - //result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv); - result = 0; - pause(); + tv.tv_sec = wait_seconds; + result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv); if ( result < 0 ) { /* error */ perror("select"); diff --git a/examples/coap-server.c b/examples/coap-server.c index f0aa59f34a..f4433314d7 100644 --- a/examples/coap-server.c +++ b/examples/coap-server.c @@ -450,7 +450,6 @@ main(int argc, char **argv) { struct timeval tv, *timeout; int result; coap_tick_t now; - coap_queue_t *nextpdu; char addr_str[NI_MAXHOST] = "::"; char port_str[NI_MAXSERV] = "5683"; int opt; @@ -498,24 +497,11 @@ main(int argc, char **argv) { FD_ZERO(&readfds); FD_SET( ctx->sockfd, &readfds ); - nextpdu = coap_peek_next( ctx ); - coap_ticks(&now); - while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) { - coap_retransmit( ctx, coap_pop_next( ctx ) ); - nextpdu = coap_peek_next( ctx ); - } - if ( nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME ) { - /* set timeout if there is a pdu to send before our automatic timeout occurs */ - tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND; - tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND; - timeout = &tv; - } else { - tv.tv_usec = 0; - tv.tv_sec = COAP_RESOURCE_CHECK_TIME; - timeout = &tv; - } + tv.tv_usec = 0; + tv.tv_sec = COAP_RESOURCE_CHECK_TIME; + timeout = &tv; result = select( FD_SETSIZE, &readfds, 0, 0, timeout ); if ( result < 0 ) { /* error */ diff --git a/platform/posix/platform_time.c b/platform/posix/platform_time.c index 460d618e5a..4d4300a0ff 100644 --- a/platform/posix/platform_time.c +++ b/platform/posix/platform_time.c @@ -14,6 +14,8 @@ static coap_time_t coap_clock_offset = 0; #define COAP_CLOCK CLOCK_REALTIME #endif +#undef COAP_CLOCK + void coap_clock_init(void) { #ifdef COAP_CLOCK @@ -61,7 +63,7 @@ coap_ticks(coap_tick_t *t) { * Both cases should not be possible here. */ - tmp = tv.tv_usec * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000.0)); + tmp = tv.tv_usec / 1000; // * Q(FRAC, (COAP_TICKS_PER_SECOND/1000000.0)); #endif /* not _POSIX_TIMERS */ /* Finally, convert temporary FP representation to multiple of diff --git a/platform/posix/platform_timer.c b/platform/posix/platform_timer.c index 8b5d737600..f2a9281550 100644 --- a/platform/posix/platform_timer.c +++ b/platform/posix/platform_timer.c @@ -6,6 +6,7 @@ #include #include // TODO needs something like HAVE_TIME_H #include // TODO needs something like HAVE_SIGNAL_H +#include // TODO needs something like HAVE_PTHREAD_H #include "libev/ev.h" @@ -15,35 +16,81 @@ #define UNUSED #endif -struct coap_timer_t; - struct coap_timer_t { + ev_timer timer; CoapTimerCallback cb; void *data; }; +static pthread_t timer_thread; +static struct ev_loop *timer_loop; +static ev_async thread_wakeup; + +static void timeout_cb(EV_P_ ev_timer *w, int revents) { + coap_timer_t *coap_timer = (coap_timer_t *)w; + if (coap_timer->cb) { + coap_timer->cb(coap_timer->data); + } +} + +static void *timer_thread_func(void* args) { + ev_run(timer_loop, 0); + return NULL; +} + +static void thread_wakeup_cb(EV_P_ ev_async *w, int revents) { + // this only exists to wake up the thread + // so it may pick up new timer watchers +} + + +// TODO coap_timer_deinit to cleanly kill the loop void coap_timer_init(void) { - struct ev_loop *loop = EV_DEFAULT; - ev_run (loop, 0); + timer_loop = EV_DEFAULT; + + // set up an async event for thread wakeup + ev_async_init(&thread_wakeup, thread_wakeup_cb); + ev_async_start(timer_loop, &thread_wakeup); + + pthread_create(&timer_thread, NULL, timer_thread_func, NULL); } coap_timer_t *coap_new_timer(CoapTimerCallback cb, void *data) { - return NULL; + coap_timer_t *coap_timer = coap_malloc_type(COAP_TIMER, sizeof(coap_timer_t)); + + if (coap_timer) { + coap_timer->cb = cb; + coap_timer->data = data; + ev_timer_init(&coap_timer->timer, timeout_cb, 0., 0.); + } + + return coap_timer; } -void coap_free_timer(coap_timer_t *timer) { - return; +void coap_free_timer(coap_timer_t *coap_timer) { + ev_timer_stop(timer_loop, &coap_timer->timer); + coap_free_type(COAP_TIMER, coap_timer); } -void coap_timer_set(coap_timer_t *timer, coap_tick_t num_ticks) { - return; +void coap_timer_set(coap_timer_t *coap_timer, coap_tick_t num_ticks) { + // stop the timer if it is running + ev_timer_stop(timer_loop, &coap_timer->timer); + + // set the new timeout + ev_tstamp time = (ev_tstamp)num_ticks / COAP_TICKS_PER_SECOND; + ev_timer_set(&coap_timer->timer, time, 0.); + ev_timer_start(timer_loop, &coap_timer->timer); + + // wake up the thread + ev_async_send(timer_loop, &thread_wakeup); } -char coap_timer_is_set(coap_timer_t *timer) { - return 0; +char coap_timer_is_set(coap_timer_t *coap_timer) { + return (ev_timer_remaining(timer_loop, &coap_timer->timer) != 0.); } -void coap_timer_unset(coap_timer_t *timer) { - return; +void coap_timer_unset(coap_timer_t *coap_timer) { + ev_timer_stop(timer_loop, &coap_timer->timer); + ev_timer_set(&coap_timer->timer, 0., 0.); } diff --git a/src/coap_context.c b/src/coap_context.c index 0ac95f8fdf..45a6121ee9 100644 --- a/src/coap_context.c +++ b/src/coap_context.c @@ -51,7 +51,6 @@ coap_context_t the_coap_context; #ifndef WITHOUT_OBSERVE static void notify_timer_cb(void *data) { - debug("NOTIFY!\n"); coap_context_t *c = data; coap_check_notify(c); coap_timer_set(c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND); @@ -60,7 +59,6 @@ static void notify_timer_cb(void *data) { // TODO this should probably be in its own file ... coap_retransmit.c? static void retransmit_timer_cb(void *data) { - debug("CALLBACK!\n"); coap_context_t *c = data; coap_queue_t *nextpdu = coap_peek_next(c); diff --git a/src/net.c b/src/net.c index a36dfca6f5..192d5504ed 100644 --- a/src/net.c +++ b/src/net.c @@ -494,7 +494,6 @@ coap_send_confirmed(coap_context_t *context, /* Reschedule the retransmit timer if the head node is the new node */ if (node == context->sendqueue) { - debug("SCHEDULING RETRANSMIT!\n"); coap_timer_set(context->retransmit_timer, node->t); } @@ -503,7 +502,6 @@ coap_send_confirmed(coap_context_t *context, coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node) { - debug("RETRANSMIT\n"); if (!context || !node) return COAP_INVALID_TID;