~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to eloop.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Event loop based on select() loop
3
 
 * Copyright (c) 2002-2005, 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
 
 
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
 
        eloop_sock_handler handler;
26
 
};
27
 
 
28
 
struct eloop_timeout {
29
 
        struct os_time time;
30
 
        void *eloop_data;
31
 
        void *user_data;
32
 
        eloop_timeout_handler handler;
33
 
        struct eloop_timeout *next;
34
 
};
35
 
 
36
 
struct eloop_signal {
37
 
        int sig;
38
 
        void *user_data;
39
 
        eloop_signal_handler handler;
40
 
        int signaled;
41
 
};
42
 
 
43
 
struct eloop_sock_table {
44
 
        int count;
45
 
        struct eloop_sock *table;
46
 
        int changed;
47
 
};
48
 
 
49
 
struct eloop_data {
50
 
        void *user_data;
51
 
 
52
 
        int max_sock;
53
 
 
54
 
        struct eloop_sock_table readers;
55
 
        struct eloop_sock_table writers;
56
 
        struct eloop_sock_table exceptions;
57
 
 
58
 
        struct eloop_timeout *timeout;
59
 
 
60
 
        int signal_count;
61
 
        struct eloop_signal *signals;
62
 
        int signaled;
63
 
        int pending_terminate;
64
 
 
65
 
        int terminate;
66
 
        int reader_table_changed;
67
 
};
68
 
 
69
 
static struct eloop_data eloop;
70
 
 
71
 
 
72
 
int eloop_init(void *user_data)
73
 
{
74
 
        os_memset(&eloop, 0, sizeof(eloop));
75
 
        eloop.user_data = user_data;
76
 
        return 0;
77
 
}
78
 
 
79
 
 
80
 
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
81
 
                                     int sock, eloop_sock_handler handler,
82
 
                                     void *eloop_data, void *user_data)
83
 
{
84
 
        struct eloop_sock *tmp;
85
 
 
86
 
        if (table == NULL)
87
 
                return -1;
88
 
 
89
 
        tmp = (struct eloop_sock *)
90
 
                os_realloc(table->table,
91
 
                           (table->count + 1) * sizeof(struct eloop_sock));
92
 
        if (tmp == NULL)
93
 
                return -1;
94
 
 
95
 
        tmp[table->count].sock = sock;
96
 
        tmp[table->count].eloop_data = eloop_data;
97
 
        tmp[table->count].user_data = user_data;
98
 
        tmp[table->count].handler = handler;
99
 
        table->count++;
100
 
        table->table = tmp;
101
 
        if (sock > eloop.max_sock)
102
 
                eloop.max_sock = sock;
103
 
        table->changed = 1;
104
 
 
105
 
        return 0;
106
 
}
107
 
 
108
 
 
109
 
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
110
 
                                         int sock)
111
 
{
112
 
        int i;
113
 
 
114
 
        if (table == NULL || table->table == NULL || table->count == 0)
115
 
                return;
116
 
 
117
 
        for (i = 0; i < table->count; i++) {
118
 
                if (table->table[i].sock == sock)
119
 
                        break;
120
 
        }
121
 
        if (i == table->count)
122
 
                return;
123
 
        if (i != table->count - 1) {
124
 
                os_memmove(&table->table[i], &table->table[i + 1],
125
 
                           (table->count - i - 1) *
126
 
                           sizeof(struct eloop_sock));
127
 
        }
128
 
        table->count--;
129
 
        table->changed = 1;
130
 
}
131
 
 
132
 
 
133
 
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
134
 
                                     fd_set *fds)
135
 
{
136
 
        int i;
137
 
 
138
 
        FD_ZERO(fds);
139
 
 
140
 
        if (table->table == NULL)
141
 
                return;
142
 
 
143
 
        for (i = 0; i < table->count; i++)
144
 
                FD_SET(table->table[i].sock, fds);
145
 
}
146
 
 
147
 
 
148
 
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
149
 
                                      fd_set *fds)
150
 
{
151
 
        int i;
152
 
 
153
 
        if (table == NULL || table->table == NULL)
154
 
                return;
155
 
 
156
 
        table->changed = 0;
157
 
        for (i = 0; i < table->count; i++) {
158
 
                if (FD_ISSET(table->table[i].sock, fds)) {
159
 
                        table->table[i].handler(table->table[i].sock,
160
 
                                                table->table[i].eloop_data,
161
 
                                                table->table[i].user_data);
162
 
                        if (table->changed)
163
 
                                break;
164
 
                }
165
 
        }
166
 
}
167
 
 
168
 
 
169
 
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
170
 
