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