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