~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to eloop_win.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Event loop based on Windows events and WaitForMultipleObjects
 
3
 * Copyright (c) 2002-2006, Jouni Malinen <j@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
#include <winsock2.h>
 
17
 
 
18
#include "common.h"
 
19
#include "eloop.h"
 
20
 
 
21
 
 
22
struct eloop_sock {
 
23
        int sock;
 
24
        void *eloop_data;
 
25
        void *user_data;
 
26
        eloop_sock_handler handler;
 
27
        WSAEVENT event;
 
28
};
 
29
 
 
30
struct eloop_event {
 
31
        void *eloop_data;
 
32
        void *user_data;
 
33
        eloop_event_handler handler;
 
34
        HANDLE event;
 
35
};
 
36
 
 
37
struct eloop_timeout {
 
38
        struct os_time time;
 
39
        void *eloop_data;
 
40
        void *user_data;
 
41
        eloop_timeout_handler handler;
 
42
        struct eloop_timeout *next;
 
43
};
 
44
 
 
45
struct eloop_signal {
 
46
        int sig;
 
47
        void *user_data;
 
48
        eloop_signal_handler handler;
 
49
        int signaled;
 
50
};
 
51
 
 
52
struct eloop_data {
 
53
        void *user_data;
 
54
 
 
55
        int max_sock;
 
56
        size_t reader_count;
 
57
        struct eloop_sock *readers;
 
58
 
 
59
        size_t event_count;
 
60
        struct eloop_event *events;
 
61
 
 
62
        struct eloop_timeout *timeout;
 
63
 
 
64
        int signal_count;
 
65
        struct eloop_signal *signals;
 
66
        int signaled;
 
67
        int pending_terminate;
 
68
 
 
69
        int terminate;
 
70
        int reader_table_changed;
 
71
 
 
72
        struct eloop_signal term_signal;
 
73
        HANDLE term_event;
 
74
 
 
75
        HANDLE *handles;
 
76
        size_t num_handles;
 
77
};
 
78
 
 
79
static struct eloop_data eloop;
 
80
 
 
81
 
 
82
int eloop_init(void *user_data)
 
83
{
 
84
        os_memset(&eloop, 0, sizeof(eloop));
 
85
        eloop.user_data = user_data;
 
86
        eloop.num_handles = 1;
 
87
        eloop.handles = os_malloc(eloop.num_handles *
 
88
                                  sizeof(eloop.handles[0]));
 
89
        if (eloop.handles == NULL)
 
90
                return -1;
 
91
 
 
92
        eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 
93
        if (eloop.term_event == NULL) {
 
94
                printf("CreateEvent() failed: %d\n",
 
95
                       (int) GetLastError());
 
96
                os_free(eloop.handles);
 
97
                return -1;
 
98
        }
 
99
 
 
100
        return 0;
 
101
}
 
102
 
 
103
 
 
104
static int eloop_prepare_handles(void)
 
105
{
 
106
        HANDLE *n;
 
107
 
 
108
        if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8)
 
109
                return 0;
 
110
        n = os_realloc(eloop.handles,
 
111
                       eloop.num_handles * 2 * sizeof(eloop.handles[0]));
 
112
        if (n == NULL)
 
113
                return -1;
 
114
        eloop.handles = n;
 
115
        eloop.num_handles *= 2;
 
116
        return 0;
 
117
}
 
118
 
 
119
 
 
120
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
 
121
                             void *eloop_data, void *user_data)
 
122
{
 
123
        WSAEVENT event;
 
124
        struct eloop_sock *tmp;
 
125
 
 
126
        if (eloop_prepare_handles())
 
127
                return -1;
 
128
 
 
129
        event = WSACreateEvent();
 
130
        if (event == WSA_INVALID_EVENT) {
 
131
                printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
 
132
                return -1;
 
133
        }
 
134
 
 
135
        if (WSAEventSelect(sock, event, FD_READ)) {
 
136
                printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
 
137
                WSACloseEvent(event);
 
138
                return -1;
 
139
        }
 
140
        tmp = os_realloc(eloop.readers,
 
141
                         (eloop.reader_count + 1) * sizeof(struct eloop_sock));
 
142
        if (tmp == NULL) {
 
143
                WSAEventSelect(sock, event, 0);
 
144
                WSACloseEvent(event);
 
145
                return -1;
 
146
        }
 
147
 
 
148
        tmp[eloop.reader_count].sock = sock;
 
149
        tmp[eloop.reader_count].eloop_data = eloop_data;
 
150
        tmp[eloop.reader_count].user_data = user_data;
 
151
        tmp[eloop.reader_count].handler = handler;
 
152
        tmp[eloop.reader_count].event = event;
 
153
        eloop.reader_count++;
 
154
        eloop.readers = tmp;
 
155
        if (sock > eloop.max_sock)
 
156
                eloop.max_sock = sock;
 
157
        eloop.reader_table_changed = 1;
 
158
 
 
159
        return 0;
 
160
}
 
