$search
00001 /* 00002 * Event loop - empty template (basic structure, but no OS specific operations) 00003 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eloop.h" 00019 00020 00021 struct eloop_sock { 00022 int sock; 00023 void *eloop_data; 00024 void *user_data; 00025 void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); 00026 }; 00027 00028 struct eloop_timeout { 00029 struct os_time time; 00030 void *eloop_data; 00031 void *user_data; 00032 void (*handler)(void *eloop_ctx, void *sock_ctx); 00033 struct eloop_timeout *next; 00034 }; 00035 00036 struct eloop_signal { 00037 int sig; 00038 void *user_data; 00039 void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); 00040 int signaled; 00041 }; 00042 00043 struct eloop_data { 00044 int max_sock, reader_count; 00045 struct eloop_sock *readers; 00046 00047 struct eloop_timeout *timeout; 00048 00049 int signal_count; 00050 struct eloop_signal *signals; 00051 int signaled; 00052 int pending_terminate; 00053 00054 int terminate; 00055 int reader_table_changed; 00056 }; 00057 00058 static struct eloop_data eloop; 00059 00060 00061 int eloop_init(void) 00062 { 00063 memset(&eloop, 0, sizeof(eloop)); 00064 return 0; 00065 } 00066 00067 00068 int eloop_register_read_sock(int sock, 00069 void (*handler)(int sock, void *eloop_ctx, 00070 void *sock_ctx), 00071 void *eloop_data, void *user_data) 00072 { 00073 struct eloop_sock *tmp; 00074 00075 tmp = (struct eloop_sock *) 00076 realloc(eloop.readers, 00077 (eloop.reader_count + 1) * sizeof(struct eloop_sock)); 00078 if (tmp == NULL) 00079 return -1; 00080 00081 tmp[eloop.reader_count].sock = sock; 00082 tmp[eloop.reader_count].eloop_data = eloop_data; 00083 tmp[eloop.reader_count].user_data = user_data; 00084 tmp[eloop.reader_count].handler = handler; 00085 eloop.reader_count++; 00086 eloop.readers = tmp; 00087 if (sock > eloop.max_sock) 00088 eloop.max_sock = sock; 00089 eloop.reader_table_changed = 1; 00090 00091 return 0; 00092 } 00093 00094 00095 void eloop_unregister_read_sock(int sock) 00096 { 00097 int i; 00098 00099 if (eloop.readers == NULL || eloop.reader_count == 0) 00100 return; 00101 00102 for (i = 0; i < eloop.reader_count; i++) { 00103 if (eloop.readers[i].sock == sock) 00104 break; 00105 } 00106 if (i == eloop.reader_count) 00107 return; 00108 if (i != eloop.reader_count - 1) { 00109 memmove(&eloop.readers[i], &eloop.readers[i + 1], 00110 (eloop.reader_count - i - 1) * 00111 sizeof(struct eloop_sock)); 00112 } 00113 eloop.reader_count--; 00114 eloop.reader_table_changed = 1; 00115 } 00116 00117 00118 int eloop_register_timeout(unsigned int secs, unsigned int usecs, 00119 void (*handler)(void *eloop_ctx, void *timeout_ctx), 00120 void *eloop_data, void *user_data) 00121 { 00122 struct eloop_timeout *timeout, *tmp, *prev; 00123 00124 timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); 00125 if (timeout == NULL) 00126 return -1; 00127 os_get_time(&timeout->time); 00128 timeout->time.sec += secs; 00129 timeout->time.usec += usecs; 00130 while (timeout->time.usec >= 1000000) { 00131 timeout->time.sec++; 00132 timeout->time.usec -= 1000000; 00133 } 00134 timeout->eloop_data = eloop_data; 00135 timeout->user_data = user_data; 00136 timeout->handler = handler; 00137 timeout->next = NULL; 00138 00139 if (eloop.timeout == NULL) { 00140 eloop.timeout = timeout; 00141 return 0; 00142 } 00143 00144 prev = NULL; 00145 tmp = eloop.timeout; 00146 while (tmp != NULL) { 00147 if (os_time_before(&timeout->time, &tmp->time)) 00148 break; 00149 prev = tmp; 00150 tmp = tmp->next; 00151 } 00152 00153 if (prev == NULL) { 00154 timeout->next = eloop.timeout; 00155 eloop.timeout = timeout; 00156 } else { 00157 timeout->next = prev->next; 00158 prev->next = timeout; 00159 } 00160 00161 return 0; 00162 } 00163 00164 00165 int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), 00166 void *eloop_data, void *user_data) 00167 { 00168 struct eloop_timeout *timeout, *prev, *next; 00169 int removed = 0; 00170 00171 prev = NULL; 00172 timeout = eloop.timeout; 00173 while (timeout != NULL) { 00174 next = timeout->next; 00175 00176 if (timeout->handler == handler && 00177 (timeout->eloop_data == eloop_data || 00178 eloop_data == ELOOP_ALL_CTX) && 00179 (timeout->user_data == user_data || 00180 user_data == ELOOP_ALL_CTX)) { 00181 if (prev == NULL) 00182 eloop.timeout = next; 00183 else 00184 prev->next = next; 00185 free(timeout); 00186 removed++; 00187 } else 00188 prev = timeout; 00189 00190 timeout = next; 00191 } 00192 00193 return removed; 00194 } 00195 00196 00197 int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, 00198 void *timeout_ctx), 00199 void *eloop_data, void *user_data) 00200 { 00201 struct eloop_timeout *tmp; 00202 00203 tmp = eloop.timeout; 00204 while (tmp != NULL) { 00205 if (tmp->handler == handler && 00206 tmp->eloop_data == eloop_data && 00207 tmp->user_data == user_data) 00208 return 1; 00209 00210 tmp = tmp->next; 00211 } 00212 00213 return 0; 00214 } 00215 00216 00217 /* TODO: replace with suitable signal handler */ 00218 #if 0 00219 static void eloop_handle_signal(int sig) 00220 { 00221 int i; 00222 00223 eloop.signaled++; 00224 for (i = 0; i < eloop.signal_count; i++) { 00225 if (eloop.signals[i].sig == sig) { 00226 eloop.signals[i].signaled++; 00227 break; 00228 } 00229 } 00230 } 00231 #endif 00232 00233 00234 static void eloop_process_pending_signals(void) 00235 { 00236 int i; 00237 00238 if (eloop.signaled == 0) 00239 return; 00240 eloop.signaled = 0; 00241 00242 if (eloop.pending_terminate) { 00243 eloop.pending_terminate = 0; 00244 } 00245 00246 for (i = 0; i < eloop.signal_count; i++) { 00247 if (eloop.signals[i].signaled) { 00248 eloop.signals[i].signaled = 0; 00249 eloop.signals[i].handler(eloop.signals[i].sig, 00250 eloop.user_data, 00251 eloop.signals[i].user_data); 00252 } 00253 } 00254 } 00255 00256 00257 int eloop_register_signal(int sig, 00258 void (*handler)(int sig, void *eloop_ctx, 00259 void *signal_ctx), 00260 void *user_data) 00261 { 00262 struct eloop_signal *tmp; 00263 00264 tmp = (struct eloop_signal *) 00265 realloc(eloop.signals, 00266 (eloop.signal_count + 1) * 00267 sizeof(struct eloop_signal)); 00268 if (tmp == NULL) 00269 return -1; 00270 00271 tmp[eloop.signal_count].sig = sig; 00272 tmp[eloop.signal_count].user_data = user_data; 00273 tmp[eloop.signal_count].handler = handler; 00274 tmp[eloop.signal_count].signaled = 0; 00275 eloop.signal_count++; 00276 eloop.signals = tmp; 00277 00278 /* TODO: register signal handler */ 00279 00280 return 0; 00281 } 00282 00283 00284 int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, 00285 void *signal_ctx), 00286 void *user_data) 00287 { 00288 #if 0 00289 /* TODO: for example */ 00290 int ret = eloop_register_signal(SIGINT, handler, user_data); 00291 if (ret == 0) 00292 ret = eloop_register_signal(SIGTERM, handler, user_data); 00293 return ret; 00294 #endif 00295 return 0; 00296 } 00297 00298 00299 int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, 00300 void *signal_ctx), 00301 void *user_data) 00302 { 00303 #if 0 00304 /* TODO: for example */ 00305 return eloop_register_signal(SIGHUP, handler, user_data); 00306 #endif 00307 return 0; 00308 } 00309 00310 00311 void eloop_run(void) 00312 { 00313 int i; 00314 struct os_time tv, now; 00315 00316 while (!eloop.terminate && 00317 (eloop.timeout || eloop.reader_count > 0)) { 00318 if (eloop.timeout) { 00319 os_get_time(&now); 00320 if (os_time_before(&now, &eloop.timeout->time)) 00321 os_time_sub(&eloop.timeout->time, &now, &tv); 00322 else 00323 tv.sec = tv.usec = 0; 00324 } 00325 00326 /* 00327 * TODO: wait for any event (read socket ready, timeout (tv), 00328 * signal 00329 */ 00330 os_sleep(1, 0); /* just a dummy wait for testing */ 00331 00332 eloop_process_pending_signals(); 00333 00334 /* check if some registered timeouts have occurred */ 00335 if (eloop.timeout) { 00336 struct eloop_timeout *tmp; 00337 00338 os_get_time(&now); 00339 if (!os_time_before(&now, &eloop.timeout->time)) { 00340 tmp = eloop.timeout; 00341 eloop.timeout = eloop.timeout->next; 00342 tmp->handler(tmp->eloop_data, 00343 tmp->user_data); 00344 free(tmp); 00345 } 00346 00347 } 00348 00349 eloop.reader_table_changed = 0; 00350 for (i = 0; i < eloop.reader_count; i++) { 00351 /* 00352 * TODO: call each handler that has pending data to 00353 * read 00354 */ 00355 if (0 /* TODO: eloop.readers[i].sock ready */) { 00356 eloop.readers[i].handler( 00357 eloop.readers[i].sock, 00358 eloop.readers[i].eloop_data, 00359 eloop.readers[i].user_data); 00360 if (eloop.reader_table_changed) 00361 break; 00362 } 00363 } 00364 } 00365 } 00366 00367 00368 void eloop_terminate(void) 00369 { 00370 eloop.terminate = 1; 00371 } 00372 00373 00374 void eloop_destroy(void) 00375 { 00376 struct eloop_timeout *timeout, *prev; 00377 00378 timeout = eloop.timeout; 00379 while (timeout != NULL) { 00380 prev = timeout; 00381 timeout = timeout->next; 00382 free(prev); 00383 } 00384 free(eloop.readers); 00385 free(eloop.signals); 00386 } 00387 00388 00389 int eloop_terminated(void) 00390 { 00391 return eloop.terminate; 00392 } 00393 00394 00395 void eloop_wait_for_read_sock(int sock) 00396 { 00397 /* 00398 * TODO: wait for the file descriptor to have something available for 00399 * reading 00400 */ 00401 }