Extend close detection to incoming connections

Stock evhttp has no means to detect when an incoming connection gets
closed by the client; it will notice the connection has gone down only
when sending back a reply.

For DAAP update requests working as a push mechanism with an HTTP request
stalled by the server until there actually is an update available, we need
to be notified when a connection goes down so we can perform proper cleanup
and not retain memory.

Do so by extending the close detection mechanism used for outgoing connections
and the connection failure callback we already have in place for streaming.
This commit is contained in:
Julien BLACHE 2010-01-28 19:19:31 +01:00
parent f425eddb62
commit 7ddd135e2b

View File

@ -1106,7 +1106,11 @@ static void
evhttp_detect_close_cb(int fd, short what, void *arg) evhttp_detect_close_cb(int fd, short what, void *arg)
{ {
struct evhttp_connection *evcon = arg; struct evhttp_connection *evcon = arg;
if (evcon->flags & EVHTTP_CON_OUTGOING)
evhttp_connection_reset(evcon); evhttp_connection_reset(evcon);
else
evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
} }
static void static void
@ -1910,6 +1914,8 @@ evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
struct evbuffer *buf = evbuffer_new(); struct evbuffer *buf = evbuffer_new();
evhttp_connection_stop_detectclose(req->evcon);
/* close the connection on error */ /* close the connection on error */
evhttp_add_header(req->output_headers, "Connection", "close"); evhttp_add_header(req->output_headers, "Connection", "close");
@ -1946,6 +1952,8 @@ void
evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
struct evbuffer *databuf) struct evbuffer *databuf)
{ {
evhttp_connection_stop_detectclose(req->evcon);
evhttp_response_code(req, code, reason); evhttp_response_code(req, code, reason);
evhttp_send(req, databuf); evhttp_send(req, databuf);
@ -1955,6 +1963,8 @@ void
evhttp_send_reply_start(struct evhttp_request *req, int code, evhttp_send_reply_start(struct evhttp_request *req, int code,
const char *reason) const char *reason)
{ {
evhttp_connection_stop_detectclose(req->evcon);
evhttp_response_code(req, code, reason); evhttp_response_code(req, code, reason);
if (req->major == 1 && req->minor == 1) { if (req->major == 1 && req->minor == 1) {
/* use chunked encoding for HTTP/1.1 */ /* use chunked encoding for HTTP/1.1 */
@ -2215,12 +2225,14 @@ evhttp_handle_request(struct evhttp_request *req, void *arg)
} }
if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) { if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
evhttp_connection_start_detectclose(req->evcon);
(*cb->cb)(req, cb->cbarg); (*cb->cb)(req, cb->cbarg);
return; return;
} }
/* Generic call back */ /* Generic call back */
if (http->gencb) { if (http->gencb) {
evhttp_connection_start_detectclose(req->evcon);
(*http->gencb)(req, http->gencbarg); (*http->gencb)(req, http->gencbarg);
return; return;
} else { } else {