1 /* $NetBSD: listener.c,v 1.1.1.2 2015/01/29 06:38:08 spz 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.2 2015/01/29 06:38:08 spz 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 evutil_closesocket(new_fd); 414 UNLOCK(lev); 415 return; 416 } 417 ++lev->refcnt; 418 cb = lev->cb; 419 user_data = lev->user_data; 420 UNLOCK(lev); 421 cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen, 422 user_data); 423 LOCK(lev); 424 if (lev->refcnt == 1) { 425 int freed = listener_decref_and_unlock(lev); 426 EVUTIL_ASSERT(freed); 427 return; 428 } 429 --lev->refcnt; 430 } 431 err = evutil_socket_geterror(fd); 432 if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) { 433 UNLOCK(lev); 434 return; 435 } 436 if (lev->errorcb != NULL) { 437 ++lev->refcnt; 438 errorcb = lev->errorcb; 439 user_data = lev->user_data; 440 UNLOCK(lev); 441 errorcb(lev, user_data); 442 LOCK(lev); 443 listener_decref_and_unlock(lev); 444 } else { 445 event_sock_warn(fd, "Error from accept() call"); 446 } 447 } 448 449 #ifdef WIN32 450 struct accepting_socket { 451 CRITICAL_SECTION lock; 452 struct event_overlapped overlapped; 453 SOCKET s; 454 int error; 455 struct deferred_cb deferred; 456 struct evconnlistener_iocp *lev; 457 ev_uint8_t buflen; 458 ev_uint8_t family; 459 unsigned free_on_cb:1; 460 char addrbuf[1]; 461 }; 462 463 static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, 464 ev_ssize_t n, int ok); 465 static void accepted_socket_invoke_user_cb(struct deferred_cb *cb, void *arg); 466 467 static void 468 iocp_listener_event_add(struct evconnlistener_iocp *lev) 469 { 470 if (lev->event_added) 471 return; 472 473 lev->event_added = 1; 474 event_base_add_virtual(lev->event_base); 475 } 476 477 static void 478 iocp_listener_event_del(struct evconnlistener_iocp *lev) 479 { 480 if (!lev->event_added) 481 return; 482 483 lev->event_added = 0; 484 event_base_del_virtual(lev->event_base); 485 } 486 487 static struct accepting_socket * 488 new_accepting_socket(struct evconnlistener_iocp *lev, int family) 489 { 490 struct accepting_socket *res; 491 int addrlen; 492 int buflen; 493 494 if (family == AF_INET) 495 addrlen = sizeof(struct sockaddr_in); 496 else if (family == AF_INET6) 497 addrlen = sizeof(struct sockaddr_in6); 498 else 499 return NULL; 500 buflen = (addrlen+16)*2; 501 502 res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen); 503 if (!res) 504 return NULL; 505 506 event_overlapped_init(&res->overlapped, accepted_socket_cb); 507 res->s = INVALID_SOCKET; 508 res->lev = lev; 509 res->buflen = buflen; 510 res->family = family; 511 512 event_deferred_cb_init(&res->deferred, 513 accepted_socket_invoke_user_cb, res); 514 515 InitializeCriticalSectionAndSpinCount(&res->lock, 1000); 516 517 return res; 518 } 519 520 static void 521 free_and_unlock_accepting_socket(struct accepting_socket *as) 522 { 523 /* requires lock. */ 524 if (as->s != INVALID_SOCKET) 525 closesocket(as->s); 526 527 LeaveCriticalSection(&as->lock); 528 DeleteCriticalSection(&as->lock); 529 mm_free(as); 530 } 531 532 static int 533 start_accepting(struct accepting_socket *as) 534 { 535 /* requires lock */ 536 const struct win32_extension_fns *ext = event_get_win32_extension_fns(); 537 DWORD pending = 0; 538 SOCKET s = socket(as->family, SOCK_STREAM, 0); 539 int error = 0; 540 541 if (!as->lev->base.enabled) 542 return 0; 543 544 if (s == INVALID_SOCKET) { 545 error = WSAGetLastError(); 546 goto report_err; 547 } 548 549 /* XXXX It turns out we need to do this again later. Does this call 550 * have any effect? */ 551 setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 552 (char *)&as->lev->fd, sizeof(&as->lev->fd)); 553 554 if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) 555 evutil_make_socket_nonblocking(s); 556 557 if (event_iocp_port_associate(as->lev->port, s, 1) < 0) { 558 closesocket(s); 559 return -1; 560 } 561 562 as->s = s; 563 564 if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0, 565 as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped)) 566 { 567 /* Immediate success! */ 568 accepted_socket_cb(&as->overlapped, 1, 0, 1); 569 } else { 570 error = WSAGetLastError(); 571 if (error != ERROR_IO_PENDING) { 572 goto report_err; 573 } 574 } 575 576 return 0; 577 578 report_err: 579 as->error = error; 580 event_deferred_cb_schedule( 581 event_base_get_deferred_cb_queue(as->lev->event_base), 582 &as->deferred); 583 return 0; 584 } 585 586 static void 587 stop_accepting(struct accepting_socket *as) 588 { 589 /* requires lock. */ 590 SOCKET s = as->s; 591 as->s = INVALID_SOCKET; 592 closesocket(s); 593 } 594 595 static void 596 accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg) 597 { 598 struct accepting_socket *as = arg; 599 600 struct sockaddr *sa_local=NULL, *sa_remote=NULL; 601 int socklen_local=0, socklen_remote=0; 602 const struct win32_extension_fns *ext = event_get_win32_extension_fns(); 603 struct evconnlistener *lev = &as->lev->base; 604 evutil_socket_t sock=-1; 605 void *data; 606 evconnlistener_cb cb=NULL; 607 evconnlistener_errorcb errorcb=NULL; 608 int error; 609 610 EVUTIL_ASSERT(ext->GetAcceptExSockaddrs); 611 612 LOCK(lev); 613 EnterCriticalSection(&as->lock); 614 if (as->free_on_cb) { 615 free_and_unlock_accepting_socket(as); 616 listener_decref_and_unlock(lev); 617 return; 618 } 619 620 ++lev->refcnt; 621 622 error = as->error; 623 if (error) { 624 as->error = 0; 625 errorcb = lev->errorcb; 626 } else { 627 ext->GetAcceptExSockaddrs( 628 as->addrbuf, 0, as->buflen/2, as->buflen/2, 629 &sa_local, &socklen_local, &sa_remote, 630 &socklen_remote); 631 sock = as->s; 632 cb = lev->cb; 633 as->s = INVALID_SOCKET; 634 635 /* We need to call this so getsockname, getpeername, and 636 * shutdown work correctly on the accepted socket. */ 637 /* XXXX handle error? */ 638 setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 639 (char *)&as->lev->fd, sizeof(&as->lev->fd)); 640 } 641 data = lev->user_data; 642 643 LeaveCriticalSection(&as->lock); 644 UNLOCK(lev); 645 646 if (errorcb) { 647 WSASetLastError(error); 648 errorcb(lev, data); 649 } else if (cb) { 650 cb(lev, sock, sa_remote, socklen_remote, data); 651 } 652 653 LOCK(lev); 654 if (listener_decref_and_unlock(lev)) 655 return; 656 657 EnterCriticalSection(&as->lock); 658 start_accepting(as); 659 LeaveCriticalSection(&as->lock); 660 } 661 662 static void 663 accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok) 664 { 665 struct accepting_socket *as = 666 EVUTIL_UPCAST(o, struct accepting_socket, overlapped); 667 668 LOCK(&as->lev->base); 669 EnterCriticalSection(&as->lock); 670 if (ok) { 671 /* XXXX Don't do this if some EV_MT flag is set. */ 672 event_deferred_cb_schedule( 673 event_base_get_deferred_cb_queue(as->lev->event_base), 674 &as->deferred); 675 LeaveCriticalSection(&as->lock); 676 } else if (as->free_on_cb) { 677 struct evconnlistener *lev = &as->lev->base; 678 free_and_unlock_accepting_socket(as); 679 listener_decref_and_unlock(lev); 680 return; 681 } else if (as->s == INVALID_SOCKET) { 682 /* This is okay; we were disabled by iocp_listener_disable. */ 683 LeaveCriticalSection(&as->lock); 684 } else { 685 /* Some error on accept that we couldn't actually handle. */ 686 BOOL ok; 687 DWORD transfer = 0, flags=0; 688 event_sock_warn(as->s, "Unexpected error on AcceptEx"); 689 ok = WSAGetOverlappedResult(as->s, &o->overlapped, 690 &transfer, FALSE, &flags); 691 if (ok) { 692 /* well, that was confusing! */ 693 as->error = 1; 694 } else { 695 as->error = WSAGetLastError(); 696 } 697 event_deferred_cb_schedule( 698 event_base_get_deferred_cb_queue(as->lev->event_base), 699 &as->deferred); 700 LeaveCriticalSection(&as->lock); 701 } 702 UNLOCK(&as->lev->base); 703 } 704 705 static int 706 iocp_listener_enable(struct evconnlistener *lev) 707 { 708 int i; 709 struct evconnlistener_iocp *lev_iocp = 710 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 711 712 LOCK(lev); 713 iocp_listener_event_add(lev_iocp); 714 for (i = 0; i < lev_iocp->n_accepting; ++i) { 715 struct accepting_socket *as = lev_iocp->accepting[i]; 716 if (!as) 717 continue; 718 EnterCriticalSection(&as->lock); 719 if (!as->free_on_cb && as->s == INVALID_SOCKET) 720 start_accepting(as); 721 LeaveCriticalSection(&as->lock); 722 } 723 UNLOCK(lev); 724 return 0; 725 } 726 727 static int 728 iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown) 729 { 730 int i; 731 struct evconnlistener_iocp *lev_iocp = 732 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 733 734 LOCK(lev); 735 iocp_listener_event_del(lev_iocp); 736 for (i = 0; i < lev_iocp->n_accepting; ++i) { 737 struct accepting_socket *as = lev_iocp->accepting[i]; 738 if (!as) 739 continue; 740 EnterCriticalSection(&as->lock); 741 if (!as->free_on_cb && as->s != INVALID_SOCKET) { 742 if (shutdown) 743 as->free_on_cb = 1; 744 stop_accepting(as); 745 } 746 LeaveCriticalSection(&as->lock); 747 } 748 749 if (shutdown && lev->flags & LEV_OPT_CLOSE_ON_FREE) 750 evutil_closesocket(lev_iocp->fd); 751 752 UNLOCK(lev); 753 return 0; 754 } 755 756 static int 757 iocp_listener_disable(struct evconnlistener *lev) 758 { 759 return iocp_listener_disable_impl(lev,0); 760 } 761 762 static void 763 iocp_listener_destroy(struct evconnlistener *lev) 764 { 765 struct evconnlistener_iocp *lev_iocp = 766 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 767 768 if (! lev_iocp->shutting_down) { 769 lev_iocp->shutting_down = 1; 770 iocp_listener_disable_impl(lev,1); 771 } 772 773 } 774 775 static evutil_socket_t 776 iocp_listener_getfd(struct evconnlistener *lev) 777 { 778 struct evconnlistener_iocp *lev_iocp = 779 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 780 return lev_iocp->fd; 781 } 782 static struct event_base * 783 iocp_listener_getbase(struct evconnlistener *lev) 784 { 785 struct evconnlistener_iocp *lev_iocp = 786 EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 787 return lev_iocp->event_base; 788 } 789 790 static const struct evconnlistener_ops evconnlistener_iocp_ops = { 791 iocp_listener_enable, 792 iocp_listener_disable, 793 iocp_listener_destroy, 794 iocp_listener_destroy, /* shutdown */ 795 iocp_listener_getfd, 796 iocp_listener_getbase 797 }; 798 799 /* XXX define some way to override this. */ 800 #define N_SOCKETS_PER_LISTENER 4 801 802 struct evconnlistener * 803 evconnlistener_new_async(struct event_base *base, 804 evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 805 evutil_socket_t fd) 806 { 807 struct sockaddr_storage ss; 808 int socklen = sizeof(ss); 809 struct evconnlistener_iocp *lev; 810 int i; 811 812 flags |= LEV_OPT_THREADSAFE; 813 814 if (!base || !event_base_get_iocp(base)) 815 goto err; 816 817 /* XXXX duplicate code */ 818 if (backlog > 0) { 819 if (listen(fd, backlog) < 0) 820 goto err; 821 } else if (backlog < 0) { 822 if (listen(fd, 128) < 0) 823 goto err; 824 } 825 if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { 826 event_sock_warn(fd, "getsockname"); 827 goto err; 828 } 829 lev = mm_calloc(1, sizeof(struct evconnlistener_iocp)); 830 if (!lev) { 831 event_warn("calloc"); 832 goto err; 833 } 834 lev->base.ops = &evconnlistener_iocp_ops; 835 lev->base.cb = cb; 836 lev->base.user_data = ptr; 837 lev->base.flags = flags; 838 lev->base.refcnt = 1; 839 lev->base.enabled = 1; 840 841 lev->port = event_base_get_iocp(base); 842 lev->fd = fd; 843 lev->event_base = base; 844 845 846 if (event_iocp_port_associate(lev->port, fd, 1) < 0) 847 goto err_free_lev; 848 849 EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 850 851 lev->n_accepting = N_SOCKETS_PER_LISTENER; 852 lev->accepting = mm_calloc(lev->n_accepting, 853 sizeof(struct accepting_socket *)); 854 if (!lev->accepting) { 855 event_warn("calloc"); 856 goto err_delete_lock; 857 } 858 for (i = 0; i < lev->n_accepting; ++i) { 859 lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); 860 if (!lev->accepting[i]) { 861 event_warnx("Couldn't create accepting socket"); 862 goto err_free_accepting; 863 } 864 if (cb && start_accepting(lev->accepting[i]) < 0) { 865 event_warnx("Couldn't start accepting on socket"); 866 EnterCriticalSection(&lev->accepting[i]->lock); 867 free_and_unlock_accepting_socket(lev->accepting[i]); 868 goto err_free_accepting; 869 } 870 ++lev->base.refcnt; 871 } 872 873 iocp_listener_event_add(lev); 874 875 return &lev->base; 876 877 err_free_accepting: 878 mm_free(lev->accepting); 879 /* XXXX free the other elements. */ 880 err_delete_lock: 881 EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 882 err_free_lev: 883 mm_free(lev); 884 err: 885 /* Don't close the fd, it is caller's responsibility. */ 886 return NULL; 887 } 888 889 #endif 890