mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.
svn:r770
This commit is contained in:
parent
d58a0a7c42
commit
0d43f0dfc5
@ -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:
|
||||
|
@ -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
52
http.c
@ -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 */
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user