1 /*
2  * dhcpcd - DHCP client daemon
3  * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4  * All rights reserved
5 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #ifndef ELOOP_H
29 #define ELOOP_H
30 
31 #include <time.h>
32 
33 #include "config.h"
34 
35 #ifndef ELOOP_QUEUE
36   #define ELOOP_QUEUE 1
37 #endif
38 
39 /* EXIT_FAILURE is a non zero value and EXIT_SUCCESS is zero.
40  * To add a CONTINUE definition, simply do the opposite of EXIT_FAILURE. */
41 #define ELOOP_CONTINUE	-EXIT_FAILURE
42 
43 struct eloop_event {
44 	TAILQ_ENTRY(eloop_event) next;
45 	int fd;
46 	void (*read_cb)(void *);
47 	void *read_cb_arg;
48 	void (*write_cb)(void *);
49 	void *write_cb_arg;
50 #if !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL)
51 	struct pollfd *pollfd;
52 #endif
53 };
54 
55 struct eloop_timeout {
56 	TAILQ_ENTRY(eloop_timeout) next;
57 	struct timespec when;
58 	void (*callback)(void *);
59 	void *arg;
60 	int queue;
61 };
62 
63 struct eloop_ctx {
64 	struct dhcpcd_ctx *ctx;
65 
66 	size_t events_len;
67 	TAILQ_HEAD (event_head, eloop_event) events;
68 	struct event_head free_events;
69 
70 	TAILQ_HEAD (timeout_head, eloop_timeout) timeouts;
71 	struct timeout_head free_timeouts;
72 
73 	void (*timeout0)(void *);
74 	void *timeout0_arg;
75 
76 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
77 	int poll_fd;
78 #else
79 	struct pollfd *fds;
80 	size_t fds_len;
81 #endif
82 
83 	int exitnow;
84 	int exitcode;
85 };
86 
87 #define eloop_timeout_add_tv(a, b, c, d) \
88     eloop_q_timeout_add_tv(a, ELOOP_QUEUE, b, c, d)
89 #define eloop_timeout_add_sec(a, b, c, d) \
90     eloop_q_timeout_add_sec(a, ELOOP_QUEUE, b, c, d)
91 #define eloop_timeout_delete(a, b, c) \
92     eloop_q_timeout_delete(a, ELOOP_QUEUE, b, c)
93 
94 int eloop_event_add(struct eloop_ctx *, int,
95     void (*)(void *), void *,
96     void (*)(void *), void *);
97 void eloop_event_delete(struct eloop_ctx *, int, int);
98 int eloop_q_timeout_add_sec(struct eloop_ctx *, int queue,
99     time_t, void (*)(void *), void *);
100 int eloop_q_timeout_add_tv(struct eloop_ctx *, int queue,
101     const struct timespec *, void (*)(void *), void *);
102 #if !defined(HAVE_KQUEUE)
103 int eloop_timeout_add_now(struct eloop_ctx *, void (*)(void *), void *);
104 #endif
105 void eloop_q_timeout_delete(struct eloop_ctx *, int, void (*)(void *), void *);
106 struct eloop_ctx * eloop_init(struct dhcpcd_ctx *);
107 #if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
108 int eloop_requeue(struct eloop_ctx *);
109 #else
110 #define eloop_requeue(a) (0)
111 #endif
112 void eloop_free(struct eloop_ctx *);
113 void eloop_exit(struct eloop_ctx *, int);
114 int eloop_start(struct eloop_ctx *);
115 
116 #endif
117