{
171
 
        if (table)
172
 
                os_free(table->table);
173
 
}
174
 
 
175
 
 
176
 
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
177
 
                             void *eloop_data, void *user_data)
178
 
{
179
 
        return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
180
 
                                   eloop_data, user_data);
181
 
}
182
 
 
183
 
 
184
 
void eloop_unregister_read_sock(int sock)
185
 
{
186
 
        eloop_unregister_sock(sock, EVENT_TYPE_READ);
187
 
}
188
 
 
189
 
 
190
 
static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
191
 
{
192
 
        switch (type) {
193
 
        case EVENT_TYPE_READ:
194
 
                return &eloop.readers;
195
 
        case EVENT_TYPE_WRITE:
196
 
                return &eloop.writers;
197
 
        case EVENT_TYPE_EXCEPTION:
198
 
                return &eloop.exceptions;
199
 
        }
200
 
 
201
 
        return NULL;
202
 
}
203
 
 
204
 
 
205
 
int eloop_register_sock(int sock, eloop_event_type type,
206
 
                        eloop_sock_handler handler,
207
 
                        void *eloop_data, void *user_data)
208
 
{
209
 
        struct eloop_sock_table *table;
210
 
 
211
 
        table = eloop_get_sock_table(type);
212
 
        return eloop_sock_table_add_sock(table, sock, handler,
213
 
                                         eloop_data, user_data);
214
 
}
215
 
 
216
 
 
217
 
void eloop_unregister_sock(int sock, eloop_event_type type)
218
 
{
219
 
        struct eloop_sock_table *table;
220
 
 
221
 
        table = eloop_get_sock_table(type);
222
 
        eloop_sock_table_remove_sock(table, sock);
223
 
}
224
 
 
225
 
 
226
 
int eloop_register_timeout(unsigned int secs, unsigned int usecs,
227
 
                           eloop_timeout_handler handler,
228
 
                           void *eloop_data, void *user_data)
229
 
{
230
 
        struct eloop_timeout *timeout, *tmp, *prev;
231
 
 
232
 
        timeout = os_malloc(sizeof(*timeout));
233
 
        if (timeout == NULL)
234
 
                return -1;
235
 
        os_get_time(&timeout->time);
236
 
        timeout->time.sec += secs;
237
 
        timeout->time.usec += usecs;
238
 
        while (timeout->time.usec >= 1000000) {
239
 
                timeout->time.sec++;
240
 
                timeout->time.usec -= 1000000;
241
 
        }
242
 
        timeout->eloop_data = eloop_data;
243
 
        timeout->user_data = user_data;
244
 
        timeout->handler = handler;
245
 
        timeout->next = NULL;
246
 
 
247
 
        if (eloop.timeout == NULL) {
248
 
                eloop.timeout = timeout;
249
 
                return 0;
250
 
        }
251
 
 
252
 
        prev = NULL;
253
 
        tmp = eloop.timeout;
254
 
        while (tmp != NULL) {
255
 
                if (os_time_before(&timeout->time, &tmp->time))
256
 
                        break;
257
 
                prev = tmp;
258
 
                tmp = tmp->next;
259
 
        }
260
 
 
261
 
        if (prev == NULL) {
262
 
                timeout->next = eloop.timeout;
263
 
                eloop.timeout = timeout;
264
 
        } else {
265
 
                timeout->next = prev->next;
266
 
                prev->next = timeout;
267
 
        }
268
 
 
269
 
        return 0;
270
 
}
271
 
 
272
 
 
273
 
int eloop_cancel_timeout(eloop_timeout_handler handler,
274
 
                         void *eloop_data, void *user_data)
275
 
{
276
 
        struct eloop_timeout *timeout, *prev, *next;
277
 
        int removed = 0;
278
 
 
279
 
        prev = NULL;
280
 
        timeout = eloop.timeout;
281
 
        while (timeout != NULL) {
282
 
                next = timeout->next;
283
 
 
284
 
                if (timeout->handler == handler &&
285
 
                    (timeout->eloop_data == eloop_data ||
286
 
                     eloop_data == ELOOP_ALL_CTX) &&
287
 
                    (timeout->user_data == user_data ||
288
 
                     user_data == ELOOP_ALL_CTX)) {
289
 
                        if (prev == NULL)
290
 
                                eloop.timeout = next;
291
 
                        else
292
 
                                prev->next = next;
293
 
                        os_free(timeout);
294
 
                        removed++;
295
 
                } else
296
 
                        prev = timeout;
297
 
 
298
 
                timeout = next;
299
 
        }
300
 
 
301
 
        return removed;
302
 
}
303
 
 
304
 
 
305
 
