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 70struct 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 79struct 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 91struct evconnlistener_event { 92 struct evconnlistener base; 93 struct event listener; 94}; 95 96#ifdef _WIN32 97struct 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 112struct evconnlistener * 113evconnlistener_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 117static int event_listener_enable(struct evconnlistener *); 118static int event_listener_disable(struct evconnlistener *); 119static void event_listener_destroy(struct evconnlistener *); 120static evutil_socket_t event_listener_getfd(struct evconnlistener *); 121static struct event_base *event_listener_getbase(struct evconnlistener *); 122 123#if 0 124static void 125listener_incref_and_lock(struct evconnlistener *listener) 126{ 127 LOCK(listener); 128 ++listener->refcnt; 129} 130#endif 131 132static int 133listener_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 148static 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 157static void listener_read_cb(evutil_socket_t, short, void *); 158 159struct evconnlistener * 160evconnlistener_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 213struct evconnlistener * 214evconnlistener_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; 267err: 268 evutil_closesocket(fd); 269 return NULL; 270} 271 272void 273evconnlistener_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 283static void 284event_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 295int 296evconnlistener_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 309int 310evconnlistener_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 320static int 321event_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 328static int 329event_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 336evutil_socket_t 337evconnlistener_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 346static evutil_socket_t 347event_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 354struct event_base * 355evconnlistener_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 364static struct event_base * 365event_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 372void 373evconnlistener_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 387void 388evconnlistener_set_error_cb(struct evconnlistener *lev, 389 evconnlistener_errorcb errorcb) 390{ 391 LOCK(lev); 392 lev->errorcb = errorcb; 393 UNLOCK(lev); 394} 395 396static void 397listener_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 462struct 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 475static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, 476 ev_ssize_t n, int ok); 477static void accepted_socket_invoke_user_cb(struct event_callback *cb, void *arg); 478 479static void 480iocp_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 489static void 490iocp_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 499static struct accepting_socket * 500new_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 533static void 534free_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 545static int 546start_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 591report_err: 592 as->error = error; 593 event_deferred_cb_schedule_( 594 as->lev->event_base, 595 &as->deferred); 596 return 0; 597} 598 599static void 600stop_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 608static void 609accepted_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 675static void 676accepted_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 718static int 719iocp_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 740static int 741iocp_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 769static int 770iocp_listener_disable(struct evconnlistener *lev) 771{ 772 return iocp_listener_disable_impl(lev,0); 773} 774 775static void 776iocp_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 788static evutil_socket_t 789iocp_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} 795static struct event_base * 796iocp_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 803static 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 815struct evconnlistener * 816evconnlistener_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 890err_free_accepting: 891 mm_free(lev->accepting); 892 /* XXXX free the other elements. */ 893err_delete_lock: 894 EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 895err_free_lev: 896 mm_free(lev); 897err: 898 /* Don't close the fd, it is caller's responsibility. */ 899 return NULL; 900} 901 902#endif 903