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