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
65struct 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
74struct 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
85struct evconnlistener_event {
86	struct evconnlistener base;
87	struct event listener;
88};
89
90#ifdef WIN32
91struct 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
106struct evconnlistener *
107evconnlistener_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
111static int event_listener_enable(struct evconnlistener *);
112static int event_listener_disable(struct evconnlistener *);
113static void event_listener_destroy(struct evconnlistener *);
114static evutil_socket_t event_listener_getfd(struct evconnlistener *);
115static struct event_base *event_listener_getbase(struct evconnlistener *);
116
117#if 0
118static void
119listener_incref_and_lock(struct evconnlistener *listener)
120{
121	LOCK(listener);
122	++listener->refcnt;
123}
124#endif
125
126static int
127listener_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
142static 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
151static void listener_read_cb(evutil_socket_t, short, void *);
152
153struct evconnlistener *
154evconnlistener_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
200struct evconnlistener *
201evconnlistener_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
256void
257evconnlistener_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
267static void
268event_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
279int
280evconnlistener_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
293int
294evconnlistener_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
304static int
305event_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
312static int
313event_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
320evutil_socket_t
321evconnlistener_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
330static evutil_socket_t
331event_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
338struct event_base *
339evconnlistener_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
348static struct event_base *
349event_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
356void
357evconnlistener_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
371void
372evconnlistener_set_error_cb(struct evconnlistener *lev,
373    evconnlistener_errorcb errorcb)
374{
375	LOCK(lev);
376	lev->errorcb = errorcb;
377	UNLOCK(lev);
378}
379
380static void
381listener_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
446struct 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
459static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key,
460    ev_ssize_t n, int ok);
461static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg);
462
463static void
464iocp_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
473static void
474iocp_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
483static struct accepting_socket *
484new_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
516static void
517free_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
528static int
529start_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
574report_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
582static void
583stop_accepting(struct accepting_socket *as)
584{
585	/* requires lock. */
586	SOCKET s = as->s;
587	as->s = INVALID_SOCKET;
588	closesocket(s);
589}
590
591static void
592accepted_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
658static void
659accepted_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
701static int
702iocp_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
723static int
724iocp_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
748static int
749iocp_listener_disable(struct evconnlistener *lev)
750{
751	return iocp_listener_disable_impl(lev,0);
752}
753
754static void
755iocp_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
767static evutil_socket_t
768iocp_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}
774static struct event_base *
775iocp_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
782static 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
794struct evconnlistener *
795evconnlistener_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
869err_free_accepting:
870	mm_free(lev->accepting);
871	/* XXXX free the other elements. */
872err_delete_lock:
873	EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
874err_free_lev:
875	mm_free(lev);
876err:
877	/* Don't close the fd, it is caller's responsibility. */
878	return NULL;
879}
880
881#endif
882