stream_process_states.c (21759B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2014-2024 Evgeny Grin (Karlson2k) 5 Copyright (C) 2007-2020 Daniel Pittman and Christian Grothoff 6 7 GNU libmicrohttpd is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 GNU libmicrohttpd is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 Alternatively, you can redistribute GNU libmicrohttpd and/or 18 modify it under the terms of the GNU General Public License as 19 published by the Free Software Foundation; either version 2 of 20 the License, or (at your option) any later version, together 21 with the eCos exception, as follows: 22 23 As a special exception, if other files instantiate templates or 24 use macros or inline functions from this file, or you compile this 25 file and link it with other works to produce a work based on this 26 file, this file does not by itself cause the resulting work to be 27 covered by the GNU General Public License. However the source code 28 for this file must still be made available in accordance with 29 section (3) of the GNU General Public License v2. 30 31 This exception does not invalidate any other reasons why a work 32 based on this file might be covered by the GNU General Public 33 License. 34 35 You should have received copies of the GNU Lesser General Public 36 License and the GNU General Public License along with this library; 37 if not, see <https://www.gnu.org/licenses/>. 38 */ 39 40 /** 41 * @file src/mhd2/stream_process_states.h 42 * @brief The definitions of internal functions for processing 43 * stream states 44 * @author Karlson2k (Evgeny Grin) 45 * 46 * Based on the MHD v0.x code by Daniel Pittman, Christian Grothoff and other 47 * contributors. 48 */ 49 50 #include "mhd_sys_options.h" 51 52 #include "sys_bool_type.h" 53 #include "sys_base_types.h" 54 55 #include "mhd_assert.h" 56 #include "mhd_unreachable.h" 57 58 #include "mhd_str_macros.h" 59 #include "mhd_socket_error_funcs.h" 60 61 #include "mhd_daemon.h" 62 #include "mhd_connection.h" 63 #include "mhd_response.h" 64 65 #include "mhd_comm_layer_state.h" 66 #ifdef MHD_SUPPORT_HTTP2 67 # include "h2/h2_comm.h" 68 #endif 69 #ifdef MHD_SUPPORT_HTTPS 70 # include "mhd_tls_funcs.h" 71 #endif /* MHD_SUPPORT_HTTPS */ 72 73 #include "stream_process_states.h" 74 #include "stream_funcs.h" 75 #include "stream_process_request.h" 76 #include "stream_process_reply.h" 77 78 #include "conn_mark_ready.h" 79 #include "conn_timeout.h" 80 81 #ifdef MHD_SUPPORT_UPGRADE 82 # include "upgrade_proc.h" 83 #endif /* MHD_SUPPORT_UPGRADE */ 84 85 #ifdef MHD_USE_TRACE_SUSPEND_RESUME 86 # include <stdio.h> 87 #endif /* MHD_USE_TRACE_SUSPEND_RESUME */ 88 89 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 90 mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) 91 { 92 #ifdef MHD_SUPPORT_HTTPS 93 mhd_assert (!mhd_C_HAS_TLS (c) \ 94 || (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); 95 mhd_assert (mhd_C_HAS_TLS (c) \ 96 || (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); 97 #endif /* MHD_SUPPORT_HTTPS */ 98 99 #ifdef MHD_SUPPORT_HTTP2 100 if (mhd_C_IS_HTTP2 (c)) 101 { 102 mhd_h2_conn_state_update (c); 103 return; 104 } 105 #endif /* MHD_SUPPORT_HTTP2 */ 106 107 switch (c->stage) 108 { 109 case mhd_HTTP_STAGE_INIT: 110 case mhd_HTTP_STAGE_REQ_LINE_RECEIVING: 111 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 112 break; 113 case mhd_HTTP_STAGE_REQ_LINE_RECEIVED: 114 mhd_assert (0 && "Impossible value"); 115 mhd_UNREACHABLE (); 116 break; 117 case mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING: 118 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 119 break; 120 case mhd_HTTP_STAGE_HEADERS_RECEIVED: 121 case mhd_HTTP_STAGE_HEADERS_PROCESSED: 122 mhd_assert (0 && "Impossible value"); 123 mhd_UNREACHABLE (); 124 break; 125 case mhd_HTTP_STAGE_CONTINUE_SENDING: 126 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 127 break; 128 case mhd_HTTP_STAGE_BODY_RECEIVING: 129 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 130 break; 131 case mhd_HTTP_STAGE_BODY_RECEIVED: 132 mhd_assert (0 && "Impossible value"); 133 mhd_UNREACHABLE (); 134 break; 135 case mhd_HTTP_STAGE_FOOTERS_RECEIVING: 136 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 137 break; 138 case mhd_HTTP_STAGE_FOOTERS_RECEIVED: 139 mhd_assert (0 && "Impossible value"); 140 mhd_UNREACHABLE (); 141 break; 142 case mhd_HTTP_STAGE_FULL_REQ_RECEIVED: 143 mhd_assert (0 && "Should not be possible"); 144 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 145 break; 146 case mhd_HTTP_STAGE_REQ_RECV_FINISHED: 147 mhd_assert (0 && "Impossible value"); 148 mhd_UNREACHABLE (); 149 break; 150 case mhd_HTTP_STAGE_START_REPLY: 151 mhd_assert (0 && "Impossible value"); 152 mhd_UNREACHABLE (); 153 break; 154 case mhd_HTTP_STAGE_HEADERS_SENDING: 155 /* headers in buffer, keep writing */ 156 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 157 break; 158 case mhd_HTTP_STAGE_HEADERS_SENT: 159 mhd_assert (0 && "Impossible value"); 160 mhd_UNREACHABLE (); 161 break; 162 #ifdef MHD_SUPPORT_UPGRADE 163 case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: 164 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 165 break; 166 #endif /* MHD_SUPPORT_UPGRADE */ 167 case mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY: 168 mhd_assert (0 && "Should not be possible"); 169 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 170 break; 171 case mhd_HTTP_STAGE_UNCHUNKED_BODY_READY: 172 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 173 break; 174 case mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY: 175 mhd_assert (0 && "Should not be possible"); 176 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 177 break; 178 case mhd_HTTP_STAGE_CHUNKED_BODY_READY: 179 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 180 break; 181 case mhd_HTTP_STAGE_CHUNKED_BODY_SENT: 182 mhd_assert (0 && "Impossible value"); 183 mhd_UNREACHABLE (); 184 break; 185 case mhd_HTTP_STAGE_FOOTERS_SENDING: 186 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 187 break; 188 case mhd_HTTP_STAGE_FULL_REPLY_SENT: 189 mhd_assert (0 && "Impossible value"); 190 mhd_UNREACHABLE (); 191 break; 192 #ifdef MHD_SUPPORT_UPGRADE 193 case mhd_HTTP_STAGE_UPGRADING: 194 mhd_assert (0 && "Impossible value"); 195 mhd_UNREACHABLE (); 196 break; 197 case mhd_HTTP_STAGE_UPGRADED: 198 mhd_assert (0 && "Should not be possible"); 199 c->event_loop_info = MHD_EVENT_LOOP_INFO_UPGRADED; 200 break; 201 case mhd_HTTP_STAGE_UPGRADED_CLEANING: 202 mhd_assert (0 && "Should be unreachable"); 203 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 204 break; 205 #endif /* MHD_SUPPORT_UPGRADE */ 206 case mhd_HTTP_STAGE_PRE_CLOSING: 207 mhd_assert (0 && "Should be unreachable"); 208 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 209 break; 210 case mhd_HTTP_STAGE_CLOSED: 211 mhd_assert (0 && "Should be unreachable"); 212 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 213 break; 214 default: 215 mhd_UNREACHABLE (); 216 break; 217 } 218 } 219 220 221 /** 222 * Process HTTP communication layer states and events 223 * @param c the connection to process 224 * @return #mhd_COMM_LAYER_PROCESSING if setting up HTTP connection is 225 * in progress, 226 * #mhd_COMM_LAYER_OK if HTTP communication can be performed now, 227 * #mhd_COMM_LAYER_BROKEN if connection is broken and should be closed. 228 */ 229 mhd_static_inline enum mhd_CommLayerState 230 process_http_comm_layer (struct MHD_Connection *restrict c) 231 { 232 #ifdef MHD_SUPPORT_HTTP2 233 if (mhd_HTTP_LAYER_CONNECTED == c->h_layer.state) 234 return mhd_COMM_LAYER_OK; /* Shortcut for the most common case */ 235 236 switch (c->h_layer.state) 237 { 238 case mhd_HTTP_LAYER_PREFACE: 239 return mhd_h2_process_preface (c); 240 case mhd_HTTP_LAYER_CONNECTED: 241 mhd_UNREACHABLE (); /* Handled above */ 242 return mhd_COMM_LAYER_OK; 243 case mhd_HTTP_LAYER_CLOSING: 244 case mhd_HTTP_LAYER_CLOSED: 245 return mhd_COMM_LAYER_OK; 246 case mhd_HTTP_LAYER_BROKEN: 247 return mhd_COMM_LAYER_BROKEN; 248 default: 249 break; 250 } 251 252 mhd_UNREACHABLE (); 253 return mhd_COMM_LAYER_BROKEN; 254 255 #else /* ! MHD_SUPPORT_HTTP2 */ 256 (void)c; /* Unused in HTTP/1.x-only modes */ 257 return mhd_COMM_LAYER_OK; 258 #endif /* ! MHD_SUPPORT_HTTP2 */ 259 } 260 261 262 /** 263 * Finalise resuming of the connection 264 * @param c the connection to resume 265 */ 266 static MHD_FN_PAR_NONNULL_ALL_ void 267 finish_resume (struct MHD_Connection *restrict c) 268 { 269 mhd_assert (c->resuming); 270 c->resuming = false; 271 272 #ifdef MHD_USE_TRACE_SUSPEND_RESUME 273 fprintf (stderr, 274 "%%%%%% Resumed connection, FD: %2llu\n", 275 (unsigned long long)c->sk.fd); 276 #endif /* MHD_USE_TRACE_SUSPEND_RESUME */ 277 mhd_assert (!c->suspended); 278 mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS == c->event_loop_info); 279 } 280 281 282 /* always return 'false' */ 283 static MHD_FN_PAR_NONNULL_ALL_ bool 284 handle_early_peer_shutdown (struct MHD_Connection *restrict c, 285 bool has_unfinished_process) 286 { 287 mhd_conn_start_closing (c, 288 has_unfinished_process ? 289 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY : 290 mhd_CONN_CLOSE_HTTP_COMPLETED, 291 NULL); 292 return false; 293 } 294 295 296 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool 297 mhd_conn_process_data (struct MHD_Connection *restrict c) 298 { 299 struct MHD_Daemon *const d = c->daemon; 300 bool daemon_closing; 301 302 if (c->suspended) 303 { 304 mhd_assert (!mhd_C_IS_HTTP2 (c)); 305 return true; 306 } 307 308 mhd_assert ((!mhd_SCKT_NET_ST_HAS_FLAG (c->sk.ready, 309 mhd_SOCKET_NET_STATE_ERROR_READY)) 310 || (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err)); 311 312 if (mhd_SOCKET_ERR_NO_ERROR == c->sk.state.discnt_err) 313 { 314 switch (process_http_comm_layer (c)) 315 { 316 case mhd_COMM_LAYER_OK: 317 break; /* Process HTTP data */ 318 case mhd_COMM_LAYER_PROCESSING: 319 mhd_assert (!c->resuming); 320 if (c->sk.state.rmt_shut_wr) 321 { 322 bool unfinished; 323 unfinished = (0 != c->read_buffer_offset); 324 #ifdef MHD_SUPPORT_HTTPS 325 if (!unfinished 326 && mhd_C_HAS_TLS (c)) 327 unfinished = 328 (mhd_TLS_ALPN_PROT_HTTP2 == mhd_tls_conn_get_alpn_prot (c->tls)); 329 #endif /* MHD_SUPPORT_HTTPS */ 330 return handle_early_peer_shutdown (c, 331 unfinished); 332 } 333 return true; /* Too early for HTTP */ 334 case mhd_COMM_LAYER_BROKEN: 335 mhd_assert (c->dbg.closing_started); 336 return false; /* Connection is broken */ 337 default: 338 mhd_UNREACHABLE (); 339 return false; 340 } 341 } 342 343 #ifdef MHD_SUPPORT_HTTP2 344 if (mhd_C_IS_HTTP2 (c)) 345 { 346 if (!mhd_h2_conn_process_data (c)) 347 return false; 348 mhd_conn_event_loop_state_update (c); 349 mhd_conn_mark_ready_update (c); 350 return true; 351 } 352 #endif /* MHD_SUPPORT_HTTP2 */ 353 354 mhd_assert (mhd_D_IS_HTTP1_ENABLED (d) || (!mhd_C_IS_HTTP2 (c)) \ 355 || c->stop_with_error); 356 357 if (c->resuming) 358 { 359 mhd_assert (!mhd_C_IS_HTTP2 (c)); 360 finish_resume (c); 361 } 362 363 if ((c->sk.state.rmt_shut_wr) && (mhd_HTTP_STAGE_START_REPLY > c->stage)) 364 { 365 if (0 == c->read_buffer_offset) 366 { /* Read buffer is empty, connection state is actual */ 367 return handle_early_peer_shutdown (c, 368 (mhd_HTTP_STAGE_INIT != c->stage)); 369 } 370 } 371 372 if (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err) 373 { 374 mhd_assert (mhd_SOCKET_ERR_IS_HARD (c->sk.state.discnt_err)); 375 mhd_conn_start_closing_skt_err (c); 376 return false; 377 } 378 379 daemon_closing = (mhd_DAEMON_STATE_STOPPING == d->state); 380 #ifdef MHD_SUPPORT_THREADS 381 daemon_closing = daemon_closing || d->threading.stop_requested; 382 #endif /* MHD_SUPPORT_THREADS */ 383 if (daemon_closing) 384 { 385 mhd_conn_start_closing_d_shutdown (c); 386 return false; 387 } 388 389 mhd_assert (!c->suspended); 390 391 while (!0) 392 { 393 #ifdef MHD_SUPPORT_HTTPS 394 mhd_assert (!mhd_C_HAS_TLS (c) \ 395 || (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); 396 mhd_assert (mhd_C_HAS_TLS (c) \ 397 || (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); 398 #endif /* MHD_SUPPORT_HTTPS */ 399 switch (c->stage) 400 { 401 case mhd_HTTP_STAGE_INIT: 402 case mhd_HTTP_STAGE_REQ_LINE_RECEIVING: 403 if (mhd_stream_get_request_line (c)) 404 { 405 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVING < c->stage); 406 mhd_assert ((MHD_HTTP_VERSION_IS_1X (c->rq.http_ver)) \ 407 || (c->discard_request) 408 || (mhd_HTTP_STAGE_PRE_CLOSING <= c->stage)); 409 continue; 410 } 411 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVING >= c->stage); 412 break; 413 case mhd_HTTP_STAGE_REQ_LINE_RECEIVED: 414 mhd_stream_switch_to_rq_headers_proc (c); 415 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVED != c->stage); 416 continue; 417 case mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING: 418 if (mhd_stream_get_request_headers (c, false)) 419 { 420 mhd_assert (mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING < c->stage); 421 mhd_assert ((mhd_HTTP_STAGE_HEADERS_RECEIVED == c->stage) \ 422 || (c->discard_request)); 423 continue; 424 } 425 mhd_assert (mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING == c->stage); 426 break; 427 case mhd_HTTP_STAGE_HEADERS_RECEIVED: 428 mhd_stream_parse_request_headers (c); 429 mhd_assert (c->stage != mhd_HTTP_STAGE_HEADERS_RECEIVED); 430 continue; 431 case mhd_HTTP_STAGE_HEADERS_PROCESSED: 432 if (mhd_stream_call_app_request_cb (c)) 433 { 434 mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED < c->stage); 435 continue; 436 } 437 // TODO: add assert 438 break; 439 case mhd_HTTP_STAGE_CONTINUE_SENDING: 440 if (c->continue_message_write_offset == 441 mhd_SSTR_LEN (mdh_HTTP_1_1_100_CONTINUE_REPLY)) 442 { 443 #ifdef MHD_SUPPORT_UPGRADE 444 c->rp.sent_100_cntn = true; 445 #endif /* MHD_SUPPORT_UPGRADE */ 446 c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; 447 continue; 448 } 449 break; 450 case mhd_HTTP_STAGE_BODY_RECEIVING: 451 mhd_assert (c->rq.cntn.recv_size < c->rq.cntn.cntn_size); 452 mhd_assert (!c->discard_request); 453 mhd_assert (NULL == c->rp.response); 454 if (0 == c->read_buffer_offset) 455 break; /* Need more data to process */ 456 457 if (mhd_stream_process_request_body (c)) 458 continue; 459 mhd_assert (!c->discard_request); 460 mhd_assert (NULL == c->rp.response); 461 break; 462 case mhd_HTTP_STAGE_BODY_RECEIVED: 463 mhd_assert (!c->discard_request); 464 mhd_assert (NULL == c->rp.response); 465 mhd_assert (c->rq.have_chunked_upload); 466 /* Reset counter variables reused for footers */ 467 c->rq.num_cr_sp_replaced = 0; 468 c->rq.skipped_broken_lines = 0; 469 mhd_stream_reset_rq_hdr_proc_state (c); 470 c->stage = mhd_HTTP_STAGE_FOOTERS_RECEIVING; 471 continue; 472 case mhd_HTTP_STAGE_FOOTERS_RECEIVING: 473 mhd_assert (c->rq.have_chunked_upload); 474 if (mhd_stream_get_request_headers (c, true)) 475 { 476 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING < c->stage); 477 mhd_assert ((mhd_HTTP_STAGE_FOOTERS_RECEIVED == c->stage) \ 478 || (c->discard_request)); 479 continue; 480 } 481 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING == c->stage); 482 break; 483 case mhd_HTTP_STAGE_FOOTERS_RECEIVED: 484 mhd_assert (c->rq.have_chunked_upload); 485 c->stage = mhd_HTTP_STAGE_FULL_REQ_RECEIVED; 486 continue; 487 case mhd_HTTP_STAGE_FULL_REQ_RECEIVED: 488 if (mhd_stream_call_app_final_upload_cb (c)) 489 { 490 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING != c->stage); 491 continue; 492 } 493 break; 494 case mhd_HTTP_STAGE_REQ_RECV_FINISHED: 495 if (mhd_stream_process_req_recv_finished (c)) 496 continue; 497 break; 498 // TODO: add stage for setup and full request buffers cleanup 499 case mhd_HTTP_STAGE_START_REPLY: 500 mhd_assert (NULL != c->rp.response); 501 mhd_stream_switch_from_recv_to_send (c); 502 if (!mhd_stream_build_header_response (c)) 503 continue; 504 mhd_assert (mhd_HTTP_STAGE_START_REPLY != c->stage); 505 break; 506 case mhd_HTTP_STAGE_HEADERS_SENDING: 507 /* no default action, wait for sending all the headers */ 508 break; 509 case mhd_HTTP_STAGE_HEADERS_SENT: 510 if (c->rp.props.send_reply_body) 511 { 512 if (c->rp.props.chunked) 513 c->stage = mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY; 514 else 515 c->stage = mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY; 516 } 517 else 518 c->stage = mhd_HTTP_STAGE_FULL_REPLY_SENT; 519 continue; 520 #ifdef MHD_SUPPORT_UPGRADE 521 case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: 522 if (!mhd_upgrade_try_start_upgrading (c)) 523 break; 524 continue; 525 #endif /* MHD_SUPPORT_UPGRADE */ 526 case mhd_HTTP_STAGE_UNCHUNKED_BODY_READY: 527 mhd_assert (c->rp.props.send_reply_body); 528 mhd_assert (!c->rp.props.chunked); 529 /* nothing to do here, send the data */ 530 break; 531 case mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY: 532 mhd_assert (c->rp.props.send_reply_body); 533 mhd_assert (!c->rp.props.chunked); 534 if (0 == c->rp.response->cntn_size) 535 { /* a shortcut */ 536 c->stage = mhd_HTTP_STAGE_FULL_REPLY_SENT; 537 continue; 538 } 539 if (mhd_stream_prep_unchunked_body (c)) 540 continue; 541 break; 542 case mhd_HTTP_STAGE_CHUNKED_BODY_READY: 543 mhd_assert (c->rp.props.send_reply_body); 544 mhd_assert (c->rp.props.chunked); 545 /* nothing to do here */ 546 break; 547 case mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY: 548 mhd_assert (c->rp.props.send_reply_body); 549 mhd_assert (c->rp.props.chunked); 550 if ((0 == c->rp.response->cntn_size) 551 || (c->rp.rsp_cntn_read_pos == 552 c->rp.response->cntn_size)) 553 { 554 c->stage = mhd_HTTP_STAGE_CHUNKED_BODY_SENT; 555 continue; 556 } 557 if (mhd_stream_prep_chunked_body (c)) 558 continue; 559 break; 560 case mhd_HTTP_STAGE_CHUNKED_BODY_SENT: 561 mhd_assert (c->rp.props.send_reply_body); 562 mhd_assert (c->rp.props.chunked); 563 mhd_assert (c->write_buffer_send_offset <= \ 564 c->write_buffer_append_offset); 565 mhd_stream_call_dcc_cleanup_if_needed (c); 566 if (mhd_stream_prep_chunked_footer (c)) 567 continue; 568 break; 569 case mhd_HTTP_STAGE_FOOTERS_SENDING: 570 mhd_assert (c->rp.props.send_reply_body); 571 mhd_assert (c->rp.props.chunked); 572 /* no default action */ 573 break; 574 case mhd_HTTP_STAGE_FULL_REPLY_SENT: 575 // FIXME: support MHD_HTTP_STATUS_PROCESSING ? 576 /* Reset connection after complete reply */ 577 mhd_stream_finish_req_serving ( \ 578 c, 579 mhd_CONN_KEEPALIVE_POSSIBLE == c->conn_reuse 580 && !c->discard_request 581 && !c->sk.state.rmt_shut_wr); 582 continue; 583 #ifdef MHD_SUPPORT_UPGRADE 584 case mhd_HTTP_STAGE_UPGRADING: 585 if (mhd_upgrade_finish_switch_to_upgraded (c)) 586 return true; /* Do not close connection */ 587 mhd_assert (mhd_HTTP_STAGE_PRE_CLOSING == c->stage); 588 continue; 589 case mhd_HTTP_STAGE_UPGRADED: 590 mhd_assert (0 && "Should be unreachable"); 591 mhd_UNREACHABLE (); 592 break; 593 case mhd_HTTP_STAGE_UPGRADED_CLEANING: 594 mhd_assert (0 && "Should be unreachable"); 595 mhd_UNREACHABLE (); 596 break; 597 #endif /* MHD_SUPPORT_UPGRADE */ 598 case mhd_HTTP_STAGE_PRE_CLOSING: 599 return false; 600 case mhd_HTTP_STAGE_CLOSED: 601 mhd_assert (0 && "Should be unreachable"); 602 mhd_UNREACHABLE (); 603 break; 604 default: 605 mhd_assert (0 && "Impossible value"); 606 mhd_UNREACHABLE (); 607 break; 608 } 609 610 mhd_assert (mhd_HTTP_STAGE_CLOSED != c->stage); 611 612 if (mhd_HTTP_STAGE_PRE_CLOSING == c->stage) 613 { 614 mhd_assert (0 && "Pre-closing should be already caught in the loop"); 615 mhd_UNREACHABLE (); 616 return false; 617 } 618 619 if (c->suspended) 620 { 621 /* Do not perform any network activity while suspended */ 622 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 623 624 mhd_conn_mark_unready (c, d); 625 mhd_conn_deinit_activity_timeout (c); 626 #ifdef MHD_USE_TRACE_SUSPEND_RESUME 627 fprintf (stderr, 628 "%%%%%% Connection suspended, FD: %2llu\n", 629 (unsigned long long)c->sk.fd); 630 #endif /* MHD_USE_TRACE_SUSPEND_RESUME */ 631 return true; 632 } 633 634 if ((c->sk.state.rmt_shut_wr) && (mhd_HTTP_STAGE_START_REPLY > c->stage)) 635 { 636 mhd_conn_start_closing (c, 637 (mhd_HTTP_STAGE_INIT == c->stage) ? 638 mhd_CONN_CLOSE_HTTP_COMPLETED : 639 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY, 640 NULL); 641 return false; 642 } 643 644 if (0 != (c->sk.ready & mhd_SOCKET_NET_STATE_ERROR_READY)) 645 { 646 mhd_assert (0 && "Should be handled earlier"); 647 mhd_conn_start_closing_skt_err (c); 648 return false; 649 } 650 651 mhd_conn_event_loop_state_update (c); 652 653 if (0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info)) 654 { 655 /* Check whether the space is available to receive data */ 656 switch (mhd_stream_check_and_grow_read_buffer_space (c)) 657 { 658 case mhd_CONN_BUFF_GROW_ERR_CONN_CLOSE: 659 mhd_assert (c->discard_request); 660 return false; 661 case mhd_CONN_BUFF_GROW_ERR_REPLY: 662 continue; /* Process error reply */ 663 case mhd_CONN_BUFF_GROW_OK: 664 break; 665 default: 666 mhd_UNREACHABLE (); 667 break; 668 } 669 } 670 671 /* Current MHD design assumes that data must be always processes when 672 * available. If it is not possible, connection must be suspended. */ 673 mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS != c->event_loop_info); 674 675 /* Sockets errors must be already handled */ 676 mhd_assert (0 == (c->sk.ready & mhd_SOCKET_NET_STATE_ERROR_READY)); 677 678 mhd_conn_mark_ready_update (c); 679 680 break; 681 } 682 683 return true; 684 }