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
|