1290001Sglebius/* 2290001Sglebius * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson 3290001Sglebius * 4290001Sglebius * Redistribution and use in source and binary forms, with or without 5290001Sglebius * modification, are permitted provided that the following conditions 6290001Sglebius * are met: 7290001Sglebius * 1. Redistributions of source code must retain the above copyright 8290001Sglebius * notice, this list of conditions and the following disclaimer. 9290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer in the 11290001Sglebius * documentation and/or other materials provided with the distribution. 12290001Sglebius * 3. The name of the author may not be used to endorse or promote products 13290001Sglebius * derived from this software without specific prior written permission. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25290001Sglebius */ 26290001Sglebius 27290001Sglebius#include "event2/event-config.h" 28290001Sglebius#include "evconfig-private.h" 29290001Sglebius 30290001Sglebius#include <sys/types.h> 31290001Sglebius 32290001Sglebius#ifdef _WIN32 33290001Sglebius#ifndef _WIN32_WINNT 34290001Sglebius/* Minimum required for InitializeCriticalSectionAndSpinCount */ 35290001Sglebius#define _WIN32_WINNT 0x0403 36290001Sglebius#endif 37290001Sglebius#include <winsock2.h> 38290001Sglebius#include <ws2tcpip.h> 39290001Sglebius#include <mswsock.h> 40290001Sglebius#endif 41290001Sglebius#include <errno.h> 42290001Sglebius#ifdef EVENT__HAVE_SYS_SOCKET_H 43290001Sglebius#include <sys/socket.h> 44290001Sglebius#endif 45290001Sglebius#ifdef EVENT__HAVE_FCNTL_H 46290001Sglebius#include <fcntl.h> 47290001Sglebius#endif 48290001Sglebius#ifdef EVENT__HAVE_UNISTD_H 49290001Sglebius#include <unistd.h> 50290001Sglebius#endif 51290001Sglebius 52290001Sglebius#include "event2/listener.h" 53290001Sglebius#include "event2/util.h" 54290001Sglebius#include "event2/event.h" 55290001Sglebius#include "event2/event_struct.h" 56290001Sglebius#include "mm-internal.h" 57290001Sglebius#include "util-internal.h" 58290001Sglebius#include "log-internal.h" 59290001Sglebius#include "evthread-internal.h" 60290001Sglebius#ifdef _WIN32 61290001Sglebius#include "iocp-internal.h" 62290001Sglebius#include "defer-internal.h" 63290001Sglebius#include "event-internal.h" 64290001Sglebius#endif 65290001Sglebius 66290001Sglebiusstruct evconnlistener_ops { 67290001Sglebius int (*enable)(struct evconnlistener *); 68290001Sglebius int (*disable)(struct evconnlistener *); 69290001Sglebius void (*destroy)(struct evconnlistener *); 70290001Sglebius void (*shutdown)(struct evconnlistener *); 71290001Sglebius evutil_socket_t (*getfd)(struct evconnlistener *); 72290001Sglebius struct event_base *(*getbase)(struct evconnlistener *); 73290001Sglebius}; 74290001Sglebius 75290001Sglebiusstruct evconnlistener { 76290001Sglebius const struct evconnlistener_ops *ops; 77290001Sglebius void *lock; 78290001Sglebius evconnlistener_cb cb; 79290001Sglebius evconnlistener_errorcb errorcb; 80290001Sglebius void *user_data; 81290001Sglebius unsigned flags; 82290001Sglebius short refcnt; 83290001Sglebius int accept4_flags; 84290001Sglebius unsigned enabled : 1; 85290001Sglebius}; 86290001Sglebius 87290001Sglebiusstruct evconnlistener_event { 88290001Sglebius struct evconnlistener base; 89290001Sglebius struct event listener; 90290001Sglebius}; 91290001Sglebius 92290001Sglebius#ifdef _WIN32 93290001Sglebiusstruct evconnlistener_iocp { 94290001Sglebius struct evconnlistener base; 95290001Sglebius evutil_socket_t fd; 96290001Sglebius struct event_base *event_base; 97290001Sglebius struct event_iocp_port *port; 98290001Sglebius short n_accepting; 99290001Sglebius unsigned shutting_down : 1; 100290001Sglebius unsigned event_added : 1; 101290001Sglebius struct accepting_socket **accepting; 102290001Sglebius}; 103290001Sglebius#endif 104290001Sglebius 105290001Sglebius#define LOCK(listener) EVLOCK_LOCK((listener)->lock, 0) 106290001Sglebius#define UNLOCK(listener) EVLOCK_UNLOCK((listener)->lock, 0) 107290001Sglebius 108290001Sglebiusstruct evconnlistener * 109290001Sglebiusevconnlistener_new_async(struct event_base *base, 110290001Sglebius evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 111290001Sglebius evutil_socket_t fd); /* XXXX export this? */ 112290001Sglebius 113290001Sglebiusstatic int event_listener_enable(struct evconnlistener *); 114290001Sglebiusstatic int event_listener_disable(struct evconnlistener *); 115290001Sglebiusstatic void event_listener_destroy(struct evconnlistener *); 116290001Sglebiusstatic evutil_socket_t event_listener_getfd(struct evconnlistener *); 117290001Sglebiusstatic struct event_base *event_listener_getbase(struct evconnlistener *); 118290001Sglebius 119290001Sglebius#if 0 120290001Sglebiusstatic void 121290001Sglebiuslistener_incref_and_lock(struct evconnlistener *listener) 122290001Sglebius{ 123290001Sglebius LOCK(listener); 124290001Sglebius ++listener->refcnt; 125290001Sglebius} 126290001Sglebius#endif 127290001Sglebius 128290001Sglebiusstatic int 129290001Sglebiuslistener_decref_and_unlock(struct evconnlistener *listener) 130290001Sglebius{ 131290001Sglebius int refcnt = --listener->refcnt; 132290001Sglebius if (refcnt == 0) { 133290001Sglebius listener->ops->destroy(listener); 134290001Sglebius UNLOCK(listener); 135290001Sglebius EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 136290001Sglebius mm_free(listener); 137290001Sglebius return 1; 138290001Sglebius } else { 139290001Sglebius UNLOCK(listener); 140290001Sglebius return 0; 141290001Sglebius } 142290001Sglebius} 143290001Sglebius 144290001Sglebiusstatic const struct evconnlistener_ops evconnlistener_event_ops = { 145290001Sglebius event_listener_enable, 146290001Sglebius event_listener_disable, 147290001Sglebius event_listener_destroy, 148290001Sglebius NULL, /* shutdown */ 149290001Sglebius event_listener_getfd, 150290001Sglebius event_listener_getbase 151290001Sglebius}; 152290001Sglebius 153290001Sglebiusstatic void listener_read_cb(evutil_socket_t, short, void *); 154290001Sglebius 155290001Sglebiusstruct evconnlistener * 156290001Sglebiusevconnlistener_new(struct event_base *base, 157290001Sglebius evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 158290001Sglebius evutil_socket_t fd) 159290001Sglebius{ 160290001Sglebius struct evconnlistener_event *lev; 161290001Sglebius 162290001Sglebius#ifdef _WIN32 163290001Sglebius if (base && event_base_get_iocp_(base)) { 164290001Sglebius const struct win32_extension_fns *ext = 165290001Sglebius event_get_win32_extension_fns_(); 166290001Sglebius if (ext->AcceptEx && ext->GetAcceptExSockaddrs) 167290001Sglebius return evconnlistener_new_async(base, cb, ptr, flags, 168290001Sglebius backlog, fd); 169290001Sglebius } 170290001Sglebius#endif 171290001Sglebius 172290001Sglebius if (backlog > 0) { 173290001Sglebius if (listen(fd, backlog) < 0) 174290001Sglebius return NULL; 175290001Sglebius } else if (backlog < 0) { 176290001Sglebius if (listen(fd, 128) < 0) 177290001Sglebius return NULL; 178290001Sglebius } 179290001Sglebius 180290001Sglebius lev = mm_calloc(1, sizeof(struct evconnlistener_event)); 181290001Sglebius if (!lev) 182290001Sglebius return NULL; 183290001Sglebius 184290001Sglebius lev->base.ops = &evconnlistener_event_ops; 185290001Sglebius lev->base.cb = cb; 186290001Sglebius lev->base.user_data = ptr; 187290001Sglebius lev->base.flags = flags; 188290001Sglebius lev->base.refcnt = 1; 189290001Sglebius 190290001Sglebius lev->base.accept4_flags = 0; 191290001Sglebius if (!(flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) 192290001Sglebius lev->base.accept4_flags |= EVUTIL_SOCK_NONBLOCK; 193290001Sglebius if (flags & LEV_OPT_CLOSE_ON_EXEC) 194290001Sglebius lev->base.accept4_flags |= EVUTIL_SOCK_CLOEXEC; 195290001Sglebius 196290001Sglebius if (flags & LEV_OPT_THREADSAFE) { 197290001Sglebius EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 198290001Sglebius } 199290001Sglebius 200290001Sglebius event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST, 201290001Sglebius listener_read_cb, lev); 202290001Sglebius 203290001Sglebius if (!(flags & LEV_OPT_DISABLED)) 204290001Sglebius evconnlistener_enable(&lev->base); 205290001Sglebius 206290001Sglebius return &lev->base; 207290001Sglebius} 208290001Sglebius 209290001Sglebiusstruct evconnlistener * 210290001Sglebiusevconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb, 211290001Sglebius void *ptr, unsigned flags, int backlog, const struct sockaddr *sa, 212290001Sglebius int socklen) 213290001Sglebius{ 214290001Sglebius struct evconnlistener *listener; 215290001Sglebius evutil_socket_t fd; 216290001Sglebius int on = 1; 217290001Sglebius int family = sa ? sa->sa_family : AF_UNSPEC; 218290001Sglebius int socktype = SOCK_STREAM | EVUTIL_SOCK_NONBLOCK; 219290001Sglebius 220290001Sglebius if (backlog == 0) 221290001Sglebius return NULL; 222290001Sglebius 223290001Sglebius if (flags & LEV_OPT_CLOSE_ON_EXEC) 224290001Sglebius socktype |= EVUTIL_SOCK_CLOEXEC; 225290001Sglebius 226290001Sglebius fd = evutil_socket_(family, socktype, 0); 227290001Sglebius if (fd == -1) 228290001Sglebius return NULL; 229290001Sglebius 230290001Sglebius if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) 231290001Sglebius goto err; 232290001Sglebius 233290001Sglebius if (flags & LEV_OPT_REUSEABLE) { 234290001Sglebius if (evutil_make_listen_socket_reuseable(fd) < 0) 235290001Sglebius goto err; 236290001Sglebius } 237290001Sglebius 238290001Sglebius if (flags & LEV_OPT_REUSEABLE_PORT) { 239290001Sglebius if (evutil_make_listen_socket_reuseable_port(fd) < 0) 240290001Sglebius goto err; 241290001Sglebius } 242290001Sglebius 243290001Sglebius if (flags & LEV_OPT_DEFERRED_ACCEPT) { 244290001Sglebius if (evutil_make_tcp_listen_socket_deferred(fd) < 0) 245290001Sglebius goto err; 246290001Sglebius } 247290001Sglebius 248290001Sglebius if (sa) { 249290001Sglebius if (bind(fd, sa, socklen)<0) 250290001Sglebius goto err; 251290001Sglebius } 252290001Sglebius 253290001Sglebius listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd); 254290001Sglebius if (!listener) 255290001Sglebius goto err; 256290001Sglebius 257290001Sglebius return listener; 258290001Sglebiuserr: 259290001Sglebius evutil_closesocket(fd); 260290001Sglebius return NULL; 261290001Sglebius} 262290001Sglebius 263290001Sglebiusvoid 264290001Sglebiusevconnlistener_free(struct evconnlistener *lev) 265290001Sglebius{ 266290001Sglebius LOCK(lev); 267290001Sglebius lev->cb = NULL; 268290001Sglebius lev->errorcb = NULL; 269290001Sglebius if (lev->ops->shutdown) 270290001Sglebius lev->ops->shutdown(lev); 271290001Sglebius listener_decref_and_unlock(lev); 272290001Sglebius} 273290001Sglebius 274290001Sglebiusstatic void 275290001Sglebiusevent_listener_destroy(struct evconnlistener *lev) 276290001Sglebius{ 277290001Sglebius struct evconnlistener_event *lev_e = 278290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 279290001Sglebius 280290001Sglebius event_del(&lev_e->listener); 281290001Sglebius if (lev->flags & LEV_OPT_CLOSE_ON_FREE) 282290001Sglebius evutil_closesocket(event_get_fd(&lev_e->listener)); 283290001Sglebius event_debug_unassign(&lev_e->listener); 284290001Sglebius} 285290001Sglebius 286290001Sglebiusint 287290001Sglebiusevconnlistener_enable(struct evconnlistener *lev) 288290001Sglebius{ 289290001Sglebius int r; 290290001Sglebius LOCK(lev); 291290001Sglebius lev->enabled = 1; 292290001Sglebius if (lev->cb) 293290001Sglebius r = lev->ops->enable(lev); 294290001Sglebius else 295290001Sglebius r = 0; 296290001Sglebius UNLOCK(lev); 297290001Sglebius return r; 298290001Sglebius} 299290001Sglebius 300290001Sglebiusint 301290001Sglebiusevconnlistener_disable(struct evconnlistener *lev) 302290001Sglebius{ 303290001Sglebius int r; 304290001Sglebius LOCK(lev); 305290001Sglebius lev->enabled = 0; 306290001Sglebius r = lev->ops->disable(lev); 307290001Sglebius UNLOCK(lev); 308290001Sglebius return r; 309290001Sglebius} 310290001Sglebius 311290001Sglebiusstatic int 312290001Sglebiusevent_listener_enable(struct evconnlistener *lev) 313290001Sglebius{ 314290001Sglebius struct evconnlistener_event *lev_e = 315290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 316290001Sglebius return event_add(&lev_e->listener, NULL); 317290001Sglebius} 318290001Sglebius 319290001Sglebiusstatic int 320290001Sglebiusevent_listener_disable(struct evconnlistener *lev) 321290001Sglebius{ 322290001Sglebius struct evconnlistener_event *lev_e = 323290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 324290001Sglebius return event_del(&lev_e->listener); 325290001Sglebius} 326290001Sglebius 327290001Sglebiusevutil_socket_t 328290001Sglebiusevconnlistener_get_fd(struct evconnlistener *lev) 329290001Sglebius{ 330290001Sglebius evutil_socket_t fd; 331290001Sglebius LOCK(lev); 332290001Sglebius fd = lev->ops->getfd(lev); 333290001Sglebius UNLOCK(lev); 334290001Sglebius return fd; 335290001Sglebius} 336290001Sglebius 337290001Sglebiusstatic evutil_socket_t 338290001Sglebiusevent_listener_getfd(struct evconnlistener *lev) 339290001Sglebius{ 340290001Sglebius struct evconnlistener_event *lev_e = 341290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 342290001Sglebius return event_get_fd(&lev_e->listener); 343290001Sglebius} 344290001Sglebius 345290001Sglebiusstruct event_base * 346290001Sglebiusevconnlistener_get_base(struct evconnlistener *lev) 347290001Sglebius{ 348290001Sglebius struct event_base *base; 349290001Sglebius LOCK(lev); 350290001Sglebius base = lev->ops->getbase(lev); 351290001Sglebius UNLOCK(lev); 352290001Sglebius return base; 353290001Sglebius} 354290001Sglebius 355290001Sglebiusstatic struct event_base * 356290001Sglebiusevent_listener_getbase(struct evconnlistener *lev) 357290001Sglebius{ 358290001Sglebius struct evconnlistener_event *lev_e = 359290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_event, base); 360290001Sglebius return event_get_base(&lev_e->listener); 361290001Sglebius} 362290001Sglebius 363290001Sglebiusvoid 364290001Sglebiusevconnlistener_set_cb(struct evconnlistener *lev, 365290001Sglebius evconnlistener_cb cb, void *arg) 366290001Sglebius{ 367290001Sglebius int enable = 0; 368290001Sglebius LOCK(lev); 369290001Sglebius if (lev->enabled && !lev->cb) 370290001Sglebius enable = 1; 371290001Sglebius lev->cb = cb; 372290001Sglebius lev->user_data = arg; 373290001Sglebius if (enable) 374290001Sglebius evconnlistener_enable(lev); 375290001Sglebius UNLOCK(lev); 376290001Sglebius} 377290001Sglebius 378290001Sglebiusvoid 379290001Sglebiusevconnlistener_set_error_cb(struct evconnlistener *lev, 380290001Sglebius evconnlistener_errorcb errorcb) 381290001Sglebius{ 382290001Sglebius LOCK(lev); 383290001Sglebius lev->errorcb = errorcb; 384290001Sglebius UNLOCK(lev); 385290001Sglebius} 386290001Sglebius 387290001Sglebiusstatic void 388290001Sglebiuslistener_read_cb(evutil_socket_t fd, short what, void *p) 389290001Sglebius{ 390290001Sglebius struct evconnlistener *lev = p; 391290001Sglebius int err; 392290001Sglebius evconnlistener_cb cb; 393290001Sglebius evconnlistener_errorcb errorcb; 394290001Sglebius void *user_data; 395290001Sglebius LOCK(lev); 396290001Sglebius while (1) { 397290001Sglebius struct sockaddr_storage ss; 398290001Sglebius ev_socklen_t socklen = sizeof(ss); 399290001Sglebius evutil_socket_t new_fd = evutil_accept4_(fd, (struct sockaddr*)&ss, &socklen, lev->accept4_flags); 400290001Sglebius if (new_fd < 0) 401290001Sglebius break; 402290001Sglebius if (socklen == 0) { 403290001Sglebius /* This can happen with some older linux kernels in 404290001Sglebius * response to nmap. */ 405290001Sglebius evutil_closesocket(new_fd); 406290001Sglebius continue; 407290001Sglebius } 408290001Sglebius 409290001Sglebius if (lev->cb == NULL) { 410290001Sglebius evutil_closesocket(new_fd); 411290001Sglebius UNLOCK(lev); 412290001Sglebius return; 413290001Sglebius } 414290001Sglebius ++lev->refcnt; 415290001Sglebius cb = lev->cb; 416290001Sglebius user_data = lev->user_data; 417290001Sglebius UNLOCK(lev); 418290001Sglebius cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen, 419290001Sglebius user_data); 420290001Sglebius LOCK(lev); 421290001Sglebius if (lev->refcnt == 1) { 422290001Sglebius int freed = listener_decref_and_unlock(lev); 423290001Sglebius EVUTIL_ASSERT(freed); 424290001Sglebius 425290001Sglebius evutil_closesocket(new_fd); 426290001Sglebius return; 427290001Sglebius } 428290001Sglebius --lev->refcnt; 429290001Sglebius } 430290001Sglebius err = evutil_socket_geterror(fd); 431290001Sglebius if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) { 432290001Sglebius UNLOCK(lev); 433290001Sglebius return; 434290001Sglebius } 435290001Sglebius if (lev->errorcb != NULL) { 436290001Sglebius ++lev->refcnt; 437290001Sglebius errorcb = lev->errorcb; 438290001Sglebius user_data = lev->user_data; 439290001Sglebius UNLOCK(lev); 440290001Sglebius errorcb(lev, user_data); 441290001Sglebius LOCK(lev); 442290001Sglebius listener_decref_and_unlock(lev); 443290001Sglebius } else { 444290001Sglebius event_sock_warn(fd, "Error from accept() call"); 445290001Sglebius } 446290001Sglebius} 447290001Sglebius 448290001Sglebius#ifdef _WIN32 449290001Sglebiusstruct accepting_socket { 450290001Sglebius CRITICAL_SECTION lock; 451290001Sglebius struct event_overlapped overlapped; 452290001Sglebius SOCKET s; 453290001Sglebius int error; 454290001Sglebius struct event_callback deferred; 455290001Sglebius struct evconnlistener_iocp *lev; 456290001Sglebius ev_uint8_t buflen; 457290001Sglebius ev_uint8_t family; 458290001Sglebius unsigned free_on_cb:1; 459290001Sglebius char addrbuf[1]; 460290001Sglebius}; 461290001Sglebius 462290001Sglebiusstatic void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, 463290001Sglebius ev_ssize_t n, int ok); 464290001Sglebiusstatic void accepted_socket_invoke_user_cb(struct event_callback *cb, void *arg); 465290001Sglebius 466290001Sglebiusstatic void 467290001Sglebiusiocp_listener_event_add(struct evconnlistener_iocp *lev) 468290001Sglebius{ 469290001Sglebius if (lev->event_added) 470290001Sglebius return; 471290001Sglebius 472290001Sglebius lev->event_added = 1; 473290001Sglebius event_base_add_virtual_(lev->event_base); 474290001Sglebius} 475290001Sglebius 476290001Sglebiusstatic void 477290001Sglebiusiocp_listener_event_del(struct evconnlistener_iocp *lev) 478290001Sglebius{ 479290001Sglebius if (!lev->event_added) 480290001Sglebius return; 481290001Sglebius 482290001Sglebius lev->event_added = 0; 483290001Sglebius event_base_del_virtual_(lev->event_base); 484290001Sglebius} 485290001Sglebius 486290001Sglebiusstatic struct accepting_socket * 487290001Sglebiusnew_accepting_socket(struct evconnlistener_iocp *lev, int family) 488290001Sglebius{ 489290001Sglebius struct accepting_socket *res; 490290001Sglebius int addrlen; 491290001Sglebius int buflen; 492290001Sglebius 493290001Sglebius if (family == AF_INET) 494290001Sglebius addrlen = sizeof(struct sockaddr_in); 495290001Sglebius else if (family == AF_INET6) 496290001Sglebius addrlen = sizeof(struct sockaddr_in6); 497290001Sglebius else 498290001Sglebius return NULL; 499290001Sglebius buflen = (addrlen+16)*2; 500290001Sglebius 501290001Sglebius res = mm_calloc(1,sizeof(struct accepting_socket)-1+buflen); 502290001Sglebius if (!res) 503290001Sglebius return NULL; 504290001Sglebius 505290001Sglebius event_overlapped_init_(&res->overlapped, accepted_socket_cb); 506290001Sglebius res->s = INVALID_SOCKET; 507290001Sglebius res->lev = lev; 508290001Sglebius res->buflen = buflen; 509290001Sglebius res->family = family; 510290001Sglebius 511290001Sglebius event_deferred_cb_init_(&res->deferred, 512290001Sglebius event_base_get_npriorities(lev->event_base) / 2, 513290001Sglebius accepted_socket_invoke_user_cb, res); 514290001Sglebius 515290001Sglebius InitializeCriticalSectionAndSpinCount(&res->lock, 1000); 516290001Sglebius 517290001Sglebius return res; 518290001Sglebius} 519290001Sglebius 520290001Sglebiusstatic void 521290001Sglebiusfree_and_unlock_accepting_socket(struct accepting_socket *as) 522290001Sglebius{ 523290001Sglebius /* requires lock. */ 524290001Sglebius if (as->s != INVALID_SOCKET) 525290001Sglebius closesocket(as->s); 526290001Sglebius 527290001Sglebius LeaveCriticalSection(&as->lock); 528290001Sglebius DeleteCriticalSection(&as->lock); 529290001Sglebius mm_free(as); 530290001Sglebius} 531290001Sglebius 532290001Sglebiusstatic int 533290001Sglebiusstart_accepting(struct accepting_socket *as) 534290001Sglebius{ 535290001Sglebius /* requires lock */ 536290001Sglebius const struct win32_extension_fns *ext = event_get_win32_extension_fns_(); 537290001Sglebius DWORD pending = 0; 538290001Sglebius SOCKET s = socket(as->family, SOCK_STREAM, 0); 539290001Sglebius int error = 0; 540290001Sglebius 541290001Sglebius if (!as->lev->base.enabled) 542290001Sglebius return 0; 543290001Sglebius 544290001Sglebius if (s == INVALID_SOCKET) { 545290001Sglebius error = WSAGetLastError(); 546290001Sglebius goto report_err; 547290001Sglebius } 548290001Sglebius 549290001Sglebius /* XXXX It turns out we need to do this again later. Does this call 550290001Sglebius * have any effect? */ 551290001Sglebius setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 552290001Sglebius (char *)&as->lev->fd, sizeof(&as->lev->fd)); 553290001Sglebius 554290001Sglebius if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) 555290001Sglebius evutil_make_socket_nonblocking(s); 556290001Sglebius 557290001Sglebius if (event_iocp_port_associate_(as->lev->port, s, 1) < 0) { 558290001Sglebius closesocket(s); 559290001Sglebius return -1; 560290001Sglebius } 561290001Sglebius 562290001Sglebius as->s = s; 563290001Sglebius 564290001Sglebius if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0, 565290001Sglebius as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped)) 566290001Sglebius { 567290001Sglebius /* Immediate success! */ 568290001Sglebius accepted_socket_cb(&as->overlapped, 1, 0, 1); 569290001Sglebius } else { 570290001Sglebius error = WSAGetLastError(); 571290001Sglebius if (error != ERROR_IO_PENDING) { 572290001Sglebius goto report_err; 573290001Sglebius } 574290001Sglebius } 575290001Sglebius 576290001Sglebius return 0; 577290001Sglebius 578290001Sglebiusreport_err: 579290001Sglebius as->error = error; 580290001Sglebius event_deferred_cb_schedule_( 581290001Sglebius as->lev->event_base, 582290001Sglebius &as->deferred); 583290001Sglebius return 0; 584290001Sglebius} 585290001Sglebius 586290001Sglebiusstatic void 587290001Sglebiusstop_accepting(struct accepting_socket *as) 588290001Sglebius{ 589290001Sglebius /* requires lock. */ 590290001Sglebius SOCKET s = as->s; 591290001Sglebius as->s = INVALID_SOCKET; 592290001Sglebius closesocket(s); 593290001Sglebius} 594290001Sglebius 595290001Sglebiusstatic void 596290001Sglebiusaccepted_socket_invoke_user_cb(struct event_callback *dcb, void *arg) 597290001Sglebius{ 598290001Sglebius struct accepting_socket *as = arg; 599290001Sglebius 600290001Sglebius struct sockaddr *sa_local=NULL, *sa_remote=NULL; 601290001Sglebius int socklen_local=0, socklen_remote=0; 602290001Sglebius const struct win32_extension_fns *ext = event_get_win32_extension_fns_(); 603290001Sglebius struct evconnlistener *lev = &as->lev->base; 604290001Sglebius evutil_socket_t sock=-1; 605290001Sglebius void *data; 606290001Sglebius evconnlistener_cb cb=NULL; 607290001Sglebius evconnlistener_errorcb errorcb=NULL; 608290001Sglebius int error; 609290001Sglebius 610290001Sglebius EVUTIL_ASSERT(ext->GetAcceptExSockaddrs); 611290001Sglebius 612290001Sglebius LOCK(lev); 613290001Sglebius EnterCriticalSection(&as->lock); 614290001Sglebius if (as->free_on_cb) { 615290001Sglebius free_and_unlock_accepting_socket(as); 616290001Sglebius listener_decref_and_unlock(lev); 617290001Sglebius return; 618290001Sglebius } 619290001Sglebius 620290001Sglebius ++lev->refcnt; 621290001Sglebius 622290001Sglebius error = as->error; 623290001Sglebius if (error) { 624290001Sglebius as->error = 0; 625290001Sglebius errorcb = lev->errorcb; 626290001Sglebius } else { 627290001Sglebius ext->GetAcceptExSockaddrs( 628290001Sglebius as->addrbuf, 0, as->buflen/2, as->buflen/2, 629290001Sglebius &sa_local, &socklen_local, &sa_remote, 630290001Sglebius &socklen_remote); 631290001Sglebius sock = as->s; 632290001Sglebius cb = lev->cb; 633290001Sglebius as->s = INVALID_SOCKET; 634290001Sglebius 635290001Sglebius /* We need to call this so getsockname, getpeername, and 636290001Sglebius * shutdown work correctly on the accepted socket. */ 637290001Sglebius /* XXXX handle error? */ 638290001Sglebius setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 639290001Sglebius (char *)&as->lev->fd, sizeof(&as->lev->fd)); 640290001Sglebius } 641290001Sglebius data = lev->user_data; 642290001Sglebius 643290001Sglebius LeaveCriticalSection(&as->lock); 644290001Sglebius UNLOCK(lev); 645290001Sglebius 646290001Sglebius if (errorcb) { 647290001Sglebius WSASetLastError(error); 648290001Sglebius errorcb(lev, data); 649290001Sglebius } else if (cb) { 650290001Sglebius cb(lev, sock, sa_remote, socklen_remote, data); 651290001Sglebius } 652290001Sglebius 653290001Sglebius LOCK(lev); 654290001Sglebius if (listener_decref_and_unlock(lev)) 655290001Sglebius return; 656290001Sglebius 657290001Sglebius EnterCriticalSection(&as->lock); 658290001Sglebius start_accepting(as); 659290001Sglebius LeaveCriticalSection(&as->lock); 660290001Sglebius} 661290001Sglebius 662290001Sglebiusstatic void 663290001Sglebiusaccepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok) 664290001Sglebius{ 665290001Sglebius struct accepting_socket *as = 666290001Sglebius EVUTIL_UPCAST(o, struct accepting_socket, overlapped); 667290001Sglebius 668290001Sglebius LOCK(&as->lev->base); 669290001Sglebius EnterCriticalSection(&as->lock); 670290001Sglebius if (ok) { 671290001Sglebius /* XXXX Don't do this if some EV_MT flag is set. */ 672290001Sglebius event_deferred_cb_schedule_( 673290001Sglebius as->lev->event_base, 674290001Sglebius &as->deferred); 675290001Sglebius LeaveCriticalSection(&as->lock); 676290001Sglebius } else if (as->free_on_cb) { 677290001Sglebius struct evconnlistener *lev = &as->lev->base; 678290001Sglebius free_and_unlock_accepting_socket(as); 679290001Sglebius listener_decref_and_unlock(lev); 680290001Sglebius return; 681290001Sglebius } else if (as->s == INVALID_SOCKET) { 682290001Sglebius /* This is okay; we were disabled by iocp_listener_disable. */ 683290001Sglebius LeaveCriticalSection(&as->lock); 684290001Sglebius } else { 685290001Sglebius /* Some error on accept that we couldn't actually handle. */ 686290001Sglebius BOOL ok; 687290001Sglebius DWORD transfer = 0, flags=0; 688290001Sglebius event_sock_warn(as->s, "Unexpected error on AcceptEx"); 689290001Sglebius ok = WSAGetOverlappedResult(as->s, &o->overlapped, 690290001Sglebius &transfer, FALSE, &flags); 691290001Sglebius if (ok) { 692290001Sglebius /* well, that was confusing! */ 693290001Sglebius as->error = 1; 694290001Sglebius } else { 695290001Sglebius as->error = WSAGetLastError(); 696290001Sglebius } 697290001Sglebius event_deferred_cb_schedule_( 698290001Sglebius as->lev->event_base, 699290001Sglebius &as->deferred); 700290001Sglebius LeaveCriticalSection(&as->lock); 701290001Sglebius } 702290001Sglebius UNLOCK(&as->lev->base); 703290001Sglebius} 704290001Sglebius 705290001Sglebiusstatic int 706290001Sglebiusiocp_listener_enable(struct evconnlistener *lev) 707290001Sglebius{ 708290001Sglebius int i; 709290001Sglebius struct evconnlistener_iocp *lev_iocp = 710290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 711290001Sglebius 712290001Sglebius LOCK(lev); 713290001Sglebius iocp_listener_event_add(lev_iocp); 714290001Sglebius for (i = 0; i < lev_iocp->n_accepting; ++i) { 715290001Sglebius struct accepting_socket *as = lev_iocp->accepting[i]; 716290001Sglebius if (!as) 717290001Sglebius continue; 718290001Sglebius EnterCriticalSection(&as->lock); 719290001Sglebius if (!as->free_on_cb && as->s == INVALID_SOCKET) 720290001Sglebius start_accepting(as); 721290001Sglebius LeaveCriticalSection(&as->lock); 722290001Sglebius } 723290001Sglebius UNLOCK(lev); 724290001Sglebius return 0; 725290001Sglebius} 726290001Sglebius 727290001Sglebiusstatic int 728290001Sglebiusiocp_listener_disable_impl(struct evconnlistener *lev, int shutdown) 729290001Sglebius{ 730290001Sglebius int i; 731290001Sglebius struct evconnlistener_iocp *lev_iocp = 732290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 733290001Sglebius 734290001Sglebius LOCK(lev); 735290001Sglebius iocp_listener_event_del(lev_iocp); 736290001Sglebius for (i = 0; i < lev_iocp->n_accepting; ++i) { 737290001Sglebius struct accepting_socket *as = lev_iocp->accepting[i]; 738290001Sglebius if (!as) 739290001Sglebius continue; 740290001Sglebius EnterCriticalSection(&as->lock); 741290001Sglebius if (!as->free_on_cb && as->s != INVALID_SOCKET) { 742290001Sglebius if (shutdown) 743290001Sglebius as->free_on_cb = 1; 744290001Sglebius stop_accepting(as); 745290001Sglebius } 746290001Sglebius LeaveCriticalSection(&as->lock); 747290001Sglebius } 748290001Sglebius 749290001Sglebius if (shutdown && lev->flags & LEV_OPT_CLOSE_ON_FREE) 750290001Sglebius evutil_closesocket(lev_iocp->fd); 751290001Sglebius 752290001Sglebius UNLOCK(lev); 753290001Sglebius return 0; 754290001Sglebius} 755290001Sglebius 756290001Sglebiusstatic int 757290001Sglebiusiocp_listener_disable(struct evconnlistener *lev) 758290001Sglebius{ 759290001Sglebius return iocp_listener_disable_impl(lev,0); 760290001Sglebius} 761290001Sglebius 762290001Sglebiusstatic void 763290001Sglebiusiocp_listener_destroy(struct evconnlistener *lev) 764290001Sglebius{ 765290001Sglebius struct evconnlistener_iocp *lev_iocp = 766290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 767290001Sglebius 768290001Sglebius if (! lev_iocp->shutting_down) { 769290001Sglebius lev_iocp->shutting_down = 1; 770290001Sglebius iocp_listener_disable_impl(lev,1); 771290001Sglebius } 772290001Sglebius 773290001Sglebius} 774290001Sglebius 775290001Sglebiusstatic evutil_socket_t 776290001Sglebiusiocp_listener_getfd(struct evconnlistener *lev) 777290001Sglebius{ 778290001Sglebius struct evconnlistener_iocp *lev_iocp = 779290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 780290001Sglebius return lev_iocp->fd; 781290001Sglebius} 782290001Sglebiusstatic struct event_base * 783290001Sglebiusiocp_listener_getbase(struct evconnlistener *lev) 784290001Sglebius{ 785290001Sglebius struct evconnlistener_iocp *lev_iocp = 786290001Sglebius EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base); 787290001Sglebius return lev_iocp->event_base; 788290001Sglebius} 789290001Sglebius 790290001Sglebiusstatic const struct evconnlistener_ops evconnlistener_iocp_ops = { 791290001Sglebius iocp_listener_enable, 792290001Sglebius iocp_listener_disable, 793290001Sglebius iocp_listener_destroy, 794290001Sglebius iocp_listener_destroy, /* shutdown */ 795290001Sglebius iocp_listener_getfd, 796290001Sglebius iocp_listener_getbase 797290001Sglebius}; 798290001Sglebius 799290001Sglebius/* XXX define some way to override this. */ 800290001Sglebius#define N_SOCKETS_PER_LISTENER 4 801290001Sglebius 802290001Sglebiusstruct evconnlistener * 803290001Sglebiusevconnlistener_new_async(struct event_base *base, 804290001Sglebius evconnlistener_cb cb, void *ptr, unsigned flags, int backlog, 805290001Sglebius evutil_socket_t fd) 806290001Sglebius{ 807290001Sglebius struct sockaddr_storage ss; 808290001Sglebius int socklen = sizeof(ss); 809290001Sglebius struct evconnlistener_iocp *lev; 810290001Sglebius int i; 811290001Sglebius 812290001Sglebius flags |= LEV_OPT_THREADSAFE; 813290001Sglebius 814290001Sglebius if (!base || !event_base_get_iocp_(base)) 815290001Sglebius goto err; 816290001Sglebius 817290001Sglebius /* XXXX duplicate code */ 818290001Sglebius if (backlog > 0) { 819290001Sglebius if (listen(fd, backlog) < 0) 820290001Sglebius goto err; 821290001Sglebius } else if (backlog < 0) { 822290001Sglebius if (listen(fd, 128) < 0) 823290001Sglebius goto err; 824290001Sglebius } 825290001Sglebius if (getsockname(fd, (struct sockaddr*)&ss, &socklen)) { 826290001Sglebius event_sock_warn(fd, "getsockname"); 827290001Sglebius goto err; 828290001Sglebius } 829290001Sglebius lev = mm_calloc(1, sizeof(struct evconnlistener_iocp)); 830290001Sglebius if (!lev) { 831290001Sglebius event_warn("calloc"); 832290001Sglebius goto err; 833290001Sglebius } 834290001Sglebius lev->base.ops = &evconnlistener_iocp_ops; 835290001Sglebius lev->base.cb = cb; 836290001Sglebius lev->base.user_data = ptr; 837290001Sglebius lev->base.flags = flags; 838290001Sglebius lev->base.refcnt = 1; 839290001Sglebius lev->base.enabled = 1; 840290001Sglebius 841290001Sglebius lev->port = event_base_get_iocp_(base); 842290001Sglebius lev->fd = fd; 843290001Sglebius lev->event_base = base; 844290001Sglebius 845290001Sglebius 846290001Sglebius if (event_iocp_port_associate_(lev->port, fd, 1) < 0) 847290001Sglebius goto err_free_lev; 848290001Sglebius 849290001Sglebius EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 850290001Sglebius 851290001Sglebius lev->n_accepting = N_SOCKETS_PER_LISTENER; 852290001Sglebius lev->accepting = mm_calloc(lev->n_accepting, 853290001Sglebius sizeof(struct accepting_socket *)); 854290001Sglebius if (!lev->accepting) { 855290001Sglebius event_warn("calloc"); 856290001Sglebius goto err_delete_lock; 857290001Sglebius } 858290001Sglebius for (i = 0; i < lev->n_accepting; ++i) { 859290001Sglebius lev->accepting[i] = new_accepting_socket(lev, ss.ss_family); 860290001Sglebius if (!lev->accepting[i]) { 861290001Sglebius event_warnx("Couldn't create accepting socket"); 862290001Sglebius goto err_free_accepting; 863290001Sglebius } 864290001Sglebius if (cb && start_accepting(lev->accepting[i]) < 0) { 865290001Sglebius event_warnx("Couldn't start accepting on socket"); 866290001Sglebius EnterCriticalSection(&lev->accepting[i]->lock); 867290001Sglebius free_and_unlock_accepting_socket(lev->accepting[i]); 868290001Sglebius goto err_free_accepting; 869290001Sglebius } 870290001Sglebius ++lev->base.refcnt; 871290001Sglebius } 872290001Sglebius 873290001Sglebius iocp_listener_event_add(lev); 874290001Sglebius 875290001Sglebius return &lev->base; 876290001Sglebius 877290001Sglebiuserr_free_accepting: 878290001Sglebius mm_free(lev->accepting); 879290001Sglebius /* XXXX free the other elements. */ 880290001Sglebiuserr_delete_lock: 881290001Sglebius EVTHREAD_FREE_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 882290001Sglebiuserr_free_lev: 883290001Sglebius mm_free(lev); 884290001Sglebiuserr: 885290001Sglebius /* Don't close the fd, it is caller's responsibility. */ 886290001Sglebius return NULL; 887290001Sglebius} 888290001Sglebius 889290001Sglebius#endif 890