161
 
 
162
 
 
163
void eloop_unregister_read_sock(int sock)
 
164
{
 
165
        size_t i;
 
166
 
 
167
        if (eloop.readers == NULL || eloop.reader_count == 0)
 
168
                return;
 
169
 
 
170
        for (i = 0; i < eloop.reader_count; i++) {
 
171
                if (eloop.readers[i].sock == sock)
 
172
                        break;
 
173
        }
 
174
        if (i == eloop.reader_count)
 
175
                return;
 
176
 
 
177
        WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0);
 
178
        WSACloseEvent(eloop.readers[i].event);
 
179
 
 
180
        if (i != eloop.reader_count - 1) {
 
181
                os_memmove(&eloop.readers[i], &eloop.readers[i + 1],
 
182
                           (eloop.reader_count - i - 1) *
 
183
                           sizeof(struct eloop_sock));
 
184
        }
 
185
        eloop.reader_count--;
 
186
        eloop.reader_table_changed = 1;
 
187
}
 
188
 
 
189
 
 
190
int eloop_register_event(void *event, size_t event_size,
 
191
                         eloop_event_handler handler,
 
192
                         void *eloop_data, void *user_data)
 
193
{
 
194
        struct eloop_event *tmp;
 
195
        HANDLE h = event;
 
196
 
 
197
        if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE)
 
198
                return -1;
 
199
 
 
200
        if (eloop_prepare_handles())
 
201
                return -1;
 
202
 
 
203
        tmp = os_realloc(eloop.events,
 
204
                         (eloop.event_count + 1) * sizeof(struct eloop_event));
 
205
        if (tmp == NULL)
 
206
                return -1;
 
207
 
 
208
        tmp[eloop.event_count].eloop_data = eloop_data;
 
209
        tmp[eloop.event_count].user_data = user_data;
 
210
        tmp[eloop.event_count].handler = handler;
 
211
        tmp[eloop.event_count].event = h;
 
212
        eloop.event_count++;
 
213
        eloop.events = tmp;
 
214
 
 
215
        return 0;
 
216
}
 
217
 
 
218
 
 
219
void eloop_unregister_event(void *event, size_t event_size)
 
220
{
 
221
        size_t i;
 
222
        HANDLE h = event;
 
223
 
 
224
        if (eloop.events == NULL || eloop.event_count == 0 ||
 
225
            event_size != sizeof(HANDLE))
 
226
                return;
 
227
 
 
228
        for (i = 0; i < eloop.event_count; i++) {
 
229
                if (eloop.events[i].event == h)
 
230
                        break;
 
231
        }
 
232
        if (i == eloop.event_count)
 
233
                return;
 
234
 
 
235
        if (i != eloop.event_count - 1) {
 
236
                os_memmove(&eloop.events[i], &eloop.events[i + 1],
 
237
                           (eloop.event_count - i - 1) *
 
238
                           sizeof(struct eloop_event));
 
239
        }
 
240
        eloop.event_count--;
 
241
}
 
242
 
 
243
 
 
244
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
 
245
                           eloop_timeout_handler handler,
 
246
                           void *eloop_data, void *user_data)
 
