Clean up Section 1 of rend-spec.txt.
[tor/rransom.git] / src / common / compat_libevent.c
blob250fa2bdb7e3aeff728a43ad2bd7d59393de891f
1 /* Copyright (c) 2009-2010, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file compat_libevent.c
6 * \brief Wrappers to handle porting between different versions of libevent.
8 * In an ideal world, we'd just use Libevent 2.0 from now on. But as of June
9 * 2009, Libevent 2.0 is still in alpha, and we will have old versions of
10 * Libevent for the forseeable future.
11 **/
13 #include "orconfig.h"
14 #include "compat.h"
15 #include "compat_libevent.h"
17 #include "util.h"
18 #include "torlog.h"
20 #ifdef HAVE_EVENT2_EVENT_H
21 #include <event2/event.h>
22 #else
23 #include <event.h>
24 #endif
26 /** A number representing a version of Libevent.
28 This is a 4-byte number, with the first three bytes representing the
29 major, minor, and patchlevel respectively of the library. The fourth
30 byte is unused.
32 This is equivalent to the format of LIBEVENT_VERSION_NUMBER on Libevent
33 2.0.1 or later. For versions of Libevent before 1.4.0, which followed the
34 format of "1.0, 1.0a, 1.0b", we define 1.0 to be equivalent to 1.0.0, 1.0a
35 to be equivalent to 1.0.1, and so on.
37 typedef uint32_t le_version_t;
39 /* Macros: returns the number of a libevent version. */
40 #define V(major, minor, patch) \
41 (((major) << 24) | ((minor) << 16) | ((patch) << 8))
42 #define V_OLD(major, minor, patch) \
43 V((major), (minor), (patch)-'a'+1)
45 #define LE_OLD V(0,0,0)
46 #define LE_OTHER V(0,0,99)
48 static le_version_t tor_get_libevent_version(const char **v_out);
50 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
51 /** A string which, if it appears in a libevent log, should be ignored. */
52 static const char *suppress_msg = NULL;
53 /** Callback function passed to event_set_log() so we can intercept
54 * log messages from libevent. */
55 static void
56 libevent_logging_callback(int severity, const char *msg)
58 char buf[1024];
59 size_t n;
60 if (suppress_msg && strstr(msg, suppress_msg))
61 return;
62 n = strlcpy(buf, msg, sizeof(buf));
63 if (n && n < sizeof(buf) && buf[n-1] == '\n') {
64 buf[n-1] = '\0';
66 switch (severity) {
67 case _EVENT_LOG_DEBUG:
68 log(LOG_DEBUG, LD_NET, "Message from libevent: %s", buf);
69 break;
70 case _EVENT_LOG_MSG:
71 log(LOG_INFO, LD_NET, "Message from libevent: %s", buf);
72 break;
73 case _EVENT_LOG_WARN:
74 log(LOG_WARN, LD_GENERAL, "Warning from libevent: %s", buf);
75 break;
76 case _EVENT_LOG_ERR:
77 log(LOG_ERR, LD_GENERAL, "Error from libevent: %s", buf);
78 break;
79 default:
80 log(LOG_WARN, LD_GENERAL, "Message [%d] from libevent: %s",
81 severity, buf);
82 break;
85 /** Set hook to intercept log messages from libevent. */
86 void
87 configure_libevent_logging(void)
89 event_set_log_callback(libevent_logging_callback);
91 /** Ignore any libevent log message that contains <b>msg</b>. */
92 void
93 suppress_libevent_log_msg(const char *msg)
95 suppress_msg = msg;
97 #else
98 void
99 configure_libevent_logging(void)
102 void
103 suppress_libevent_log_msg(const char *msg)
105 (void)msg;
107 #endif
109 #ifndef HAVE_EVENT2_EVENT_H
110 /** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
111 struct event *
112 tor_event_new(struct event_base *base, int sock, short what,
113 void (*cb)(int, short, void *), void *arg)
115 struct event *e = tor_malloc_zero(sizeof(struct event));
116 event_set(e, sock, what, cb, arg);
117 if (! base)
118 base = tor_libevent_get_base();
119 event_base_set(base, e);
120 return e;
122 /** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */
123 struct event *
124 tor_evtimer_new(struct event_base *base,
125 void (*cb)(int, short, void *), void *arg)
127 return tor_event_new(base, -1, 0, cb, arg);
129 /** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */
130 struct event *
131 tor_evsignal_new(struct event_base * base, int sig,
132 void (*cb)(int, short, void *), void *arg)
134 return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg);
136 /** Work-alike replacement for event_free() on pre-Libevent-2.0 systems. */
137 void
138 tor_event_free(struct event *ev)
140 event_del(ev);
141 tor_free(ev);
143 #endif
145 /** Global event base for use by the main thread. */
146 struct event_base *the_event_base = NULL;
148 /* This is what passes for version detection on OSX. We set
149 * MACOSX_KQUEUE_IS_BROKEN to true iff we're on a version of OSX before
150 * 10.4.0 (aka 1040). */
151 #ifdef __APPLE__
152 #ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
153 #define MACOSX_KQUEUE_IS_BROKEN \
154 (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1040)
155 #else
156 #define MACOSX_KQUEUE_IS_BROKEN 0
157 #endif
158 #endif
160 /** Initialize the Libevent library and set up the event base. */
161 void
162 tor_libevent_initialize(void)
164 tor_assert(the_event_base == NULL);
166 #ifdef __APPLE__
167 if (MACOSX_KQUEUE_IS_BROKEN ||
168 tor_get_libevent_version(NULL) < V_OLD(1,1,'b')) {
169 setenv("EVENT_NOKQUEUE","1",1);
171 #endif
173 #ifdef HAVE_EVENT2_EVENT_H
174 the_event_base = event_base_new();
175 #else
176 the_event_base = event_init();
177 #endif
179 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
180 /* Making this a NOTICE for now so we can link bugs to a libevent versions
181 * or methods better. */
182 log(LOG_NOTICE, LD_GENERAL,
183 "Initialized libevent version %s using method %s. Good.",
184 event_get_version(), tor_libevent_get_method());
185 #else
186 log(LOG_NOTICE, LD_GENERAL,
187 "Initialized old libevent (version 1.0b or earlier).");
188 log(LOG_WARN, LD_GENERAL,
189 "You have a *VERY* old version of libevent. It is likely to be buggy; "
190 "please build Tor with a more recent version.");
191 #endif
194 /** Return the current Libevent event base that we're set up to use. */
195 struct event_base *
196 tor_libevent_get_base(void)
198 return the_event_base;
201 #ifndef HAVE_EVENT_BASE_LOOPEXIT
202 /* Replacement for event_base_loopexit on some very old versions of Libevent
203 that we are not yet brave enough to deprecate. */
205 tor_event_base_loopexit(struct event_base *base, struct timeval *tv)
207 tor_assert(base == the_event_base);
208 return event_loopexit(tv);
210 #endif
212 /** Return the name of the Libevent backend we're using. */
213 const char *
214 tor_libevent_get_method(void)
216 #ifdef HAVE_EVENT2_EVENT_H
217 return event_base_get_method(the_event_base);
218 #elif defined(HAVE_EVENT_GET_METHOD)
219 return event_get_method();
220 #else
221 return "<unknown>";
222 #endif
225 /** Return the le_version_t for the current version of libevent. If the
226 * version is very new, return LE_OTHER. If the version is so old that it
227 * doesn't support event_get_version(), return LE_OLD. DOCDOC */
228 static le_version_t
229 tor_decode_libevent_version(const char *v)
231 unsigned major, minor, patchlevel;
232 char c, e, extra;
233 int fields;
235 /* Try the new preferred "1.4.11-stable" format.
236 * Also accept "1.4.14b-stable". */
237 fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
238 if (fields == 3 ||
239 ((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
240 (fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
241 return V(major,minor,patchlevel);
244 /* Try the old "1.3e" format. */
245 fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
246 if (fields == 3 && TOR_ISALPHA(c)) {
247 return V_OLD(major, minor, c);
248 } else if (fields == 2) {
249 return V(major, minor, 0);
252 return LE_OTHER;
255 /** Return an integer representing the binary interface of a Libevent library.
256 * Two different versions with different numbers are sure not to be binary
257 * compatible. Two different versions with the same numbers have a decent
258 * chance of binary compatibility.*/
259 static int
260 le_versions_compatibility(le_version_t v)
262 if (v == LE_OTHER)
263 return 0;
264 if (v < V_OLD(1,0,'c'))
265 return 1;
266 else if (v < V(1,4,0))
267 return 2;
268 else if (v < V(1,4,99))
269 return 3;
270 else if (v < V(2,0,1))
271 return 4;
272 else /* Everything 2.0 and later should be compatible. */
273 return 5;
276 /** Return the version number of the currently running version of Libevent.
277 See le_version_t for info on the format.
279 static le_version_t
280 tor_get_libevent_version(const char **v_out)
282 const char *v;
283 le_version_t r;
284 #if defined(HAVE_EVENT_GET_VERSION_NUMBER)
285 v = event_get_version();
286 r = event_get_version_number();
287 #elif defined (HAVE_EVENT_GET_VERSION)
288 v = event_get_version();
289 r = tor_decode_libevent_version(v);
290 #else
291 v = "pre-1.0c";
292 r = LE_OLD;
293 #endif
294 if (v_out)
295 *v_out = v;
296 return r;
299 /** Return a string representation of the version of the currently running
300 * version of Libevent. */
301 const char *
302 tor_libevent_get_version_str(void)
304 #ifdef HAVE_EVENT_GET_VERSION
305 return event_get_version();
306 #else
307 return "pre-1.0c";
308 #endif
312 * Compare the current Libevent method and version to a list of versions
313 * which are known not to work. Warn the user as appropriate.
315 void
316 tor_check_libevent_version(const char *m, int server,
317 const char **badness_out)
319 int buggy = 0, iffy = 0, slow = 0, thread_unsafe = 0;
320 le_version_t version;
321 const char *v = NULL;
322 const char *badness = NULL;
323 const char *sad_os = "";
325 version = tor_get_libevent_version(&v);
327 /* XXX Would it be worthwhile disabling the methods that we know
328 * are buggy, rather than just warning about them and then proceeding
329 * to use them? If so, we should probably not wrap this whole thing
330 * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
331 /* XXXX The problem is that it's not trivial to get libevent to change it's
332 * method once it's initialized, and it's not trivial to tell what method it
333 * will use without initializing it. I guess we could preemptively disable
334 * buggy libevent modes based on the version _before_ initializing it,
335 * though, but then there's no good way (afaict) to warn "I would have used
336 * kqueue, but instead I'm using select." -NM */
337 /* XXXX022 revist the above; it is fixable now. */
338 if (!strcmp(m, "kqueue")) {
339 if (version < V_OLD(1,1,'b'))
340 buggy = 1;
341 } else if (!strcmp(m, "epoll")) {
342 if (version < V(1,1,0))
343 iffy = 1;
344 } else if (!strcmp(m, "poll")) {
345 if (version < V_OLD(1,0,'e'))
346 buggy = 1;
347 if (version < V(1,1,0))
348 slow = 1;
349 } else if (!strcmp(m, "select")) {
350 if (version < V(1,1,0))
351 slow = 1;
352 } else if (!strcmp(m, "win32")) {
353 if (version < V_OLD(1,1,'b'))
354 buggy = 1;
357 /* Libevent versions before 1.3b do very badly on operating systems with
358 * user-space threading implementations. */
359 #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
360 if (server && version < V_OLD(1,3,'b')) {
361 thread_unsafe = 1;
362 sad_os = "BSD variants";
364 #elif defined(__APPLE__) || defined(__darwin__)
365 if (server && version < V_OLD(1,3,'b')) {
366 thread_unsafe = 1;
367 sad_os = "Mac OS X";
369 #endif
371 if (thread_unsafe) {
372 log(LOG_WARN, LD_GENERAL,
373 "Libevent version %s often crashes when running a Tor server with %s. "
374 "Please use the latest version of libevent (1.3b or later)",v,sad_os);
375 badness = "BROKEN";
376 } else if (buggy) {
377 log(LOG_WARN, LD_GENERAL,
378 "There are serious bugs in using %s with libevent %s. "
379 "Please use the latest version of libevent.", m, v);
380 badness = "BROKEN";
381 } else if (iffy) {
382 log(LOG_WARN, LD_GENERAL,
383 "There are minor bugs in using %s with libevent %s. "
384 "You may want to use the latest version of libevent.", m, v);
385 badness = "BUGGY";
386 } else if (slow && server) {
387 log(LOG_WARN, LD_GENERAL,
388 "libevent %s can be very slow with %s. "
389 "When running a server, please use the latest version of libevent.",
390 v,m);
391 badness = "SLOW";
394 *badness_out = badness;
397 #if defined(LIBEVENT_VERSION)
398 #define HEADER_VERSION LIBEVENT_VERSION
399 #elif defined(_EVENT_VERSION)
400 #define HEADER_VERSION _EVENT_VERSION
401 #endif
403 /** See whether the headers we were built against differ from the library we
404 * linked against so much that we're likely to crash. If so, warn the
405 * user. */
406 void
407 tor_check_libevent_header_compatibility(void)
409 (void) le_versions_compatibility;
410 (void) tor_decode_libevent_version;
412 /* In libevent versions before 2.0, it's hard to keep binary compatibility
413 * between upgrades, and unpleasant to detect when the version we compiled
414 * against is unlike the version we have linked against. Here's how. */
415 #if defined(HEADER_VERSION) && defined(HAVE_EVENT_GET_VERSION)
416 /* We have a header-file version and a function-call version. Easy. */
417 if (strcmp(HEADER_VERSION, event_get_version())) {
418 le_version_t v1, v2;
419 int compat1 = -1, compat2 = -1;
420 int verybad;
421 v1 = tor_decode_libevent_version(HEADER_VERSION);
422 v2 = tor_decode_libevent_version(event_get_version());
423 compat1 = le_versions_compatibility(v1);
424 compat2 = le_versions_compatibility(v2);
426 verybad = compat1 != compat2;
428 log(verybad ? LOG_WARN : LOG_NOTICE,
429 LD_GENERAL, "We were compiled with headers from version %s "
430 "of Libevent, but we're using a Libevent library that says it's "
431 "version %s.", HEADER_VERSION, event_get_version());
432 if (verybad)
433 log_warn(LD_GENERAL, "This will almost certainly make Tor crash.");
434 else
435 log_info(LD_GENERAL, "I think these versions are binary-compatible.");
437 #elif defined(HAVE_EVENT_GET_VERSION)
438 /* event_get_version but no _EVENT_VERSION. We might be in 1.4.0-beta or
439 earlier, where that's normal. To see whether we were compiled with an
440 earlier version, let's see whether the struct event defines MIN_HEAP_IDX.
442 #ifdef HAVE_STRUCT_EVENT_MIN_HEAP_IDX
443 /* The header files are 1.4.0-beta or later. If the version is not
444 * 1.4.0-beta, we are incompatible. */
446 if (strcmp(event_get_version(), "1.4.0-beta")) {
447 log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
448 "Libevent 1.4.0-beta header files, whereas you have linked "
449 "against Libevent %s. This will probably make Tor crash.",
450 event_get_version());
453 #else
454 /* Our headers are 1.3e or earlier. If the library version is not 1.4.x or
455 later, we're probably fine. */
457 const char *v = event_get_version();
458 if ((v[0] == '1' && v[2] == '.' && v[3] > '3') || v[0] > '1') {
459 log_warn(LD_GENERAL, "It's a little hard to tell, but you seem to have "
460 "Libevent header file from 1.3e or earlier, whereas you have "
461 "linked against Libevent %s. This will probably make Tor "
462 "crash.", event_get_version());
465 #endif
467 #elif defined(HEADER_VERSION)
468 #warn "_EVENT_VERSION is defined but not get_event_version(): Libevent is odd."
469 #else
470 /* Your libevent is ancient. */
471 #endif
475 If possible, we're going to try to use Libevent's periodic timer support,
476 since it does a pretty good job of making sure that periodic events get
477 called exactly M seconds apart, rather than starting each one exactly M
478 seconds after the time that the last one was run.
480 #ifdef HAVE_EVENT2_EVENT_H
481 #define HAVE_PERIODIC
482 #define PERIODIC_FLAGS EV_PERSIST
483 #else
484 #define PERIODIC_FLAGS 0
485 #endif
487 /** Represents a timer that's run every N microseconds by Libevent. */
488 struct periodic_timer_t {
489 /** Underlying event used to implement this periodic event. */
490 struct event *ev;
491 /** The callback we'll be invoking whenever the event triggers */
492 void (*cb)(struct periodic_timer_t *, void *);
493 /** User-supplied data for the callback */
494 void *data;
495 #ifndef HAVE_PERIODIC
496 /** If Libevent doesn't know how to invoke events every N microseconds,
497 * we'll need to remember the timeout interval here. */
498 struct timeval tv;
499 #endif
502 /** Libevent callback to implement a periodic event. */
503 static void
504 periodic_timer_cb(evutil_socket_t fd, short what, void *arg)
506 periodic_timer_t *timer = arg;
507 (void) what;
508 (void) fd;
509 #ifndef HAVE_PERIODIC
510 /** reschedule the event as needed. */
511 event_add(timer->ev, &timer->tv);
512 #endif
513 timer->cb(timer, timer->data);
516 /** Create and schedule a new timer that will run every <b>tv</b> in
517 * the event loop of <b>base</b>. When the timer fires, it will
518 * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */
519 periodic_timer_t *
520 periodic_timer_new(struct event_base *base,
521 const struct timeval *tv,
522 void (*cb)(periodic_timer_t *timer, void *data),
523 void *data)
525 periodic_timer_t *timer;
526 tor_assert(base);
527 tor_assert(tv);
528 tor_assert(cb);
529 timer = tor_malloc_zero(sizeof(periodic_timer_t));
530 if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS,
531 periodic_timer_cb, timer))) {
532 tor_free(timer);
533 return NULL;
535 timer->cb = cb;
536 timer->data = data;
537 #ifndef HAVE_PERIODIC
538 memcpy(&timer->tv, tv, sizeof(struct timeval));
539 #endif
540 event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/
541 return timer;
544 /** Stop and free a periodic timer */
545 void
546 periodic_timer_free(periodic_timer_t *timer)
548 if (!timer)
549 return;
550 tor_event_free(timer->ev);
551 tor_free(timer);