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