root/opal/mca/event/libevent2022/libevent/listener.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. listener_incref_and_lock
  2. listener_decref_and_unlock
  3. evconnlistener_new
  4. evconnlistener_new_bind
  5. evconnlistener_free
  6. event_listener_destroy
  7. evconnlistener_enable
  8. evconnlistener_disable
  9. event_listener_enable
  10. event_listener_disable
  11. evconnlistener_get_fd
  12. event_listener_getfd
  13. evconnlistener_get_base
  14. event_listener_getbase
  15. evconnlistener_set_cb
  16. evconnlistener_set_error_cb
  17. listener_read_cb
  18. iocp_listener_event_add
  19. iocp_listener_event_del
  20. new_accepting_socket
  21. free_and_unlock_accepting_socket
  22. start_accepting
  23. stop_accepting
  24. accepted_socket_invoke_user_cb
  25. accepted_socket_cb
  26. iocp_listener_enable
  27. iocp_listener_disable_impl
  28. iocp_listener_disable
  29. iocp_listener_destroy
  30. iocp_listener_getfd
  31. iocp_listener_getbase
  32. evconnlistener_new_async

   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

/* [<][>][^][v][top][bottom][index][help] */