on a given file descriptor.
@param base The event base to associate the listener with.
- @param cb A callback to be invoked when a new connection arrives.
+ @param cb A callback to be invoked when a new connection arrives. If the
+ callback is NULL, the listener will be treated as disabled until the
+ callback is set.
@param ptr A user-supplied pointer to give to the callback.
@param flags Any number of LEV_OPT_* flags
@param backlog Passed to the listen() call to determine the length of the
on a given address.
@param base The event base to associate the listener with.
- @param cb A callback to be invoked when a new connection arrives.
+ @param cb A callback to be invoked when a new connection arrives. If the
+ callback is NULL, the listener will be treated as disabled until the
+ callback is set.
@param ptr A user-supplied pointer to give to the callback.
@param flags Any number of LEV_OPT_* flags
@param backlog Passed to the listen() call to determine the length of the
/** Return the socket that an evconnlistner is listening on. */
evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev);
+/** Change the callback on the listener to cb and its user_data to arg.
+ */
+void evconnlistener_set_cb(struct evconnlistener *lev,
+ evconnlistener_cb cb, void *arg);
+
/** Set an evconnlistener's error callback. */
void evconnlistener_set_error_cb(struct evconnlistener *lev,
evconnlistener_errorcb errorcb);
evconnlistener_errorcb errorcb;
void *user_data;
unsigned flags;
- int refcnt;
+ short refcnt;
+ unsigned enabled : 1;
};
struct evconnlistener_event {
struct event_iocp_port *port;
short n_accepting;
unsigned shutting_down : 1;
- unsigned enabled : 1;
struct accepting_socket **accepting;
};
#endif
event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
listener_read_cb, lev);
+
evconnlistener_enable(&lev->base);
return &lev->base;
{
int r;
LOCK(lev);
- r = lev->ops->enable(lev);
+ lev->enabled = 1;
+ if (lev->cb)
+ r = lev->ops->enable(lev);
+ else
+ r = 0;
UNLOCK(lev);
return r;
}
{
int r;
LOCK(lev);
+ lev->enabled = 0;
r = lev->ops->disable(lev);
UNLOCK(lev);
return r;
return event_get_base(&lev_e->listener);
}
-void evconnlistener_set_error_cb(struct evconnlistener *lev,
+void
+evconnlistener_set_cb(struct evconnlistener *lev,
+ evconnlistener_cb cb, void *arg)
+{
+ int enable = 0;
+ LOCK(lev);
+ if (lev->enabled && !lev->cb)
+ enable = 1;
+ lev->cb = cb;
+ lev->user_data = arg;
+ if (enable)
+ evconnlistener_enable(lev);
+ UNLOCK(lev);
+}
+
+void
+evconnlistener_set_error_cb(struct evconnlistener *lev,
evconnlistener_errorcb errorcb)
{
LOCK(lev);
SOCKET s = socket(as->family, SOCK_STREAM, 0);
int error = 0;
- if (!as->lev->enabled)
+ if (!as->lev->base.enabled)
return 0;
if (s == INVALID_SOCKET) {
if (errorcb) {
WSASetLastError(error);
errorcb(lev, data);
- } else {
+ } else if (cb) {
cb(lev, sock, sa_remote, socklen_remote, data);
}
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
LOCK(lev);
- lev_iocp->enabled = 1;
for (i = 0; i < lev_iocp->n_accepting; ++i) {
struct accepting_socket *as = lev_iocp->accepting[i];
if (!as)
EVUTIL_UPCAST(lev, struct evconnlistener_iocp, base);
LOCK(lev);
- lev_iocp->enabled = 0;
for (i = 0; i < lev_iocp->n_accepting; ++i) {
struct accepting_socket *as = lev_iocp->accepting[i];
if (!as)
lev->base.user_data = ptr;
lev->base.flags = flags;
lev->base.refcnt = 1;
+ lev->base.enabled = 1;
lev->port = event_base_get_iocp(base);
lev->fd = fd;
lev->event_base = base;
- lev->enabled = 1;
+
if (event_iocp_port_associate(lev->port, fd, 1) < 0)
goto err_free_lev;
event_warnx("Couldn't create accepting socket");
goto err_free_accepting;
}
- if (start_accepting(lev->accepting[i]) < 0) {
+ if (cb && start_accepting(lev->accepting[i]) < 0) {
event_warnx("Couldn't start accepting on socket");
EnterCriticalSection(&lev->accepting[i]->lock);
free_and_unlock_accepting_socket(lev->accepting[i]);