247
{
 
248
        struct eloop_timeout *timeout, *tmp, *prev;
 
249
 
 
250
        timeout = os_malloc(sizeof(*timeout));
 
251
        if (timeout == NULL)
 
252
                return -1;
 
253
        os_get_time(&timeout->time);
 
254
        timeout->time.sec += secs;
 
255
        timeout->time.usec += usecs;
 
256
        while (timeout->time.usec >= 1000000) {
 
257
                timeout->time.sec++;
 
258
                timeout->time.usec -= 1000000;
 
259
        }
 
260
        timeout->eloop_data = eloop_data;
 
261
        timeout->user_data = user_data;
 
262
        timeout->handler = handler;
 
263
        timeout->next = NULL;
 
264
 
 
265
        if (eloop.timeout == NULL) {
 
266
                eloop.timeout = timeout;
 
267
                return 0;
 
268
        }
 
269
 
 
270
        prev = NULL;
 
271
        tmp = eloop.timeout;
 
272
        while (tmp != NULL) {
 
273
                if (os_time_before(&timeout->time, &tmp->time))
 
274
                        break;
 
275
                prev = tmp;
 
276
                tmp = tmp->next;
 
277
        }
 
278
 
 
279
        if (prev == NULL) {
 
280
                timeout->next = eloop.timeout;
 
281
                eloop.timeout = timeout;
 
282
        } else {
 
283
                timeout->next = prev->next;
 
284
                prev->next = timeout;
 
285
        }
 
286
 
 
287
        return 0;
 
288
}
 
289
 
 
290
 
 
291
int eloop_cancel_timeout(eloop_timeout_handler handler,
 
292
                         void *eloop_data, void *user_data)
 
293
{
 
294
        struct eloop_timeout *timeout, *prev, *next;
 
295
        int removed = 0;
 
296
 
 
297
        prev = NULL;
 
298
        timeout = eloop.timeout;
 
299
        while (timeout != NULL) {
 
300
                next = timeout->next;
 
301
 
 
302
                if (timeout->handler == handler &&
 
303
                    (timeout->eloop_data == eloop_data ||
 
304
                     eloop_data == ELOOP_ALL_CTX) &&
 
305
                    (timeout->user_data == user_data ||
 
306
                     user_data == ELOOP_ALL_CTX)) {
 
307
                        if (prev == NULL)
 
308
                                eloop.timeout = next;
 
309
                        else
 
310
                                prev->next = next;
 
311
                        os_free(timeout);
 
312
                        removed++;
 
313
                } else
 
314
                        prev = timeout;
 
315
 
 
316
                timeout = next;
 
317
        }
 
318
 
 
319
        return removed;
 
320
}
 
321
 
 
322
 
 
323
/* TODO: replace with suitable signal handler */
 
324
#if 0
 
325
static void eloop_handle_signal(int sig)
 
326
{
 
327
        int i;
 
328
 
 
329
        eloop.signaled++;
 
330
        for (i = 0; i < eloop.signal_count; i++) {
 
331
                if (eloop.signals[i].sig == sig) {
 
332
                        eloop.signals[i].signaled++;
 
333
                        break;
 
334
                }
 
335
        }
 
336
}
 
337
#endif
 
338
 
 
339
 
 
340
static void eloop_process_pending_signals(void)
 
341
{
 
342
        int i;
 
343
 
 
344
        if (eloop.signaled == 0)
 
345
                return;
 
346
        eloop.signaled = 0;
 
347
 
 
348
        if (eloop.pending_terminate) {
 
349
                eloop.pending_terminate = 0;
 
350
        }
 
351
 
 
352
        for (i = 0; i < eloop.signal_count; i++) {
 
353
                if (eloop.signals[i].signaled) {
 
354
                        eloop.signals[i].signaled = 0;
 
355
                        eloop.signals[i].handler(eloop.signals[i].sig,
 
356
                                                 eloop.user_data,
 
357
                                                 eloop.signals[i].user_data);
 
358
                }
 
359
        }
 
360
 
 
361
        if (eloop.term_signal.signaled) {
 
362
                eloop.term_signal.signaled = 0;
 
363
                eloop.term_signal.handler(eloop.term_signal.sig,
 
364
                                          eloop.user_data,
 
365
                                          eloop.term_signal.user_data);
 
366
        }
 
367
}
 
368
 
 
369
 
 
370
int eloop_register_signal(int sig, eloop_signal_handler handler,
 
371
                          void *user_data)
 
