ub_event_pluggable.c revision 356345
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) ((struct my_event_base*)x)
148#define AS_MY_EVENT(x) ((struct my_event*)x)
149
150const char* ub_event_get_version(void)
151{
152	return "pluggable-event"PACKAGE_VERSION;
153}
154
155static void
156my_event_add_bits(struct ub_event* ev, short bits)
157{
158	AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
159}
160
161static void
162my_event_del_bits(struct ub_event* ev, short bits)
163{
164	AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
165}
166
167static void
168my_event_set_fd(struct ub_event* ev, int fd)
169{
170	AS_MY_EVENT(ev)->ev.ev_fd = fd;
171}
172
173static void
174my_event_free(struct ub_event* ev)
175{
176	free(AS_MY_EVENT(ev));
177}
178
179static int
180my_event_add(struct ub_event* ev, struct timeval* tv)
181{
182	return event_add(&AS_MY_EVENT(ev)->ev, tv);
183}
184
185static int
186my_event_del(struct ub_event* ev)
187{
188	return event_del(&AS_MY_EVENT(ev)->ev);
189}
190
191static int
192my_timer_add(struct ub_event* ev, struct ub_event_base* base,
193	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
194{
195	event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
196	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
197		!= 0)
198		return -1;
199	return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
200}
201
202static int
203my_timer_del(struct ub_event* ev)
204{
205	return evtimer_del(&AS_MY_EVENT(ev)->ev);
206}
207
208static int
209my_signal_add(struct ub_event* ev, struct timeval* tv)
210{
211	return signal_add(&AS_MY_EVENT(ev)->ev, tv);
212}
213
214static int
215my_signal_del(struct ub_event* ev)
216{
217	return signal_del(&AS_MY_EVENT(ev)->ev);
218}
219
220static void
221my_winsock_unregister_wsaevent(struct ub_event* ev)
222{
223#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
224	winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
225	free(AS_MY_EVENT(ev));
226#else
227	(void)ev;
228#endif
229}
230
231static void
232my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
233{
234#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
235	winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
236#else
237	(void)ev;
238	(void)eventbits;
239#endif
240}
241
242static struct ub_event_vmt default_event_vmt = {
243	my_event_add_bits, my_event_del_bits, my_event_set_fd,
244	my_event_free, my_event_add, my_event_del,
245	my_timer_add, my_timer_del, my_signal_add, my_signal_del,
246	my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
247};
248
249static void
250my_event_base_free(struct ub_event_base* base)
251{
252#ifdef USE_MINI_EVENT
253	event_base_free(AS_MY_EVENT_BASE(base)->base);
254#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
255	/* only libevent 1.2+ has it, but in 1.2 it is broken -
256	   assertion fails on signal handling ev that is not deleted
257 	   in libevent 1.3c (event_base_once appears) this is fixed. */
258	event_base_free(AS_MY_EVENT_BASE(base)->base);
259#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
260	free(AS_MY_EVENT_BASE(base));
261}
262
263static int
264my_event_base_dispatch(struct ub_event_base* base)
265{
266	return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
267}
268
269static int
270my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
271{
272	return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
273}
274
275static struct ub_event*
276my_event_new(struct ub_event_base* base, int fd, short bits,
277	void (*cb)(int, short, void*), void* arg)
278{
279	struct my_event *my_ev = (struct my_event*)calloc(1,
280		sizeof(struct my_event));
281
282	if (!my_ev)
283		return NULL;
284
285	event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
286	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
287		free(my_ev);
288		return NULL;
289	}
290	my_ev->super.magic = UB_EVENT_MAGIC;
291	my_ev->super.vmt = &default_event_vmt;
292	return &my_ev->super;
293}
294
295static struct ub_event*
296my_signal_new(struct ub_event_base* base, int fd,
297	void (*cb)(int, short, void*), void* arg)
298{
299	struct my_event *my_ev = (struct my_event*)calloc(1,
300		sizeof(struct my_event));
301
302	if (!my_ev)
303		return NULL;
304
305	signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
306	if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
307		free(my_ev);
308		return NULL;
309	}
310	my_ev->super.magic = UB_EVENT_MAGIC;
311	my_ev->super.vmt = &default_event_vmt;
312	return &my_ev->super;
313}
314
315static struct ub_event*
316my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
317	void (*cb)(int, short, void*), void* arg)
318{
319#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
320	struct my_event *my_ev = (struct my_event*)calloc(1,
321		sizeof(struct my_event));
322
323	if (!my_ev)
324		return NULL;
325
326	if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
327		&my_ev->ev, wsaevent, cb, arg)) {
328		free(my_ev);
329		return NULL;
330
331	}
332	my_ev->super.magic = UB_EVENT_MAGIC;
333	my_ev->super.vmt = &default_event_vmt;
334	return &my_ev->super;
335#else
336	(void)base;
337	(void)wsaevent;
338	(void)cb;
339	(void)arg;
340	return NULL;
341#endif
342}
343
344static struct ub_event_base_vmt default_event_base_vmt = {
345	my_event_base_free, my_event_base_dispatch,
346	my_event_base_loopexit, my_event_new, my_signal_new,
347	my_winsock_register_wsaevent
348};
349
350struct ub_event_base*
351ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
352{
353	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
354		sizeof(struct my_event_base));
355
356	if (!my_base)
357		return NULL;
358
359#ifdef USE_MINI_EVENT
360	(void)sigs;
361	/* use mini event time-sharing feature */
362	my_base->base = event_init(time_secs, time_tv);
363#else
364	(void)time_secs;
365	(void)time_tv;
366#  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
367	/* libev */
368	if(sigs)
369		my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
370	else
371		my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
372#  else
373	(void)sigs;
374#    ifdef HAVE_EVENT_BASE_NEW
375	my_base->base = event_base_new();
376#    else
377	my_base->base = event_init();
378#    endif
379#  endif
380#endif
381	if (!my_base->base) {
382		free(my_base);
383		return NULL;
384	}
385	my_base->super.magic = UB_EVENT_MAGIC;
386	my_base->super.vmt = &default_event_base_vmt;
387	return &my_base->super;
388}
389
390struct ub_event_base*
391ub_libevent_event_base(struct event_base* base)
392{
393#ifdef USE_MINI_EVENT
394	(void)base;
395	return NULL;
396#else
397	struct my_event_base* my_base = (struct my_event_base*)calloc(1,
398		sizeof(struct my_event_base));
399
400	if (!my_base)
401		return NULL;
402	my_base->super.magic = UB_EVENT_MAGIC;
403	my_base->super.vmt = &default_event_base_vmt;
404	my_base->base = base;
405	return &my_base->super;
406#endif
407}
408
409struct event_base*
410ub_libevent_get_event_base(struct ub_event_base* base)
411{
412#ifndef USE_MINI_EVENT
413	if (base->vmt == &default_event_base_vmt)
414		return AS_MY_EVENT_BASE(base)->base;
415#else
416	(void)base;
417#endif
418	return NULL;
419}
420
421#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
422static const char* ub_ev_backend2str_pluggable(int b)
423{
424	switch(b) {
425	case EVBACKEND_SELECT:	return "select";
426	case EVBACKEND_POLL:	return "poll";
427	case EVBACKEND_EPOLL:	return "epoll";
428	case EVBACKEND_KQUEUE:	return "kqueue";
429	case EVBACKEND_DEVPOLL: return "devpoll";
430	case EVBACKEND_PORT:	return "evport";
431	}
432	return "unknown";
433}
434#endif
435
436void
437ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
438	const char** m)
439{
440#ifdef USE_WINSOCK
441	(void)ub_base;
442	*n = "pluggable-event";
443	*s = "winsock";
444	*m = "WSAWaitForMultipleEvents";
445#elif defined(USE_MINI_EVENT)
446	(void)ub_base;
447	*n = "pluggable-event";
448	*s = "internal";
449	*m = "select";
450#else
451	struct event_base* b = ub_libevent_get_event_base(ub_base);
452	/* This function is only called from comm_base_create, so
453	 * ub_base is guaranteed to exist and to be the default
454	 * event base.
455	 */
456	assert(b != NULL);
457	*n = "pluggable-event";
458	*s = event_get_version();
459#  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
460	*n = "pluggable-libev";
461#    ifdef EVBACKEND_SELECT
462	*m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
463#    else
464	*m = "not obtainable";
465#    endif
466#  elif defined(HAVE_EVENT_BASE_GET_METHOD)
467	*n = "pluggable-libevent";
468	*m = event_base_get_method(b);
469#  else
470	*m = "not obtainable";
471#  endif
472#endif
473}
474
475void
476ub_event_base_free(struct ub_event_base* base)
477{
478	if (base && base->magic == UB_EVENT_MAGIC) {
479		fptr_ok(base->vmt != &default_event_base_vmt ||
480			base->vmt->free == my_event_base_free);
481		(*base->vmt->free)(base);
482	}
483}
484
485int
486ub_event_base_dispatch(struct ub_event_base* base)
487{
488	if (base->magic == UB_EVENT_MAGIC) {
489		fptr_ok(base->vmt != &default_event_base_vmt ||
490			base->vmt->dispatch == my_event_base_dispatch);
491		return (*base->vmt->dispatch)(base);
492	}
493	return -1;
494}
495
496int
497ub_event_base_loopexit(struct ub_event_base* base)
498{
499	if (base->magic == UB_EVENT_MAGIC) {
500		fptr_ok(base->vmt != &default_event_base_vmt ||
501			base->vmt->loopexit == my_event_base_loopexit);
502		return (*base->vmt->loopexit)(base, NULL);
503	}
504	return -1;
505}
506
507struct ub_event*
508ub_event_new(struct ub_event_base* base, int fd, short bits,
509	void (*cb)(int, short, void*), void* arg)
510{
511	if (base->magic == UB_EVENT_MAGIC) {
512		fptr_ok(base->vmt != &default_event_base_vmt ||
513			base->vmt->new_event == my_event_new);
514		return (*base->vmt->new_event)(base, fd, bits, cb, arg);
515	}
516	return NULL;
517}
518
519struct ub_event*
520ub_signal_new(struct ub_event_base* base, int fd,
521	void (*cb)(int, short, void*), void* arg)
522{
523	if (base->magic == UB_EVENT_MAGIC) {
524		fptr_ok(base->vmt != &default_event_base_vmt ||
525			base->vmt->new_signal == my_signal_new);
526		return (*base->vmt->new_signal)(base, fd, cb, arg);
527	}
528	return NULL;
529}
530
531struct ub_event*
532ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
533	void (*cb)(int, short, void*), void* arg)
534{
535	if (base->magic == UB_EVENT_MAGIC) {
536		fptr_ok(base->vmt != &default_event_base_vmt ||
537			base->vmt->winsock_register_wsaevent ==
538			my_winsock_register_wsaevent);
539		return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
540	}
541	return NULL;
542}
543
544void
545ub_event_add_bits(struct ub_event* ev, short bits)
546{
547	if (ev->magic == UB_EVENT_MAGIC) {
548		fptr_ok(ev->vmt != &default_event_vmt ||
549			ev->vmt->add_bits == my_event_add_bits);
550		(*ev->vmt->add_bits)(ev, bits);
551	}
552}
553
554void
555ub_event_del_bits(struct ub_event* ev, short bits)
556{
557	if (ev->magic == UB_EVENT_MAGIC) {
558		fptr_ok(ev->vmt != &default_event_vmt ||
559			ev->vmt->del_bits == my_event_del_bits);
560		(*ev->vmt->del_bits)(ev, bits);
561	}
562}
563
564void
565ub_event_set_fd(struct ub_event* ev, int fd)
566{
567	if (ev->magic == UB_EVENT_MAGIC) {
568		fptr_ok(ev->vmt != &default_event_vmt ||
569			ev->vmt->set_fd == my_event_set_fd);
570		(*ev->vmt->set_fd)(ev, fd);
571	}
572}
573
574void
575ub_event_free(struct ub_event* ev)
576{
577	if (ev && ev->magic == UB_EVENT_MAGIC) {
578		fptr_ok(ev->vmt != &default_event_vmt ||
579			ev->vmt->free == my_event_free);
580		(*ev->vmt->free)(ev);
581	}
582}
583
584int
585ub_event_add(struct ub_event* ev, struct timeval* tv)
586{
587	if (ev->magic == UB_EVENT_MAGIC) {
588		fptr_ok(ev->vmt != &default_event_vmt ||
589			ev->vmt->add == my_event_add);
590		return (*ev->vmt->add)(ev, tv);
591	}
592       return -1;
593}
594
595int
596ub_event_del(struct ub_event* ev)
597{
598	if (ev && ev->magic == UB_EVENT_MAGIC) {
599		fptr_ok(ev->vmt != &default_event_vmt ||
600			ev->vmt->del == my_event_del);
601		return (*ev->vmt->del)(ev);
602	}
603	return -1;
604}
605
606int
607ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
608	void (*cb)(int, short, void*), void* arg, struct timeval* tv)
609{
610	if (ev->magic == UB_EVENT_MAGIC) {
611		fptr_ok(ev->vmt != &default_event_vmt ||
612			ev->vmt->add_timer == my_timer_add);
613		return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
614	}
615	return -1;
616}
617
618int
619ub_timer_del(struct ub_event* ev)
620{
621	if (ev && ev->magic == UB_EVENT_MAGIC) {
622		fptr_ok(ev->vmt != &default_event_vmt ||
623			ev->vmt->del_timer == my_timer_del);
624		return (*ev->vmt->del_timer)(ev);
625	}
626	return -1;
627}
628
629int
630ub_signal_add(struct ub_event* ev, struct timeval* tv)
631{
632	if (ev->magic == UB_EVENT_MAGIC) {
633		fptr_ok(ev->vmt != &default_event_vmt ||
634			ev->vmt->add_signal == my_signal_add);
635		return (*ev->vmt->add_signal)(ev, tv);
636	}
637	return -1;
638}
639
640int
641ub_signal_del(struct ub_event* ev)
642{
643	if (ev && ev->magic == UB_EVENT_MAGIC) {
644		fptr_ok(ev->vmt != &default_event_vmt ||
645			ev->vmt->del_signal == my_signal_del);
646		return (*ev->vmt->del_signal)(ev);
647	}
648	return -1;
649}
650
651void
652ub_winsock_unregister_wsaevent(struct ub_event* ev)
653{
654	if (ev && ev->magic == UB_EVENT_MAGIC) {
655		fptr_ok(ev->vmt != &default_event_vmt ||
656			ev->vmt->winsock_unregister_wsaevent ==
657			my_winsock_unregister_wsaevent);
658		(*ev->vmt->winsock_unregister_wsaevent)(ev);
659	}
660}
661
662void
663ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
664{
665	if (ev->magic == UB_EVENT_MAGIC) {
666		fptr_ok(ev->vmt != &default_event_vmt ||
667			ev->vmt->winsock_tcp_wouldblock ==
668			my_winsock_tcp_wouldblock);
669		(*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
670	}
671}
672
673void ub_comm_base_now(struct comm_base* cb)
674{
675	time_t *tt;
676	struct timeval *tv;
677
678#ifdef USE_MINI_EVENT
679/** minievent updates the time when it blocks. */
680	if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
681	    comm_base_internal(cb)->vmt == &default_event_base_vmt)
682		return; /* Actually using mini event, so do not set time */
683#endif /* USE_MINI_EVENT */
684
685/** fillup the time values in the event base */
686	comm_base_timept(cb, &tt, &tv);
687	if(gettimeofday(tv, NULL) < 0) {
688		log_err("gettimeofday: %s", strerror(errno));
689	}
690#ifndef S_SPLINT_S
691	*tt = tv->tv_sec;
692#endif
693}
694
695