1 /* 2 * util/ub_event.c - directly call libevent (compatability) 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 and implementation for the indirection layer for pluggable 40 * events that transparently passes it either directly to libevent, or calls 41 * the libevent compatibility layer functions. 42 */ 43 #include "config.h" 44 #include <sys/time.h> 45 #include "util/ub_event.h" 46 #include "util/log.h" 47 #include "util/netevent.h" 48 #include "util/tube.h" 49 50 /* We define libevent structures here to hide the libevent stuff. */ 51 52 #ifdef USE_MINI_EVENT 53 # ifdef USE_WINSOCK 54 # include "util/winsock_event.h" 55 # else 56 # include "util/mini_event.h" 57 # endif /* USE_WINSOCK */ 58 #else /* USE_MINI_EVENT */ 59 /* we use libevent */ 60 # ifdef HAVE_EVENT_H 61 # include <event.h> 62 # else 63 # include "event2/event.h" 64 # include "event2/event_struct.h" 65 # include "event2/event_compat.h" 66 # endif 67 #endif /* USE_MINI_EVENT */ 68 69 #if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \ 70 UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \ 71 UB_EV_PERSIST != EV_PERSIST 72 /* Only necessary for libev */ 73 # define NATIVE_BITS(b) ( \ 74 (((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \ 75 | (((b) & UB_EV_READ ) ? EV_READ : 0) \ 76 | (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \ 77 | (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \ 78 | (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0)) 79 80 # define UB_EV_BITS(b) ( \ 81 (((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \ 82 | (((b) & EV_READ ) ? UB_EV_READ : 0) \ 83 | (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \ 84 | (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \ 85 | (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0)) 86 87 # define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \ 88 { (C)(fd, UB_EV_BITS(bits), arg); } 89 90 UB_EV_BITS_CB(comm_point_udp_callback); 91 UB_EV_BITS_CB(comm_point_udp_ancil_callback) 92 UB_EV_BITS_CB(comm_point_tcp_accept_callback) 93 UB_EV_BITS_CB(comm_point_tcp_handle_callback) 94 UB_EV_BITS_CB(comm_timer_callback) 95 UB_EV_BITS_CB(comm_signal_callback) 96 UB_EV_BITS_CB(comm_point_local_handle_callback) 97 UB_EV_BITS_CB(comm_point_raw_handle_callback) 98 UB_EV_BITS_CB(comm_point_http_handle_callback) 99 UB_EV_BITS_CB(tube_handle_signal) 100 UB_EV_BITS_CB(comm_base_handle_slow_accept) 101 102 static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*) 103 { 104 if(cb == comm_point_udp_callback) 105 return my_comm_point_udp_callback; 106 else if(cb == comm_point_udp_ancil_callback) 107 return my_comm_point_udp_ancil_callback; 108 else if(cb == comm_point_tcp_accept_callback) 109 return my_comm_point_tcp_accept_callback; 110 else if(cb == comm_point_tcp_handle_callback) 111 return my_comm_point_tcp_handle_callback; 112 else if(cb == comm_timer_callback) 113 return my_comm_timer_callback; 114 else if(cb == comm_signal_callback) 115 return my_comm_signal_callback; 116 else if(cb == comm_point_local_handle_callback) 117 return my_comm_point_local_handle_callback; 118 else if(cb == comm_point_raw_handle_callback) 119 return my_comm_point_raw_handle_callback; 120 else if(cb == comm_point_http_handle_callback) 121 return my_comm_point_http_handle_callback; 122 else if(cb == tube_handle_signal) 123 return my_tube_handle_signal; 124 else if(cb == comm_base_handle_slow_accept) 125 return my_comm_base_handle_slow_accept; 126 else { 127 log_assert(0); /* this NULL callback pointer should not happen, 128 we should have the necessary routine listed above */ 129 return NULL; 130 } 131 } 132 #else 133 # define NATIVE_BITS(b) (b) 134 # define NATIVE_BITS_CB(c) (c) 135 #endif 136 137 #ifndef EVFLAG_AUTO 138 #define EVFLAG_AUTO 0 139 #endif 140 141 #define AS_EVENT_BASE(x) ((struct event_base*)x) 142 #define AS_UB_EVENT_BASE(x) ((struct ub_event_base*)x) 143 #define AS_EVENT(x) ((struct event*)x) 144 #define AS_UB_EVENT(x) ((struct ub_event*)x) 145 146 const char* ub_event_get_version(void) 147 { 148 return event_get_version(); 149 } 150 151 #if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EV_FEATURE_BACKENDS) 152 static const char* ub_ev_backend2str(int b) 153 { 154 switch(b) { 155 case EVBACKEND_SELECT: return "select"; 156 case EVBACKEND_POLL: return "poll"; 157 case EVBACKEND_EPOLL: return "epoll"; 158 case EVBACKEND_KQUEUE: return "kqueue"; 159 case EVBACKEND_DEVPOLL: return "devpoll"; 160 case EVBACKEND_PORT: return "evport"; 161 } 162 return "unknown"; 163 } 164 #endif 165 166 void 167 ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s, 168 const char** m) 169 { 170 #ifdef USE_WINSOCK 171 (void)base; 172 *n = "event"; 173 *s = "winsock"; 174 *m = "WSAWaitForMultipleEvents"; 175 #elif defined(USE_MINI_EVENT) 176 (void)base; 177 *n = "mini-event"; 178 *s = "internal"; 179 *m = "select"; 180 #else 181 struct event_base* b = AS_EVENT_BASE(base); 182 *s = event_get_version(); 183 # if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) 184 *n = "libev"; 185 if (!b) 186 b = (struct event_base*)ev_default_loop(EVFLAG_AUTO); 187 # ifdef EV_FEATURE_BACKENDS 188 *m = ub_ev_backend2str(ev_backend((struct ev_loop*)b)); 189 # else 190 *m = "not obtainable"; 191 # endif 192 # elif defined(HAVE_EVENT_BASE_GET_METHOD) 193 *n = "libevent"; 194 if (!b) 195 b = event_base_new(); 196 *m = event_base_get_method(b); 197 # else 198 *n = "unknown"; 199 *m = "not obtainable"; 200 (void)b; 201 # endif 202 # ifdef HAVE_EVENT_BASE_FREE 203 if (b && b != AS_EVENT_BASE(base)) 204 event_base_free(b); 205 # endif 206 #endif 207 } 208 209 struct ub_event_base* 210 ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv) 211 { 212 void* base; 213 214 (void)base; 215 #ifdef USE_MINI_EVENT 216 (void)sigs; 217 /* use mini event time-sharing feature */ 218 base = event_init(time_secs, time_tv); 219 #else 220 (void)time_secs; 221 (void)time_tv; 222 # if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) 223 /* libev */ 224 if(sigs) 225 base = ev_default_loop(EVFLAG_AUTO); 226 else 227 base = ev_loop_new(EVFLAG_AUTO); 228 # else 229 (void)sigs; 230 # ifdef HAVE_EVENT_BASE_NEW 231 base = event_base_new(); 232 # else 233 base = event_init(); 234 # endif 235 # endif 236 #endif 237 return (struct ub_event_base*)base; 238 } 239 240 struct ub_event_base * 241 ub_libevent_event_base(struct event_base* libevent_base) 242 { 243 #ifdef USE_MINI_EVENT 244 (void)libevent_base; 245 return NULL; 246 #else 247 return AS_UB_EVENT_BASE(libevent_base); 248 #endif 249 } 250 251 struct event_base * 252 ub_libevent_get_event_base(struct ub_event_base* base) 253 { 254 #ifdef USE_MINI_EVENT 255 (void)base; 256 return NULL; 257 #else 258 return AS_EVENT_BASE(base); 259 #endif 260 } 261 262 void 263 ub_event_base_free(struct ub_event_base* base) 264 { 265 #ifdef USE_MINI_EVENT 266 event_base_free(AS_EVENT_BASE(base)); 267 #elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE) 268 /* only libevent 1.2+ has it, but in 1.2 it is broken - 269 assertion fails on signal handling ev that is not deleted 270 in libevent 1.3c (event_base_once appears) this is fixed. */ 271 event_base_free(AS_EVENT_BASE(base)); 272 #else 273 (void)base; 274 #endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */ 275 } 276 277 int 278 ub_event_base_dispatch(struct ub_event_base* base) 279 { 280 return event_base_dispatch(AS_EVENT_BASE(base)); 281 } 282 283 int 284 ub_event_base_loopexit(struct ub_event_base* base) 285 { 286 return event_base_loopexit(AS_EVENT_BASE(base), NULL); 287 } 288 289 struct ub_event* 290 ub_event_new(struct ub_event_base* base, int fd, short bits, 291 void (*cb)(int, short, void*), void* arg) 292 { 293 struct event *ev = (struct event*)calloc(1, sizeof(struct event)); 294 295 if (!ev) 296 return NULL; 297 298 #ifndef HAVE_EVENT_ASSIGN 299 event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg); 300 if (event_base_set(AS_EVENT_BASE(base), ev) != 0) { 301 free(ev); 302 return NULL; 303 } 304 #else 305 if (event_assign(ev, AS_EVENT_BASE(base), fd, bits, cb, arg) != 0) { 306 free(ev); 307 return NULL; 308 } 309 #endif 310 return AS_UB_EVENT(ev); 311 } 312 313 struct ub_event* 314 ub_signal_new(struct ub_event_base* base, int fd, 315 void (*cb)(int, short, void*), void* arg) 316 { 317 struct event *ev = (struct event*)calloc(1, sizeof(struct event)); 318 319 if (!ev) 320 return NULL; 321 322 #if !HAVE_DECL_EVSIGNAL_ASSIGN 323 signal_set(ev, fd, NATIVE_BITS_CB(cb), arg); 324 if (event_base_set(AS_EVENT_BASE(base), ev) != 0) { 325 free(ev); 326 return NULL; 327 } 328 #else 329 if (evsignal_assign(ev, AS_EVENT_BASE(base), fd, cb, arg) != 0) { 330 free(ev); 331 return NULL; 332 } 333 #endif 334 return AS_UB_EVENT(ev); 335 } 336 337 struct ub_event* 338 ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent, 339 void (*cb)(int, short, void*), void* arg) 340 { 341 #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) 342 struct event *ev = (struct event*)calloc(1, sizeof(struct event)); 343 344 if (!ev) 345 return NULL; 346 347 if (winsock_register_wsaevent(AS_EVENT_BASE(base), ev, wsaevent, cb, 348 arg)) 349 return AS_UB_EVENT(ev); 350 free(ev); 351 return NULL; 352 #else 353 (void)base; 354 (void)wsaevent; 355 (void)cb; 356 (void)arg; 357 return NULL; 358 #endif 359 } 360 361 void 362 ub_event_add_bits(struct ub_event* ev, short bits) 363 { 364 AS_EVENT(ev)->ev_events |= NATIVE_BITS(bits); 365 } 366 367 void 368 ub_event_del_bits(struct ub_event* ev, short bits) 369 { 370 AS_EVENT(ev)->ev_events &= ~NATIVE_BITS(bits); 371 } 372 373 void 374 ub_event_set_fd(struct ub_event* ev, int fd) 375 { 376 AS_EVENT(ev)->ev_fd = fd; 377 } 378 379 void 380 ub_event_free(struct ub_event* ev) 381 { 382 if (ev) 383 free(AS_EVENT(ev)); 384 } 385 386 int 387 ub_event_add(struct ub_event* ev, struct timeval* tv) 388 { 389 return event_add(AS_EVENT(ev), tv); 390 } 391 392 int 393 ub_event_del(struct ub_event* ev) 394 { 395 return event_del(AS_EVENT(ev)); 396 } 397 398 int 399 ub_timer_add(struct ub_event* ev, struct ub_event_base* base, 400 void (*cb)(int, short, void*), void* arg, struct timeval* tv) 401 { 402 event_set(AS_EVENT(ev), -1, EV_TIMEOUT, NATIVE_BITS_CB(cb), arg); 403 if (event_base_set(AS_EVENT_BASE(base), AS_EVENT(ev)) != 0) 404 return -1; 405 return evtimer_add(AS_EVENT(ev), tv); 406 } 407 408 int 409 ub_timer_del(struct ub_event* ev) 410 { 411 return evtimer_del(AS_EVENT(ev)); 412 } 413 414 int 415 ub_signal_add(struct ub_event* ev, struct timeval* tv) 416 { 417 return signal_add(AS_EVENT(ev), tv); 418 } 419 420 int 421 ub_signal_del(struct ub_event* ev) 422 { 423 return signal_del(AS_EVENT(ev)); 424 } 425 426 void 427 ub_winsock_unregister_wsaevent(struct ub_event* ev) 428 { 429 #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) 430 winsock_unregister_wsaevent(AS_EVENT(ev)); 431 free(AS_EVENT(ev)); 432 #else 433 (void)ev; 434 #endif 435 } 436 437 void 438 ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits) 439 { 440 #if defined(USE_MINI_EVENT) && defined(USE_WINSOCK) 441 winsock_tcp_wouldblock(AS_EVENT(ev), NATIVE_BITS(eventbits)); 442 #else 443 (void)ev; 444 (void)eventbits; 445 #endif 446 } 447 448 void ub_comm_base_now(struct comm_base* cb) 449 { 450 #ifdef USE_MINI_EVENT 451 /** minievent updates the time when it blocks. */ 452 (void)cb; /* nothing to do */ 453 #else /* !USE_MINI_EVENT */ 454 /** fillup the time values in the event base */ 455 time_t *tt; 456 struct timeval *tv; 457 comm_base_timept(cb, &tt, &tv); 458 if(gettimeofday(tv, NULL) < 0) { 459 log_err("gettimeofday: %s", strerror(errno)); 460 } 461 #ifndef S_SPLINT_S 462 *tt = tv->tv_sec; 463 #endif 464 #endif /* USE_MINI_EVENT */ 465 } 466 467