lib/crypto: add aes_gcm_128 support.
[samba.git] / lib / tevent / tevent.c
1 /* 
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    Copyright (C) Andrew Tridgell 2003
5    Copyright (C) Stefan Metzmacher 2009
6
7      ** NOTE! The following LGPL license applies to the tevent
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26   PLEASE READ THIS BEFORE MODIFYING!
27
28   This module is a general abstraction for the main select loop and
29   event handling. Do not ever put any localised hacks in here, instead
30   register one of the possible event types and implement that event
31   somewhere else.
32
33   There are 2 types of event handling that are handled in this module:
34
35   1) a file descriptor becoming readable or writeable. This is mostly
36      used for network sockets, but can be used for any type of file
37      descriptor. You may only register one handler for each file
38      descriptor/io combination or you will get unpredictable results
39      (this means that you can have a handler for read events, and a
40      separate handler for write events, but not two handlers that are
41      both handling read events)
42
43   2) a timed event. You can register an event that happens at a
44      specific time.  You can register as many of these as you
45      like. They are single shot - add a new timed event in the event
46      handler to get another event.
47
48   To setup a set of events you first need to create a event_context
49   structure using the function tevent_context_init(); This returns a
50   'struct tevent_context' that you use in all subsequent calls.
51
52   After that you can add/remove events that you are interested in
53   using tevent_add_*() and talloc_free()
54
55   Finally, you call tevent_loop_wait_once() to block waiting for one of the
56   events to occor or tevent_loop_wait() which will loop
57   forever.
58
59 */
60 #include "replace.h"
61 #include "system/filesys.h"
62 #define TEVENT_DEPRECATED 1
63 #include "tevent.h"
64 #include "tevent_internal.h"
65 #include "tevent_util.h"
66
67 struct tevent_ops_list {
68         struct tevent_ops_list *next, *prev;
69         const char *name;
70         const struct tevent_ops *ops;
71 };
72
73 /* list of registered event backends */
74 static struct tevent_ops_list *tevent_backends = NULL;
75 static char *tevent_default_backend = NULL;
76
77 /*
78   register an events backend
79 */
80 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
81 {
82         struct tevent_ops_list *e;
83
84         for (e = tevent_backends; e != NULL; e = e->next) {
85                 if (0 == strcmp(e->name, name)) {
86                         /* already registered, skip it */
87                         return true;
88                 }
89         }
90
91         e = talloc(NULL, struct tevent_ops_list);
92         if (e == NULL) return false;
93
94         e->name = name;
95         e->ops = ops;
96         DLIST_ADD(tevent_backends, e);
97
98         return true;
99 }
100
101 /*
102   set the default event backend
103  */
104 void tevent_set_default_backend(const char *backend)
105 {
106         talloc_free(tevent_default_backend);
107         tevent_default_backend = talloc_strdup(NULL, backend);
108 }
109
110 /*
111   initialise backends if not already done
112 */
113 static void tevent_backend_init(void)
114 {
115         static bool done;
116
117         if (done) {
118                 return;
119         }
120
121         done = true;
122
123         tevent_select_init();
124         tevent_poll_init();
125         tevent_poll_mt_init();
126 #ifdef HAVE_EPOLL
127         tevent_epoll_init();
128 #endif
129         tevent_standard_init();
130 }
131
132 _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
133 {
134         struct tevent_ops_list *e;
135
136         tevent_backend_init();
137
138         if (name == NULL) {
139                 name = tevent_default_backend;
140         }
141         if (name == NULL) {
142                 name = "standard";
143         }
144
145         for (e = tevent_backends; e != NULL; e = e->next) {
146                 if (0 == strcmp(e->name, name)) {
147                         return e->ops;
148                 }
149         }
150
151         return NULL;
152 }
153
154 /*
155   list available backends
156 */
157 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
158 {
159         const char **list = NULL;
160         struct tevent_ops_list *e;
161
162         tevent_backend_init();
163
164         for (e=tevent_backends;e;e=e->next) {
165                 list = ev_str_list_add(list, e->name);
166         }
167
168         talloc_steal(mem_ctx, list);
169
170         return list;
171 }
172
173 int tevent_common_context_destructor(struct tevent_context *ev)
174 {
175         struct tevent_fd *fd, *fn;
176         struct tevent_timer *te, *tn;
177         struct tevent_immediate *ie, *in;
178         struct tevent_signal *se, *sn;
179
180         if (ev->pipe_fde) {
181                 talloc_free(ev->pipe_fde);
182                 close(ev->pipe_fds[0]);
183                 close(ev->pipe_fds[1]);
184                 ev->pipe_fde = NULL;
185         }
186
187         for (fd = ev->fd_events; fd; fd = fn) {
188                 fn = fd->next;
189                 fd->event_ctx = NULL;
190                 DLIST_REMOVE(ev->fd_events, fd);
191         }
192
193         ev->last_zero_timer = NULL;
194         for (te = ev->timer_events; te; te = tn) {
195                 tn = te->next;
196                 te->event_ctx = NULL;
197                 DLIST_REMOVE(ev->timer_events, te);
198         }
199
200         for (ie = ev->immediate_events; ie; ie = in) {
201                 in = ie->next;
202                 ie->event_ctx = NULL;
203                 ie->cancel_fn = NULL;
204                 DLIST_REMOVE(ev->immediate_events, ie);
205         }
206
207         for (se = ev->signal_events; se; se = sn) {
208                 sn = se->next;
209                 se->event_ctx = NULL;
210                 DLIST_REMOVE(ev->signal_events, se);
211                 /*
212                  * This is important, Otherwise signals
213                  * are handled twice in child. eg, SIGHUP.
214                  * one added in parent, and another one in
215                  * the child. -- BoYang
216                  */
217                 tevent_cleanup_pending_signal_handlers(se);
218         }
219
220         /* removing nesting hook or we get an abort when nesting is
221          * not allowed. -- SSS
222          * Note that we need to leave the allowed flag at its current
223          * value, otherwise the use in tevent_re_initialise() will
224          * leave the event context with allowed forced to false, which
225          * will break users that expect nesting to be allowed
226          */
227         ev->nesting.level = 0;
228         ev->nesting.hook_fn = NULL;
229         ev->nesting.hook_private = NULL;
230
231         return 0;
232 }
233
234 /*
235   create a event_context structure for a specific implemementation.
236   This must be the first events call, and all subsequent calls pass
237   this event_context as the first element. Event handlers also
238   receive this as their first argument.
239
240   This function is for allowing third-party-applications to hook in gluecode
241   to their own event loop code, so that they can make async usage of our client libs
242
243   NOTE: use tevent_context_init() inside of samba!
244 */
245 struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
246                                                const struct tevent_ops *ops,
247                                                void *additional_data)
248 {
249         struct tevent_context *ev;
250         int ret;
251
252         ev = talloc_zero(mem_ctx, struct tevent_context);
253         if (!ev) return NULL;
254
255         talloc_set_destructor(ev, tevent_common_context_destructor);
256
257         ev->ops = ops;
258         ev->additional_data = additional_data;
259
260         ret = ev->ops->context_init(ev);
261         if (ret != 0) {
262                 talloc_free(ev);
263                 return NULL;
264         }
265
266         return ev;
267 }
268
269 /*
270   create a event_context structure. This must be the first events
271   call, and all subsequent calls pass this event_context as the first
272   element. Event handlers also receive this as their first argument.
273 */
274 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
275                                                   const char *name)
276 {
277         const struct tevent_ops *ops;
278
279         ops = tevent_find_ops_byname(name);
280         if (ops == NULL) {
281                 return NULL;
282         }
283
284         return tevent_context_init_ops(mem_ctx, ops, NULL);
285 }
286
287
288 /*
289   create a event_context structure. This must be the first events
290   call, and all subsequent calls pass this event_context as the first
291   element. Event handlers also receive this as their first argument.
292 */
293 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
294 {
295         return tevent_context_init_byname(mem_ctx, NULL);
296 }
297
298 /*
299   add a fd based event
300   return NULL on failure (memory allocation error)
301 */
302 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
303                                  TALLOC_CTX *mem_ctx,
304                                  int fd,
305                                  uint16_t flags,
306                                  tevent_fd_handler_t handler,
307                                  void *private_data,
308                                  const char *handler_name,
309                                  const char *location)
310 {
311         return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
312                                handler_name, location);
313 }
314
315 /*
316   set a close function on the fd event
317 */
318 void tevent_fd_set_close_fn(struct tevent_fd *fde,
319                             tevent_fd_close_fn_t close_fn)
320 {
321         if (!fde) return;
322         if (!fde->event_ctx) return;
323         fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
324 }
325
326 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
327                                     struct tevent_fd *fde,
328                                     int fd,
329                                     void *private_data)
330 {
331         close(fd);
332 }
333
334 void tevent_fd_set_auto_close(struct tevent_fd *fde)
335 {
336         tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
337 }
338
339 /*
340   return the fd event flags
341 */
342 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
343 {
344         if (!fde) return 0;
345         if (!fde->event_ctx) return 0;
346         return fde->event_ctx->ops->get_fd_flags(fde);
347 }
348
349 /*
350   set the fd event flags
351 */
352 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
353 {
354         if (!fde) return;
355         if (!fde->event_ctx) return;
356         fde->event_ctx->ops->set_fd_flags(fde, flags);
357 }
358
359 bool tevent_signal_support(struct tevent_context *ev)
360 {
361         if (ev->ops->add_signal) {
362                 return true;
363         }
364         return false;
365 }
366
367 static void (*tevent_abort_fn)(const char *reason);
368
369 void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
370 {
371         tevent_abort_fn = abort_fn;
372 }
373
374 static void tevent_abort(struct tevent_context *ev, const char *reason)
375 {
376         tevent_debug(ev, TEVENT_DEBUG_FATAL,
377                      "abort: %s\n", reason);
378
379         if (!tevent_abort_fn) {
380                 abort();
381         }
382
383         tevent_abort_fn(reason);
384 }
385
386 /*
387   add a timer event
388   return NULL on failure
389 */
390 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
391                                        TALLOC_CTX *mem_ctx,
392                                        struct timeval next_event,
393                                        tevent_timer_handler_t handler,
394                                        void *private_data,
395                                        const char *handler_name,
396                                        const char *location)
397 {
398         return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
399                                   handler_name, location);
400 }
401
402 /*
403   allocate an immediate event
404   return NULL on failure (memory allocation error)
405 */
406 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
407                                                   const char *location)
408 {
409         struct tevent_immediate *im;
410
411         im = talloc(mem_ctx, struct tevent_immediate);
412         if (im == NULL) return NULL;
413
414         im->prev                = NULL;
415         im->next                = NULL;
416         im->event_ctx           = NULL;
417         im->create_location     = location;
418         im->handler             = NULL;
419         im->private_data        = NULL;
420         im->handler_name        = NULL;
421         im->schedule_location   = NULL;
422         im->cancel_fn           = NULL;
423         im->additional_data     = NULL;
424
425         return im;
426 }
427
428 /*
429   schedule an immediate event
430 */
431 void _tevent_schedule_immediate(struct tevent_immediate *im,
432                                 struct tevent_context *ev,
433                                 tevent_immediate_handler_t handler,
434                                 void *private_data,
435                                 const char *handler_name,
436                                 const char *location)
437 {
438         ev->ops->schedule_immediate(im, ev, handler, private_data,
439                                     handler_name, location);
440 }
441
442 /*
443   add a signal event
444
445   sa_flags are flags to sigaction(2)
446
447   return NULL on failure
448 */
449 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
450                                          TALLOC_CTX *mem_ctx,
451                                          int signum,
452                                          int sa_flags,
453                                          tevent_signal_handler_t handler,
454                                          void *private_data,
455                                          const char *handler_name,
456                                          const char *location)
457 {
458         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
459                                    handler_name, location);
460 }
461
462 void tevent_loop_allow_nesting(struct tevent_context *ev)
463 {
464         ev->nesting.allowed = true;
465 }
466
467 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
468                                   tevent_nesting_hook hook,
469                                   void *private_data)
470 {
471         if (ev->nesting.hook_fn && 
472             (ev->nesting.hook_fn != hook ||
473              ev->nesting.hook_private != private_data)) {
474                 /* the way the nesting hook code is currently written
475                    we cannot support two different nesting hooks at the
476                    same time. */
477                 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
478         }
479         ev->nesting.hook_fn = hook;
480         ev->nesting.hook_private = private_data;
481 }
482
483 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
484 {
485         const char *reason;
486
487         reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
488                                  location);
489         if (!reason) {
490                 reason = "tevent_loop_once() nesting";
491         }
492
493         tevent_abort(ev, reason);
494 }
495
496 /*
497   do a single event loop using the events defined in ev 
498 */
499 int _tevent_loop_once(struct tevent_context *ev, const char *location)
500 {
501         int ret;
502         void *nesting_stack_ptr = NULL;
503
504         ev->nesting.level++;
505
506         if (ev->nesting.level > 1) {
507                 if (!ev->nesting.allowed) {
508                         tevent_abort_nesting(ev, location);
509                         errno = ELOOP;
510                         return -1;
511                 }
512         }
513         if (ev->nesting.level > 0) {
514                 if (ev->nesting.hook_fn) {
515                         int ret2;
516                         ret2 = ev->nesting.hook_fn(ev,
517                                                    ev->nesting.hook_private,
518                                                    ev->nesting.level,
519                                                    true,
520                                                    (void *)&nesting_stack_ptr,
521                                                    location);
522                         if (ret2 != 0) {
523                                 ret = ret2;
524                                 goto done;
525                         }
526                 }
527         }
528
529         tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
530         ret = ev->ops->loop_once(ev, location);
531         tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
532
533         if (ev->nesting.level > 0) {
534                 if (ev->nesting.hook_fn) {
535                         int ret2;
536                         ret2 = ev->nesting.hook_fn(ev,
537                                                    ev->nesting.hook_private,
538                                                    ev->nesting.level,
539                                                    false,
540                                                    (void *)&nesting_stack_ptr,
541                                                    location);
542                         if (ret2 != 0) {
543                                 ret = ret2;
544                                 goto done;
545                         }
546                 }
547         }
548
549 done:
550         ev->nesting.level--;
551         return ret;
552 }
553
554 /*
555   this is a performance optimization for the samba4 nested event loop problems
556 */
557 int _tevent_loop_until(struct tevent_context *ev,
558                        bool (*finished)(void *private_data),
559                        void *private_data,
560                        const char *location)
561 {
562         int ret = 0;
563         void *nesting_stack_ptr = NULL;
564
565         ev->nesting.level++;
566
567         if (ev->nesting.level > 1) {
568                 if (!ev->nesting.allowed) {
569                         tevent_abort_nesting(ev, location);
570                         errno = ELOOP;
571                         return -1;
572                 }
573         }
574         if (ev->nesting.level > 0) {
575                 if (ev->nesting.hook_fn) {
576                         int ret2;
577                         ret2 = ev->nesting.hook_fn(ev,
578                                                    ev->nesting.hook_private,
579                                                    ev->nesting.level,
580                                                    true,
581                                                    (void *)&nesting_stack_ptr,
582                                                    location);
583                         if (ret2 != 0) {
584                                 ret = ret2;
585                                 goto done;
586                         }
587                 }
588         }
589
590         while (!finished(private_data)) {
591                 tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
592                 ret = ev->ops->loop_once(ev, location);
593                 tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
594                 if (ret != 0) {
595                         break;
596                 }
597         }
598
599         if (ev->nesting.level > 0) {
600                 if (ev->nesting.hook_fn) {
601                         int ret2;
602                         ret2 = ev->nesting.hook_fn(ev,
603                                                    ev->nesting.hook_private,
604                                                    ev->nesting.level,
605                                                    false,
606                                                    (void *)&nesting_stack_ptr,
607                                                    location);
608                         if (ret2 != 0) {
609                                 ret = ret2;
610                                 goto done;
611                         }
612                 }
613         }
614
615 done:
616         ev->nesting.level--;
617         return ret;
618 }
619
620 /*
621   return on failure or (with 0) if all fd events are removed
622 */
623 int tevent_common_loop_wait(struct tevent_context *ev,
624                             const char *location)
625 {
626         /*
627          * loop as long as we have events pending
628          */
629         while (ev->fd_events ||
630                ev->timer_events ||
631                ev->immediate_events ||
632                ev->signal_events) {
633                 int ret;
634                 ret = _tevent_loop_once(ev, location);
635                 if (ret != 0) {
636                         tevent_debug(ev, TEVENT_DEBUG_FATAL,
637                                      "_tevent_loop_once() failed: %d - %s\n",
638                                      ret, strerror(errno));
639                         return ret;
640                 }
641         }
642
643         tevent_debug(ev, TEVENT_DEBUG_WARNING,
644                      "tevent_common_loop_wait() out of events\n");
645         return 0;
646 }
647
648 /*
649   return on failure or (with 0) if all fd events are removed
650 */
651 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
652 {
653         return ev->ops->loop_wait(ev, location);
654 }
655
656
657 /*
658   re-initialise a tevent context. This leaves you with the same
659   event context, but all events are wiped and the structure is
660   re-initialised. This is most useful after a fork()  
661
662   zero is returned on success, non-zero on failure
663 */
664 int tevent_re_initialise(struct tevent_context *ev)
665 {
666         tevent_common_context_destructor(ev);
667
668         return ev->ops->context_init(ev);
669 }