]> arthur.barton.de Git - netatalk.git/blob - libevent/listener.c
Merge 2-2
[netatalk.git] / libevent / listener.c
1 /*
2  * Copyright (c) 2009-2012 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                 if (socklen == 0) {
394                         /* This can happen with some older linux kernels in
395                          * response to nmap. */
396                         evutil_closesocket(new_fd);
397                         continue;
398                 }
399
400                 if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
401                         evutil_make_socket_nonblocking(new_fd);
402
403                 if (lev->cb == NULL) {
404                         UNLOCK(lev);
405                         return;
406                 }
407                 ++lev->refcnt;
408                 cb = lev->cb;
409                 user_data = lev->user_data;
410                 UNLOCK(lev);
411                 cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
412                     user_data);
413                 LOCK(lev);
414                 if (lev->refcnt == 1) {
415                         int freed = listener_decref_and_unlock(lev);
416                         EVUTIL_ASSERT(freed);
417                         return;
418                 }
419                 --lev->refcnt;
420         }
421         err = evutil_socket_geterror(fd);
422         if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
423                 UNLOCK(lev);
424                 return;
425         }
426         if (lev->errorcb != NULL) {
427                 ++lev->refcnt;
428                 errorcb = lev->errorcb;
429                 user_data = lev->user_data;
430                 UNLOCK(lev);
431                 errorcb(lev, user_data);
432                 LOCK(lev);
433                 listener_decref_and_unlock(lev);
434         } else {
435                 event_sock_warn(fd, "Error from accept() call");
436         }
437 }
438
439 #ifdef WIN32
440 struct accepting_socket {
441         CRITICAL_SECTION lock;
442         struct event_overlapped overlapped;
443         SOCKET s;
444         int error;
445         struct deferred_cb deferred;
446         struct evconnlistener_iocp *lev;
447         ev_uint8_t buflen;
448         ev_uint8_t family;
449         unsigned free_on_cb:1;
450         char addrbuf[1];
451 };
452
453 static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
454     ev_ssize_t n, int ok);
455 static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
456
457 static void
458 iocp_listener_event_add(struct evconnlistener_iocp *lev)
459 {
460         if (lev->event_added)
461                 return;
462
463         lev->event_added = 1;
464         event_base_add_virtual(lev->event_base);
465 }
466
467 static void
468 iocp_listener_event_del(struct evconnlistener_iocp *lev)
469 {
470         if (!lev->event_added)
471                 return;
472
473         lev->event_added = 0;
474         event_base_del_virtual(lev->event_base);
475 }
476
477 static struct accepting_socket *
478 new_accepting_socket(struct evconnlistener_iocp *lev, int family)
479 {
480         struct accepting_socket *res;
481         int addrlen;
482         int buflen;
483
484         if (family == AF_INET)
485                 addrlen = sizeof(struct sockaddr_in);
486         else if (family == AF_INET6)
487                 addrlen = sizeof(struct sockaddr_in6);
488         else
489                 return NULL;
490         buflen = (addrlen+16)*2;
491
492         res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen);
493         if (!res)
494                 return NULL;
495
496         event_overlapped_init(&res->overlapped, accepted_socket_cb);
497         res->s = INVALID_SOCKET;
498         res->lev = lev;
499         res->buflen = buflen;
500         res->family = family;
501
502         event_deferred_cb_init(&res->deferred,
503                 accepted_socket_invoke_user_cb, res);
504
505         InitializeCriticalSectionAndSpinCount(&res->lock, 1000);
506
507         return res;
508 }
509
510 static void
511 free_and_unlock_accepting_socket(struct accepting_socket *as)
512 {
513         /* requires lock. */
514         if (as->s != INVALID_SOCKET)
515                 closesocket(as->s);
516
517         LeaveCriticalSection(&as->lock);
518         DeleteCriticalSection(&as->lock);
519         mm_free(as);
520 }
521
522 static int
523 start_accepting(struct accepting_socket *as)
524 {
525         /* requires lock */
526         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
527         DWORD pending = 0;
528         SOCKET s = socket(as->family, SOCK_STREAM, 0);
529         int error = 0;
530
531         if (!as->lev->base.enabled)
532                 return 0;
533
534         if (s == INVALID_SOCKET) {
535                 error = WSAGetLastError();
536                 goto report_err;
537         }
538
539         /* XXXX It turns out we need to do this again later.  Does this call
540          * have any effect? */
541         setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
542             (char *)&as->lev->fd, sizeof(&as->lev->fd));
543
544         if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
545                 evutil_make_socket_nonblocking(s);
546
547         if (event_iocp_port_associate(as->lev->port, s, 1) < 0) {
548                 closesocket(s);
549                 return -1;
550         }
551
552         as->s = s;
553
554         if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0,
555                 as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped))
556         {
557                 /* Immediate success! */
558                 accepted_socket_cb(&as->overlapped, 1, 0, 1);
559         } else {
560                 error = WSAGetLastError();
561                 if (error != ERROR_IO_PENDING) {
562                         goto report_err;
563                 }
564         }
565
566         return 0;
567
568 report_err:
569         as->error = error;
570         event_deferred_cb_schedule(
571                 event_base_get_deferred_cb_queue(as->lev->event_base),
572                 &as->deferred);
573         return 0;
574 }
575
576 static void
577 stop_accepting(struct accepting_socket *as)
578 {
579         /* requires lock. */
580         SOCKET s = as->s;
581         as->s = INVALID_SOCKET;
582         closesocket(s);
583 }
584
585 static void
586 accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
587 {
588         struct accepting_socket *as = arg;
589
590         struct sockaddr *sa_local=NULL, *sa_remote=NULL;
591         int socklen_local=0, socklen_remote=0;
592         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
593         struct evconnlistener *lev = &as->lev->base;
594         evutil_socket_t sock=-1;
595         void *data;
596         evconnlistener_cb cb=NULL;
597         evconnlistener_errorcb errorcb=NULL;
598         int error;
599
600         EVUTIL_ASSERT(ext->GetAcceptExSockaddrs);
601
602         LOCK(lev);
603         EnterCriticalSection(&as->lock);
604         if (as->free_on_cb) {
605                 free_and_unlock_accepting_socket(as);
606                 listener_decref_and_unlock(lev);
607                 return;
608         }
609
610         ++lev->refcnt;
611
612         error = as->error;
613         if (error) {
614                 as->error = 0;
615                 errorcb = lev->errorcb;
616         } else {
617                 ext->GetAcceptExSockaddrs(
618                         as->addrbuf, 0, as->buflen/2, as->buflen/2,
619                         &sa_local, &socklen_local, &sa_remote,
620                         &socklen_remote);
621                 sock = as->s;
622                 cb = lev->cb;
623                 as->s = INVALID_SOCKET;
624
625                 /* We need to call this so getsockname, getpeername, and
626                  * shutdown work correctly on the accepted socket. */
627                 /* XXXX handle error? */
628                 setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
629                     (char *)&as->lev->fd, sizeof(&as->lev->fd));
630         }
631         data = lev->user_data;
632
633         LeaveCriticalSection(&as->lock);
634         UNLOCK(lev);
635
636         if (errorcb) {
637                 WSASetLastError(error);
638                 errorcb(lev, data);
639         } else if (cb) {
640                 cb(lev, sock, sa_remote, socklen_remote, data);
641         }
642
643         LOCK(lev);
644         if (listener_decref_and_unlock(lev))
645                 return;
646
647         EnterCriticalSection(&as->lock);
648         start_accepting(as);
649         LeaveCriticalSection(&as->lock);
650 }
651
652 static void
653 accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok)
654 {
655         struct accepting_socket *as =
656             EVUTIL_UPCAST(o, struct accepting_socket, overlapped);
657
658         LOCK(&as->lev->base);
659         EnterCriticalSection(&as->lock);
660         if (ok) {
661                 /* XXXX Don't do this if some EV_MT flag is set. */
662                 event_deferred_cb_schedule(
663                         event_base_get_deferred_cb_queue(as->lev->event_base),
664                         &as->deferred);
665                 LeaveCriticalSection(&as->lock);
666         } else if (as->free_on_cb) {
667                 struct evconnlistener *lev = &as->lev->base;
668                 free_and_unlock_accepting_socket(as);
669                 listener_decref_and_unlock(lev);
670                 return;
671         } else if (as->s == INVALID_SOCKET) {
672                 /* This is okay; we were disabled by iocp_listener_disable. */
673                 LeaveCriticalSection(&as->lock);
674         } else {
675                 /* Some error on accept that we couldn't actually handle. */
676                 BOOL ok;
677                 DWORD transfer = 0, flags=0;
678                 event_sock_warn(as->s, "Unexpected error on AcceptEx");
679                 ok = WSAGetOverlappedResult(as->s, &o->overlapped,
680                     &transfer, FALSE, &flags);
681                 if (ok) {
682                         /* well, that was confusing! */
683                         as->error = 1;
684                 } else {
685                         as->error = WSAGetLastError();
686                 }
687                 event_deferred_cb_schedule(
688                         event_base_get_deferred_cb_queue(as->lev->event_base),
689                         &as->deferred);
690                 LeaveCriticalSection(&as->lock);
691         }
692         UNLOCK(&as->lev->base);
693 }
694
695 static int
696 iocp_listener_enable(struct evconnlistener *lev)
697 {
698         int i;
699         struct evconnlistener_iocp *lev_iocp =
700             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
701
702         LOCK(lev);
703         iocp_listener_event_add(lev_iocp);
704         for (i = 0; i < lev_iocp->n_accepting; ++i) {
705                 struct accepting_socket *as = lev_iocp->accepting[i];
706                 if (!as)
707                         continue;
708                 EnterCriticalSection(&as->lock);
709                 if (!as->free_on_cb && as->s == INVALID_SOCKET)
710                         start_accepting(as);
711                 LeaveCriticalSection(&as->lock);
712         }
713         UNLOCK(lev);
714         return 0;
715 }
716
717 static int
718 iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
719 {
720         int i;
721         struct evconnlistener_iocp *lev_iocp =
722             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
723
724         LOCK(lev);
725         iocp_listener_event_del(lev_iocp);
726         for (i = 0; i < lev_iocp->n_accepting; ++i) {
727                 struct accepting_socket *as = lev_iocp->accepting[i];
728                 if (!as)
729                         continue;
730                 EnterCriticalSection(&as->lock);
731                 if (!as->free_on_cb && as->s != INVALID_SOCKET) {
732                         if (shutdown)
733                                 as->free_on_cb = 1;
734                         stop_accepting(as);
735                 }
736                 LeaveCriticalSection(&as->lock);
737         }
738         UNLOCK(lev);
739         return 0;
740 }
741
742 static int
743 iocp_listener_disable(struct evconnlistener *lev)
744 {
745         return iocp_listener_disable_impl(lev,0);
746 }
747
748 static void
749 iocp_listener_destroy(struct evconnlistener *lev)
750 {
751         struct evconnlistener_iocp *lev_iocp =
752             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
753
754         if (! lev_iocp->shutting_down) {
755                 lev_iocp->shutting_down = 1;
756                 iocp_listener_disable_impl(lev,1);
757         }
758
759 }
760
761 static evutil_socket_t
762 iocp_listener_getfd(struct evconnlistener *lev)
763 {
764         struct evconnlistener_iocp *lev_iocp =
765             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
766         return lev_iocp->fd;
767 }
768 static struct event_base *
769 iocp_listener_getbase(struct evconnlistener *lev)
770 {
771         struct evconnlistener_iocp *lev_iocp =
772             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
773         return lev_iocp->event_base;
774 }
775
776 static const struct evconnlistener_ops evconnlistener_iocp_ops = {
777         iocp_listener_enable,
778         iocp_listener_disable,
779         iocp_listener_destroy,
780         iocp_listener_destroy, /* shutdown */
781         iocp_listener_getfd,
782         iocp_listener_getbase
783 };
784
785 /* XXX define some way to override this. */
786 #define N_SOCKETS_PER_LISTENER 4
787
788 struct evconnlistener *
789 evconnlistener_new_async(struct event_base *base,
790     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
791     evutil_socket_t fd)
792 {
793         struct sockaddr_storage ss;
794         int socklen = sizeof(ss);
795         struct evconnlistener_iocp *lev;
796         int i;
797
798         flags |= LEV_OPT_THREADSAFE;
799
800         if (!base || !event_base_get_iocp(base))
801                 goto err;
802
803         /* XXXX duplicate code */
804         if (backlog > 0) {
805                 if (listen(fd, backlog) < 0)
806                         goto err;
807         } else if (backlog < 0) {
808                 if (listen(fd, 128) < 0)
809                         goto err;
810         }
811         if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
812                 event_sock_warn(fd, "getsockname");
813                 goto err;
814         }
815         lev = mm_calloc(1, sizeof(struct evconnlistener_iocp));
816         if (!lev) {
817                 event_warn("calloc");
818                 goto err;
819         }
820         lev->base.ops = &evconnlistener_iocp_ops;
821         lev->base.cb = cb;
822         lev->base.user_data = ptr;
823         lev->base.flags = flags;
824         lev->base.refcnt = 1;
825         lev->base.enabled = 1;
826
827         lev->port = event_base_get_iocp(base);
828         lev->fd = fd;
829         lev->event_base = base;
830
831
832         if (event_iocp_port_associate(lev->port, fd, 1) < 0)
833                 goto err_free_lev;
834
835         EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
836
837         lev->n_accepting = N_SOCKETS_PER_LISTENER;
838         lev->accepting = mm_calloc(lev->n_accepting,
839             sizeof(struct accepting_socket *));
840         if (!lev->accepting) {
841                 event_warn("calloc");
842                 goto err_delete_lock;
843         }
844         for (i = 0; i < lev->n_accepting; ++i) {
845                 lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
846                 if (!lev->accepting[i]) {
847                         event_warnx("Couldn't create accepting socket");
848                         goto err_free_accepting;
849                 }
850                 if (cb && start_accepting(lev->accepting[i]) < 0) {
851                         event_warnx("Couldn't start accepting on socket");
852                         EnterCriticalSection(&lev->accepting[i]->lock);
853                         free_and_unlock_accepting_socket(lev->accepting[i]);
854                         goto err_free_accepting;
855                 }
856                 ++lev->base.refcnt;
857         }
858
859         iocp_listener_event_add(lev);
860
861         return &lev->base;
862
863 err_free_accepting:
864         mm_free(lev->accepting);
865         /* XXXX free the other elements. */
866 err_delete_lock:
867         EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
868 err_free_lev:
869         mm_free(lev);
870 err:
871         /* Don't close the fd, it is caller's responsibility. */
872         return NULL;
873 }
874
875 #endif