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