1 /* $NetBSD: listener.c,v 1.1.1.1 2013/04/11 16:43:26 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 <sys/types.h> 29 30 #include "event2/event-config.h" 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: listener.c,v 1.1.1.1 2013/04/11 16:43:26 christos Exp $"); 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 68 struct 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 77 struct 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 unsigned enabled : 1; 86 }; 87 88 struct evconnlistener_event { 89 struct evconnlistener base; 90 struct event listener; 91 }; 92 93 #ifdef WIN32 94 struct evconnlistener_iocp { 95 struct evconnlistener base; 96 evutil_socket_t fd; 97 struct event_base *event_base; 98 struct event_iocp_port *port; 99 short n_accepting; 100 unsigned shutting_down : 1; 101 unsigned event_added : 1; 102 struct accepting_socket **accepting; 103 }; 104 #endif 105 106 #define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0) 107 #define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0) 108 109 struct evconnlistener * 110 evconnlistener_new_async(struct event_base *base, 111 evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 112 evutil_socket_t fd); /* XXXX export this? */ 113 114 static int event_listener_enable(struct evconnlistener *); 115 static int event_listener_disable(struct evconnlistener *); 116 static void event_listener_destroy(struct evconnlistener *); 117 static evutil_socket_t event_listener_getfd(struct evconnlistener *); 118 static struct event_base *event_listener_getbase(struct evconnlistener *); 119 120 #if 0 121 static void 122 listener_incref_and_lock(struct evconnlistener *listener) 123 { 124 LOCK(listener); 125 ++listener->refcnt; 126 } 127 #endif 128 129 static int 130 listener_decref_and_unlock(struct evconnlistener *listener) 131 { 132 int refcnt = --listener->refcnt; 133 if (refcnt == 0) { 134 listener->ops->destroy(listener); 135 UNLOCK(listener); 136 EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 137 mm_free(listener); 138 return 1; 139 } else { 140 UNLOCK(listener); 141 return 0; 142 } 143 } 144 145 static const struct evconnlistener_ops evconnlistener_event_ops = { 146 event_listener_enable, 147 event_listener_disable, 148 event_listener_destroy, 149 NULL, /* shutdown */ 150 event_listener_getfd, 151 event_listener_getbase 152 }; 153 154 static void listener_read_cb(evutil_socket_t, short, void *); 155 156 struct evconnlistener * 157 evconnlistener_new(struct event_base *base, 158 evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 159 evutil_socket_t fd) 160 { 161 struct evconnlistener_event *lev; 162 163 #ifdef WIN32 164 if (base && event_base_get_iocp(base)) { 165 const struct win32_extension_fns *ext = 166 event_get_win32_extension_fns(); 167 if (ext->AcceptEx && ext->GetAcceptExSockaddrs) 168 return evconnlistener_new_async(base, cb, ptr, flags, 169 backlog, fd); 170 } 171 #endif 172 173 if (backlog > 0) { 174 if (listen(fd, backlog) < 0) 175 return NULL; 176 } else if (backlog < 0) { 177 if (listen(fd, 128) < 0) 178 return NULL; 179 } 180 181 lev = mm_calloc(1, sizeof(struct evconnlistener_event)); 182 if (!lev) 183 return NULL; 184 185 lev->base.ops = &evconnlistener_event_ops; 186 lev->base.cb = cb; 187 lev->base.user_data = ptr; 188 lev->base.flags = flags; 189 lev->base.refcnt = 1; 190 191 if (flags & LEV_OPT_THREADSAFE) { 192 EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 193 } 194 195 event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST, 196 listener_read_cb, lev); 197 198 evconnlistener_enable(&lev->base); 199 200 return &lev->base; 201 } 202 203 struct evconnlistener * 204 evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, 205 void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, 206 int socklen) 207 { 208 struct evconnlistener *listener; 209 evutil_socket_t fd; 210 int on = 1; 211 int family = sa ? sa->sa_family : AF_UNSPEC; 212 213 if (backlog == 0) 214 return NULL; 215 216 fd = socket(family, SOCK_STREAM, 0); 217 if (fd == -1) 218 return NULL; 219 220 if (evutil_make_socket_nonblocking(fd) < 0) { 221 evutil_closesocket(fd); 222 return NULL; 223 } 224 225 if (flags & LEV_OPT_CLOSE_ON_EXEC) { 226 if (evutil_make_socket_closeonexec(fd) < 0) { 227 evutil_closesocket(fd); 228 return NULL; 229 } 230 } 231 232 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) { 233 evutil_closesocket(fd); 234 return NULL; 235 } 236 if (flags & LEV_OPT_REUSEABLE) { 237 if (evutil_make_listen_socket_reuseable(fd) < 0) { 238 evutil_closesocket(fd); 239 return NULL; 240 } 241 } 242 243 if (sa) { 244 if (bind(fd, sa, socklen)<0) { 245 evutil_closesocket(fd); 246 return NULL; 247 } 248 } 249 250 listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); 251 if (!listener) { 252 evutil_closesocket(fd); 253 return NULL; 254 } 255 256 return listener; 257 } 258 259 void 260 evconnlistener_free(struct evconnlistener *lev) 261 { 262 LOCK(lev); 263 lev->cb = NULL; 264 lev->errorcb = NULL; 265 if (lev->ops->shutdown) 266 lev->ops->shutdown(lev); 267 listener_decref_and_unlock(lev); 268 } 269 270 static void 271 event_listener_destroy(struct evconnlistener *lev) 272 { 273 struct evconnlistener_event *lev_e = 274 EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 275 276 event_del(&lev_e->listener); 277 if (lev->flags & LEV_OPT_CLOSE_ON_FREE) 278 evutil_closesocket(event_get_fd(&lev_e->listener)); 279 event_debug_unassign(&lev_e->listener); 280 } 281 282 int 283 evconnlistener_enable(struct evconnlistener *lev) 284 { 285 int r; 286 LOCK(lev); 287 lev->enabled = 1; 288 if (lev->cb) 289 r = lev->ops->enable(lev); 290 else 291 r = 0; 292 UNLOCK(lev); 293 return r; 294 } 295 296 int 297 evconnlistener_disable(struct evconnlistener *lev) 298 { 299 int r; 300 LOCK(lev); 301 lev->enabled = 0; 302 r = lev->ops->disable(lev); 303 UNLOCK(lev); 304 return r; 305 } 306 307 static int 308 event_listener_enable(struct evconnlistener *lev) 309 { 310 struct evconnlistener_event *lev_e = 311 EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 312 return event_add(&lev_e->listener, NULL); 313 } 314 315 static int 316 event_listener_disable(struct evconnlistener *lev) 317 { 318 struct evconnlistener_event *lev_e = 319 EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 320 return event_del(&lev_e->listener); 321 } 322 323 evutil_socket_t 324 evconnlistener_get_fd(struct evconnlistener *lev) 325 { 326 evutil_socket_t fd; 327 LOCK(lev); 328 fd = lev->ops->getfd(lev); 329 UNLOCK(lev); 330 return fd; 331 } 332 333 static evutil_socket_t 334 event_listener_getfd(struct evconnlistener *lev) 335 { 336 struct evconnlistener_event *lev_e = 337 EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 338 return event_get_fd(&lev_e->listener); 339 } 340 341 struct event_base * 342 evconnlistener_get_base(struct evconnlistener *lev) 343 { 344 struct event_base *base; 345 LOCK(lev); 346 base = lev->ops->getbase(lev); 347 UNLOCK(lev); 348 return base; 349 } 350 351 static struct event_base * 352 event_listener_getbase(struct evconnlistener *lev) 353 { 354 struct evconnlistener_event *lev_e = 355 EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 356 return event_get_base(&lev_e->listener); 357 } 358 359 void 360 evconnlistener_set_cb(struct evconnlistener *lev, 361 evconnlistener_cb cb, void *arg) 362 { 363 int enable = 0; 364 LOCK(lev); 365 if (lev->enabled && !lev->cb) 366 enable = 1; 367 lev->cb = cb; 368 lev->user_data = arg; 369 if (enable) 370 evconnlistener_enable(lev); 371 UNLOCK(lev); 372 } 373 374 void 375 evconnlistener_set_error_cb(struct evconnlistener *lev, 376 evconnlistener_errorcb errorcb) 377 { 378 LOCK(lev); 379 lev->errorcb = errorcb; 380 UNLOCK(lev); 381 } 382 383 static void 384 listener_read_cb(evutil_socket_t fd, short what, void *p) 385 { 386 struct evconnlistener *lev = p; 387 int err; 388 evconnlistener_cb cb; 389 evconnlistener_errorcb errorcb; 390 void *user_data; 391 LOCK(lev); 392 while (1) { 393 struct sockaddr_storage ss; 394 #ifdef WIN32 395 int socklen = sizeof(ss); 396 #else 397 socklen_t socklen = sizeof(ss); 398 #endif 399 evutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen); 400 if (new_fd < 0) 401 break; 402 if (socklen == 0) { 403 /* This can happen with some older linux kernels in 404 * response to nmap. */ 405 evutil_closesocket(new_fd); 406 continue; 407 } 408 409 if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) 410 evutil_make_socket_nonblocking(new_fd); 411 412 if (lev->cb == NULL) { 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 return; 427 } 428 --lev->refcnt; 429 } 430 err = evutil_socket_geterror(fd); 431 if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) { 432 UNLOCK(lev); 433 return; 434 } 435 if (lev->errorcb != NULL) { 436 ++lev->refcnt; 437 errorcb = lev->errorcb; 438 user_data = lev->user_data; 439 UNLOCK(lev); 440 errorcb(lev, user_data); 441 LOCK(lev); 442 listener_decref_and_unlock(lev); 443 } else { 444 event_sock_warn(fd, "Error from accept() call"); 445 } 446 } 447 448 #ifdef WIN32 449 struct accepting_socket { 450 CRITICAL_SECTION lock; 451 struct event_overlapped overlapped; 452 SOCKET s; 453 int error; 454 struct deferred_cb deferred; 455 struct evconnlistener_iocp *lev; 456 ev_uint8_t buflen; 457 ev_uint8_t family; 458 unsigned free_on_cb:1; 459 char addrbuf[1]; 460 }; 461 462 static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, 463 ev_ssize_t n, int ok); 464 static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg); 465 466 static void 467 iocp_listener_event_add(struct evconnlistener_iocp *lev) 468 { 469 if (lev->event_added) 470 return; 471 472 lev->event_added = 1; 473 event_base_add_virtual(lev->event_base); 474 } 475 476 static void 477 iocp_listener_event_del(struct evconnlistener_iocp *lev) 478 { 479 if (!lev->event_added) 480 return; 481 482 lev->event_added = 0; 483 event_base_del_virtual(lev->event_base); 484 } 485 486 static struct accepting_socket * 487 new_accepting_socket(struct evconnlistener_iocp *lev, int family) 488 { 489 struct accepting_socket *res; 490 int addrlen; 491 int buflen; 492 493 if (family == AF_INET) 494 addrlen = sizeof(struct sockaddr_in); 495 else if (family == AF_INET6) 496 addrlen = sizeof(struct sockaddr_in6); 497 else 498 return NULL; 499 buflen = (addrlen+16)*2; 500 501 res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen); 502 if (!res) 503 return NULL; 504 505 event_overlapped_init(&res->overlapped, accepted_socket_cb); 506 res->s = INVALID_SOCKET; 507 res->lev = lev; 508 res->buflen = buflen; 509 res->family = family; 510 511 event_deferred_cb_init(&res->deferred, 512 accepted_socket_invoke_user_cb, res); 513 514 InitializeCriticalSectionAndSpinCount(&res->lock, 1000); 515 516 return res; 517 } 518 519 static void 520 free_and_unlock_accepting_socket(struct accepting_socket *as) 521 { 522 /* requires lock. */ 523 if (as->s != INVALID_SOCKET) 524 closesocket(as->s); 525 526 LeaveCriticalSection(&as->lock); 527 DeleteCriticalSection(&as->lock); 528 mm_free(as); 529 } 530 531 static int 532 start_accepting(struct accepting_socket *as) 533 { 534 /* requires lock */ 535 const struct win32_extension_fns *ext = event_get_win32_extension_fns(); 536 DWORD pending = 0; 537 SOCKET s = socket(as->family, SOCK_STREAM, 0); 538 int error = 0; 539 540 if (!as->lev->base.enabled) 541 return 0; 542 543 if (s == INVALID_SOCKET) { 544 error = WSAGetLastError(); 545 goto report_err; 546 } 547 548 /* XXXX It turns out we need to do this again later. Does this call 549 * have any effect? */ 550 setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 551 (char *)&as->lev->fd, sizeof(&as->lev->fd)); 552 553 if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) 554 evutil_make_socket_nonblocking(s); 555 556 if (event_iocp_port_associate(as->lev->port, s, 1) < 0) { 557 closesocket(s); 558 return -1; 559 } 560 561 as->s = s; 562 563 if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0, 564 as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped)) 565 { 566 /* Immediate success! */ 567 accepted_socket_cb(&as->overlapped, 1, 0, 1); 568 } else { 569 error = WSAGetLastError(); 570 if (error != ERROR_IO_PENDING) { 571 goto report_err; 572 } 573 } 574 575 return 0; 576 577 report_err: 578 as->error = error; 579 event_deferred_cb_schedule( 580 event_base_get_deferred_cb_queue(as->lev->event_base), 581 &as->deferred); 582 return 0; 583 } 584 585 static void 586 stop_accepting(struct accepting_socket *as) 587 { 588 /* requires lock. */ 589 SOCKET s = as->s; 590 as->s = INVALID_SOCKET; 591 closesocket(s); 592 } 593 594 static void 595 accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg) 596 { 597 struct accepting_socket *as = arg; 598 599 struct sockaddr *sa_local=NULL, *sa_remote=NULL; 600 int socklen_local=0, socklen_remote=0; 601 const struct win32_extension_fns *ext = event_get_win32_extension_fns(); 602 struct evconnlistener *lev = &as->lev->base; 603 evutil_socket_t sock=-1; 604 void *data; 605 evconnlistener_cb cb=NULL; 606 evconnlistener_errorcb errorcb=NULL; 607 int error; 608 609 EVUTIL_ASSERT(ext->GetAcceptExSockaddrs); 610 611 LOCK(lev); 612 EnterCriticalSection(&as->lock); 613 if (as->free_on_cb) { 614 free_and_unlock_accepting_socket(as); 615 listener_decref_and_unlock(lev); 616 return; 617 } 618 619 ++lev->refcnt; 620 621 error = as->error; 622 if (error) { 623 as->error = 0; 624 errorcb = lev->errorcb; 625 } else { 626 ext->GetAcceptExSockaddrs( 627 as->addrbuf, 0, as->buflen/2, as->buflen/2, 628 &sa_local, &socklen_local, &sa_remote, 629 &socklen_remote); 630 sock = as->s; 631 cb = lev->cb; 632 as->s = INVALID_SOCKET; 633 634 /* We need to call this so getsockname, getpeername, and 635 * shutdown work correctly on the accepted socket. */ 636 /* XXXX handle error? */ 637 setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 638 (char *)&as->lev->fd, sizeof(&as->lev->fd)); 639 } 640 data = lev->user_data; 641 642 LeaveCriticalSection(&as->lock); 643 UNLOCK(lev); 644 645 if (errorcb) { 646 WSASetLastError(error); 647 errorcb(lev, data); 648 } else if (cb) { 649 cb(lev, sock, sa_remote, socklen_remote, data); 650 } 651 652 LOCK(lev); 653 if (listener_decref_and_unlock(lev)) 654 return; 655 656 EnterCriticalSection(&as->lock); 657 start_accepting(as); 658 LeaveCriticalSection(&as->lock); 659 } 660 661 static void 662 accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok) 663 { 664 struct accepting_socket *as = 665 EVUTIL_UPCAST(o, struct accepting_socket, overlapped); 666 667 LOCK(&as->lev->base); 668 EnterCriticalSection(&as->lock); 669 if (ok) { 670 /* XXXX Don't do this if some EV_MT flag is set. */ 671 event_deferred_cb_schedule( 672 event_base_get_deferred_cb_queue(as->lev->event_base), 673 &as->deferred); 674 LeaveCriticalSection(&as->lock); 675 } else if (as->free_on_cb) { 676 struct evconnlistener *lev = &as->lev->base; 677 free_and_unlock_accepting_socket(as); 678 listener_decref_and_unlock(lev); 679 return; 680 } else if (as->s == INVALID_SOCKET) { 681 /* This is okay; we were disabled by iocp_listener_disable. */ 682 LeaveCriticalSection(&as->lock); 683 } else { 684 /* Some error on accept that we couldn't actually handle. */ 685 BOOL ok; 686 DWORD transfer = 0, flags=0; 687 event_sock_warn(as->s, "Unexpected error on AcceptEx"); 688 ok = WSAGetOverlappedResult(as->s, &o->overlapped, 689 &transfer, FALSE, &flags); 690 if (ok) { 691 /* well, that was confusing! */ 692 as->error = 1; 693 } else { 694 as->error = WSAGetLastError(); 695 } 696 event_deferred_cb_schedule( 697 event_base_get_deferred_cb_queue(as->lev->event_base), 698 &as->deferred); 699 LeaveCriticalSection(&as->lock); 700 } 701 UNLOCK(&as->lev->base); 702 } 703 704 static int 705 iocp_listener_enable(struct evconnlistener *lev) 706 { 707 int i; 708 struct evconnlistener_iocp *lev_iocp = 709 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 710 711 LOCK(lev); 712 iocp_listener_event_add(lev_iocp); 713 for (i = 0; i < lev_iocp->n_accepting; ++i) { 714 struct accepting_socket *as = lev_iocp->accepting[i]; 715 if (!as) 716 continue; 717 EnterCriticalSection(&as->lock); 718 if (!as->free_on_cb && as->s == INVALID_SOCKET) 719 start_accepting(as); 720 LeaveCriticalSection(&as->lock); 721 } 722 UNLOCK(lev); 723 return 0; 724 } 725 726 static int 727 iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown) 728 { 729 int i; 730 struct evconnlistener_iocp *lev_iocp = 731 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 732 733 LOCK(lev); 734 iocp_listener_event_del(lev_iocp); 735 for (i = 0; i < lev_iocp->n_accepting; ++i) { 736 struct accepting_socket *as = lev_iocp->accepting[i]; 737 if (!as) 738 continue; 739 EnterCriticalSection(&as->lock); 740 if (!as->free_on_cb && as->s != INVALID_SOCKET) { 741 if (shutdown) 742 as->free_on_cb = 1; 743 stop_accepting(as); 744 } 745 LeaveCriticalSection(&as->lock); 746 } 747 748 if (shutdown && lev->flags & LEV_OPT_CLOSE_ON_FREE) 749 evutil_closesocket(lev_iocp->fd); 750 751 UNLOCK(lev); 752 return 0; 753 } 754 755 static int 756 iocp_listener_disable(struct evconnlistener *lev) 757 { 758 return iocp_listener_disable_impl(lev,0); 759 } 760 761 static void 762 iocp_listener_destroy(struct evconnlistener *lev) 763 { 764 struct evconnlistener_iocp *lev_iocp = 765 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 766 767 if (! lev_iocp->shutting_down) { 768 lev_iocp->shutting_down = 1; 769 iocp_listener_disable_impl(lev,1); 770 } 771 772 } 773 774 static evutil_socket_t 775 iocp_listener_getfd(struct evconnlistener *lev) 776 { 777 struct evconnlistener_iocp *lev_iocp = 778 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 779 return lev_iocp->fd; 780 } 781 static struct event_base * 782 iocp_listener_getbase(struct evconnlistener *lev) 783 { 784 struct evconnlistener_iocp *lev_iocp = 785 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 786 return lev_iocp->event_base; 787 } 788 789 static const struct evconnlistener_ops evconnlistener_iocp_ops = { 790 iocp_listener_enable, 791 iocp_listener_disable, 792 iocp_listener_destroy, 793 iocp_listener_destroy, /* shutdown */ 794 iocp_listener_getfd, 795 iocp_listener_getbase 796 }; 797 798 /* XXX define some way to override this. */ 799 #define N_SOCKETS_PER_LISTENER 4 800 801 struct evconnlistener * 802 evconnlistener_new_async(struct event_base *base, 803 evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 804 evutil_socket_t fd) 805 { 806 struct sockaddr_storage ss; 807 int socklen = sizeof(ss); 808 struct evconnlistener_iocp *lev; 809 int i; 810 811 flags |= LEV_OPT_THREADSAFE; 812 813 if (!base || !event_base_get_iocp(base)) 814 goto err; 815 816 /* XXXX duplicate code */ 817 if (backlog > 0) { 818 if (listen(fd, backlog) < 0) 819 goto err; 820 } else if (backlog < 0) { 821 if (listen(fd, 128) < 0) 822 goto err; 823 } 824 if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { 825 event_sock_warn(fd, "getsockname"); 826 goto err; 827 } 828 lev = mm_calloc(1, sizeof(struct evconnlistener_iocp)); 829 if (!lev) { 830 event_warn("calloc"); 831 goto err; 832 } 833 lev->base.ops = &evconnlistener_iocp_ops; 834 lev->base.cb = cb; 835 lev->base.user_data = ptr; 836 lev->base.flags = flags; 837 lev->base.refcnt = 1; 838 lev->base.enabled = 1; 839 840 lev->port = event_base_get_iocp(base); 841 lev->fd = fd; 842 lev->event_base = base; 843 844 845 if (event_iocp_port_associate(lev->port, fd, 1) < 0) 846 goto err_free_lev; 847 848 EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 849 850 lev->n_accepting = N_SOCKETS_PER_LISTENER; 851 lev->accepting = mm_calloc(lev->n_accepting, 852 sizeof(struct accepting_socket *)); 853 if (!lev->accepting) { 854 event_warn("calloc"); 855 goto err_delete_lock; 856 } 857 for (i = 0; i < lev->n_accepting; ++i) { 858 lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); 859 if (!lev->accepting[i]) { 860 event_warnx("Couldn't create accepting socket"); 861 goto err_free_accepting; 862 } 863 if (cb && start_accepting(lev->accepting[i]) < 0) { 864 event_warnx("Couldn't start accepting on socket"); 865 EnterCriticalSection(&lev->accepting[i]->lock); 866 free_and_unlock_accepting_socket(lev->accepting[i]); 867 goto err_free_accepting; 868 } 869 ++lev->base.refcnt; 870 } 871 872 iocp_listener_event_add(lev); 873 874 return &lev->base; 875 876 err_free_accepting: 877 mm_free(lev->accepting); 878 /* XXXX free the other elements. */ 879 err_delete_lock: 880 EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 881 err_free_lev: 882 mm_free(lev); 883 err: 884 /* Don't close the fd, it is caller's responsibility. */ 885 return NULL; 886 } 887 888 #endif 889