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