eloop_none.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
1/*
2 * Event loop - empty template (basic structure, but no OS specific operations)
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "eloop.h"
13
14
15struct eloop_sock {
16	int sock;
17	void *eloop_data;
18	void *user_data;
19	void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
20};
21
22struct eloop_timeout {
23	struct os_time time;
24	void *eloop_data;
25	void *user_data;
26	void (*handler)(void *eloop_ctx, void *sock_ctx);
27	struct eloop_timeout *next;
28};
29
30struct eloop_signal {
31	int sig;
32	void *user_data;
33	void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
34	int signaled;
35};
36
37struct eloop_data {
38	int max_sock, reader_count;
39	struct eloop_sock *readers;
40
41	struct eloop_timeout *timeout;
42
43	int signal_count;
44	struct eloop_signal *signals;
45	int signaled;
46	int pending_terminate;
47
48	int terminate;
49	int reader_table_changed;
50};
51
52static struct eloop_data eloop;
53
54
55int eloop_init(void)
56{
57	memset(&eloop, 0, sizeof(eloop));
58	return 0;
59}
60
61
62int eloop_register_read_sock(int sock,
63			     void (*handler)(int sock, void *eloop_ctx,
64					     void *sock_ctx),
65			     void *eloop_data, void *user_data)
66{
67	struct eloop_sock *tmp;
68
69	tmp = (struct eloop_sock *)
70		realloc(eloop.readers,
71			(eloop.reader_count + 1) * sizeof(struct eloop_sock));
72	if (tmp == NULL)
73		return -1;
74
75	tmp[eloop.reader_count].sock = sock;
76	tmp[eloop.reader_count].eloop_data = eloop_data;
77	tmp[eloop.reader_count].user_data = user_data;
78	tmp[eloop.reader_count].handler = handler;
79	eloop.reader_count++;
80	eloop.readers = tmp;
81	if (sock > eloop.max_sock)
82		eloop.max_sock = sock;
83	eloop.reader_table_changed = 1;
84
85	return 0;
86}
87
88
89void eloop_unregister_read_sock(int sock)
90{
91	int i;
92
93	if (eloop.readers == NULL || eloop.reader_count == 0)
94		return;
95
96	for (i = 0; i < eloop.reader_count; i++) {
97		if (eloop.readers[i].sock == sock)
98			break;
99	}
100	if (i == eloop.reader_count)
101		return;
102	if (i != eloop.reader_count - 1) {
103		memmove(&eloop.readers[i], &eloop.readers[i + 1],
104			(eloop.reader_count - i - 1) *
105			sizeof(struct eloop_sock));
106	}
107	eloop.reader_count--;
108	eloop.reader_table_changed = 1;
109}
110
111
112int eloop_register_timeout(unsigned int secs, unsigned int usecs,
113			   void (*handler)(void *eloop_ctx, void *timeout_ctx),
114			   void *eloop_data, void *user_data)
115{
116	struct eloop_timeout *timeout, *tmp, *prev;
117
118	timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
119	if (timeout == NULL)
120		return -1;
121	os_get_time(&timeout->time);
122	timeout->time.sec += secs;
123	timeout->time.usec += usecs;
124	while (timeout->time.usec >= 1000000) {
125		timeout->time.sec++;
126		timeout->time.usec -= 1000000;
127	}
128	timeout->eloop_data = eloop_data;
129	timeout->user_data = user_data;
130	timeout->handler = handler;
131	timeout->next = NULL;
132
133	if (eloop.timeout == NULL) {
134		eloop.timeout = timeout;
135		return 0;
136	}
137
138	prev = NULL;
139	tmp = eloop.timeout;
140	while (tmp != NULL) {
141		if (os_time_before(&timeout->time, &tmp->time))
142			break;
143		prev = tmp;
144		tmp = tmp->next;
145	}
146
147	if (prev == NULL) {
148		timeout->next = eloop.timeout;
149		eloop.timeout = timeout;
150	} else {
151		timeout->next = prev->next;
152		prev->next = timeout;
153	}
154
155	return 0;
156}
157
158
159int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
160			 void *eloop_data, void *user_data)
161{
162	struct eloop_timeout *timeout, *prev, *next;
163	int removed = 0;
164
165	prev = NULL;
166	timeout = eloop.timeout;
167	while (timeout != NULL) {
168		next = timeout->next;
169
170		if (timeout->handler == handler &&
171		    (timeout->eloop_data == eloop_data ||
172		     eloop_data == ELOOP_ALL_CTX) &&
173		    (timeout->user_data == user_data ||
174		     user_data == ELOOP_ALL_CTX)) {
175			if (prev == NULL)
176				eloop.timeout = next;
177			else
178				prev->next = next;
179			free(timeout);
180			removed++;
181		} else
182			prev = timeout;
183
184		timeout = next;
185	}
186
187	return removed;
188}
189
190
191int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
192						void *timeout_ctx),
193				void *eloop_data, void *user_data)
194{
195	struct eloop_timeout *tmp;
196
197	tmp = eloop.timeout;
198	while (tmp != NULL) {
199		if (tmp->handler == handler &&
200		    tmp->eloop_data == eloop_data &&
201		    tmp->user_data == user_data)
202			return 1;
203
204		tmp = tmp->next;
205	}
206
207	return 0;
208}
209
210
211/* TODO: replace with suitable signal handler */
212#if 0
213static void eloop_handle_signal(int sig)
214{
215	int i;
216
217	eloop.signaled++;
218	for (i = 0; i < eloop.signal_count; i++) {
219		if (eloop.signals[i].sig == sig) {
220			eloop.signals[i].signaled++;
221			break;
222		}
223	}
224}
225#endif
226
227
228static void eloop_process_pending_signals(void)
229{
230	int i;
231
232	if (eloop.signaled == 0)
233		return;
234	eloop.signaled = 0;
235
236	if (eloop.pending_terminate) {
237		eloop.pending_terminate = 0;
238	}
239
240	for (i = 0; i < eloop.signal_count; i++) {
241		if (eloop.signals[i].signaled) {
242			eloop.signals[i].signaled = 0;
243			eloop.signals[i].handler(eloop.signals[i].sig,
244						 eloop.user_data,
245						 eloop.signals[i].user_data);
246		}
247	}
248}
249
250
251int eloop_register_signal(int sig,
252			  void (*handler)(int sig, void *eloop_ctx,
253					  void *signal_ctx),
254			  void *user_data)
255{
256	struct eloop_signal *tmp;
257
258	tmp = (struct eloop_signal *)
259		realloc(eloop.signals,
260			(eloop.signal_count + 1) *
261			sizeof(struct eloop_signal));
262	if (tmp == NULL)
263		return -1;
264
265	tmp[eloop.signal_count].sig = sig;
266	tmp[eloop.signal_count].user_data = user_data;
267	tmp[eloop.signal_count].handler = handler;
268	tmp[eloop.signal_count].signaled = 0;
269	eloop.signal_count++;
270	eloop.signals = tmp;
271
272	/* TODO: register signal handler */
273
274	return 0;
275}
276
277
278int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx,
279						    void *signal_ctx),
280				    void *user_data)
281{
282#if 0
283	/* TODO: for example */
284	int ret = eloop_register_signal(SIGINT, handler, user_data);
285	if (ret == 0)
286		ret = eloop_register_signal(SIGTERM, handler, user_data);
287	return ret;
288#endif
289	return 0;
290}
291
292
293int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx,
294						   void *signal_ctx),
295				   void *user_data)
296{
297#if 0
298	/* TODO: for example */
299	return eloop_register_signal(SIGHUP, handler, user_data);
300#endif
301	return 0;
302}
303
304
305void eloop_run(void)
306{
307	int i;
308	struct os_time tv, now;
309
310	while (!eloop.terminate &&
311		(eloop.timeout || eloop.reader_count > 0)) {
312		if (eloop.timeout) {
313			os_get_time(&now);
314			if (os_time_before(&now, &eloop.timeout->time))
315				os_time_sub(&eloop.timeout->time, &now, &tv);
316			else
317				tv.sec = tv.usec = 0;
318		}
319
320		/*
321		 * TODO: wait for any event (read socket ready, timeout (tv),
322		 * signal
323		 */
324		os_sleep(1, 0); /* just a dummy wait for testing */
325
326		eloop_process_pending_signals();
327
328		/* check if some registered timeouts have occurred */
329		if (eloop.timeout) {
330			struct eloop_timeout *tmp;
331
332			os_get_time(&now);
333			if (!os_time_before(&now, &eloop.timeout->time)) {
334				tmp = eloop.timeout;
335				eloop.timeout = eloop.timeout->next;
336				tmp->handler(tmp->eloop_data,
337					     tmp->user_data);
338				free(tmp);
339			}
340
341		}
342
343		eloop.reader_table_changed = 0;
344		for (i = 0; i < eloop.reader_count; i++) {
345			/*
346			 * TODO: call each handler that has pending data to
347			 * read
348			 */
349			if (0 /* TODO: eloop.readers[i].sock ready */) {
350				eloop.readers[i].handler(
351					eloop.readers[i].sock,
352					eloop.readers[i].eloop_data,
353					eloop.readers[i].user_data);
354				if (eloop.reader_table_changed)
355					break;
356			}
357		}
358	}
359}
360
361
362void eloop_terminate(void)
363{
364	eloop.terminate = 1;
365}
366
367
368void eloop_destroy(void)
369{
370	struct eloop_timeout *timeout, *prev;
371
372	timeout = eloop.timeout;
373	while (timeout != NULL) {
374		prev = timeout;
375		timeout = timeout->next;
376		free(prev);
377	}
378	free(eloop.readers);
379	free(eloop.signals);
380}
381
382
383int eloop_terminated(void)
384{
385	return eloop.terminate;
386}
387
388
389void eloop_wait_for_read_sock(int sock)
390{
391	/*
392	 * TODO: wait for the file descriptor to have something available for
393	 * reading
394	 */
395}
396