cleanup spec
[platform/upstream/libevent.git] / 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         if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) {
230                 evutil_closesocket(fd);
231                 return NULL;
232         }
233         if (flags & LEV_OPT_REUSEABLE) {
234                 if (evutil_make_listen_socket_reuseable(fd) < 0) {
235                         evutil_closesocket(fd);
236                         return NULL;
237                 }
238         }
239
240         if (sa) {
241                 if (bind(fd, sa, socklen)<0) {
242                         evutil_closesocket(fd);
243                         return NULL;
244                 }
245         }
246
247         listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);
248         if (!listener) {
249                 evutil_closesocket(fd);
250                 return NULL;
251         }
252
253         return listener;
254 }
255
256 void
257 evconnlistener_free(struct evconnlistener *lev)
258 {
259         LOCK(lev);
260         lev->cb = NULL;
261         lev->errorcb = NULL;
262         if (lev->ops->shutdown)
263                 lev->ops->shutdown(lev);
264         listener_decref_and_unlock(lev);
265 }
266
267 static void
268 event_listener_destroy(struct evconnlistener *lev)
269 {
270         struct evconnlistener_event *lev_e =
271             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
272
273         event_del(&lev_e->listener);
274         if (lev->flags & LEV_OPT_CLOSE_ON_FREE)
275                 evutil_closesocket(event_get_fd(&lev_e->listener));
276         event_debug_unassign(&lev_e->listener);
277 }
278
279 int
280 evconnlistener_enable(struct evconnlistener *lev)
281 {
282         int r;
283         LOCK(lev);
284         lev->enabled = 1;
285         if (lev->cb)
286                 r = lev->ops->enable(lev);
287         else
288                 r = 0;
289         UNLOCK(lev);
290         return r;
291 }
292
293 int
294 evconnlistener_disable(struct evconnlistener *lev)
295 {
296         int r;
297         LOCK(lev);
298         lev->enabled = 0;
299         r = lev->ops->disable(lev);
300         UNLOCK(lev);
301         return r;
302 }
303
304 static int
305 event_listener_enable(struct evconnlistener *lev)
306 {
307         struct evconnlistener_event *lev_e =
308             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
309         return event_add(&lev_e->listener, NULL);
310 }
311
312 static int
313 event_listener_disable(struct evconnlistener *lev)
314 {
315         struct evconnlistener_event *lev_e =
316             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
317         return event_del(&lev_e->listener);
318 }
319
320 evutil_socket_t
321 evconnlistener_get_fd(struct evconnlistener *lev)
322 {
323         evutil_socket_t fd;
324         LOCK(lev);
325         fd = lev->ops->getfd(lev);
326         UNLOCK(lev);
327         return fd;
328 }
329
330 static evutil_socket_t
331 event_listener_getfd(struct evconnlistener *lev)
332 {
333         struct evconnlistener_event *lev_e =
334             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
335         return event_get_fd(&lev_e->listener);
336 }
337
338 struct event_base *
339 evconnlistener_get_base(struct evconnlistener *lev)
340 {
341         struct event_base *base;
342         LOCK(lev);
343         base = lev->ops->getbase(lev);
344         UNLOCK(lev);
345         return base;
346 }
347
348 static struct event_base *
349 event_listener_getbase(struct evconnlistener *lev)
350 {
351         struct evconnlistener_event *lev_e =
352             EVUTIL_UPCAST(lev, struct evconnlistener_event, base);
353         return event_get_base(&lev_e->listener);
354 }
355
356 void
357 evconnlistener_set_cb(struct evconnlistener *lev,
358     evconnlistener_cb cb, void *arg)
359 {
360         int enable = 0;
361         LOCK(lev);
362         if (lev->enabled && !lev->cb)
363                 enable = 1;
364         lev->cb = cb;
365         lev->user_data = arg;
366         if (enable)
367                 evconnlistener_enable(lev);
368         UNLOCK(lev);
369 }
370
371 void
372 evconnlistener_set_error_cb(struct evconnlistener *lev,
373     evconnlistener_errorcb errorcb)
374 {
375         LOCK(lev);
376         lev->errorcb = errorcb;
377         UNLOCK(lev);
378 }
379
380 static void
381 listener_read_cb(evutil_socket_t fd, short what, void *p)
382 {
383         struct evconnlistener *lev = p;
384         int err;
385         evconnlistener_cb cb;
386         evconnlistener_errorcb errorcb;
387         void *user_data;
388         LOCK(lev);
389         while (1) {
390                 struct sockaddr_storage ss;
391 #ifdef WIN32
392                 int socklen = sizeof(ss);
393 #else
394                 socklen_t socklen = sizeof(ss);
395 #endif
396                 evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);
397                 if (new_fd < 0)
398                         break;
399                 if (socklen == 0) {
400                         /* This can happen with some older linux kernels in
401                          * response to nmap. */
402                         evutil_closesocket(new_fd);
403                         continue;
404                 }
405
406                 if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
407                         evutil_make_socket_nonblocking(new_fd);
408
409                 if (lev->cb == NULL) {
410                         UNLOCK(lev);
411                         return;
412                 }
413                 ++lev->refcnt;
414                 cb = lev->cb;
415                 user_data = lev->user_data;
416                 UNLOCK(lev);
417                 cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,
418                     user_data);
419                 LOCK(lev);
420                 if (lev->refcnt == 1) {
421                         int freed = listener_decref_and_unlock(lev);
422                         EVUTIL_ASSERT(freed);
423                         return;
424                 }
425                 --lev->refcnt;
426         }
427         err = evutil_socket_geterror(fd);
428         if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {
429                 UNLOCK(lev);
430                 return;
431         }
432         if (lev->errorcb != NULL) {
433                 ++lev->refcnt;
434                 errorcb = lev->errorcb;
435                 user_data = lev->user_data;
436                 UNLOCK(lev);
437                 errorcb(lev, user_data);
438                 LOCK(lev);
439                 listener_decref_and_unlock(lev);
440         } else {
441                 event_sock_warn(fd, "Error from accept() call");
442         }
443 }
444
445 #ifdef WIN32
446 struct accepting_socket {
447         CRITICAL_SECTION lock;
448         struct event_overlapped overlapped;
449         SOCKET s;
450         int error;
451         struct deferred_cb deferred;
452         struct evconnlistener_iocp *lev;
453         ev_uint8_t buflen;
454         ev_uint8_t family;
455         unsigned free_on_cb:1;
456         char addrbuf[1];
457 };
458
459 static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
460     ev_ssize_t n, int ok);
461 static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
462
463 static void
464 iocp_listener_event_add(struct evconnlistener_iocp *lev)
465 {
466         if (lev->event_added)
467                 return;
468
469         lev->event_added = 1;
470         event_base_add_virtual(lev->event_base);
471 }
472
473 static void
474 iocp_listener_event_del(struct evconnlistener_iocp *lev)
475 {
476         if (!lev->event_added)
477                 return;
478
479         lev->event_added = 0;
480         event_base_del_virtual(lev->event_base);
481 }
482
483 static struct accepting_socket *
484 new_accepting_socket(struct evconnlistener_iocp *lev, int family)
485 {
486         struct accepting_socket *res;
487         int addrlen;
488         int buflen;
489
490         if (family == AF_INET)
491                 addrlen = sizeof(struct sockaddr_in);
492         else if (family == AF_INET6)
493                 addrlen = sizeof(struct sockaddr_in6);
494         else
495                 return NULL;
496         buflen = (addrlen+16)*2;
497
498         res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen);
499         if (!res)
500                 return NULL;
501
502         event_overlapped_init(&res->overlapped, accepted_socket_cb);
503         res->s = INVALID_SOCKET;
504         res->lev = lev;
505         res->buflen = buflen;
506         res->family = family;
507
508         event_deferred_cb_init(&res->deferred,
509                 accepted_socket_invoke_user_cb, res);
510
511         InitializeCriticalSectionAndSpinCount(&res->lock, 1000);
512
513         return res;
514 }
515
516 static void
517 free_and_unlock_accepting_socket(struct accepting_socket *as)
518 {
519         /* requires lock. */
520         if (as->s != INVALID_SOCKET)
521                 closesocket(as->s);
522
523         LeaveCriticalSection(&as->lock);
524         DeleteCriticalSection(&as->lock);
525         mm_free(as);
526 }
527
528 static int
529 start_accepting(struct accepting_socket *as)
530 {
531         /* requires lock */
532         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
533         DWORD pending = 0;
534         SOCKET s = socket(as->family, SOCK_STREAM, 0);
535         int error = 0;
536
537         if (!as->lev->base.enabled)
538                 return 0;
539
540         if (s == INVALID_SOCKET) {
541                 error = WSAGetLastError();
542                 goto report_err;
543         }
544
545         /* XXXX It turns out we need to do this again later.  Does this call
546          * have any effect? */
547         setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
548             (char *)&as->lev->fd, sizeof(&as->lev->fd));
549
550         if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))
551                 evutil_make_socket_nonblocking(s);
552
553         if (event_iocp_port_associate(as->lev->port, s, 1) < 0) {
554                 closesocket(s);
555                 return -1;
556         }
557
558         as->s = s;
559
560         if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0,
561                 as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped))
562         {
563                 /* Immediate success! */
564                 accepted_socket_cb(&as->overlapped, 1, 0, 1);
565         } else {
566                 error = WSAGetLastError();
567                 if (error != ERROR_IO_PENDING) {
568                         goto report_err;
569                 }
570         }
571
572         return 0;
573
574 report_err:
575         as->error = error;
576         event_deferred_cb_schedule(
577                 event_base_get_deferred_cb_queue(as->lev->event_base),
578                 &as->deferred);
579         return 0;
580 }
581
582 static void
583 stop_accepting(struct accepting_socket *as)
584 {
585         /* requires lock. */
586         SOCKET s = as->s;
587         as->s = INVALID_SOCKET;
588         closesocket(s);
589 }
590
591 static void
592 accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
593 {
594         struct accepting_socket *as = arg;
595
596         struct sockaddr *sa_local=NULL, *sa_remote=NULL;
597         int socklen_local=0, socklen_remote=0;
598         const struct win32_extension_fns *ext = event_get_win32_extension_fns();
599         struct evconnlistener *lev = &as->lev->base;
600         evutil_socket_t sock=-1;
601         void *data;
602         evconnlistener_cb cb=NULL;
603         evconnlistener_errorcb errorcb=NULL;
604         int error;
605
606         EVUTIL_ASSERT(ext->GetAcceptExSockaddrs);
607
608         LOCK(lev);
609         EnterCriticalSection(&as->lock);
610         if (as->free_on_cb) {
611                 free_and_unlock_accepting_socket(as);
612                 listener_decref_and_unlock(lev);
613                 return;
614         }
615
616         ++lev->refcnt;
617
618         error = as->error;
619         if (error) {
620                 as->error = 0;
621                 errorcb = lev->errorcb;
622         } else {
623                 ext->GetAcceptExSockaddrs(
624                         as->addrbuf, 0, as->buflen/2, as->buflen/2,
625                         &sa_local, &socklen_local, &sa_remote,
626                         &socklen_remote);
627                 sock = as->s;
628                 cb = lev->cb;
629                 as->s = INVALID_SOCKET;
630
631                 /* We need to call this so getsockname, getpeername, and
632                  * shutdown work correctly on the accepted socket. */
633                 /* XXXX handle error? */
634                 setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
635                     (char *)&as->lev->fd, sizeof(&as->lev->fd));
636         }
637         data = lev->user_data;
638
639         LeaveCriticalSection(&as->lock);
640         UNLOCK(lev);
641
642         if (errorcb) {
643                 WSASetLastError(error);
644                 errorcb(lev, data);
645         } else if (cb) {
646                 cb(lev, sock, sa_remote, socklen_remote, data);
647         }
648
649         LOCK(lev);
650         if (listener_decref_and_unlock(lev))
651                 return;
652
653         EnterCriticalSection(&as->lock);
654         start_accepting(as);
655         LeaveCriticalSection(&as->lock);
656 }
657
658 static void
659 accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok)
660 {
661         struct accepting_socket *as =
662             EVUTIL_UPCAST(o, struct accepting_socket, overlapped);
663
664         LOCK(&as->lev->base);
665         EnterCriticalSection(&as->lock);
666         if (ok) {
667                 /* XXXX Don't do this if some EV_MT flag is set. */
668                 event_deferred_cb_schedule(
669                         event_base_get_deferred_cb_queue(as->lev->event_base),
670                         &as->deferred);
671                 LeaveCriticalSection(&as->lock);
672         } else if (as->free_on_cb) {
673                 struct evconnlistener *lev = &as->lev->base;
674                 free_and_unlock_accepting_socket(as);
675                 listener_decref_and_unlock(lev);
676                 return;
677         } else if (as->s == INVALID_SOCKET) {
678                 /* This is okay; we were disabled by iocp_listener_disable. */
679                 LeaveCriticalSection(&as->lock);
680         } else {
681                 /* Some error on accept that we couldn't actually handle. */
682                 BOOL ok;
683                 DWORD transfer = 0, flags=0;
684                 event_sock_warn(as->s, "Unexpected error on AcceptEx");
685                 ok = WSAGetOverlappedResult(as->s, &o->overlapped,
686                     &transfer, FALSE, &flags);
687                 if (ok) {
688                         /* well, that was confusing! */
689                         as->error = 1;
690                 } else {
691                         as->error = WSAGetLastError();
692                 }
693                 event_deferred_cb_schedule(
694                         event_base_get_deferred_cb_queue(as->lev->event_base),
695                         &as->deferred);
696                 LeaveCriticalSection(&as->lock);
697         }
698         UNLOCK(&as->lev->base);
699 }
700
701 static int
702 iocp_listener_enable(struct evconnlistener *lev)
703 {
704         int i;
705         struct evconnlistener_iocp *lev_iocp =
706             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
707
708         LOCK(lev);
709         iocp_listener_event_add(lev_iocp);
710         for (i = 0; i < lev_iocp->n_accepting; ++i) {
711                 struct accepting_socket *as = lev_iocp->accepting[i];
712                 if (!as)
713                         continue;
714                 EnterCriticalSection(&as->lock);
715                 if (!as->free_on_cb && as->s == INVALID_SOCKET)
716                         start_accepting(as);
717                 LeaveCriticalSection(&as->lock);
718         }
719         UNLOCK(lev);
720         return 0;
721 }
722
723 static int
724 iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
725 {
726         int i;
727         struct evconnlistener_iocp *lev_iocp =
728             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
729
730         LOCK(lev);
731         iocp_listener_event_del(lev_iocp);
732         for (i = 0; i < lev_iocp->n_accepting; ++i) {
733                 struct accepting_socket *as = lev_iocp->accepting[i];
734                 if (!as)
735                         continue;
736                 EnterCriticalSection(&as->lock);
737                 if (!as->free_on_cb && as->s != INVALID_SOCKET) {
738                         if (shutdown)
739                                 as->free_on_cb = 1;
740                         stop_accepting(as);
741                 }
742                 LeaveCriticalSection(&as->lock);
743         }
744         UNLOCK(lev);
745         return 0;
746 }
747
748 static int
749 iocp_listener_disable(struct evconnlistener *lev)
750 {
751         return iocp_listener_disable_impl(lev,0);
752 }
753
754 static void
755 iocp_listener_destroy(struct evconnlistener *lev)
756 {
757         struct evconnlistener_iocp *lev_iocp =
758             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
759
760         if (! lev_iocp->shutting_down) {
761                 lev_iocp->shutting_down = 1;
762                 iocp_listener_disable_impl(lev,1);
763         }
764
765 }
766
767 static evutil_socket_t
768 iocp_listener_getfd(struct evconnlistener *lev)
769 {
770         struct evconnlistener_iocp *lev_iocp =
771             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
772         return lev_iocp->fd;
773 }
774 static struct event_base *
775 iocp_listener_getbase(struct evconnlistener *lev)
776 {
777         struct evconnlistener_iocp *lev_iocp =
778             EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
779         return lev_iocp->event_base;
780 }
781
782 static const struct evconnlistener_ops evconnlistener_iocp_ops = {
783         iocp_listener_enable,
784         iocp_listener_disable,
785         iocp_listener_destroy,
786         iocp_listener_destroy, /* shutdown */
787         iocp_listener_getfd,
788         iocp_listener_getbase
789 };
790
791 /* XXX define some way to override this. */
792 #define N_SOCKETS_PER_LISTENER 4
793
794 struct evconnlistener *
795 evconnlistener_new_async(struct event_base *base,
796     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
797     evutil_socket_t fd)
798 {
799         struct sockaddr_storage ss;
800         int socklen = sizeof(ss);
801         struct evconnlistener_iocp *lev;
802         int i;
803
804         flags |= LEV_OPT_THREADSAFE;
805
806         if (!base || !event_base_get_iocp(base))
807                 goto err;
808
809         /* XXXX duplicate code */
810         if (backlog > 0) {
811                 if (listen(fd, backlog) < 0)
812                         goto err;
813         } else if (backlog < 0) {
814                 if (listen(fd, 128) < 0)
815                         goto err;
816         }
817         if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) {
818                 event_sock_warn(fd, "getsockname");
819                 goto err;
820         }
821         lev = mm_calloc(1, sizeof(struct evconnlistener_iocp));
822         if (!lev) {
823                 event_warn("calloc");
824                 goto err;
825         }
826         lev->base.ops = &evconnlistener_iocp_ops;
827         lev->base.cb = cb;
828         lev->base.user_data = ptr;
829         lev->base.flags = flags;
830         lev->base.refcnt = 1;
831         lev->base.enabled = 1;
832
833         lev->port = event_base_get_iocp(base);
834         lev->fd = fd;
835         lev->event_base = base;
836
837
838         if (event_iocp_port_associate(lev->port, fd, 1) < 0)
839                 goto err_free_lev;
840
841         EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
842
843         lev->n_accepting = N_SOCKETS_PER_LISTENER;
844         lev->accepting = mm_calloc(lev->n_accepting,
845             sizeof(struct accepting_socket *));
846         if (!lev->accepting) {
847                 event_warn("calloc");
848                 goto err_delete_lock;
849         }
850         for (i = 0; i < lev->n_accepting; ++i) {
851                 lev->accepting[i] = new_accepting_socket(lev, ss.ss_family);
852                 if (!lev->accepting[i]) {
853                         event_warnx("Couldn't create accepting socket");
854                         goto err_free_accepting;
855                 }
856                 if (cb && start_accepting(lev->accepting[i]) < 0) {
857                         event_warnx("Couldn't start accepting on socket");
858                         EnterCriticalSection(&lev->accepting[i]->lock);
859                         free_and_unlock_accepting_socket(lev->accepting[i]);
860                         goto err_free_accepting;
861                 }
862                 ++lev->base.refcnt;
863         }
864
865         iocp_listener_event_add(lev);
866
867         return &lev->base;
868
869 err_free_accepting:
870         mm_free(lev->accepting);
871         /* XXXX free the other elements. */
872 err_delete_lock:
873         EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
874 err_free_lev:
875         mm_free(lev);
876 err:
877         /* Don't close the fd, it is caller's responsibility. */
878         return NULL;
879 }
880
881 #endif