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