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