From: Stephan Bosch Date: Tue, 17 Oct 2017 14:04:38 +0000 (+0200) Subject: lib-http: server: Allow determining at any time whether the connection will be closed... X-Git-Tag: 2.3.0.rc1~774 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a5886aec87fbfd767a110e6168ce96411acfe798;p=thirdparty%2Fdovecot%2Fcore.git lib-http: server: Allow determining at any time whether the connection will be closed after handling a request. Previously, this was only possible during response submission, which potentially requires making a `close' parameter available for any API function that submits a (failure) response. This would become very ugly and inflexible. --- diff --git a/src/lib-http/http-server-private.h b/src/lib-http/http-server-private.h index 193babcd1a..94a6ac51b6 100644 --- a/src/lib-http/http-server-private.h +++ b/src/lib-http/http-server-private.h @@ -89,7 +89,6 @@ struct http_server_response { bool payload_blocking:1; bool payload_direct:1; bool payload_corked:1; - bool close:1; bool submitted:1; }; @@ -119,6 +118,7 @@ struct http_server_request { bool delay_destroy:1; bool destroy_pending:1; bool failed:1; + bool connection_close:1; }; struct http_server_connection { diff --git a/src/lib-http/http-server-request.c b/src/lib-http/http-server-request.c index 8ff55eaf94..23aba2a567 100644 --- a/src/lib-http/http-server-request.c +++ b/src/lib-http/http-server-request.c @@ -123,6 +123,13 @@ bool http_server_request_unref(struct http_server_request **_req) return FALSE; } +void http_server_request_connection_close(struct http_server_request *req, + bool close) +{ + i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE); + req->connection_close = close; +} + void http_server_request_destroy(struct http_server_request **_req) { struct http_server_request *req = *_req; @@ -324,7 +331,7 @@ void http_server_request_finished(struct http_server_request *req) conn->stats.response_count++; if (tunnel_callback == NULL) { - if (resp->close) { + if (req->connection_close) { http_server_connection_close(&conn, t_strdup_printf("Server closed connection: %u %s", resp->status, resp->reason)); @@ -376,28 +383,28 @@ http_server_request_create_fail_response(struct http_server_request *req, static void http_server_request_fail_full(struct http_server_request *req, - unsigned int status, const char *reason, bool close) + unsigned int status, const char *reason) { struct http_server_response *resp; req->failed = TRUE; resp = http_server_request_create_fail_response(req, status, reason); - if (close) - http_server_response_submit_close(resp); - else - http_server_response_submit(resp); + http_server_response_submit(resp); + if (req->conn->input_broken) + req->connection_close = TRUE; } void http_server_request_fail(struct http_server_request *req, unsigned int status, const char *reason) { - http_server_request_fail_full(req, status, reason, FALSE); + http_server_request_fail_full(req, status, reason); } void http_server_request_fail_close(struct http_server_request *req, unsigned int status, const char *reason) { - http_server_request_fail_full(req, status, reason, TRUE); + http_server_request_connection_close(req, TRUE); + http_server_request_fail_full(req, status, reason); } void http_server_request_fail_auth(struct http_server_request *req, diff --git a/src/lib-http/http-server-response.c b/src/lib-http/http-server-response.c index 8082e56b44..2f2ee7139b 100644 --- a/src/lib-http/http-server-response.c +++ b/src/lib-http/http-server-response.c @@ -189,41 +189,38 @@ void http_server_response_add_auth_basic( http_server_response_add_auth(resp, &chlng); } -static void http_server_response_do_submit(struct http_server_response *resp, - bool close) +static void +http_server_response_do_submit(struct http_server_response *resp) { + i_assert(!resp->submitted); if (resp->date == (time_t)-1) resp->date = ioloop_time; - resp->close = close; resp->submitted = TRUE; http_server_request_submit_response(resp->request); } void http_server_response_submit(struct http_server_response *resp) { - i_assert(!resp->submitted); http_server_response_debug(resp, "Submitted"); - http_server_response_do_submit(resp, FALSE); + http_server_response_do_submit(resp); } void http_server_response_submit_close(struct http_server_response *resp) { - i_assert(!resp->submitted); - http_server_response_debug(resp, "Submitted"); - - http_server_response_do_submit(resp, TRUE); + http_server_request_connection_close(resp->request, TRUE); + http_server_response_submit(resp); } void http_server_response_submit_tunnel(struct http_server_response *resp, http_server_tunnel_callback_t callback, void *context) { - i_assert(!resp->submitted); http_server_response_debug(resp, "Started tunnelling"); resp->tunnel_callback = callback; resp->tunnel_context = context; - http_server_response_do_submit(resp, TRUE); + http_server_request_connection_close(resp->request, TRUE); + http_server_response_do_submit(resp); } static void @@ -556,6 +553,7 @@ static int http_server_response_send_real(struct http_server_response *resp, string_t *rtext = t_str_new(256); struct const_iovec iov[3]; bool is_head = http_request_method_is(&req->req, "HEAD"); + bool close = FALSE; int ret = 0; *error_r = NULL; @@ -590,7 +588,7 @@ static int http_server_response_send_real(struct http_server_response *resp, resp->payload_output = output; o_stream_ref(output); /* connection close marks end of payload */ - resp->close = TRUE; + close = TRUE; } } else { if (!resp->have_hdr_body_spec) @@ -638,8 +636,8 @@ static int http_server_response_send_real(struct http_server_response *resp, str_append(rtext, "Content-Length: 0\r\n"); } if (!resp->have_hdr_connection) { - bool close = resp->close || req->req.connection_close || - req->conn->input_broken; + close = close || req->req.connection_close || + req->connection_close || req->conn->input_broken; if (close && resp->tunnel_callback == NULL) str_append(rtext, "Connection: close\r\n"); else if (http_server_request_version_equals(req, 1, 0)) diff --git a/src/lib-http/http-server.h b/src/lib-http/http-server.h index 76dcf1f8dc..6daf0f500f 100644 --- a/src/lib-http/http-server.h +++ b/src/lib-http/http-server.h @@ -148,6 +148,11 @@ void http_server_request_ref(struct http_server_request *req); references, FALSE if not. */ bool http_server_request_unref(struct http_server_request **_req); +/* Set flag that determines whether the connection is closed after the + request is handled. */ +void http_server_request_connection_close(struct http_server_request *req, + bool close); + /* Get the pool for this request. */ pool_t http_server_request_get_pool(struct http_server_request *req); /* Returns the response created for the request with