transmission: fix compilation build type without BT Client
[tomato.git] / release / src / router / libevent / WIN32-Code / win32.c
blob8a603b7eceb4e00b5c6f5ce5acb63d84d4779eb4
1 /*
2 * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
3 * Copyright 2003 Michael A. Davis <mike@datanerds.net>
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifdef _MSC_VER
29 #include "./config.h"
30 #else
31 /* Avoid the windows/msvc thing. */
32 #include "../config.h"
33 #endif
35 #include <winsock2.h>
36 #include <windows.h>
37 #include <sys/types.h>
38 #include <sys/queue.h>
39 #include <signal.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <assert.h>
46 #define RB_AUGMENT(x) (void)(x)
47 #include "./tree.h"
48 #include "log.h"
49 #include "event.h"
50 #include "event-internal.h"
52 #define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
54 extern struct event_list timequeue;
55 extern struct event_list addqueue;
56 #if 0
57 extern struct event_list signalqueue;
58 #endif
60 struct win_fd_set {
61 u_int fd_count;
62 SOCKET fd_array[1];
65 int evsigcaught[NSIG];
66 volatile sig_atomic_t signal_caught = 0;
67 /* MSDN says this is required to handle SIGFPE */
68 volatile double SIGFPE_REQ = 0.0f;
70 #if 0
71 static void signal_handler(int sig);
73 void signal_process(void);
74 int signal_recalc(void);
75 #endif
77 struct event_entry {
78 RB_ENTRY(event_entry) node;
79 SOCKET sock;
80 int read_pos;
81 int write_pos;
82 struct event *read_event;
83 struct event *write_event;
86 static int
87 compare(struct event_entry *a, struct event_entry *b)
89 if (a->sock < b->sock)
90 return -1;
91 else if (a->sock > b->sock)
92 return 1;
93 else
94 return 0;
97 struct win32op {
98 int fd_setsz;
99 struct win_fd_set *readset_in;
100 struct win_fd_set *writeset_in;
101 struct win_fd_set *readset_out;
102 struct win_fd_set *writeset_out;
103 struct win_fd_set *exset_out;
104 RB_HEAD(event_map, event_entry) event_root;
106 unsigned signals_are_broken : 1;
109 RB_PROTOTYPE(event_map, event_entry, node, compare);
110 RB_GENERATE(event_map, event_entry, node, compare);
112 void *win32_init (struct event_base *);
113 int win32_insert (void *, struct event *);
114 int win32_del (void *, struct event *);
115 int win32_dispatch (struct event_base *base, void *, struct timeval *);
116 void win32_dealloc (struct event_base *, void *);
118 struct eventop win32ops = {
119 "win32",
120 win32_init,
121 win32_insert,
122 win32_del,
123 win32_dispatch,
124 win32_dealloc,
128 #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
130 static int
131 realloc_fd_sets(struct win32op *op, size_t new_size)
133 size_t size;
135 assert(new_size >= op->readset_in->fd_count &&
136 new_size >= op->writeset_in->fd_count);
137 assert(new_size >= 1);
139 size = FD_SET_ALLOC_SIZE(new_size);
140 if (!(op->readset_in = realloc(op->readset_in, size)))
141 return (-1);
142 if (!(op->writeset_in = realloc(op->writeset_in, size)))
143 return (-1);
144 if (!(op->readset_out = realloc(op->readset_out, size)))
145 return (-1);
146 if (!(op->exset_out = realloc(op->exset_out, size)))
147 return (-1);
148 if (!(op->writeset_out = realloc(op->writeset_out, size)))
149 return (-1);
150 op->fd_setsz = new_size;
151 return (0);
154 static int
155 timeval_to_ms(struct timeval *tv)
157 return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
160 static struct event_entry*
161 get_event_entry(struct win32op *op, SOCKET s, int create)
163 struct event_entry key, *val;
164 key.sock = s;
165 val = RB_FIND(event_map, &op->event_root, &key);
166 if (val || !create)
167 return val;
168 if (!(val = calloc(1, sizeof(struct event_entry)))) {
169 event_warn("%s: calloc", __func__);
170 return NULL;
172 val->sock = s;
173 val->read_pos = val->write_pos = -1;
174 RB_INSERT(event_map, &op->event_root, val);
175 return val;
178 static int
179 do_fd_set(struct win32op *op, struct event_entry *ent, int read)
181 SOCKET s = ent->sock;
182 struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
183 if (read) {
184 if (ent->read_pos >= 0)
185 return (0);
186 } else {
187 if (ent->write_pos >= 0)
188 return (0);
190 if (set->fd_count == op->fd_setsz) {
191 if (realloc_fd_sets(op, op->fd_setsz*2))
192 return (-1);
193 /* set pointer will have changed and needs reiniting! */
194 set = read ? op->readset_in : op->writeset_in;
196 set->fd_array[set->fd_count] = s;
197 if (read)
198 ent->read_pos = set->fd_count;
199 else
200 ent->write_pos = set->fd_count;
201 return (set->fd_count++);
204 static int
205 do_fd_clear(struct win32op *op, struct event_entry *ent, int read)
207 int i;
208 struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
209 if (read) {
210 i = ent->read_pos;
211 ent->read_pos = -1;
212 } else {
213 i = ent->write_pos;
214 ent->write_pos = -1;
216 if (i < 0)
217 return (0);
218 if (--set->fd_count != i) {
219 struct event_entry *ent2;
220 SOCKET s2;
221 s2 = set->fd_array[i] = set->fd_array[set->fd_count];
222 ent2 = get_event_entry(op, s2, 0);
223 if (!ent) /* This indicates a bug. */
224 return (0);
225 if (read)
226 ent2->read_pos = i;
227 else
228 ent2->write_pos = i;
230 return (0);
233 #define NEVENT 64
234 void *
235 win32_init(struct event_base *_base)
237 struct win32op *winop;
238 size_t size;
239 if (!(winop = calloc(1, sizeof(struct win32op))))
240 return NULL;
241 winop->fd_setsz = NEVENT;
242 size = FD_SET_ALLOC_SIZE(NEVENT);
243 if (!(winop->readset_in = malloc(size)))
244 goto err;
245 if (!(winop->writeset_in = malloc(size)))
246 goto err;
247 if (!(winop->readset_out = malloc(size)))
248 goto err;
249 if (!(winop->writeset_out = malloc(size)))
250 goto err;
251 if (!(winop->exset_out = malloc(size)))
252 goto err;
253 RB_INIT(&winop->event_root);
254 winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
255 winop->readset_out->fd_count = winop->writeset_out->fd_count
256 = winop->exset_out->fd_count = 0;
258 if (evsignal_init(_base) < 0)
259 winop->signals_are_broken = 1;
261 return (winop);
262 err:
263 XFREE(winop->readset_in);
264 XFREE(winop->writeset_in);
265 XFREE(winop->readset_out);
266 XFREE(winop->writeset_out);
267 XFREE(winop->exset_out);
268 XFREE(winop);
269 return (NULL);
273 win32_insert(void *op, struct event *ev)
275 struct win32op *win32op = op;
276 struct event_entry *ent;
278 if (ev->ev_events & EV_SIGNAL) {
279 if (win32op->signals_are_broken)
280 return (-1);
281 return (evsignal_add(ev));
283 if (!(ev->ev_events & (EV_READ|EV_WRITE)))
284 return (0);
285 ent = get_event_entry(win32op, ev->ev_fd, 1);
286 if (!ent)
287 return (-1); /* out of memory */
289 event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
290 if (ev->ev_events & EV_READ) {
291 if (do_fd_set(win32op, ent, 1)<0)
292 return (-1);
293 ent->read_event = ev;
295 if (ev->ev_events & EV_WRITE) {
296 if (do_fd_set(win32op, ent, 0)<0)
297 return (-1);
298 ent->write_event = ev;
300 return (0);
304 win32_del(void *op, struct event *ev)
306 struct win32op *win32op = op;
307 struct event_entry *ent;
309 if (ev->ev_events & EV_SIGNAL)
310 return (evsignal_del(ev));
312 if (!(ent = get_event_entry(win32op, ev->ev_fd, 0)))
313 return (-1);
314 event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
315 if (ev == ent->read_event) {
316 do_fd_clear(win32op, ent, 1);
317 ent->read_event = NULL;
319 if (ev == ent->write_event) {
320 do_fd_clear(win32op, ent, 0);
321 ent->write_event = NULL;
323 if (!ent->read_event && !ent->write_event) {
324 RB_REMOVE(event_map, &win32op->event_root, ent);
325 free(ent);
328 return 0;
331 static void
332 fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
334 out->fd_count = in->fd_count;
335 memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
339 static void dump_fd_set(struct win_fd_set *s)
341 unsigned int i;
342 printf("[ ");
343 for(i=0;i<s->fd_count;++i)
344 printf("%d ",(int)s->fd_array[i]);
345 printf("]\n");
350 win32_dispatch(struct event_base *base, void *op,
351 struct timeval *tv)
353 struct win32op *win32op = op;
354 int res = 0;
355 unsigned j, i;
356 int fd_count;
357 SOCKET s;
358 struct event_entry *ent;
360 fd_set_copy(win32op->readset_out, win32op->readset_in);
361 fd_set_copy(win32op->exset_out, win32op->readset_in);
362 fd_set_copy(win32op->writeset_out, win32op->writeset_in);
364 fd_count =
365 (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
366 win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
368 if (!fd_count) {
369 /* Windows doesn't like you to call select() with no sockets */
370 Sleep(timeval_to_ms(tv));
371 evsignal_process(base);
372 return (0);
375 res = select(fd_count,
376 (struct fd_set*)win32op->readset_out,
377 (struct fd_set*)win32op->writeset_out,
378 (struct fd_set*)win32op->exset_out, tv);
380 event_debug(("%s: select returned %d", __func__, res));
382 if(res <= 0) {
383 evsignal_process(base);
384 return res;
385 } else if (base->sig.evsignal_caught) {
386 evsignal_process(base);
389 if (win32op->readset_out->fd_count) {
390 i = rand() % win32op->readset_out->fd_count;
391 for (j=0; j<win32op->readset_out->fd_count; ++j) {
392 if (++i >= win32op->readset_out->fd_count)
393 i = 0;
394 s = win32op->readset_out->fd_array[i];
395 if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
396 event_active(ent->read_event, EV_READ, 1);
399 if (win32op->exset_out->fd_count) {
400 i = rand() % win32op->exset_out->fd_count;
401 for (j=0; j<win32op->exset_out->fd_count; ++j) {
402 if (++i >= win32op->exset_out->fd_count)
403 i = 0;
404 s = win32op->exset_out->fd_array[i];
405 if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
406 event_active(ent->read_event, EV_READ, 1);
409 if (win32op->writeset_out->fd_count) {
410 i = rand() % win32op->writeset_out->fd_count;
411 for (j=0; j<win32op->writeset_out->fd_count; ++j) {
412 if (++i >= win32op->exset_out->fd_count)
413 i = 0;
414 s = win32op->writeset_out->fd_array[i];
415 if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
416 event_active(ent->write_event, EV_WRITE, 1);
421 return (0);
424 void
425 win32_dealloc(struct event_base *_base, void *arg)
427 struct win32op *win32op = arg;
429 evsignal_dealloc(_base);
430 if (win32op->readset_in)
431 free(win32op->readset_in);
432 if (win32op->writeset_in)
433 free(win32op->writeset_in);
434 if (win32op->readset_out)
435 free(win32op->readset_out);
436 if (win32op->writeset_out)
437 free(win32op->writeset_out);
438 if (win32op->exset_out)
439 free(win32op->exset_out);
440 /* XXXXX free the tree. */
442 memset(win32op, 0, sizeof(win32op));
443 free(win32op);
446 #if 0
447 static void
448 signal_handler(int sig)
450 evsigcaught[sig]++;
451 signal_caught = 1;
455 signal_recalc(void)
457 struct event *ev;
459 /* Reinstall our signal handler. */
460 TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
461 if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
462 return (-1);
464 return (0);
467 void
468 signal_process(void)
470 struct event *ev;
471 short ncalls;
473 TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
474 ncalls = evsigcaught[EVENT_SIGNAL(ev)];
475 if (ncalls) {
476 if (!(ev->ev_events & EV_PERSIST))
477 event_del(ev);
478 event_active(ev, EV_SIGNAL, ncalls);
482 memset(evsigcaught, 0, sizeof(evsigcaught));
483 signal_caught = 0;
485 #endif