#ifndef CONFIG_NATIVE_WINDOWS
306
 
static void eloop_handle_alarm(int sig)
307
 
{
308
 
        fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
309
 
                "seconds. Looks like there\n"
310
 
                "is a bug that ends up in a busy loop that "
311
 
                "prevents clean shutdown.\n"
312
 
                "Killing program forcefully.\n");
313
 
        exit(1);
314
 
}
315
 
#endif /* CONFIG_NATIVE_WINDOWS */
316
 
 
317
 
 
318
 
static void eloop_handle_signal(int sig)
319
 
{
320
 
        int i;
321
 
 
322
 
#ifndef CONFIG_NATIVE_WINDOWS
323
 
        if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
324
 
                /* Use SIGALRM to break out from potential busy loops that
325
 
                 * would not allow the program to be killed. */
326
 
                eloop.pending_terminate = 1;
327
 
                signal(SIGALRM, eloop_handle_alarm);
328
 
                alarm(2);
329
 
        }
330
 
#endif /* CONFIG_NATIVE_WINDOWS */
331
 
 
332
 
        eloop.signaled++;
333
 
        for (i = 0; i < eloop.signal_count; i++) {
334
 
                if (eloop.signals[i].sig == sig) {
335
 
                        eloop.signals[i].signaled++;
336
 
                        break;
337
 
                }
338
 
        }
339
 
}
340
 
 
341
 
 
342
 
static void eloop_process_pending_signals(void)
343
 
{
344
 
        int i;
345
 
 
346
 
        if (eloop.signaled == 0)
347
 
                return;
348
 
        eloop.signaled = 0;
349
 
 
350
 
        if (eloop.pending_terminate) {
351
 
#ifndef CONFIG_NATIVE_WINDOWS
352
 
                alarm(0);
353
 
#endif /* CONFIG_NATIVE_WINDOWS */
354
 
                eloop.pending_terminate = 0;
355
 
        }
356
 
 
357
 
        for (i = 0; i < eloop.signal_count; i++) {
358
 
                if (eloop.signals[i].signaled) {
359
 
                        eloop.signals[i].signaled = 0;
360
 
                        eloop.signals[i].handler(eloop.signals[i].sig,
361
 
                                                 eloop.user_data,
362
 
                                                 eloop.signals[i].user_data);
363
 
                }
364
 
        }
365
 
}
366
 
 
367
 
 
368
 
int eloop_register_signal(int sig, eloop_signal_handler handler,
369
 
                          void *user_data)
370
 
{
371
 
        struct eloop_signal *tmp;
372
 
 
373
 
        tmp = (struct eloop_signal *)
374
 
                os_realloc(eloop.signals,
375
 
                           (eloop.signal_count + 1) *
376
 
                           sizeof(struct eloop_signal));
377
 
        if (tmp == NULL)
378
 
                return -1;
379
 
 
380
 
        tmp[eloop.signal_count].sig = sig;
381
 
        tmp[eloop.signal_count].user_data = user_data;
382
 
        tmp[eloop.signal_count].handler = handler;
383
 
        tmp[eloop.signal_count].signaled = 0;
384
 
        eloop.signal_count++;
385
 
        eloop.signals = tmp;
386
 
        signal(sig, eloop_handle_signal);
387
 
 
388
 
        return 0;
389
 
}
390
 
 
391
 
 
392
 
int eloop_register_signal_terminate(eloop_signal_handler handler,
393
 
                                    void *user_data)
394
 
{
395
 
        int ret = eloop_register_signal(SIGINT, handler, user_data);
396
 
        if (ret == 0)
397
 
                ret = eloop_register_signal(SIGTERM, handler, user_data);
398
 
        return ret;
399
 
}
400
 
 
401
 
 
402
 
int eloop_register_signal_reconfig(eloop_signal_handler handler,
403
 
                                   void *user_data)
404
 
{
405
 
#ifdef CONFIG_NATIVE_WINDOWS
406
 
        return 0;
407
 
#else /* CONFIG_NATIVE_WINDOWS */
408
 
        return eloop_register_signal(SIGHUP, handler, user_data);
409
 
#endif /* CONFIG_NATIVE_WINDOWS */
410
 
}
411
 
 
412
 
 
413
 
void eloop_run(void)
414
 
