fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.

svn:r770
This commit is contained in:
Niels Provos 2008-05-04 22:28:22 +00:00
parent d58a0a7c42
commit 0d43f0dfc5
4 changed files with 87 additions and 10 deletions

View File

@ -8,6 +8,7 @@ Changes in 1.4.4-stable:
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
o reduce system calls for getting current time by caching it.
o fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.
Changes in 1.4.3-stable:

View File

@ -89,8 +89,15 @@ struct evhttp_cb {
/* both the http server as well as the rpc system need to queue connections */
TAILQ_HEAD(evconq, evhttp_connection);
/* each bound socket is stored in one of these */
struct evhttp_bound_socket {
TAILQ_ENTRY(evhttp_bound_socket) (next);
struct event bind_ev;
};
struct evhttp {
struct event bind_ev;
TAILQ_HEAD(boundq, evhttp_bound_socket) sockets;
TAILQ_HEAD(httpcbq, evhttp_cb) callbacks;
struct evconq connections;

52
http.c
View File

@ -162,6 +162,7 @@ static void evhttp_connection_start_detectclose(
static void evhttp_connection_stop_detectclose(
struct evhttp_connection *evcon);
static void evhttp_request_dispatch(struct evhttp_connection* evcon);
static int evhttp_accept_socket(struct evhttp *http, int fd);
void evhttp_read(int, short, void *);
void evhttp_write(int, short, void *);
@ -1999,24 +2000,52 @@ accept_socket(int fd, short what, void *arg)
int
evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
{
struct event *ev = &http->bind_ev;
int fd;
int res;
if ((fd = bind_socket(address, port)) == -1)
return (-1);
if (listen(fd, 10) == -1) {
if (listen(fd, 128) == -1) {
event_warn("%s: listen", __func__);
EVUTIL_CLOSESOCKET(fd);
return (-1);
}
res = evhttp_accept_socket(http, fd);
if (res != -1)
event_debug(("Bound to port %d - Awaiting connections ... ",
port));
return (res);
}
static int
evhttp_accept_socket(struct evhttp *http, int fd)
{
struct evhttp_bound_socket *bound;
struct event *ev;
int res;
bound = malloc(sizeof(struct evhttp_bound_socket));
if (bound == NULL)
return (-1);
ev = &bound->bind_ev;
/* Schedule the socket for accepting */
event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http);
EVHTTP_BASE_SET(http, ev);
event_add(ev, NULL);
event_debug(("Bound to port %d - Awaiting connections ... ", port));
res = event_add(ev, NULL);
if (res == -1) {
free(bound);
return (-1);
}
TAILQ_INSERT_TAIL(&http->sockets, bound, next);
return (0);
}
@ -2033,6 +2062,7 @@ evhttp_new_object(void)
http->timeout = -1;
TAILQ_INIT(&http->sockets);
TAILQ_INIT(&http->callbacks);
TAILQ_INIT(&http->connections);
@ -2071,11 +2101,19 @@ evhttp_free(struct evhttp* http)
{
struct evhttp_cb *http_cb;
struct evhttp_connection *evcon;
int fd = http->bind_ev.ev_fd;
struct evhttp_bound_socket *bound;
int fd;
/* Remove the accepting part */
event_del(&http->bind_ev);
EVUTIL_CLOSESOCKET(fd);
while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
TAILQ_REMOVE(&http->sockets, bound, next);
fd = bound->bind_ev.ev_fd;
event_del(&bound->bind_ev);
EVUTIL_CLOSESOCKET(fd);
free(bound);
}
while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
/* evhttp_connection_free removes the connection */

View File

@ -224,6 +224,12 @@ http_basic_test(void)
fprintf(stdout, "Testing Basic HTTP Server: ");
http = http_setup(&port, NULL);
/* bind to a second socket */
if (evhttp_bind_socket(http, "127.0.0.1", port + 1) == -1) {
fprintf(stdout, "FAILED (bind)\n");
exit(1);
}
fd = http_connect("127.0.0.1", port);
@ -241,16 +247,41 @@ http_basic_test(void)
event_dispatch();
if (test_ok != 2) {
fprintf(stdout, "FAILED\n");
exit(1);
}
/* connect to the second port */
bufferevent_free(bev);
close(fd);
fd = http_connect("127.0.0.1", port + 1);
/* Stupid thing to send a request */
bev = bufferevent_new(fd, http_readcb, http_writecb,
http_errorcb, NULL);
http_request =
"GET /test HTTP/1.1\r\n"
"Host: somehost\r\n"
"Connection: close\r\n"
"\r\n";
bufferevent_write(bev, http_request, strlen(http_request));
event_dispatch();
bufferevent_free(bev);
close(fd);
evhttp_free(http);
if (test_ok != 2) {
if (test_ok != 4) {
fprintf(stdout, "FAILED\n");
exit(1);
}
fprintf(stdout, "OK\n");
}