372
{
 
373
        struct eloop_signal *tmp;
 
374
 
 
375
        tmp = os_realloc(eloop.signals,
 
376
                         (eloop.signal_count + 1) *
 
377
                         sizeof(struct eloop_signal));
 
378
        if (tmp == NULL)
 
379
                return -1;
 
380
 
 
381
        tmp[eloop.signal_count].sig = sig;
 
382
        tmp[eloop.signal_count].user_data = user_data;
 
383
        tmp[eloop.signal_count].handler = handler;
 
384
        tmp[eloop.signal_count].signaled = 0;
 
385
        eloop.signal_count++;
 
386
        eloop.signals = tmp;
 
387
 
 
388
        /* TODO: register signal handler */
 
389
 
 
390
        return 0;
 
391
}
 
392
 
 
393
 
 
394
#ifndef _WIN32_WCE
 
395
static BOOL eloop_handle_console_ctrl(DWORD type)
 
396
{
 
397
        switch (type) {
 
398
        case CTRL_C_EVENT:
 
399
        case CTRL_BREAK_EVENT:
 
400
                eloop.signaled++;
 
401
                eloop.term_signal.signaled++;
 
402
                SetEvent(eloop.term_event);
 
403
                return TRUE;
 
404
        default:
 
405
                return FALSE;
 
406
        }
 
407
}
 
408
#endif /* _WIN32_WCE */
 
409
 
 
410
 
 
411
int eloop_register_signal_terminate(eloop_signal_handler handler,
 
412
                                    void *user_data)
 
413
{
 
414
#ifndef _WIN32_WCE
 
415
        if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl,
 
416
                                  TRUE) == 0) {
 
417
                printf("SetConsoleCtrlHandler() failed: %d\n",
 
418
                       (int) GetLastError());
 
419
                return -1;
 
420
        }
 
421
#endif /* _WIN32_WCE */
 
422
 
 
423
        eloop.term_signal.handler = handler;
 
424
        eloop.term_signal.user_data = user_data;
 
425
                
 
426
        return 0;
 
427
}
 
428
 
 
429
 
 
430
int eloop_register_signal_reconfig(eloop_signal_handler handler,
 
431
                                   void *user_data)
 
432
{
 
433
        /* TODO */
 
434
        return 0;
 
435
}
 
436
 
 
437
 
 
438
void eloop_run(void)
 
439
{
 
440
        struct os_time tv, now;
 
441
        DWORD count, ret, timeout, err;
 
442
        size_t i;
 
443
 
 
444
        while (!eloop.terminate &&
 
445
               (eloop.timeout || eloop.reader_count > 0 ||
 
446
                eloop.event_count > 0)) {
 
447
                if (eloop.timeout) {
 
448
                        os_get_time(&now);
 
449
                        if (os_time_before(&now, &eloop.timeout->time))
 
450
                                os_time_sub(&eloop.timeout->time, &now, &tv);
 
451
                        else
 
452
                                tv.sec = tv.usec = 0;
 
453
                }
 
454
 
 
455
                count = 0;
 
456
                for (i = 0; i < eloop.event_count; i++)
 
457
                        eloop.handles[count++] = eloop.events[i].event;
 
458
 
 
459
                for (i = 0; i < eloop.reader_count; i++)
 
460
                        eloop.handles[count++] = eloop.readers[i].event;
 
461
 
 
462
                if (eloop.term_event)
 
463
                        eloop.handles[count++] = eloop.term_event;
 
464
 
 
465
                if (eloop.timeout)
 
466
                        timeout = tv.sec * 1000 + tv.usec / 1000;
 
467
                else
 
468
                        timeout = INFINITE;
 
469
 
 
470
                if (count > MAXIMUM_WAIT_OBJECTS) {
 
471
                        printf("WaitForMultipleObjects: Too many events: "
 
472
                               "%d > %d (ignoring extra events)\n",
 
473
                               (int) count, MAXIMUM_WAIT_OBJECTS);
 
474
                        count = MAXIMUM_WAIT_OBJECTS;
 
475
                }
 
476
#ifdef _WIN32_WCE
 
477
                ret = WaitForMultipleObjects(count, eloop.handles, FALSE,
 
478
                                             timeout);
 
479
#else /* _WIN32_WCE */
 
480
                ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE,
 
481
                                               timeout, TRUE);
 
482
#endif /* _WIN32_WCE */
 
483
                err = GetLastError();
 
484
 
 
485
                eloop_process_pending_signals();
 
486
 
 
487
                /* check if some registered timeouts have occurred */
 
488
                if (eloop.timeout) {
 
489
                        struct eloop_timeout *tmp;
 
490
 
 
491
                        os_get_time(&now);
 
492
                        if (!os_time_before(&now, &eloop.timeout->time)) {
 
493
                                tmp = eloop.timeout;
 
494
                                eloop.timeout = eloop.timeout->next;
 
495
                                tmp->handler(tmp->eloop_data,
 
496
                                             tmp->user_data);
 
497
                                os_free(tmp);
 
498
                        }
 
499
 
 
500
                }
 
501
 
 
502
                if (ret == WAIT_FAILED) {
 
503
                        printf("WaitForMultipleObjects(count=%d) failed: %d\n",
 
504
                               (int) count, (int) err);
 
505
                        os_sleep(1, 0);
 
506
                        continue;
 
507
                }
 
508
 
 
509
#ifndef _WIN32_WCE
 
510
                if (ret == WAIT_IO_COMPLETION)
 
511
                        continue;
 
512
#endif /* _WIN32_WCE */
 
513
 
 
514
                if (ret == WAIT_TIMEOUT)
 
515
                        continue;
 
516
 
 
517
                while (ret >= WAIT_OBJECT_0 &&
 
518
                       ret < WAIT_OBJECT_0 + eloop.event_count) {
 
519
                        eloop.events[ret].handler(
 
520
                                eloop.events[ret].eloop_data,
 
521
                                eloop.events[ret].user_data);
 
522
                        ret = WaitForMultipleObjects(eloop.event_count,
 
523
                                                     eloop.handles, FALSE, 0);
 
524
                }
 
525
 
 
526
                eloop.reader_table_changed = 0;
 
527
                for (i = 0; i < eloop.reader_count; i++) {
 
528
                        WSANETWORKEVENTS events;
 
529
                        if (WSAEnumNetworkEvents(eloop.readers[i].sock,
 
530
                                                 eloop.readers[i].event,
 
531
                                                 &events) == 0 &&
 
532
                            (events.lNetworkEvents & FD_READ)) {
 
533
                                eloop.readers[i].handler(
 
534
                                        eloop.readers[i].sock,
 
535
                                        eloop.readers[i].eloop_data,
 
536
                                        eloop.readers[i].user_data);
 
537
                                if (eloop.reader_table_changed)
 
538
                                        break;
 
539
                        }
 
540
                }
 
541
        }
 
