mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-15 15:25:09 -04:00
Merge remote branch 'github/http_and_listener'
This commit is contained in:
commit
9c71a3413a
38
http.c
38
http.c
@ -2764,23 +2764,35 @@ evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
|
||||
const int flags =
|
||||
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
|
||||
|
||||
listener = evconnlistener_new(http->base, NULL, NULL,
|
||||
flags,
|
||||
0, /* Backlog is '0' because we already said 'listen' */
|
||||
fd);
|
||||
if (!listener)
|
||||
return (NULL);
|
||||
|
||||
bound = evhttp_bind_listener(http, listener);
|
||||
if (!bound) {
|
||||
evconnlistener_free(listener);
|
||||
return (NULL);
|
||||
}
|
||||
return (bound);
|
||||
}
|
||||
|
||||
struct evhttp_bound_socket *
|
||||
evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
|
||||
{
|
||||
struct evhttp_bound_socket *bound;
|
||||
|
||||
bound = mm_malloc(sizeof(struct evhttp_bound_socket));
|
||||
if (bound == NULL)
|
||||
return (NULL);
|
||||
|
||||
listener = evconnlistener_new(http->base, accept_socket_cb, http,
|
||||
flags,
|
||||
0, /* Backlog is '0' because we already said 'listen' */
|
||||
fd);
|
||||
if (!listener) {
|
||||
mm_free(bound);
|
||||
return (NULL);
|
||||
}
|
||||
bound->listener = listener;
|
||||
|
||||
TAILQ_INSERT_TAIL(&http->sockets, bound, next);
|
||||
|
||||
return (bound);
|
||||
evconnlistener_set_cb(listener, accept_socket_cb, http);
|
||||
return bound;
|
||||
}
|
||||
|
||||
evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
|
||||
@ -2788,6 +2800,12 @@ evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
|
||||
return evconnlistener_get_fd(bound->listener);
|
||||
}
|
||||
|
||||
struct evconnlistener *
|
||||
evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
|
||||
{
|
||||
return bound->listener;
|
||||
}
|
||||
|
||||
void
|
||||
evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
|
||||
{
|
||||
|
@ -63,6 +63,7 @@ struct evhttp;
|
||||
struct evhttp_request;
|
||||
struct evkeyvalq;
|
||||
struct evhttp_bound_socket;
|
||||
struct evconnlistener;
|
||||
|
||||
/**
|
||||
* Create a new HTTP server.
|
||||
@ -130,6 +131,18 @@ int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd);
|
||||
*/
|
||||
struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd);
|
||||
|
||||
/**
|
||||
* The most low-level evhttp_bind/accept method: takes an evconnlistener, and
|
||||
* returns an evhttp_bound_socket. The listener will be freed when the bound
|
||||
* socket is freed.
|
||||
*/
|
||||
struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener);
|
||||
|
||||
/**
|
||||
* Return the listener used to implement a bound socket.
|
||||
*/
|
||||
struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound);
|
||||
|
||||
/**
|
||||
* Makes an HTTP server stop accepting connections on the specified socket
|
||||
*
|
||||
|
@ -75,7 +75,9 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
|
||||
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
|
||||
@ -93,7 +95,9 @@ struct evconnlistener *evconnlistener_new(struct event_base *base,
|
||||
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
|
||||
@ -123,6 +127,11 @@ struct event_base *evconnlistener_get_base(struct evconnlistener *lev);
|
||||
/** 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);
|
||||
|
41
listener.c
41
listener.c
@ -73,7 +73,8 @@ struct evconnlistener {
|
||||
evconnlistener_errorcb errorcb;
|
||||
void *user_data;
|
||||
unsigned flags;
|
||||
int refcnt;
|
||||
short refcnt;
|
||||
unsigned enabled : 1;
|
||||
};
|
||||
|
||||
struct evconnlistener_event {
|
||||
@ -89,7 +90,6 @@ struct evconnlistener_iocp {
|
||||
struct event_iocp_port *port;
|
||||
short n_accepting;
|
||||
unsigned shutting_down : 1;
|
||||
unsigned enabled : 1;
|
||||
struct accepting_socket **accepting;
|
||||
};
|
||||
#endif
|
||||
@ -185,6 +185,7 @@ evconnlistener_new(struct event_base *base,
|
||||
|
||||
event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,
|
||||
listener_read_cb, lev);
|
||||
|
||||
evconnlistener_enable(&lev->base);
|
||||
|
||||
return &lev->base;
|
||||
@ -268,7 +269,11 @@ evconnlistener_enable(struct evconnlistener *lev)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -278,6 +283,7 @@ evconnlistener_disable(struct evconnlistener *lev)
|
||||
{
|
||||
int r;
|
||||
LOCK(lev);
|
||||
lev->enabled = 0;
|
||||
r = lev->ops->disable(lev);
|
||||
UNLOCK(lev);
|
||||
return r;
|
||||
@ -335,7 +341,23 @@ event_listener_getbase(struct evconnlistener *lev)
|
||||
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);
|
||||
@ -474,7 +496,7 @@ start_accepting(struct accepting_socket *as)
|
||||
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) {
|
||||
@ -574,7 +596,7 @@ accepted_socket_invoke_user_cb(struct deferred_cb *dcb, void *arg)
|
||||
if (errorcb) {
|
||||
WSASetLastError(error);
|
||||
errorcb(lev, data);
|
||||
} else {
|
||||
} else if (cb) {
|
||||
cb(lev, sock, sa_remote, socklen_remote, data);
|
||||
}
|
||||
|
||||
@ -638,7 +660,6 @@ iocp_listener_enable(struct evconnlistener *lev)
|
||||
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)
|
||||
@ -660,7 +681,6 @@ iocp_listener_disable_impl(struct evconnlistener *lev, int shutdown)
|
||||
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)
|
||||
@ -760,11 +780,12 @@ evconnlistener_new_async(struct event_base *base,
|
||||
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;
|
||||
@ -784,7 +805,7 @@ evconnlistener_new_async(struct event_base *base,
|
||||
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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user