static void accepted_socket_cb(struct event_overlapped *o, ev_uintptr_t key, ev_ssize_t n, int ok) { struct accepting_socket *as = EVUTIL_UPCAST(o, struct accepting_socket, overlapped); LOCK(&as->lev->base); EnterCriticalSection(&as->lock); if (ok) { /* XXXX Don't do this if some EV_MT flag is set. */ event_deferred_cb_schedule_( as->lev->event_base, &as->deferred); LeaveCriticalSection(&as->lock); } else if (as->free_on_cb) { struct evconnlistener *lev = &as->lev->base; free_and_unlock_accepting_socket(as); listener_decref_and_unlock(lev); return; } else if (as->s == INVALID_SOCKET) { /* This is okay; we were disabled by iocp_listener_disable. */ LeaveCriticalSection(&as->lock); } else { /* Some error on accept that we couldn't actually handle. */ BOOL ok; DWORD transfer = 0, flags=0; event_sock_warn(as->s, "Unexpected error on AcceptEx"); ok = WSAGetOverlappedResult(as->s, &o->overlapped, &transfer, FALSE, &flags); if (ok) { /* well, that was confusing! */ as->error = 1; } else { as->error = WSAGetLastError(); } event_deferred_cb_schedule_( as->lev->event_base, &as->deferred); LeaveCriticalSection(&as->lock); } UNLOCK(&as->lev->base); }
static int start_accepting(struct accepting_socket *as) { /* requires lock */ const struct win32_extension_fns *ext = event_get_win32_extension_fns_(); DWORD pending = 0; SOCKET s = socket(as->family, SOCK_STREAM, 0); int error = 0; if (!as->lev->base.enabled) return 0; if (s == INVALID_SOCKET) { error = WSAGetLastError(); goto report_err; } /* XXXX It turns out we need to do this again later. Does this call * have any effect? */ setsockopt(s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&as->lev->fd, sizeof(&as->lev->fd)); if (!(as->lev->base.flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING)) evutil_make_socket_nonblocking(s); if (event_iocp_port_associate_(as->lev->port, s, 1) < 0) { closesocket(s); return -1; } as->s = s; if (ext->AcceptEx(as->lev->fd, s, as->addrbuf, 0, as->buflen/2, as->buflen/2, &pending, &as->overlapped.overlapped)) { /* Immediate success! */ accepted_socket_cb(&as->overlapped, 1, 0, 1); } else { error = WSAGetLastError(); if (error != ERROR_IO_PENDING) { goto report_err; } } return 0; report_err: as->error = error; event_deferred_cb_schedule_( as->lev->event_base, &as->deferred); return 0; }
static THREAD_FN load_deferred_queue(void *arg) { struct deferred_test_data *data = arg; size_t i; for (i = 0; i < CB_COUNT; ++i) { event_deferred_cb_init_(&data->cbs[i], 0, deferred_callback, NULL); event_deferred_cb_schedule_(data->queue, &data->cbs[i]); SLEEP_MS(1); } THREAD_RETURN(); }