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