diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-08-21 16:39:35 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-08-21 18:35:20 +0300 |
commit | 4fb57ae153ddd856c80885425eb2321cd95a2cf0 (patch) | |
tree | 794757846326cd4f8ea182f20539ff5f31b7e5e8 | |
parent | 55785fe949779a18c461000ce0b4356f790fb8c5 (diff) | |
download | libmicrohttpd-4fb57ae153ddd856c80885425eb2321cd95a2cf0.tar.gz libmicrohttpd-4fb57ae153ddd856c80885425eb2321cd95a2cf0.zip |
Added new connection flag "stop_with_error".
Stopped usage of "read_close" flag when read hasn't been closed.
-rw-r--r-- | src/microhttpd/connection.c | 59 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 12 |
2 files changed, 43 insertions, 28 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index a01ca32e..7b61916f 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -829,6 +829,7 @@ connection_close_error (struct MHD_Connection *connection, | |||
829 | const char *emsg) | 829 | const char *emsg) |
830 | { | 830 | { |
831 | #ifdef HAVE_MESSAGES | 831 | #ifdef HAVE_MESSAGES |
832 | connection->stop_with_error = true; | ||
832 | if (NULL != emsg) | 833 | if (NULL != emsg) |
833 | MHD_DLOG (connection->daemon, | 834 | MHD_DLOG (connection->daemon, |
834 | "%s\n", | 835 | "%s\n", |
@@ -865,7 +866,8 @@ connection_close_error_check (struct MHD_Connection *connection, | |||
865 | { | 866 | { |
866 | if ( (NULL != connection->response) && | 867 | if ( (NULL != connection->response) && |
867 | (400 <= connection->responseCode) && | 868 | (400 <= connection->responseCode) && |
868 | (connection->read_closed) && | 869 | (NULL == connection->response->crc) && /* Static response only! */ |
870 | (connection->stop_with_error) && | ||
869 | (MHD_CONNECTION_HEADERS_SENDING == connection->state) ) | 871 | (MHD_CONNECTION_HEADERS_SENDING == connection->state) ) |
870 | return; /* An error response was already queued */ | 872 | return; /* An error response was already queued */ |
871 | 873 | ||
@@ -1188,9 +1190,7 @@ keepalive_possible (struct MHD_Connection *connection) | |||
1188 | } | 1190 | } |
1189 | #endif /* UPGRADE_SUPPORT */ | 1191 | #endif /* UPGRADE_SUPPORT */ |
1190 | 1192 | ||
1191 | /* TODO: use additional flags, like "error_closure" or | 1193 | if ((c->read_closed) || (c->stop_with_error)) |
1192 | * "! read_completed" */ | ||
1193 | if (c->read_closed) | ||
1194 | return MHD_CONN_MUST_CLOSE; | 1194 | return MHD_CONN_MUST_CLOSE; |
1195 | 1195 | ||
1196 | if (0 != (r->flags & MHD_RF_HTTP_1_0_COMPATIBLE_STRICT)) | 1196 | if (0 != (r->flags & MHD_RF_HTTP_1_0_COMPATIBLE_STRICT)) |
@@ -2126,7 +2126,7 @@ transmit_error_response_len (struct MHD_Connection *connection, | |||
2126 | enum MHD_Result iret; | 2126 | enum MHD_Result iret; |
2127 | 2127 | ||
2128 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 2128 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
2129 | connection->read_closed = true; | 2129 | connection->stop_with_error = true; |
2130 | if (0 != connection->read_buffer_size) | 2130 | if (0 != connection->read_buffer_size) |
2131 | { | 2131 | { |
2132 | /* Read buffer is not needed anymore, discard it | 2132 | /* Read buffer is not needed anymore, discard it |
@@ -2254,7 +2254,7 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) | |||
2254 | REQUEST_TOO_BIG); | 2254 | REQUEST_TOO_BIG); |
2255 | continue; | 2255 | continue; |
2256 | } | 2256 | } |
2257 | if (! connection->read_closed) | 2257 | if (! connection->stop_with_error) |
2258 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; | 2258 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; |
2259 | else | 2259 | else |
2260 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK; | 2260 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK; |
@@ -2294,7 +2294,7 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) | |||
2294 | } | 2294 | } |
2295 | } | 2295 | } |
2296 | if ( (connection->read_buffer_offset < connection->read_buffer_size) && | 2296 | if ( (connection->read_buffer_offset < connection->read_buffer_size) && |
2297 | (! connection->read_closed) ) | 2297 | (! connection->stop_with_error) ) |
2298 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; | 2298 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; |
2299 | else | 2299 | else |
2300 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK; | 2300 | connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK; |
@@ -2303,7 +2303,7 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection) | |||
2303 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: | 2303 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: |
2304 | /* while reading footers, we always grow the | 2304 | /* while reading footers, we always grow the |
2305 | read buffer if needed, no size-check required */ | 2305 | read buffer if needed, no size-check required */ |
2306 | if (connection->read_closed) | 2306 | if (connection->stop_with_error) |
2307 | { | 2307 | { |
2308 | CONNECTION_CLOSE_ERROR (connection, | 2308 | CONNECTION_CLOSE_ERROR (connection, |
2309 | NULL); | 2309 | NULL); |
@@ -2930,8 +2930,9 @@ process_request_body (struct MHD_Connection *connection) | |||
2930 | { | 2930 | { |
2931 | /* malformed encoding */ | 2931 | /* malformed encoding */ |
2932 | CONNECTION_CLOSE_ERROR (connection, | 2932 | CONNECTION_CLOSE_ERROR (connection, |
2933 | _ ( | 2933 | _ ("Received malformed HTTP request " \ |
2934 | "Received malformed HTTP request (bad chunked encoding). Closing connection.")); | 2934 | "(bad chunked encoding). " \ |
2935 | "Closing connection.")); | ||
2935 | return; | 2936 | return; |
2936 | } | 2937 | } |
2937 | available -= i; | 2938 | available -= i; |
@@ -3009,8 +3010,9 @@ process_request_body (struct MHD_Connection *connection) | |||
3009 | { | 3010 | { |
3010 | /* malformed encoding */ | 3011 | /* malformed encoding */ |
3011 | CONNECTION_CLOSE_ERROR (connection, | 3012 | CONNECTION_CLOSE_ERROR (connection, |
3012 | _ ( | 3013 | _ ("Received malformed HTTP request " \ |
3013 | "Received malformed HTTP request (bad chunked encoding). Closing connection.")); | 3014 | "(bad chunked encoding). " \ |
3015 | "Closing connection.")); | ||
3014 | return; | 3016 | return; |
3015 | } | 3017 | } |
3016 | /* skip 2nd part of line feed */ | 3018 | /* skip 2nd part of line feed */ |
@@ -3065,8 +3067,8 @@ process_request_body (struct MHD_Connection *connection) | |||
3065 | { | 3067 | { |
3066 | /* serious internal error, close connection */ | 3068 | /* serious internal error, close connection */ |
3067 | CONNECTION_CLOSE_ERROR (connection, | 3069 | CONNECTION_CLOSE_ERROR (connection, |
3068 | _ ( | 3070 | _ ("Application reported internal error, " \ |
3069 | "Application reported internal error, closing connection.")); | 3071 | "closing connection.")); |
3070 | return; | 3072 | return; |
3071 | } | 3073 | } |
3072 | if (left_unprocessed > to_be_processed) | 3074 | if (left_unprocessed > to_be_processed) |
@@ -3089,8 +3091,8 @@ process_request_body (struct MHD_Connection *connection) | |||
3089 | if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && | 3091 | if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && |
3090 | (! connection->suspended) ) | 3092 | (! connection->suspended) ) |
3091 | MHD_DLOG (daemon, | 3093 | MHD_DLOG (daemon, |
3092 | _ ( | 3094 | _ ("WARNING: incomplete upload processing and connection " \ |
3093 | "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n")); | 3095 | "not suspended may result in hung connection.\n")); |
3094 | #endif | 3096 | #endif |
3095 | } | 3097 | } |
3096 | processed_size = to_be_processed - left_unprocessed; | 3098 | processed_size = to_be_processed - left_unprocessed; |
@@ -3326,7 +3328,7 @@ parse_connection_headers (struct MHD_Connection *connection) | |||
3326 | 3328 | ||
3327 | /* die, http 1.1 request without host and we are pedantic */ | 3329 | /* die, http 1.1 request without host and we are pedantic */ |
3328 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 3330 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
3329 | connection->read_closed = true; | 3331 | connection->stop_with_error = true; |
3330 | #ifdef HAVE_MESSAGES | 3332 | #ifdef HAVE_MESSAGES |
3331 | MHD_DLOG (connection->daemon, | 3333 | MHD_DLOG (connection->daemon, |
3332 | _ ("Received HTTP 1.1 request without `Host' header.\n")); | 3334 | _ ("Received HTTP 1.1 request without `Host' header.\n")); |
@@ -3535,7 +3537,7 @@ MHD_connection_handle_read (struct MHD_Connection *connection) | |||
3535 | case MHD_CONNECTION_BODY_RECEIVED: | 3537 | case MHD_CONNECTION_BODY_RECEIVED: |
3536 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: | 3538 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: |
3537 | /* nothing to do but default action */ | 3539 | /* nothing to do but default action */ |
3538 | if (connection->read_closed) | 3540 | if ((connection->read_closed) || (connection->stop_with_error)) |
3539 | { | 3541 | { |
3540 | MHD_connection_close_ (connection, | 3542 | MHD_connection_close_ (connection, |
3541 | MHD_REQUEST_TERMINATED_READ_ERROR); | 3543 | MHD_REQUEST_TERMINATED_READ_ERROR); |
@@ -4111,7 +4113,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4111 | { | 4113 | { |
4112 | if (MHD_CONNECTION_INIT != connection->state) | 4114 | if (MHD_CONNECTION_INIT != connection->state) |
4113 | continue; | 4115 | continue; |
4114 | if (connection->read_closed) | 4116 | if (connection->stop_with_error) |
4115 | { | 4117 | { |
4116 | CONNECTION_CLOSE_ERROR (connection, | 4118 | CONNECTION_CLOSE_ERROR (connection, |
4117 | NULL); | 4119 | NULL); |
@@ -4137,7 +4139,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4137 | { | 4139 | { |
4138 | if (MHD_CONNECTION_URL_RECEIVED != connection->state) | 4140 | if (MHD_CONNECTION_URL_RECEIVED != connection->state) |
4139 | continue; | 4141 | continue; |
4140 | if (connection->read_closed) | 4142 | if (connection->stop_with_error) |
4141 | { | 4143 | { |
4142 | CONNECTION_CLOSE_ERROR (connection, | 4144 | CONNECTION_CLOSE_ERROR (connection, |
4143 | NULL); | 4145 | NULL); |
@@ -4169,7 +4171,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4169 | { | 4171 | { |
4170 | if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED) | 4172 | if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED) |
4171 | continue; | 4173 | continue; |
4172 | if (connection->read_closed) | 4174 | if (connection->stop_with_error) |
4173 | { | 4175 | { |
4174 | CONNECTION_CLOSE_ERROR (connection, | 4176 | CONNECTION_CLOSE_ERROR (connection, |
4175 | NULL); | 4177 | NULL); |
@@ -4216,7 +4218,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4216 | /* we refused (no upload allowed!) */ | 4218 | /* we refused (no upload allowed!) */ |
4217 | connection->remaining_upload_size = 0; | 4219 | connection->remaining_upload_size = 0; |
4218 | /* force close, in case client still tries to upload... */ | 4220 | /* force close, in case client still tries to upload... */ |
4219 | connection->read_closed = true; | 4221 | connection->stop_with_error = true; |
4220 | } | 4222 | } |
4221 | connection->state = (0 == connection->remaining_upload_size) | 4223 | connection->state = (0 == connection->remaining_upload_size) |
4222 | ? MHD_CONNECTION_FOOTERS_RECEIVED | 4224 | ? MHD_CONNECTION_FOOTERS_RECEIVED |
@@ -4242,10 +4244,10 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4242 | if ( (0 == connection->remaining_upload_size) || | 4244 | if ( (0 == connection->remaining_upload_size) || |
4243 | ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) && | 4245 | ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) && |
4244 | (0 == connection->read_buffer_offset) && | 4246 | (0 == connection->read_buffer_offset) && |
4245 | (connection->read_closed) ) ) | 4247 | (connection->stop_with_error) ) ) |
4246 | { | 4248 | { |
4247 | if ( (connection->have_chunked_upload) && | 4249 | if ( (connection->have_chunked_upload) && |
4248 | (! connection->read_closed) ) | 4250 | (! connection->stop_with_error) ) |
4249 | connection->state = MHD_CONNECTION_BODY_RECEIVED; | 4251 | connection->state = MHD_CONNECTION_BODY_RECEIVED; |
4250 | else | 4252 | else |
4251 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 4253 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
@@ -4261,7 +4263,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4261 | { | 4263 | { |
4262 | if (connection->state != MHD_CONNECTION_BODY_RECEIVED) | 4264 | if (connection->state != MHD_CONNECTION_BODY_RECEIVED) |
4263 | continue; | 4265 | continue; |
4264 | if (connection->read_closed) | 4266 | if (connection->stop_with_error) |
4265 | { | 4267 | { |
4266 | CONNECTION_CLOSE_ERROR (connection, | 4268 | CONNECTION_CLOSE_ERROR (connection, |
4267 | NULL); | 4269 | NULL); |
@@ -4293,7 +4295,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4293 | { | 4295 | { |
4294 | if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED) | 4296 | if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED) |
4295 | continue; | 4297 | continue; |
4296 | if (connection->read_closed) | 4298 | if (connection->stop_with_error) |
4297 | { | 4299 | { |
4298 | CONNECTION_CLOSE_ERROR (connection, | 4300 | CONNECTION_CLOSE_ERROR (connection, |
4299 | NULL); | 4301 | NULL); |
@@ -4471,7 +4473,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
4471 | /* Reset connection after complete reply */ | 4473 | /* Reset connection after complete reply */ |
4472 | connection_reset (connection, | 4474 | connection_reset (connection, |
4473 | MHD_CONN_USE_KEEPALIVE == connection->keepalive && | 4475 | MHD_CONN_USE_KEEPALIVE == connection->keepalive && |
4474 | ! connection->read_closed); | 4476 | ! connection->read_closed && |
4477 | ! connection->stop_with_error); | ||
4475 | continue; | 4478 | continue; |
4476 | case MHD_CONNECTION_CLOSED: | 4479 | case MHD_CONNECTION_CLOSED: |
4477 | cleanup_connection (connection); | 4480 | cleanup_connection (connection); |
@@ -4881,7 +4884,7 @@ MHD_queue_response (struct MHD_Connection *connection, | |||
4881 | { | 4884 | { |
4882 | /* response was queued "early", refuse to read body / footers or | 4885 | /* response was queued "early", refuse to read body / footers or |
4883 | further requests! */ | 4886 | further requests! */ |
4884 | connection->read_closed = true; | 4887 | connection->stop_with_error = true; |
4885 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 4888 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; |
4886 | connection->remaining_upload_size = 0; | 4889 | connection->remaining_upload_size = 0; |
4887 | } | 4890 | } |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 60d1862d..a2a454f1 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1186,6 +1186,18 @@ struct MHD_Connection | |||
1186 | */ | 1186 | */ |
1187 | bool read_closed; | 1187 | bool read_closed; |
1188 | 1188 | ||
1189 | /** | ||
1190 | * Some error happens during processing the connection therefore this | ||
1191 | * connection must be closed. | ||
1192 | * The error may come from the client side (like wrong request format), | ||
1193 | * from the application side (like data callback returned error), or from | ||
1194 | * the OS side (like out-of-memory). | ||
1195 | * The connection cannot be reused for additional requests as the current | ||
1196 | * request may be incompletely read and it is unclear where is the initial | ||
1197 | * byte of the next request. | ||
1198 | */ | ||
1199 | bool stop_with_error; | ||
1200 | |||
1189 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) | 1201 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) |
1190 | /** | 1202 | /** |
1191 | * Set to `true` if the thread has been joined. | 1203 | * Set to `true` if the thread has been joined. |