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