]> arthur.barton.de Git - netatalk.git/blob - libevent/listener.c
Add libevent
[netatalk.git] / libevent / listener.c
1 /*
2  * Copyright (c) 2009-2010 Niels Provos, Nick Mathewson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/types.h>
28
29 #include "event2/event-config.h"
30
31 #ifdef WIN32
32 #include <winsock2.h>
33 #include <ws2tcpip.h>
34 #include <mswsock.h>
35 #endif
36 #include <errno.h>
37 #ifdef _EVENT_HAVE_SYS_SOCKET_H
38 #include <sys/socket.h>
39 #endif
40 #ifdef _EVENT_HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43 #ifdef _EVENT_HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46
47 #include "event2/listener.h"
48 #include "event2/util.h"
49 #include "event2/event.h"
50 #include "event2/event_struct.h"
51 #include "mm-internal.h"
52 #include "util-internal.h"
53 #include "log-internal.h"
54 #include "evthread-internal.h"
55 #ifdef WIN32
56 #include "iocp-internal.h"
57 #include "defer-internal.h"
58 #include "event-internal.h"
59 #endif
60
61 struct evconnlistener_ops {
62         int (*enable)(struct evconnlistener *);
63         int (*disable)(struct evconnlistener *);
64         void (*destroy)(struct evconnlistener *);
65         void (*shutdown)(struct evconnlistener *);
66         evutil_socket_t (*getfd)(struct evconnlistener *);
67         struct event_base *(*getbase)(struct evconnlistener *);
68 };
69
70 struct evconnlistener {
71         const struct evconnlistener_ops *ops;
72         void *lock;
73         evconnlistener_cb cb;
74         evconnlistener_errorcb errorcb;
75         void *user_data;
76         unsigned flags;
77         short refcnt;
78         unsigned enabled : 1;
79 };
80
81 struct evconnlistener_event {
82         struct evconnlistener base;
83         struct event listener;
84 };
85
86 #ifdef WIN32
87 struct evconnlistener_iocp {
88         struct evconnlistener base;
89         evutil_socket_t fd;
90         struct event_base *event_base;
91         struct event_iocp_port *port;
92         short n_accepting;
93         unsigned shutting_down : 1;
94         unsigned event_added : 1;
95         struct accepting_socket **accepting;
96 };
97 #endif
98
99 #define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0)
100 #define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0)
101
102 struct evconnlistener *
103 evconnlistener_new_async(struct event_base *base,
104     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
105     evutil_socket_t fd); /* XXXX export this? */
106
107 static int event_listener_enable(struct evconnlistener *);
108 static int event_listener_disable(struct evconnlistener *);
109 static void event_listener_destroy(struct evconnlistener *);
110 static evutil_socket_t event_listener_getfd(struct evconnlistener *);
111 static struct event_base *event_listener_getbase(struct evconnlistener *);
112
113 #if 0
114 static void
115 listener_incref_and_lock(struct evconnlistener *listener)
116 {
117         LOCK(listener);
118         ++listener->refcnt;
119 }
120 #endif
121
122 static int
123 listener_decref_and_unlock(struct evconnlistener *listener)
124 {
125         int refcnt = --listener->refcnt;
126         if (refcnt == 0) {
127                 listener->ops->destroy(listener);
128                 UNLOCK(listener);
129                 EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE);
130                 mm_free(listener);
131                 return 1;
132         } else {
133                 UNLOCK(listener);
134                 return 0;
135         }
136 }
137
138 static const struct evconnlistener_ops evconnlistener_event_ops = {
139         event_listener_enable,
140         event_listener_disable,
141         event_listener_destroy,
142         NULL, /* shutdown */
143         event_listener_getfd,
144         event_listener_getbase
145 };
146
147 static void listener_read_cb(evutil_socket_t, short, void *);
148
149 struct evconnlistener *
150 evconnlistener_new(struct event_base *base,
151     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
152     evutil_socket_t fd)
153 {
154         struct evconnlistener_event *lev;
155
156 #ifdef WIN32
157         if (base && event_base_get_iocp(base)) {
158                 const struct win32_extension_fns *ext =
159                         event_get_win32_extension_fns();
160                 if (ext->AcceptEx && ext->GetAcceptExSockaddrs)
161                         return evconnlistener_new_async(base, cb, ptr, flags,
162                                 backlog, fd);
163         }
164 #endif
165
166         if (backlog > 0) {
167                 if (listen(fd, backlog) < 0)
168                         return NULL;
169         } else if (backlog < 0) {
170                 if (listen(fd, 128) < 0)
171                         return NULL;
172         }
173
174         lev = mm_calloc(1, sizeof(struct evconnlistener_event));
175         if (!lev)
176                 return NULL;
177
178         lev->base.ops = &evconnlistener_event_ops;
179         lev->base.cb = cb;
180         lev->base.user_data = ptr;
181         lev->base.flags = flags;
182         lev->base.refcnt = 1;
183
184         if (flags & LEV_OPT_THREADSAFE) {
185                 EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
186         }
187
188         event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
189             listener_read_cb, lev);
190
191         evconnlistener_enable(&lev->base);
192
193         return &lev->base;
194 }
195
196 struct evconnlistener *
197 evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,
198     void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,
199     int socklen)
200 {
201         struct evconnlistener *listener;
202         evutil_socket_t fd;
203         int on = 1;
204         int family = sa ? sa->sa_family : AF_UNSPEC;
205
206         if (backlog == 0)
207                 return NULL;
208
209         fd = socket(family, SOCK_STREAM, 0);
210         if (fd == -1)
211                 return NULL;
212
213         if (evutil_make_socket_nonblocking(fd) < 0) {
214                 evutil_closesocket(fd);
215                 return NULL;
216         }
217
218         if (flags & LEV_OPT_CLOSE_ON_EXEC) {
219                 if (evutil_make_socket_closeonexec(fd) < 0) {
220                         evutil_closesocket(fd);
221                         return NULL;
222                 }
223         }
224
225         setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on));
226         if (flags & LEV_OPT_REUSEABLE) {
227                 evutil_make_listen_socket_reuseable(fd);
228         }
229
230         if (sa) {
231                 if (bind(fd, sa, socklen)<0) {
232                         evutil_closesocket(fd);
233                         return NULL;
234                 }
235         }
236
237         listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);
238         if (!listener) {
239                 evutil_closesocket(fd);
240                 return NULL;
241         }
242
243         return listener;
244 }
245
246 void
247 evconnlistener_free(struct evconnlistener *lev)
248 {
249         LOCK(lev);
250         lev->cb = NULL;
251         lev->errorcb = NULL;
252         if (lev->ops->shutdown)
253                 lev->ops->shutdown(lev);
254         listener_decref_and_unlock(lev);
255 }
256
257 static void
258 event_listener_destroy(struct evconnlistener *lev)
259 {
260         struct evconnlistener_event *lev_e =
261             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
262
263         event_del(&lev_e->listener);
264         if (lev->flags & LEV_OPT_CLOSE_ON_FREE)
265                 evutil_closesocket(event_get_fd(&lev_e->listener));
266         event_debug_unassign(&lev_e->listener);
267 }
268
269 int
270 evconnlistener_enable(struct evconnlistener *lev)
271 {
272         int r;
273         LOCK(lev);
274         lev->enabled = 1;
275         if (lev->cb)
276                 r = lev->ops->enable(lev);
277         else
278                 r = 0;
279         UNLOCK(lev);
280         return r;
281 }
282
283 int
284 evconnlistener_disable(struct evconnlistener *lev)
285 {
286         int r;
287         LOCK(lev);
288         lev->enabled = 0;
289         r = lev->ops->disable(lev);
290         UNLOCK(lev);
291         return r;
292 }
293
294 static int
295 event_listener_enable(struct evconnlistener *lev)
296 {
297         struct evconnlistener_event *lev_e =
298             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
299         return event_add(&lev_e->listener, NULL);
300 }
301
302 static int
303 event_listener_disable(struct evconnlistener *lev)
304 {
305         struct evconnlistener_event *lev_e =
306             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
307         return event_del(&lev_e->listener);
308 }
309
310 evutil_socket_t
311 evconnlistener_get_fd(struct evconnlistener *lev)
312 {
313         evutil_socket_t fd;
314         LOCK(lev);
315         fd = lev->ops->getfd(lev);
316         UNLOCK(lev);
317         return fd;
318 }
319
320 static evutil_socket_t
321 event_listener_getfd(struct evconnlistener *lev)
322 {
323         struct evconnlistener_event *lev_e =
324             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
325         return event_get_fd(&lev_e->listener);
326 }
327
328 struct event_base *
329 evconnlistener_get_base(struct evconnlistener *lev)
330 {
331         struct event_base *base;
332         LOCK(lev);
333         base = lev->ops->getbase(lev);
334         UNLOCK(lev);
335         return base;
336 }
337
338 static struct event_base *
339 event_listener_getbase(struct evconnlistener *lev)
340 {
341         struct evconnlistener_event *lev_e =
342             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
343         return event_get_base(&lev_e->listener);
344 }
345
346 void
347 evconnlistener_set_cb(struct evconnlistener *lev,
348     evconnlistener_cb cb, void *arg)
349 {
350         int enable = 0;
351         LOCK(lev);
352         if (lev->enabled && !lev->cb)
353                 enable = 1;
354         lev->cb = cb;
355         lev->user_data = arg;
356         if (enable)
357                 evconnlistener_enable(lev);
358         UNLOCK(lev);
359 }
360
361 void
362 evconnlistener_set_error_cb(struct evconnlistener *lev,
363     evconnlistener_errorcb errorcb)
364 {
365         LOCK(lev);
366         lev->errorcb = errorcb;
367         UNLOCK(lev);
368 }
369
370 static void
371 listener_read_cb(evutil_socket_t fd, short what, void *p)
372 {
373         struct evconnlistener *lev = p;
374         int err;
375         evconnlistener_cb cb;
376         evconnlistener_errorcb errorcb;
377         void *user_data;
378         LOCK(lev);
379         while (1) {
380                 struct sockaddr_storage ss;
381 #ifdef WIN32
382                 int socklen = sizeof(ss);
383 #else
384                 socklen_t socklen = sizeof(ss);
385 #endif
386                 evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
387                 if (new_fd < 0)
388                         break;
389
390                 if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
391                         evutil_make_socket_nonblocking(new_fd);
392
393                 if (lev->cb == NULL) {
394                         UNLOCK(lev);
395                         return;
396                 }
397                 ++lev->refcnt;
398                 cb = lev->cb;
399                 user_data = lev->user_data;
400                 UNLOCK(lev);
401                 cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
402                     user_data);
403                 LOCK(lev);
404                 if (lev->refcnt == 1) {
405                         int freed = listener_decref_and_unlock(lev);
406                         EVUTIL_ASSERT(freed);
407                         return;
408                 }
409                 --lev->refcnt;
410         }
411         err = evutil_socket_geterror(fd);
412         if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
413                 UNLOCK(lev);
414                 return;
415         }
416         if (lev->errorcb != NULL) {
417                 ++lev->refcnt;
418                 errorcb = lev->errorcb;
419                 user_data = lev->user_data;
420                 UNLOCK(lev);
421                 errorcb(lev, user_data);
422                 LOCK(lev);
423                 listener_decref_and_unlock(lev);
424         } else {
425                 event_sock_warn(fd, "Error from accept() call");
426         }
427 }
428
429 #ifdef WIN32
430 struct accepting_socket {
431         CRITICAL_SECTION lock;
432         struct event_overlapped overlapped;
433         SOCKET s;
434         int error;
435         struct deferred_cb deferred;
436         struct evconnlistener_iocp *lev;
437         ev_uint8_t buflen;
438         ev_uint8_t family;
439         unsigned free_on_cb:1;
440         char addrbuf[1];
441 };
442
443 static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
444     ev_ssize_t n, int ok);
445 static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
446
447 static void
448 iocp_listener_event_add(struct evconnlistener_iocp *lev)
449 {
450         if (lev->event_added)
451                 return;
452
453         lev->event_added = 1;
454         event_base_add_virtual(lev->event_base);
455 }
456
457 static void
458 iocp_listener_event_del(struct evconnlistener_iocp *lev)
459 {
460         if (!lev->event_added)
461                 return;
462
463         lev->event_added = 0;
464         event_base_del_virtual(lev->event_base);
465 }
466
467 static struct accepting_socket *
468 new_accepting_socket(struct evconnlistener_iocp *lev, int family)
469 {
470         struct accepting_socket *res;
471         int addrlen;
472         int buflen;
473
474         if (family == AF_INET)
475                 addrlen = sizeof(struct sockaddr_in);
476         else if (family == AF_INET6)
477                 addrlen = sizeof(struct sockaddr_in6);
478         else
479                 return NULL;
480         buflen = (addrlen+16)*2;
481
482         res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen);
483         if (!res)
484                 return NULL;
485
486         event_overlapped_init(&res->overlapped, accepted_socket_cb);
487         res->s = INVALID_SOCKET;
488         res->lev = lev;
489         res->buflen = buflen;
490         res->family = family;
491
492         event_deferred_cb_init(&res->deferred,
493                 accepted_socket_invoke_user_cb, res);
494
495         InitializeCriticalSectionAndSpinCount(&res->lock, 1000);
496
497         return res;
498 }
499
500 static void
501 free_and_unlock_accepting_socket(struct accepting_socket *as)
502 {
503         /* requires lock. */
504         if (as->s != INVALID_SOCKET)
505                 closesocket(as->s);
506
507         LeaveCriticalSection(&as->lock);
508         DeleteCriticalSection(&as->lock);
509         mm_free(as);
510 }
511
512 static int
513 start_accepting(struct accepting_socket *as)
514 {
515         /* requires lock */
516         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
517         DWORD pending = 0;
518         SOCKET s = socket(as->family, SOCK_STREAM, 0);
519         int error = 0;
520
521         if (!as->lev->base.enabled)
522                 return 0;
523
524         if (s == INVALID_SOCKET) {
525                 error = WSAGetLastError();
526                 goto report_err;
527         }
528
529         /* XXXX It turns out we need to do this again later.  Does this call
530          * have any effect? */
531         setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
532             (char *)&as->lev->fd, sizeof(&as->lev->fd));
533
534         if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
535                 evutil_make_socket_nonblocking(s);
536
537         if (event_iocp_port_associate(as->lev->port, s, 1) < 0) {
538                 closesocket(s);
539                 return -1;
540         }
541
542         as->s = s;
543
544         if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0,
545                 as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped))
546         {
547                 /* Immediate success! */
548                 accepted_socket_cb(&as->overlapped, 1, 0, 1);
549         } else {
550                 error = WSAGetLastError();
551                 if (error != ERROR_IO_PENDING) {
552                         goto report_err;
553                 }
554         }
555
556         return 0;
557
558 report_err:
559         as->error = error;
560         event_deferred_cb_schedule(
561                 event_base_get_deferred_cb_queue(as->lev->event_base),
562                 &as->deferred);
563         return 0;
564 }
565
566 static void
567 stop_accepting(struct accepting_socket *as)
568 {
569         /* requires lock. */
570         SOCKET s = as->s;
571         as->s = INVALID_SOCKET;
572         closesocket(s);
573 }
574
575 static void
576 accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
577 {
578         struct accepting_socket *as = arg;
579
580         struct sockaddr *sa_local=NULL, *sa_remote=NULL;
581         int socklen_local=0, socklen_remote=0;
582         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
583         struct evconnlistener *lev = &as->lev->base;
584         evutil_socket_t sock=-1;
585         void *data;
586         evconnlistener_cb cb=NULL;
587         evconnlistener_errorcb errorcb=NULL;
588         int error;
589
590         EVUTIL_ASSERT(ext->GetAcceptExSockaddrs);
591
592         LOCK(lev);
593         EnterCriticalSection(&as->lock);
594         if (as->free_on_cb) {
595                 free_and_unlock_accepting_socket(as);
596                 listener_decref_and_unlock(lev);
597                 return;
598         }
599
600         ++lev->refcnt;
601
602         error = as->error;
603         if (error) {
604                 as->error = 0;
605                 errorcb = lev->errorcb;
606         } else {
607                 ext->GetAcceptExSockaddrs(
608                         as->addrbuf, 0, as->buflen/2, as->buflen/2,
609                         &sa_local, &socklen_local, &sa_remote,
610                         &socklen_remote);
611                 sock = as->s;
612                 cb = lev->cb;
613                 as->s = INVALID_SOCKET;
614
615                 /* We need to call this so getsockname, getpeername, and
616                  * shutdown work correctly on the accepted socket. */
617                 /* XXXX handle error? */
618                 setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
619                     (char *)&as->lev->fd, sizeof(&as->lev->fd));
620         }
621         data = lev->user_data;
622
623         LeaveCriticalSection(&as->lock);
624         UNLOCK(lev);
625
626         if (errorcb) {
627                 WSASetLastError(error);
628                 errorcb(lev, data);
629         } else if (cb) {
630                 cb(lev, sock, sa_remote, socklen_remote, data);
631         }
632
633         LOCK(lev);
634         if (listener_decref_and_unlock(lev))
635                 return;
636
637         EnterCriticalSection(&as->lock);
638         start_accepting(as);
639         LeaveCriticalSection(&as->lock);
640 }
641
642 static void
643 accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok)
644 {
645         struct accepting_socket *as =
646             EVUTIL_UPCAST(o, struct accepting_socket, overlapped);
647
648         LOCK(&as->lev->base);
649         EnterCriticalSection(&as->lock);
650         if (ok) {
651                 /* XXXX Don't do this if some EV_MT flag is set. */
652                 event_deferred_cb_schedule(
653                         event_base_get_deferred_cb_queue(as->lev->event_base),
654                         &as->deferred);
655                 LeaveCriticalSection(&as->lock);
656         } else if (as->free_on_cb) {
657                 struct evconnlistener *lev = &as->lev->base;
658                 free_and_unlock_accepting_socket(as);
659                 listener_decref_and_unlock(lev);
660                 return;
661         } else if (as->s == INVALID_SOCKET) {
662                 /* This is okay; we were disabled by iocp_listener_disable. */
663                 LeaveCriticalSection(&as->lock);
664         } else {
665                 /* Some error on accept that we couldn't actually handle. */
666                 BOOL ok;
667                 DWORD transfer = 0, flags=0;
668                 event_sock_warn(as->s, "Unexpected error on AcceptEx");
669                 ok = WSAGetOverlappedResult(as->s, &o->overlapped,
670                     &transfer, FALSE, &flags);
671                 if (ok) {
672                         /* well, that was confusing! */
673                         as->error = 1;
674                 } else {
675                         as->error = WSAGetLastError();
676                 }
677                 event_deferred_cb_schedule(
678                         event_base_get_deferred_cb_queue(as->lev->event_base),
679                         &as->deferred);
680                 LeaveCriticalSection(&as->lock);
681         }
682         UNLOCK(&as->lev->base);
683 }
684
685 static int
686 iocp_listener_enable(struct evconnlistener *lev)
687 {
688         int i;
689         struct evconnlistener_iocp *lev_iocp =
690             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
691
692         LOCK(lev);
693         iocp_listener_event_add(lev_iocp);
694         for (i = 0; i < lev_iocp->n_accepting; ++i) {
695                 struct accepting_socket *as = lev_iocp->accepting[i];
696                 if (!as)
697                         continue;
698                 EnterCriticalSection(&as->lock);
699                 if (!as->free_on_cb && as->s == INVALID_SOCKET)
700                         start_accepting(as);
701                 LeaveCriticalSection(&as->lock);
702         }
703         UNLOCK(lev);
704         return 0;
705 }
706
707 static int
708 iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
709 {
710         int i;
711         struct evconnlistener_iocp *lev_iocp =
712             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
713
714         LOCK(lev);
715         iocp_listener_event_del(lev_iocp);
716         for (i = 0; i < lev_iocp->n_accepting; ++i) {
717                 struct accepting_socket *as = lev_iocp->accepting[i];
718                 if (!as)
719                         continue;
720                 EnterCriticalSection(&as->lock);
721                 if (!as->free_on_cb && as->s != INVALID_SOCKET) {
722                         if (shutdown)
723                                 as->free_on_cb = 1;
724                         stop_accepting(as);
725                 }
726                 LeaveCriticalSection(&as->lock);
727         }
728         UNLOCK(lev);
729         return 0;
730 }
731
732 static int
733 iocp_listener_disable(struct evconnlistener *lev)
734 {
735         return iocp_listener_disable_impl(lev,0);
736 }
737
738 static void
739 iocp_listener_destroy(struct evconnlistener *lev)
740 {
741         struct evconnlistener_iocp *lev_iocp =
742             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
743
744         if (! lev_iocp->shutting_down) {
745                 lev_iocp->shutting_down = 1;
746                 iocp_listener_disable_impl(lev,1);
747         }
748
749 }
750
751 static evutil_socket_t
752 iocp_listener_getfd(struct evconnlistener *lev)
753 {
754         struct evconnlistener_iocp *lev_iocp =
755             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
756         return lev_iocp->fd;
757 }
758 static struct event_base *
759 iocp_listener_getbase(struct evconnlistener *lev)
760 {
761         struct evconnlistener_iocp *lev_iocp =
762             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
763         return lev_iocp->event_base;
764 }
765
766 static const struct evconnlistener_ops evconnlistener_iocp_ops = {
767         iocp_listener_enable,
768         iocp_listener_disable,
769         iocp_listener_destroy,
770         iocp_listener_destroy, /* shutdown */
771         iocp_listener_getfd,
772         iocp_listener_getbase
773 };
774
775 /* XXX define some way to override this. */
776 #define N_SOCKETS_PER_LISTENER 4
777
778 struct evconnlistener *
779 evconnlistener_new_async(struct event_base *base,
780     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
781     evutil_socket_t fd)
782 {
783         struct sockaddr_storage ss;
784         int socklen = sizeof(ss);
785         struct evconnlistener_iocp *lev;
786         int i;
787
788         flags |= LEV_OPT_THREADSAFE;
789
790         if (!base || !event_base_get_iocp(base))
791                 goto err;
792
793         /* XXXX duplicate code */
794         if (backlog > 0) {
795                 if (listen(fd, backlog) < 0)
796                         goto err;
797         } else if (backlog < 0) {
798                 if (listen(fd, 128) < 0)
799                         goto err;
800         }
801         if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
802                 event_sock_warn(fd, "getsockname");
803                 goto err;
804         }
805         lev = mm_calloc(1, sizeof(struct evconnlistener_iocp));
806         if (!lev) {
807                 event_warn("calloc");
808                 goto err;
809         }
810         lev->base.ops = &evconnlistener_iocp_ops;
811         lev->base.cb = cb;
812         lev->base.user_data = ptr;
813         lev->base.flags = flags;
814         lev->base.refcnt = 1;
815         lev->base.enabled = 1;
816
817         lev->port = event_base_get_iocp(base);
818         lev->fd = fd;
819         lev->event_base = base;
820
821
822         if (event_iocp_port_associate(lev->port, fd, 1) < 0)
823                 goto err_free_lev;
824
825         EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
826
827         lev->n_accepting = N_SOCKETS_PER_LISTENER;
828         lev->accepting = mm_calloc(lev->n_accepting,
829             sizeof(struct accepting_socket *));
830         if (!lev->accepting) {
831                 event_warn("calloc");
832                 goto err_delete_lock;
833         }
834         for (i = 0; i < lev->n_accepting; ++i) {
835                 lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
836                 if (!lev->accepting[i]) {
837                         event_warnx("Couldn't create accepting socket");
838                         goto err_free_accepting;
839                 }
840                 if (cb && start_accepting(lev->accepting[i]) < 0) {
841                         event_warnx("Couldn't start accepting on socket");
842                         EnterCriticalSection(&lev->accepting[i]->lock);
843                         free_and_unlock_accepting_socket(lev->accepting[i]);
844                         goto err_free_accepting;
845                 }
846                 ++lev->base.refcnt;
847         }
848
849         iocp_listener_event_add(lev);
850
851         return &lev->base;
852
853 err_free_accepting:
854         mm_free(lev->accepting);
855         /* XXXX free the other elements. */
856 err_delete_lock:
857         EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
858 err_free_lev:
859         mm_free(lev);
860 err:
861         /* Don't close the fd, it is caller's responsibility. */
862         return NULL;
863 }
864
865 #endif