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