• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
listener_decref_and_unlock(struct evconnlistener * listener)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 *
evconnlistener_new(struct event_base * base,evconnlistener_cb cb,void * ptr,unsigned flags,int backlog,evutil_socket_t fd)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 *
evconnlistener_new_bind(struct event_base * base,evconnlistener_cb cb,void * ptr,unsigned flags,int backlog,const struct sockaddr * sa,int socklen)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
evconnlistener_free(struct evconnlistener * lev)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
event_listener_destroy(struct evconnlistener * lev)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
evconnlistener_enable(struct evconnlistener * lev)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
evconnlistener_disable(struct evconnlistener * lev)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
event_listener_enable(struct evconnlistener * lev)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
event_listener_disable(struct evconnlistener * lev)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
evconnlistener_get_fd(struct evconnlistener * lev)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
event_listener_getfd(struct evconnlistener * lev)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 *
evconnlistener_get_base(struct evconnlistener * lev)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 *
event_listener_getbase(struct evconnlistener * lev)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
evconnlistener_set_cb(struct evconnlistener * lev,evconnlistener_cb cb,void * arg)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
evconnlistener_set_error_cb(struct evconnlistener * lev,evconnlistener_errorcb errorcb)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
listener_read_cb(evutil_socket_t fd,short what,void * p)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
iocp_listener_event_add(struct evconnlistener_iocp * lev)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
iocp_listener_event_del(struct evconnlistener_iocp * lev)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 *
new_accepting_socket(struct evconnlistener_iocp * lev,int family)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
free_and_unlock_accepting_socket(struct accepting_socket * as)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
start_accepting(struct accepting_socket * as)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
stop_accepting(struct accepting_socket * as)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
accepted_socket_invoke_user_cb(struct deferred_cb * dcb,void * arg)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
accepted_socket_cb(struct event_overlapped * o,ev_uintptr_t key,ev_ssize_t n,int ok)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
iocp_listener_enable(struct evconnlistener * lev)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
iocp_listener_disable_impl(struct evconnlistener * lev,int shutdown)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
iocp_listener_disable(struct evconnlistener * lev)754 iocp_listener_disable(struct evconnlistener *lev)
755 {
756 	return iocp_listener_disable_impl(lev,0);
757 }
758 
759 static void
iocp_listener_destroy(struct evconnlistener * lev)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
iocp_listener_getfd(struct evconnlistener * lev)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 *
iocp_listener_getbase(struct evconnlistener * lev)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 *
evconnlistener_new_async(struct event_base * base,evconnlistener_cb cb,void * ptr,unsigned flags,int backlog,evutil_socket_t fd)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