542
}
 
543
 
 
544
 
 
545
void eloop_terminate(void)
 
546
{
 
547
        eloop.terminate = 1;
 
548
        SetEvent(eloop.term_event);
 
549
}
 
550
 
 
551
 
 
552
void eloop_destroy(void)
 
553
{
 
554
        struct eloop_timeout *timeout, *prev;
 
555
 
 
556
        timeout = eloop.timeout;
 
557
        while (timeout != NULL) {
 
558
                prev = timeout;
 
559
                timeout = timeout->next;
 
560
                os_free(prev);
 
561
        }
 
562
        os_free(eloop.readers);
 
563
        os_free(eloop.signals);
 
564
        if (eloop.term_event)
 
565
                CloseHandle(eloop.term_event);
 
566
        os_free(eloop.handles);
 
567
        eloop.handles = NULL;
 
568
        os_free(eloop.events);
 
569
        eloop.events = NULL;
 
570
}
 
571
 
 
572
 
 
573
int eloop_terminated(void)
 
574
{
 
575
        return eloop.terminate;
 
576
}
 
577
 
 
578
 
 
579
void eloop_wait_for_read_sock(int sock)
 
580
{
 
581
        WSAEVENT event;
 
582
 
 
583
        event = WSACreateEvent();
 
584
        if (event == WSA_INVALID_EVENT) {
 
585
                printf("WSACreateEvent() failed: %d\n", WSAGetLastError());
 
586
                return;
 
587
        }
 
588
 
 
589
        if (WSAEventSelect(sock, event, FD_READ)) {
 
590
                printf("WSAEventSelect() failed: %d\n", WSAGetLastError());
 
591
                WSACloseEvent(event);
 
592
                return ;
 
593
        }
 
594
 
 
595
        WaitForSingleObject(event, INFINITE);
 
596
        WSAEventSelect(sock, event, 0);
 
597
        WSACloseEvent(event);
 
598
}
 
599
 
 
600
 
 
601
void * eloop_get_user_data(void)
 
602
{
 
603
        return eloop.user_data;
 
604
}