ub_event_pluggable.c revision 1.1.1.1
1/*
2 * util/ub_event_pluggable.c - call registered pluggable event functions
3 *
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/**
37 * \file
38 *
39 * This file contains an implementation for the indirection layer for pluggable
40 * events that calls the registered pluggable event loop.  It also defines a
41 * default pluggable event loop based on the default libevent (compatibility)
42 * functions.
43 */
44#include "config.h"
45#include <sys/time.h>
46#include "util/ub_event.h"
47#include "libunbound/unbound-event.h"
48#include "util/netevent.h"
49#include "util/log.h"
50#include "util/fptr_wlist.h"
51
52/* We define libevent structures here to hide the libevent stuff. */
53
54#ifdef USE_MINI_EVENT
55#  ifdef USE_WINSOCK
56#    include "util/winsock_event.h"
57#  else
58#    include "util/mini_event.h"
59#  endif /* USE_WINSOCK */
60#else /* USE_MINI_EVENT */
61   /* we use libevent */
62#  ifdef HAVE_EVENT_H
63#    include <event.h>
64#  else
65#    include "event2/event.h"
66#    include "event2/event_struct.h"
67#    include "event2/event_compat.h"
68#  endif
69#endif /* USE_MINI_EVENT */
70
71#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
72    UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
73    UB_EV_PERSIST != EV_PERSIST
74/* Only necessary for libev */
75#  define NATIVE_BITS(b) ( \
76	  (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
77	| (((b) & UB_EV_READ   ) ? EV_READ    : 0) \
78	| (((b) & UB_EV_WRITE  ) ? EV_WRITE   : 0) \
79	| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL  : 0) \
80	| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
81
82#  define UB_EV_BITS(b) ( \
83	  (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
84	| (((b) & EV_READ   ) ? UB_EV_READ    : 0) \
85	| (((b) & EV_WRITE  ) ? UB_EV_WRITE   : 0) \
86	| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL  : 0) \
87	| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
88
89#  define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
90	{ (C)(fd, UB_EV_BITS(bits), arg); }
91
92UB_EV_BITS_CB(comm_point_udp_callback);
93UB_EV_BITS_CB(comm_point_udp_ancil_callback)
94UB_EV_BITS_CB(comm_point_tcp_accept_callback)
95UB_EV_BITS_CB(comm_point_tcp_handle_callback)
96UB_EV_BITS_CB(comm_timer_callback)
97UB_EV_BITS_CB(comm_signal_callback)
98UB_EV_BITS_CB(comm_point_local_handle_callback)
99UB_EV_BITS_CB(comm_point_raw_handle_callback)
100UB_EV_BITS_CB(tube_handle_signal)
101UB_EV_BITS_CB(comm_base_handle_slow_accept)
102
103static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
104{
105	if(cb == comm_point_udp_callback)
106		return my_comm_point_udp_callback;
107	else if(cb == comm_point_udp_ancil_callback)
108		return my_comm_point_udp_ancil_callback;
109	else if(cb == comm_point_tcp_accept_callback)
110		return my_comm_point_tcp_accept_callback;
111	else if(cb == comm_point_tcp_handle_callback)
112		return my_comm_point_tcp_handle_callback;
113	else if(cb == comm_timer_callback)
114		return my_comm_timer_callback;
115	else if(cb == comm_signal_callback)
116		return my_comm_signal_callback;
117	else if(cb == comm_point_local_handle_callback)
118		return my_comm_point_local_handle_callback;
119	else if(cb == comm_point_raw_handle_callback)
120		return my_comm_point_raw_handle_callback;
121	else if(cb == tube_handle_signal)
122		return my_tube_handle_signal;
123	else if(cb == comm_base_handle_slow_accept)
124		return my_comm_base_handle_slow_accept;
125	else
126		return NULL;
127}
128#else
129#  define NATIVE_BITS(b) (b)
130#  define NATIVE_BITS_CB(c) (c)
131#endif
132
133#ifndef EVFLAG_AUTO
134#define EVFLAG_AUTO 0
135#endif
136
137struct my_event_base {
138	struct ub_event_base super;
139	struct event_base* base;
140};
141
142struct my_event {
143	struct ub_event super;
144	struct event ev;
145};
146
147#define AS_MY_EVENT_BASE(x) \
148	(((union {struct ub_event_base* a; struct my_event_base* b;})x).b)
149#define AS_MY_EVENT(x) \
150	(((union {struct ub_event* a; struct my_event* b;})x).b)
151
152const char* ub_event_get_version()
153{
154	return "pluggable-event"PACKAGE_VERSION;
155}
156
157static void
158my_event_add_bits(struct ub_event* ev, short bits)
159{
160	AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
161}
162
163static void
164my_event_del_bits(struct ub_event* ev, short bits)
165{
166	AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
167}
168
169static void
170my_event_set_fd(struct ub_event* ev, int fd)
171{
172	AS_MY_EVENT(ev)->ev.ev_fd = fd;
173}
174
175static void
176my_event_free(struct ub_event* ev)
177{
178	free(AS_MY_EVENT(ev));
179}
180
181static int
182my_event_add(struct ub_event* ev, struct timeval* tv)
183{
184	return event_add(&AS_MY_EVENT(ev)->ev, tv);
185}
186
187static int
188my_event_del(struct ub_event* ev)
189{
190	return event_del(&AS_MY_EVENT(ev)->ev);
191}
192
193static int
194my_timer_add(struct ub_event* ev, struct ub_event_base* base,
195	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
196{
197	event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
198	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
199		!= 0)
200		return -1;
201	return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
202}
203
204static int
205my_timer_del(struct ub_event* ev)
206{
207	return evtimer_del(&AS_MY_EVENT(ev)->ev);
208}
209
210static int
211my_signal_add(struct ub_event* ev, struct timeval* tv)
212{
213	return signal_add(&AS_MY_EVENT(ev)->ev, tv);
214}
215
216static int
217my_signal_del(struct ub_event* ev)
218{
219	return signal_del(&AS_MY_EVENT(ev)->ev);
220}
221
222static void
223my_winsock_unregister_wsaevent(struct ub_event* ev)
224{
225#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
226	winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
227	free(AS_MY_EVENT(ev));
228#else
229	(void)ev;
230#endif
231}
232
233static void
234my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
235{
236#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
237	winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
238#else
239	(void)ev;
240	(void)eventbits;
241#endif
242}
243
244static struct ub_event_vmt default_event_vmt = {
245	my_event_add_bits, my_event_del_bits, my_event_set_fd,
246	my_event_free, my_event_add, my_event_del,
247	my_timer_add, my_timer_del, my_signal_add, my_signal_del,
248	my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
249};
250
251static void
252my_event_base_free(struct ub_event_base* base)
253{
254#ifdef USE_MINI_EVENT
255	event_base_free(AS_MY_EVENT_BASE(base)->base);
256#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
257	/* only libevent 1.2+ has it, but in 1.2 it is broken -
258	   assertion fails on signal handling ev that is not deleted
259 	   in libevent 1.3c (event_base_once appears) this is fixed. */
260	event_base_free(AS_MY_EVENT_BASE(base)->base);
261#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
262	free(AS_MY_EVENT_BASE(base));
263}
264
265static int
266my_event_base_dispatch(struct ub_event_base* base)
267{
268	return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
269}
270
271static int
272my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
273{
274	return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
275}
276
277static struct ub_event*
278my_event_new(struct ub_event_base* base, int fd, short bits,
279	void (*cb)(int, short, void*), void* arg)
280{
281	struct my_event *my_ev = (struct my_event*)calloc(1,
282		sizeof(struct my_event));
283
284	if (!my_ev)
285		return NULL;
286
287	event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
288	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
289		free(my_ev);
290		return NULL;
291	}
292	my_ev->super.magic = UB_EVENT_MAGIC;
293	my_ev->super.vmt = &default_event_vmt;
294	return &my_ev->super;
295}
296
297static struct ub_event*
298my_signal_new(struct ub_event_base* base, int fd,
299	void (*cb)(int, short, void*), void* arg)
300{
301	struct my_event *my_ev = (struct my_event*)calloc(1,
302		sizeof(struct my_event));
303
304	if (!my_ev)
305		return NULL;
306
307	signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
308	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
309		free(my_ev);
310		return NULL;
311	}
312	my_ev->super.magic = UB_EVENT_MAGIC;
313	my_ev->super.vmt = &default_event_vmt;
314	return &my_ev->super;
315}
316
317static struct ub_event*
318my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
319	void (*cb)(int, short, void*), void* arg)
320{
321#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
322	struct my_event *my_ev = (struct my_event*)calloc(1,
323		sizeof(struct my_event));
324
325	if (!my_ev)
326		return NULL;
327
328	if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
329		&my_ev->ev, wsaevent, cb, arg)) {
330		free(my_ev);
331		return NULL;
332
333	}
334	my_ev->super.magic = UB_EVENT_MAGIC;
335	my_ev->super.vmt = &default_event_vmt;
336	return &my_ev->super;
337#else
338	(void)base;
339	(void)wsaevent;
340	(void)cb;
341	(void)arg;
342	return NULL;
343#endif
344}
345
346static struct ub_event_base_vmt default_event_base_vmt = {
347	my_event_base_free, my_event_base_dispatch,
348	my_event_base_loopexit, my_event_new, my_signal_new,
349	my_winsock_register_wsaevent
350};
351
352struct ub_event_base*
353ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
354{
355	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
356		sizeof(struct my_event_base));
357
358	if (!my_base)
359		return NULL;
360
361#ifdef USE_MINI_EVENT
362	(void)sigs;
363	/* use mini event time-sharing feature */
364	my_base->base = event_init(time_secs, time_tv);
365#else
366	(void)time_secs;
367	(void)time_tv;
368#  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
369	/* libev */
370	if(sigs)
371		my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
372	else
373		my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
374#  else
375	(void)sigs;
376#    ifdef HAVE_EVENT_BASE_NEW
377	my_base->base = event_base_new();
378#    else
379	my_base->base = event_init();
380#    endif
381#  endif
382#endif
383	if (!my_base->base) {
384		free(my_base);
385		return NULL;
386	}
387	my_base->super.magic = UB_EVENT_MAGIC;
388	my_base->super.vmt = &default_event_base_vmt;
389	return &my_base->super;
390}
391
392struct ub_event_base*
393ub_libevent_event_base(struct event_base* base)
394{
395#ifdef USE_MINI_EVENT
396	(void)base;
397	return NULL;
398#else
399	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
400		sizeof(struct my_event_base));
401
402	if (!my_base)
403		return NULL;
404	my_base->super.magic = UB_EVENT_MAGIC;
405	my_base->super.vmt = &default_event_base_vmt;
406	my_base->base = base;
407	return &my_base->super;
408#endif
409}
410
411struct event_base*
412ub_libevent_get_event_base(struct ub_event_base* base)
413{
414#ifndef USE_MINI_EVENT
415	if (base->vmt == &default_event_base_vmt)
416		return AS_MY_EVENT_BASE(base)->base;
417#else
418	(void)base;
419#endif
420	return NULL;
421}
422
423#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
424static const char* ub_ev_backend2str_pluggable(int b)
425{
426	switch(b) {
427	case EVBACKEND_SELECT:	return "select";
428	case EVBACKEND_POLL:	return "poll";
429	case EVBACKEND_EPOLL:	return "epoll";
430	case EVBACKEND_KQUEUE:	return "kqueue";
431	case EVBACKEND_DEVPOLL: return "devpoll";
432	case EVBACKEND_PORT:	return "evport";
433	}
434	return "unknown";
435}
436#endif
437
438void
439ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
440	const char** m)
441{
442#ifdef USE_WINSOCK
443	(void)ub_base;
444	*n = "pluggable-event";
445	*s = "winsock";
446	*m = "WSAWaitForMultipleEvents";
447#elif defined(USE_MINI_EVENT)
448	(void)ub_base;
449	*n = "pluggable-event";
450	*s = "internal";
451	*m = "select";
452#else
453	struct event_base* b = ub_libevent_get_event_base(ub_base);
454	/* This function is only called from comm_base_create, so
455	 * ub_base is guaranteed to exist and to be the default
456	 * event base.
457	 */
458	assert(b);
459	*n = "pluggable-event";
460	*s = event_get_version();
461#  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
462	*n = "pluggable-libev";
463#    ifdef EVBACKEND_SELECT
464	*m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
465#    else
466	*m = "not obtainable";
467#    endif
468#  elif defined(HAVE_EVENT_BASE_GET_METHOD)
469	*n = "pluggable-libevent";
470	*m = event_base_get_method(b);
471#  else
472	*m = "not obtainable";
473#  endif
474#endif
475}
476
477void
478ub_event_base_free(struct ub_event_base* base)
479{
480	if (base && base->magic == UB_EVENT_MAGIC) {
481		fptr_ok(base->vmt != &default_event_base_vmt ||
482			base->vmt->free == my_event_base_free);
483		(*base->vmt->free)(base);
484	}
485}
486
487int
488ub_event_base_dispatch(struct ub_event_base* base)
489{
490	if (base->magic == UB_EVENT_MAGIC) {
491		fptr_ok(base->vmt != &default_event_base_vmt ||
492			base->vmt->dispatch == my_event_base_dispatch);
493		return (*base->vmt->dispatch)(base);
494	}
495	return -1;
496}
497
498int
499ub_event_base_loopexit(struct ub_event_base* base)
500{
501	if (base->magic == UB_EVENT_MAGIC) {
502		fptr_ok(base->vmt != &default_event_base_vmt ||
503			base->vmt->loopexit == my_event_base_loopexit);
504		return (*base->vmt->loopexit)(base, NULL);
505	}
506	return -1;
507}
508
509struct ub_event*
510ub_event_new(struct ub_event_base* base, int fd, short bits,
511	void (*cb)(int, short, void*), void* arg)
512{
513	if (base->magic == UB_EVENT_MAGIC) {
514		fptr_ok(base->vmt != &default_event_base_vmt ||
515			base->vmt->new_event == my_event_new);
516		return (*base->vmt->new_event)(base, fd, bits, cb, arg);
517	}
518	return NULL;
519}
520
521struct ub_event*
522ub_signal_new(struct ub_event_base* base, int fd,
523	void (*cb)(int, short, void*), void* arg)
524{
525	if (base->magic == UB_EVENT_MAGIC) {
526		fptr_ok(base->vmt != &default_event_base_vmt ||
527			base->vmt->new_signal == my_signal_new);
528		return (*base->vmt->new_signal)(base, fd, cb, arg);
529	}
530	return NULL;
531}
532
533struct ub_event*
534ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
535	void (*cb)(int, short, void*), void* arg)
536{
537	if (base->magic == UB_EVENT_MAGIC) {
538		fptr_ok(base->vmt != &default_event_base_vmt ||
539			base->vmt->winsock_register_wsaevent ==
540			my_winsock_register_wsaevent);
541		return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
542	}
543	return NULL;
544}
545
546void
547ub_event_add_bits(struct ub_event* ev, short bits)
548{
549	if (ev->magic == UB_EVENT_MAGIC) {
550		fptr_ok(ev->vmt != &default_event_vmt ||
551			ev->vmt->add_bits == my_event_add_bits);
552		(*ev->vmt->add_bits)(ev, bits);
553	}
554}
555
556void
557ub_event_del_bits(struct ub_event* ev, short bits)
558{
559	if (ev->magic == UB_EVENT_MAGIC) {
560		fptr_ok(ev->vmt != &default_event_vmt ||
561			ev->vmt->del_bits == my_event_del_bits);
562		(*ev->vmt->del_bits)(ev, bits);
563	}
564}
565
566void
567ub_event_set_fd(struct ub_event* ev, int fd)
568{
569	if (ev->magic == UB_EVENT_MAGIC) {
570		fptr_ok(ev->vmt != &default_event_vmt ||
571			ev->vmt->set_fd == my_event_set_fd);
572		(*ev->vmt->set_fd)(ev, fd);
573	}
574}
575
576void
577ub_event_free(struct ub_event* ev)
578{
579	if (ev && ev->magic == UB_EVENT_MAGIC) {
580		fptr_ok(ev->vmt != &default_event_vmt ||
581			ev->vmt->free == my_event_free);
582		(*ev->vmt->free)(ev);
583	}
584}
585
586int
587ub_event_add(struct ub_event* ev, struct timeval* tv)
588{
589	if (ev->magic == UB_EVENT_MAGIC) {
590		fptr_ok(ev->vmt != &default_event_vmt ||
591			ev->vmt->add == my_event_add);
592		return (*ev->vmt->add)(ev, tv);
593	}
594       return -1;
595}
596
597int
598ub_event_del(struct ub_event* ev)
599{
600	if (ev->magic == UB_EVENT_MAGIC) {
601		fptr_ok(ev->vmt != &default_event_vmt ||
602			ev->vmt->del == my_event_del);
603		return (*ev->vmt->del)(ev);
604	}
605	return -1;
606}
607
608int
609ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
610	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
611{
612	if (ev->magic == UB_EVENT_MAGIC) {
613		fptr_ok(ev->vmt != &default_event_vmt ||
614			ev->vmt->add_timer == my_timer_add);
615		return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
616	}
617	return -1;
618}
619
620int
621ub_timer_del(struct ub_event* ev)
622{
623	if (ev->magic == UB_EVENT_MAGIC) {
624		fptr_ok(ev->vmt != &default_event_vmt ||
625			ev->vmt->del_timer == my_timer_del);
626		return (*ev->vmt->del_timer)(ev);
627	}
628	return -1;
629}
630
631int
632ub_signal_add(struct ub_event* ev, struct timeval* tv)
633{
634	if (ev->magic == UB_EVENT_MAGIC) {
635		fptr_ok(ev->vmt != &default_event_vmt ||
636			ev->vmt->add_signal == my_signal_add);
637		return (*ev->vmt->add_signal)(ev, tv);
638	}
639	return -1;
640}
641
642int
643ub_signal_del(struct ub_event* ev)
644{
645	if (ev->magic == UB_EVENT_MAGIC) {
646		fptr_ok(ev->vmt != &default_event_vmt ||
647			ev->vmt->del_signal == my_signal_del);
648		return (*ev->vmt->del_signal)(ev);
649	}
650	return -1;
651}
652
653void
654ub_winsock_unregister_wsaevent(struct ub_event* ev)
655{
656	if (ev->magic == UB_EVENT_MAGIC) {
657		fptr_ok(ev->vmt != &default_event_vmt ||
658			ev->vmt->winsock_unregister_wsaevent ==
659			my_winsock_unregister_wsaevent);
660		(*ev->vmt->winsock_unregister_wsaevent)(ev);
661	}
662}
663
664void
665ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
666{
667	if (ev->magic == UB_EVENT_MAGIC) {
668		fptr_ok(ev->vmt != &default_event_vmt ||
669			ev->vmt->winsock_tcp_wouldblock ==
670			my_winsock_tcp_wouldblock);
671		(*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
672	}
673}
674
675void ub_comm_base_now(struct comm_base* cb)
676{
677	time_t *tt;
678	struct timeval *tv;
679
680#ifdef USE_MINI_EVENT
681/** minievent updates the time when it blocks. */
682	if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
683	    comm_base_internal(cb)->vmt == &default_event_base_vmt)
684		return; /* Actually using mini event, so do not set time */
685#endif /* USE_MINI_EVENT */
686
687/** fillup the time values in the event base */
688	comm_base_timept(cb, &tt, &tv);
689	if(gettimeofday(tv, NULL) < 0) {
690		log_err("gettimeofday: %s", strerror(errno));
691	}
692	*tt = tv->tv_sec;
693}
694
695