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