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