LCOV - code coverage report
Current view: top level - ipc/chromium/src/third_party/libevent - listener.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 175 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13