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