{
415
 
        fd_set *rfds, *wfds, *efds;
416
 
        int res;
417
 
        struct timeval _tv;
418
 
        struct os_time tv, now;
419
 
 
420
 
        rfds = os_malloc(sizeof(*rfds));
421
 
        wfds = os_malloc(sizeof(*wfds));
422
 
        efds = os_malloc(sizeof(*efds));
423
 
        if (rfds == NULL || wfds == NULL || efds == NULL) {
424
 
                printf("eloop_run - malloc failed\n");
425
 
                goto out;
426
 
        }
427
 
 
428
 
        while (!eloop.terminate &&
429
 
               (eloop.timeout || eloop.readers.count > 0 ||
430
 
                eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
431
 
                if (eloop.timeout) {
432
 
                        os_get_time(&now);
433
 
                        if (os_time_before(&now, &eloop.timeout->time))
434
 
                                os_time_sub(&eloop.timeout->time, &now, &tv);
435
 
                        else
436
 
                                tv.sec = tv.usec = 0;
437
 
#if 0
438
 
                        printf("next timeout in %lu.%06lu sec\n",
439
 
                               tv.sec, tv.usec);
440
 
#endif
441
 
                        _tv.tv_sec = tv.sec;
442
 
                        _tv.tv_usec = tv.usec;
443
 
                }
444
 
 
445
 
                eloop_sock_table_set_fds(&eloop.readers, rfds);
446
 
                eloop_sock_table_set_fds(&eloop.writers, wfds);
447
 
                eloop_sock_table_set_fds(&eloop.exceptions, efds);
448
 
                res = select(eloop.max_sock + 1, rfds, wfds, efds,
449
 
                             eloop.timeout ? &_tv : NULL);
450
 
                if (res < 0 && errno != EINTR && errno != 0) {
451
 
                        perror("select");
452
 
                        goto out;
453
 
                }
454
 
                eloop_process_pending_signals();
455
 
 
456
 
                /* check if some registered timeouts have occurred */
457
 
                if (eloop.timeout) {
458
 
                        struct eloop_timeout *tmp;
459
 
 
460
 
                        os_get_time(&now);
461
 
                        if (!os_time_before(&now, &eloop.timeout->time)) {
462
 
                                tmp = eloop.timeout;
463
 
                                eloop.timeout = eloop.timeout->next;
464
 
                                tmp->handler(tmp->eloop_data,
465
 
                                             tmp->user_data);
466
 
                                os_free(tmp);
467
 
                        }
468
 
 
469
 
                }
470
 
 
471
 
                if (res <= 0)
472
 
                        continue;
473
 
 
474
 
                eloop_sock_table_dispatch(&eloop.readers, rfds);
475
 
                eloop_sock_table_dispatch(&eloop.writers, wfds);
476
 
                eloop_sock_table_dispatch(&eloop.exceptions, efds);
477
 
        }
478
 
 
479
 
out:
480
 
        os_free(rfds);
481
 
        os_free(wfds);
482
 
        os_free(efds);
483
 
}
484
 
 
485
 
 
486
 
void eloop_terminate(void)
487
 
{
488
 
        eloop.terminate = 1;
489
 
}
490
 
 
491
 
 
492
 
void eloop_destroy(void)
493
 
{
494
 
        struct eloop_timeout *timeout, *prev;
495
 
 
496
 
        timeout = eloop.timeout;
497
 
        while (timeout != NULL) {
498
 
                prev = timeout;
499
 
                timeout = timeout->next;
500
 
                os_free(prev);
501
 
        }
502
 
        eloop_sock_table_destroy(&eloop.readers);
503
 
        eloop_sock_table_destroy(&eloop.writers);
504
 
        eloop_sock_table_destroy(&eloop.exceptions);
505
 
        os_free(eloop.signals);
506
 
}
507
 
 
508
 
 
509
 
int eloop_terminated(void)
510
 
{
511
 
        return eloop.terminate;
512
 
}
513
 
 
514
 
 
515
 
void eloop_wait_for_read_sock(int sock)
516
 
{
517
 
        fd_set rfds;
518
 
 
519
 
        if (sock < 0)
520
 
                return;
521
 
 
522
 
        FD_ZERO(&rfds);
523
 
        FD_SET(sock, &rfds);
524
 
        select(sock + 1, &rfds, NULL, NULL, NULL);
525
 
}
526
 
 
527
 
 
528
 
void * eloop_get_user_data(void)
529
 
{
530
 
        return eloop.user_data;
531
 
}