Make http use evconnlistener.

Now that we have a generic listen-on-a-socket mechanism, there's no
longer any reason to have a separate listen-on-a-socket implementation
in http.c.

This also lets us use IOCP and AcceptEx() when they're enabled.

Possibly, we should have a new mechanism to add a socket given only a
listener.
This commit is contained in:
Nick Mathewson 2009-12-30 00:41:03 -05:00
parent a334b31c6f
commit ec34533a9c
2 changed files with 16 additions and 32 deletions

View File

@ -115,7 +115,7 @@ TAILQ_HEAD(evconq, evhttp_connection);
struct evhttp_bound_socket { struct evhttp_bound_socket {
TAILQ_ENTRY(evhttp_bound_socket) (next); TAILQ_ENTRY(evhttp_bound_socket) (next);
struct event bind_ev; struct evconnlistener *listener;
}; };
struct evhttp { struct evhttp {

46
http.c
View File

@ -93,6 +93,7 @@
#include "event2/http_struct.h" #include "event2/http_struct.h"
#include "event2/http_compat.h" #include "event2/http_compat.h"
#include "event2/util.h" #include "event2/util.h"
#include "event2/listener.h"
#include "log-internal.h" #include "log-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include "http-internal.h" #include "http-internal.h"
@ -2434,23 +2435,11 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
} }
static void static void
accept_socket(evutil_socket_t fd, short what, void *arg) accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
{ {
struct evhttp *http = arg; struct evhttp *http = arg;
struct sockaddr_storage ss;
ev_socklen_t addrlen = sizeof(ss);
evutil_socket_t nfd;
if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) { evhttp_get_request(http, nfd, peer_sa, peer_socklen);
int err = evutil_socket_geterror(fd);
if (! EVUTIL_ERR_ACCEPT_RETRIABLE(err))
event_warn("%s: bad accept", __func__);
return;
}
if (evutil_make_socket_nonblocking(nfd) < 0)
return;
evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen);
} }
int int
@ -2504,25 +2493,23 @@ struct evhttp_bound_socket *
evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd) evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
{ {
struct evhttp_bound_socket *bound; struct evhttp_bound_socket *bound;
struct event *ev; struct evconnlistener *listener;
int res; const int flags =
LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
bound = mm_malloc(sizeof(struct evhttp_bound_socket)); bound = mm_malloc(sizeof(struct evhttp_bound_socket));
if (bound == NULL) if (bound == NULL)
return (NULL); return (NULL);
ev = &bound->bind_ev; listener = evconnlistener_new(http->base, accept_socket_cb, http,
flags,
/* Schedule the socket for accepting */ 0, /* Backlog is '0' because we already said 'listen' */
event_assign(ev, http->base, fd);
fd, EV_READ | EV_PERSIST, accept_socket, http); if (!listener) {
res = event_add(ev, NULL);
if (res == -1) {
mm_free(bound); mm_free(bound);
return (NULL); return (NULL);
} }
bound->listener = listener;
TAILQ_INSERT_TAIL(&http->sockets, bound, next); TAILQ_INSERT_TAIL(&http->sockets, bound, next);
@ -2531,14 +2518,14 @@ evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound) evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
{ {
return bound->bind_ev.ev_fd; return evconnlistener_get_fd(bound->listener);
} }
void void
evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound) evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
{ {
TAILQ_REMOVE(&http->sockets, bound, next); TAILQ_REMOVE(&http->sockets, bound, next);
event_del(&bound->bind_ev); evconnlistener_free(bound->listener);
mm_free(bound); mm_free(bound);
} }
@ -2598,15 +2585,12 @@ evhttp_free(struct evhttp* http)
struct evhttp_connection *evcon; struct evhttp_connection *evcon;
struct evhttp_bound_socket *bound; struct evhttp_bound_socket *bound;
struct evhttp* vhost; struct evhttp* vhost;
evutil_socket_t fd;
/* Remove the accepting part */ /* Remove the accepting part */
while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) { while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
TAILQ_REMOVE(&http->sockets, bound, next); TAILQ_REMOVE(&http->sockets, bound, next);
fd = bound->bind_ev.ev_fd; evconnlistener_free(bound->listener);
event_del(&bound->bind_ev);
EVUTIL_CLOSESOCKET(fd);
mm_free(bound); mm_free(bound);
} }