eloop_win.c
Go to the documentation of this file.
00001 /*
00002  * Event loop based on Windows events and WaitForMultipleObjects
00003  * Copyright (c) 2002-2006, 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 #include <winsock2.h>
00017 
00018 #include "common.h"
00019 #include "eloop.h"
00020 
00021 
00022 struct eloop_sock {
00023         int sock;
00024         void *eloop_data;
00025         void *user_data;
00026         eloop_sock_handler handler;
00027         WSAEVENT event;
00028 };
00029 
00030 struct eloop_event {
00031         void *eloop_data;
00032         void *user_data;
00033         eloop_event_handler handler;
00034         HANDLE event;
00035 };
00036 
00037 struct eloop_timeout {
00038         struct os_time time;
00039         void *eloop_data;
00040         void *user_data;
00041         eloop_timeout_handler handler;
00042         struct eloop_timeout *next;
00043 };
00044 
00045 struct eloop_signal {
00046         int sig;
00047         void *user_data;
00048         eloop_signal_handler handler;
00049         int signaled;
00050 };
00051 
00052 struct eloop_data {
00053         int max_sock;
00054         size_t reader_count;
00055         struct eloop_sock *readers;
00056 
00057         size_t event_count;
00058         struct eloop_event *events;
00059 
00060         struct eloop_timeout *timeout;
00061 
00062         int signal_count;
00063         struct eloop_signal *signals;
00064         int signaled;
00065         int pending_terminate;
00066 
00067         int terminate;
00068         int reader_table_changed;
00069 
00070         struct eloop_signal term_signal;
00071         HANDLE term_event;
00072 
00073         HANDLE *handles;
00074         size_t num_handles;
00075 };
00076 
00077 static struct eloop_data eloop;
00078 
00079 
00080 int eloop_init(void)
00081 {
00082         os_memset(&eloop, 0, sizeof(eloop));
00083         eloop.num_handles = 1;
00084         eloop.handles = os_malloc(eloop.num_handles *
00085                                   sizeof(eloop.handles[0]));
00086         if (eloop.handles == NULL)
00087                 return -1;
00088 
00089         eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
00090         if (eloop.term_event == NULL) {
00091                 printf("CreateEvent() failed: %d\n",
00092                        (int) GetLastError());
00093                 os_free(eloop.handles);
00094                 return -1;
00095         }
00096 
00097         return 0;
00098 }
00099 
00100 
00101 static int eloop_prepare_handles(void)
00102 {
00103         HANDLE *n;
00104 
00105         if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
00106                 return 0;
00107         n = os_realloc(eloop.handles,
00108                        eloop.num_handles * 2 * sizeof(eloop.handles[0]));
00109         if (n == NULL)
00110                 return -1;
00111         eloop.handles = n;
00112         eloop.num_handles *= 2;
00113         return 0;
00114 }
00115 
00116 
00117 int eloop_register_read_sock(int sock, eloop_sock_handler handler,
00118                              void *eloop_data, void *user_data)
00119 {
00120         WSAEVENT event;
00121         struct eloop_sock *tmp;
00122 
00123         if (eloop_prepare_handles())
00124                 return -1;
00125 
00126         event = WSACreateEvent();
00127         if (event == WSA_INVALID_EVENT) {
00128                 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
00129                 return -1;
00130         }
00131 
00132         if (WSAEventSelect(sock, event, FD_READ)) {
00133                 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
00134                 WSACloseEvent(event);
00135                 return -1;
00136         }
00137         tmp = os_realloc(eloop.readers,
00138                          (eloop.reader_count + 1) * sizeof(struct eloop_sock));
00139         if (tmp == NULL) {
00140                 WSAEventSelect(sock, event, 0);
00141                 WSACloseEvent(event);
00142                 return -1;
00143         }
00144 
00145         tmp[eloop.reader_count].sock = sock;
00146         tmp[eloop.reader_count].eloop_data = eloop_data;
00147         tmp[eloop.reader_count].user_data = user_data;
00148         tmp[eloop.reader_count].handler = handler;
00149         tmp[eloop.reader_count].event = event;
00150         eloop.reader_count++;
00151         eloop.readers = tmp;
00152         if (sock > eloop.max_sock)
00153                 eloop.max_sock = sock;
00154         eloop.reader_table_changed = 1;
00155 
00156         return 0;
00157 }
00158 
00159 
00160 void eloop_unregister_read_sock(int sock)
00161 {
00162         size_t i;
00163 
00164         if (eloop.readers == NULL || eloop.reader_count == 0)
00165                 return;
00166 
00167         for (i = 0; i < eloop.reader_count; i++) {
00168                 if (eloop.readers[i].sock == sock)
00169                         break;
00170         }
00171         if (i == eloop.reader_count)
00172                 return;
00173 
00174         WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
00175         WSACloseEvent(eloop.readers[i].event);
00176 
00177         if (i != eloop.reader_count - 1) {
00178                 os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
00179                            (eloop.reader_count - i - 1) *
00180                            sizeof(struct eloop_sock));
00181         }
00182         eloop.reader_count--;
00183         eloop.reader_table_changed = 1;
00184 }
00185 
00186 
00187 int eloop_register_event(void *event, size_t event_size,
00188                          eloop_event_handler handler,
00189                          void *eloop_data, void *user_data)
00190 {
00191         struct eloop_event *tmp;
00192         HANDLE h = event;
00193 
00194         if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
00195                 return -1;
00196 
00197         if (eloop_prepare_handles())
00198                 return -1;
00199 
00200         tmp = os_realloc(eloop.events,
00201                          (eloop.event_count + 1) * sizeof(struct eloop_event));
00202         if (tmp == NULL)
00203                 return -1;
00204 
00205         tmp[eloop.event_count].eloop_data = eloop_data;
00206         tmp[eloop.event_count].user_data = user_data;
00207         tmp[eloop.event_count].handler = handler;
00208         tmp[eloop.event_count].event = h;
00209         eloop.event_count++;
00210         eloop.events = tmp;
00211 
00212         return 0;
00213 }
00214 
00215 
00216 void eloop_unregister_event(void *event, size_t event_size)
00217 {
00218         size_t i;
00219         HANDLE h = event;
00220 
00221         if (eloop.events == NULL || eloop.event_count == 0 ||
00222             event_size != sizeof(HANDLE))
00223                 return;
00224 
00225         for (i = 0; i < eloop.event_count; i++) {
00226                 if (eloop.events[i].event == h)
00227                         break;
00228         }
00229         if (i == eloop.event_count)
00230                 return;
00231 
00232         if (i != eloop.event_count - 1) {
00233                 os_memmove(&eloop.events[i], &eloop.events[i + 1],
00234                            (eloop.event_count - i - 1) *
00235                            sizeof(struct eloop_event));
00236         }
00237         eloop.event_count--;
00238 }
00239 
00240 
00241 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
00242                            eloop_timeout_handler handler,
00243                            void *eloop_data, void *user_data)
00244 {
00245         struct eloop_timeout *timeout, *tmp, *prev;
00246 
00247         timeout = os_malloc(sizeof(*timeout));
00248         if (timeout == NULL)
00249                 return -1;
00250         os_get_time(&timeout->time);
00251         timeout->time.sec += secs;
00252         timeout->time.usec += usecs;
00253         while (timeout->time.usec >= 1000000) {
00254                 timeout->time.sec++;
00255                 timeout->time.usec -= 1000000;
00256         }
00257         timeout->eloop_data = eloop_data;
00258         timeout->user_data = user_data;
00259         timeout->handler = handler;
00260         timeout->next = NULL;
00261 
00262         if (eloop.timeout == NULL) {
00263                 eloop.timeout = timeout;
00264                 return 0;
00265         }
00266 
00267         prev = NULL;
00268         tmp = eloop.timeout;
00269         while (tmp != NULL) {
00270                 if (os_time_before(&timeout->time, &tmp->time))
00271                         break;
00272                 prev = tmp;
00273                 tmp = tmp->next;
00274         }
00275 
00276         if (prev == NULL) {
00277                 timeout->next = eloop.timeout;
00278                 eloop.timeout = timeout;
00279         } else {
00280                 timeout->next = prev->next;
00281                 prev->next = timeout;
00282         }
00283 
00284         return 0;
00285 }
00286 
00287 
00288 int eloop_cancel_timeout(eloop_timeout_handler handler,
00289                          void *eloop_data, void *user_data)
00290 {
00291         struct eloop_timeout *timeout, *prev, *next;
00292         int removed = 0;
00293 
00294         prev = NULL;
00295         timeout = eloop.timeout;
00296         while (timeout != NULL) {
00297                 next = timeout->next;
00298 
00299                 if (timeout->handler == handler &&
00300                     (timeout->eloop_data == eloop_data ||
00301                      eloop_data == ELOOP_ALL_CTX) &&
00302                     (timeout->user_data == user_data ||
00303                      user_data == ELOOP_ALL_CTX)) {
00304                         if (prev == NULL)
00305                                 eloop.timeout = next;
00306                         else
00307                                 prev->next = next;
00308                         os_free(timeout);
00309                         removed++;
00310                 } else
00311                         prev = timeout;
00312 
00313                 timeout = next;
00314         }
00315 
00316         return removed;
00317 }
00318 
00319 
00320 int eloop_is_timeout_registered(eloop_timeout_handler handler,
00321                                 void *eloop_data, void *user_data)
00322 {
00323         struct eloop_timeout *tmp;
00324 
00325         tmp = eloop.timeout;
00326         while (tmp != NULL) {
00327                 if (tmp->handler == handler &&
00328                     tmp->eloop_data == eloop_data &&
00329                     tmp->user_data == user_data)
00330                         return 1;
00331 
00332                 tmp = tmp->next;
00333         }
00334 
00335         return 0;
00336 }
00337 
00338 
00339 /* TODO: replace with suitable signal handler */
00340 #if 0
00341 static void eloop_handle_signal(int sig)
00342 {
00343         int i;
00344 
00345         eloop.signaled++;
00346         for (i = 0; i < eloop.signal_count; i++) {
00347                 if (eloop.signals[i].sig == sig) {
00348                         eloop.signals[i].signaled++;
00349                         break;
00350                 }
00351         }
00352 }
00353 #endif
00354 
00355 
00356 static void eloop_process_pending_signals(void)
00357 {
00358         int i;
00359 
00360         if (eloop.signaled == 0)
00361                 return;
00362         eloop.signaled = 0;
00363 
00364         if (eloop.pending_terminate) {
00365                 eloop.pending_terminate = 0;
00366         }
00367 
00368         for (i = 0; i < eloop.signal_count; i++) {
00369                 if (eloop.signals[i].signaled) {
00370                         eloop.signals[i].signaled = 0;
00371                         eloop.signals[i].handler(eloop.signals[i].sig,
00372                                                  eloop.signals[i].user_data);
00373                 }
00374         }
00375 
00376         if (eloop.term_signal.signaled) {
00377                 eloop.term_signal.signaled = 0;
00378                 eloop.term_signal.handler(eloop.term_signal.sig,
00379                                           eloop.term_signal.user_data);
00380         }
00381 }
00382 
00383 
00384 int eloop_register_signal(int sig, eloop_signal_handler handler,
00385                           void *user_data)
00386 {
00387         struct eloop_signal *tmp;
00388 
00389         tmp = os_realloc(eloop.signals,
00390                          (eloop.signal_count + 1) *
00391                          sizeof(struct eloop_signal));
00392         if (tmp == NULL)
00393                 return -1;
00394 
00395         tmp[eloop.signal_count].sig = sig;
00396         tmp[eloop.signal_count].user_data = user_data;
00397         tmp[eloop.signal_count].handler = handler;
00398         tmp[eloop.signal_count].signaled = 0;
00399         eloop.signal_count++;
00400         eloop.signals = tmp;
00401 
00402         /* TODO: register signal handler */
00403 
00404         return 0;
00405 }
00406 
00407 
00408 #ifndef _WIN32_WCE
00409 static BOOL eloop_handle_console_ctrl(DWORD type)
00410 {
00411         switch (type) {
00412         case CTRL_C_EVENT:
00413         case CTRL_BREAK_EVENT:
00414                 eloop.signaled++;
00415                 eloop.term_signal.signaled++;
00416                 SetEvent(eloop.term_event);
00417                 return TRUE;
00418         default:
00419                 return FALSE;
00420         }
00421 }
00422 #endif /* _WIN32_WCE */
00423 
00424 
00425 int eloop_register_signal_terminate(eloop_signal_handler handler,
00426                                     void *user_data)
00427 {
00428 #ifndef _WIN32_WCE
00429         if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
00430                                   TRUE) == 0) {
00431                 printf("SetConsoleCtrlHandler() failed: %d\n",
00432                        (int) GetLastError());
00433                 return -1;
00434         }
00435 #endif /* _WIN32_WCE */
00436 
00437         eloop.term_signal.handler = handler;
00438         eloop.term_signal.user_data = user_data;
00439                 
00440         return 0;
00441 }
00442 
00443 
00444 int eloop_register_signal_reconfig(eloop_signal_handler handler,
00445                                    void *user_data)
00446 {
00447         /* TODO */
00448         return 0;
00449 }
00450 
00451 
00452 void eloop_run(void)
00453 {
00454         struct os_time tv, now;
00455         DWORD count, ret, timeout, err;
00456         size_t i;
00457 
00458         while (!eloop.terminate &&
00459                (eloop.timeout || eloop.reader_count > 0 ||
00460                 eloop.event_count > 0)) {
00461                 tv.sec = tv.usec = 0;
00462                 if (eloop.timeout) {
00463                         os_get_time(&now);
00464                         if (os_time_before(&now, &eloop.timeout->time))
00465                                 os_time_sub(&eloop.timeout->time, &now, &tv);
00466                 }
00467 
00468                 count = 0;
00469                 for (i = 0; i < eloop.event_count; i++)
00470                         eloop.handles[count++] = eloop.events[i].event;
00471 
00472                 for (i = 0; i < eloop.reader_count; i++)
00473                         eloop.handles[count++] = eloop.readers[i].event;
00474 
00475                 if (eloop.term_event)
00476                         eloop.handles[count++] = eloop.term_event;
00477 
00478                 if (eloop.timeout)
00479                         timeout = tv.sec * 1000 + tv.usec / 1000;
00480                 else
00481                         timeout = INFINITE;
00482 
00483                 if (count > MAXIMUM_WAIT_OBJECTS) {
00484                         printf("WaitForMultipleObjects: Too many events: "
00485                                "%d > %d (ignoring extra events)\n",
00486                                (int) count, MAXIMUM_WAIT_OBJECTS);
00487                         count = MAXIMUM_WAIT_OBJECTS;
00488                 }
00489 #ifdef _WIN32_WCE
00490                 ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
00491                                              timeout);
00492 #else /* _WIN32_WCE */
00493                 ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
00494                                                timeout, TRUE);
00495 #endif /* _WIN32_WCE */
00496                 err = GetLastError();
00497 
00498                 eloop_process_pending_signals();
00499 
00500                 /* check if some registered timeouts have occurred */
00501                 if (eloop.timeout) {
00502                         struct eloop_timeout *tmp;
00503 
00504                         os_get_time(&now);
00505                         if (!os_time_before(&now, &eloop.timeout->time)) {
00506                                 tmp = eloop.timeout;
00507                                 eloop.timeout = eloop.timeout->next;
00508                                 tmp->handler(tmp->eloop_data,
00509                                              tmp->user_data);
00510                                 os_free(tmp);
00511                         }
00512 
00513                 }
00514 
00515                 if (ret == WAIT_FAILED) {
00516                         printf("WaitForMultipleObjects(count=%d) failed: %d\n",
00517                                (int) count, (int) err);
00518                         os_sleep(1, 0);
00519                         continue;
00520                 }
00521 
00522 #ifndef _WIN32_WCE
00523                 if (ret == WAIT_IO_COMPLETION)
00524                         continue;
00525 #endif /* _WIN32_WCE */
00526 
00527                 if (ret == WAIT_TIMEOUT)
00528                         continue;
00529 
00530                 while (ret >= WAIT_OBJECT_0 &&
00531                        ret < WAIT_OBJECT_0 + eloop.event_count) {
00532                         eloop.events[ret].handler(
00533                                 eloop.events[ret].eloop_data,
00534                                 eloop.events[ret].user_data);
00535                         ret = WaitForMultipleObjects(eloop.event_count,
00536                                                      eloop.handles, FALSE, 0);
00537                 }
00538 
00539                 eloop.reader_table_changed = 0;
00540                 for (i = 0; i < eloop.reader_count; i++) {
00541                         WSANETWORKEVENTS events;
00542                         if (WSAEnumNetworkEvents(eloop.readers[i].sock,
00543                                                  eloop.readers[i].event,
00544                                                  &events) == 0 &&
00545                             (events.lNetworkEvents & FD_READ)) {
00546                                 eloop.readers[i].handler(
00547                                         eloop.readers[i].sock,
00548                                         eloop.readers[i].eloop_data,
00549                                         eloop.readers[i].user_data);
00550                                 if (eloop.reader_table_changed)
00551                                         break;
00552                         }
00553                 }
00554         }
00555 }
00556 
00557 
00558 void eloop_terminate(void)
00559 {
00560         eloop.terminate = 1;
00561         SetEvent(eloop.term_event);
00562 }
00563 
00564 
00565 void eloop_destroy(void)
00566 {
00567         struct eloop_timeout *timeout, *prev;
00568 
00569         timeout = eloop.timeout;
00570         while (timeout != NULL) {
00571                 prev = timeout;
00572                 timeout = timeout->next;
00573                 os_free(prev);
00574         }
00575         os_free(eloop.readers);
00576         os_free(eloop.signals);
00577         if (eloop.term_event)
00578                 CloseHandle(eloop.term_event);
00579         os_free(eloop.handles);
00580         eloop.handles = NULL;
00581         os_free(eloop.events);
00582         eloop.events = NULL;
00583 }
00584 
00585 
00586 int eloop_terminated(void)
00587 {
00588         return eloop.terminate;
00589 }
00590 
00591 
00592 void eloop_wait_for_read_sock(int sock)
00593 {
00594         WSAEVENT event;
00595 
00596         event = WSACreateEvent();
00597         if (event == WSA_INVALID_EVENT) {
00598                 printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
00599                 return;
00600         }
00601 
00602         if (WSAEventSelect(sock, event, FD_READ)) {
00603                 printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
00604                 WSACloseEvent(event);
00605                 return ;
00606         }
00607 
00608         WaitForSingleObject(event, INFINITE);
00609         WSAEventSelect(sock, event, 0);
00610         WSACloseEvent(event);
00611 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:37