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