Fix crashing http server when callback do not reply in place from *gencb*

This is the second hunk of the first patch
5ff8eb26371c4dc56f384b2de35bea2d87814779 ("Fix crashing http server when
callback do not reply in place")

Fixes: #567
This commit is contained in:
Azat Khuzhin 2017-11-04 19:13:28 +03:00
parent 3f19c5eb83
commit 306747e51c
2 changed files with 50 additions and 20 deletions

4
http.c
View File

@ -3421,6 +3421,8 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
/* we have a new request on which the user needs to take action */
req->userdone = 0;
bufferevent_disable(req->evcon->bufev, EV_READ);
if (req->type == 0 || req->uri == NULL) {
evhttp_send_error(req, req->response_code, NULL);
return;
@ -3440,8 +3442,6 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
}
if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
bufferevent_disable(req->evcon->bufev, EV_READ);
(*cb->cb)(req, cb->cbarg);
return;
}

View File

@ -129,7 +129,8 @@ https_bev(struct event_base *base, void *arg)
}
#endif
static struct evhttp *
http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
http_setup_gencb(ev_uint16_t *pport, struct event_base *base, int mask,
void (*cb)(struct evhttp_request *, void *), void *cbarg)
{
struct evhttp *myhttp;
@ -145,6 +146,8 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
}
#endif
evhttp_set_gencb(myhttp, cb, cbarg);
/* Register a callback for certain types of requests */
evhttp_set_cb(myhttp, "/test", http_basic_cb, myhttp);
evhttp_set_cb(myhttp, "/timeout", http_timeout_cb, myhttp);
@ -161,6 +164,9 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base);
return (myhttp);
}
static struct evhttp *
http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
{ return http_setup_gencb(pport, base, mask, NULL, NULL); }
#ifndef NI_MAXSERV
#define NI_MAXSERV 1024
@ -4526,44 +4532,68 @@ http_request_own_test(void *arg)
test_ok = 1;
}
static void http_run_bev_request(struct event_base *base, int port,
const char *fmt, ...)
{
struct bufferevent *bev = NULL;
va_list ap;
evutil_socket_t fd;
struct evbuffer *out;
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
bev = create_bev(base, fd, 0);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, base);
out = bufferevent_get_output(bev);
va_start(ap, fmt);
evbuffer_add_vprintf(out, fmt, ap);
va_end(ap);
event_base_dispatch(base);
bufferevent_free(bev);
}
static void
http_request_extra_body_test(void *arg)
{
struct basic_test_data *data = arg;
struct bufferevent *bev = NULL;
evutil_socket_t fd;
ev_uint16_t port = 0;
int i;
struct evhttp *http = http_setup(&port, data->base, 0);
struct evbuffer *out, *body = NULL;
struct evhttp *http =
http_setup_gencb(&port, data->base, 0, http_timeout_cb, NULL);
struct evbuffer *body = NULL;
exit_base = data->base;
test_ok = 0;
fd = http_connect("127.0.0.1", port);
/* Stupid thing to send a request */
bev = create_bev(data->base, fd, 0);
bufferevent_setcb(bev, http_readcb, http_writecb,
http_errorcb, data->base);
out = bufferevent_get_output(bev);
body = evbuffer_new();
for (i = 0; i < 10000; ++i)
evbuffer_add_printf(body, "this is the body that HEAD should not have");
evbuffer_add_printf(out,
http_run_bev_request(data->base, port,
"HEAD /timeout HTTP/1.1\r\n"
"Host: somehost\r\n"
"Connection: close\r\n"
"Content-Length: %i\r\n"
"\r\n",
(int)evbuffer_get_length(body)
"\r\n%s",
(int)evbuffer_get_length(body),
evbuffer_pullup(body, -1)
);
evbuffer_add_buffer(out, body);
event_base_dispatch(data->base);
tt_assert(test_ok == -2);
http_run_bev_request(data->base, port,
"HEAD /__gencb__ HTTP/1.1\r\n"
"Host: somehost\r\n"
"Connection: close\r\n"
"Content-Length: %i\r\n"
"\r\n%s",
(int)evbuffer_get_length(body),
evbuffer_pullup(body, -1)
);
tt_assert(test_ok == -2);
end: