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 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 15 struct 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 22 struct 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 30 struct 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 37 struct 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 52 static struct eloop_data eloop; 53 54 55 int eloop_init(void) 56 { 57 memset(&eloop, 0, sizeof(eloop)); 58 return 0; 59 } 60 61 62 int 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 89 void 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 112 int 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 159 int 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 191 int 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 213 static 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 228 static 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 251 int 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 278 int 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 293 int 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 305 void 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 362 void eloop_terminate(void) 363 { 364 eloop.terminate = 1; 365 } 366 367 368 void 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 383 int eloop_terminated(void) 384 { 385 return eloop.terminate; 386 } 387 388 389 void 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