stream_process_states.c (20872B)
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 70 #include "stream_process_states.h" 71 #include "stream_funcs.h" 72 #include "stream_process_request.h" 73 #include "stream_process_reply.h" 74 75 #include "conn_mark_ready.h" 76 #include "conn_timeout.h" 77 78 #ifdef MHD_SUPPORT_UPGRADE 79 # include "upgrade_proc.h" 80 #endif /* MHD_SUPPORT_UPGRADE */ 81 82 #ifdef mhd_DEBUG_SUSPEND_RESUME 83 # include <stdio.h> 84 #endif /* mhd_DEBUG_SUSPEND_RESUME */ 85 86 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 87 mhd_conn_event_loop_state_update (struct MHD_Connection *restrict c) 88 { 89 #ifdef MHD_SUPPORT_HTTPS 90 mhd_assert (! mhd_C_HAS_TLS (c) || \ 91 (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); 92 mhd_assert (mhd_C_HAS_TLS (c) || \ 93 (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); 94 #endif /* MHD_SUPPORT_HTTPS */ 95 96 #ifdef MHD_SUPPORT_HTTP2 97 if (mhd_C_IS_HTTP2 (c)) 98 { 99 mhd_h2_conn_state_update (c); 100 return; 101 } 102 #endif /* MHD_SUPPORT_HTTP2 */ 103 104 switch (c->stage) 105 { 106 case mhd_HTTP_STAGE_INIT: 107 case mhd_HTTP_STAGE_REQ_LINE_RECEIVING: 108 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 109 break; 110 case mhd_HTTP_STAGE_REQ_LINE_RECEIVED: 111 mhd_assert (0 && "Impossible value"); 112 mhd_UNREACHABLE (); 113 break; 114 case mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING: 115 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 116 break; 117 case mhd_HTTP_STAGE_HEADERS_RECEIVED: 118 case mhd_HTTP_STAGE_HEADERS_PROCESSED: 119 mhd_assert (0 && "Impossible value"); 120 mhd_UNREACHABLE (); 121 break; 122 case mhd_HTTP_STAGE_CONTINUE_SENDING: 123 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 124 break; 125 case mhd_HTTP_STAGE_BODY_RECEIVING: 126 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 127 break; 128 case mhd_HTTP_STAGE_BODY_RECEIVED: 129 mhd_assert (0 && "Impossible value"); 130 mhd_UNREACHABLE (); 131 break; 132 case mhd_HTTP_STAGE_FOOTERS_RECEIVING: 133 c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; 134 break; 135 case mhd_HTTP_STAGE_FOOTERS_RECEIVED: 136 mhd_assert (0 && "Impossible value"); 137 mhd_UNREACHABLE (); 138 break; 139 case mhd_HTTP_STAGE_FULL_REQ_RECEIVED: 140 mhd_assert (0 && "Should not be possible"); 141 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 142 break; 143 case mhd_HTTP_STAGE_REQ_RECV_FINISHED: 144 mhd_assert (0 && "Impossible value"); 145 mhd_UNREACHABLE (); 146 break; 147 case mhd_HTTP_STAGE_START_REPLY: 148 mhd_assert (0 && "Impossible value"); 149 mhd_UNREACHABLE (); 150 break; 151 case mhd_HTTP_STAGE_HEADERS_SENDING: 152 /* headers in buffer, keep writing */ 153 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 154 break; 155 case mhd_HTTP_STAGE_HEADERS_SENT: 156 mhd_assert (0 && "Impossible value"); 157 mhd_UNREACHABLE (); 158 break; 159 #ifdef MHD_SUPPORT_UPGRADE 160 case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: 161 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 162 break; 163 #endif /* MHD_SUPPORT_UPGRADE */ 164 case mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY: 165 mhd_assert (0 && "Should not be possible"); 166 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 167 break; 168 case mhd_HTTP_STAGE_UNCHUNKED_BODY_READY: 169 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 170 break; 171 case mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY: 172 mhd_assert (0 && "Should not be possible"); 173 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 174 break; 175 case mhd_HTTP_STAGE_CHUNKED_BODY_READY: 176 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 177 break; 178 case mhd_HTTP_STAGE_CHUNKED_BODY_SENT: 179 mhd_assert (0 && "Impossible value"); 180 mhd_UNREACHABLE (); 181 break; 182 case mhd_HTTP_STAGE_FOOTERS_SENDING: 183 c->event_loop_info = MHD_EVENT_LOOP_INFO_SEND; 184 break; 185 case mhd_HTTP_STAGE_FULL_REPLY_SENT: 186 mhd_assert (0 && "Impossible value"); 187 mhd_UNREACHABLE (); 188 break; 189 #ifdef MHD_SUPPORT_UPGRADE 190 case mhd_HTTP_STAGE_UPGRADING: 191 mhd_assert (0 && "Impossible value"); 192 mhd_UNREACHABLE (); 193 break; 194 case mhd_HTTP_STAGE_UPGRADED: 195 mhd_assert (0 && "Should not be possible"); 196 c->event_loop_info = MHD_EVENT_LOOP_INFO_UPGRADED; 197 break; 198 case mhd_HTTP_STAGE_UPGRADED_CLEANING: 199 mhd_assert (0 && "Should be unreachable"); 200 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 201 break; 202 #endif /* MHD_SUPPORT_UPGRADE */ 203 case mhd_HTTP_STAGE_PRE_CLOSING: 204 mhd_assert (0 && "Should be unreachable"); 205 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 206 break; 207 case mhd_HTTP_STAGE_CLOSED: 208 mhd_assert (0 && "Should be unreachable"); 209 c->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 210 break; 211 default: 212 mhd_UNREACHABLE (); 213 break; 214 } 215 } 216 217 218 /** 219 * Process HTTP communication layer states and events 220 * @param c the connection to process 221 * @return #mhd_COMM_LAYER_PROCESSING if setting up HTTP connection is 222 * in progress, 223 * #mhd_COMM_LAYER_OK if HTTP communication can be performed now, 224 * #mhd_COMM_LAYER_BROKEN if connection is broken and should be closed. 225 */ 226 mhd_static_inline enum mhd_CommLayerState 227 process_http_comm_layer (struct MHD_Connection *restrict c) 228 { 229 #ifdef MHD_SUPPORT_HTTP2 230 if (mhd_HTTP_LAYER_CONNECTED == c->h_layer.state) 231 return mhd_COMM_LAYER_OK; /* Shortcut for the most common case */ 232 233 switch (c->h_layer.state) 234 { 235 case mhd_HTTP_LAYER_PREFACE: 236 return mhd_h2_process_preface (c); 237 case mhd_HTTP_LAYER_CONNECTED: 238 mhd_UNREACHABLE (); /* Handled above */ 239 return mhd_COMM_LAYER_OK; 240 case mhd_HTTP_LAYER_CLOSING: 241 case mhd_HTTP_LAYER_CLOSED: 242 return mhd_COMM_LAYER_OK; 243 case mhd_HTTP_LAYER_BROKEN: 244 return mhd_COMM_LAYER_BROKEN; 245 default: 246 break; 247 } 248 249 mhd_UNREACHABLE (); 250 return mhd_COMM_LAYER_BROKEN; 251 252 #else /* ! MHD_SUPPORT_HTTP2 */ 253 (void) c; /* Unused in HTTP/1.x-only modes */ 254 return mhd_COMM_LAYER_OK; 255 #endif /* ! MHD_SUPPORT_HTTP2 */ 256 } 257 258 259 /** 260 * Finalise resuming of the connection 261 * @param c the connection to resume 262 */ 263 static MHD_FN_PAR_NONNULL_ALL_ void 264 finish_resume (struct MHD_Connection *restrict c) 265 { 266 mhd_assert (c->resuming); 267 c->resuming = false; 268 269 #ifdef mhd_DEBUG_SUSPEND_RESUME 270 fprintf (stderr, 271 "%%%%%% Resumed connection, FD: %2llu\n", 272 (unsigned long long) c->sk.fd); 273 #endif /* mhd_DEBUG_SUSPEND_RESUME */ 274 mhd_assert (! c->suspended); 275 mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS == c->event_loop_info); 276 } 277 278 279 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool 280 mhd_conn_process_data (struct MHD_Connection *restrict c) 281 { 282 struct MHD_Daemon *const d = c->daemon; 283 bool daemon_closing; 284 285 if (c->suspended) 286 { 287 mhd_assert (! mhd_C_IS_HTTP2 (c)); 288 return true; 289 } 290 291 switch (process_http_comm_layer (c)) 292 { 293 case mhd_COMM_LAYER_OK: 294 break; /* Process HTTP data */ 295 case mhd_COMM_LAYER_PROCESSING: 296 mhd_assert (! c->resuming); 297 return true; /* Too early for HTTP */ 298 case mhd_COMM_LAYER_BROKEN: 299 mhd_assert (c->dbg.closing_started); 300 return false; /* Connection is broken */ 301 default: 302 mhd_UNREACHABLE (); 303 return false; 304 } 305 306 if (c->resuming) 307 { 308 mhd_assert (! mhd_C_IS_HTTP2 (c)); 309 finish_resume (c); 310 } 311 312 #ifdef MHD_SUPPORT_HTTP2 313 if (mhd_C_IS_HTTP2 (c)) 314 { 315 if (! mhd_h2_conn_process_data (c)) 316 return false; 317 mhd_conn_event_loop_state_update (c); 318 mhd_conn_mark_ready_update (c); 319 return true; 320 } 321 #endif /* MHD_SUPPORT_HTTP2 */ 322 323 mhd_assert (mhd_D_IS_HTTP1_ENABLED (d) || (! mhd_C_IS_HTTP2 (c)) || \ 324 c->stop_with_error); 325 326 if ((c->sk.state.rmt_shut_wr) && (mhd_HTTP_STAGE_START_REPLY > c->stage)) 327 { 328 if (0 == c->read_buffer_offset) 329 { /* Read buffer is empty, connection state is actual */ 330 mhd_conn_start_closing (c, 331 (mhd_HTTP_STAGE_INIT == c->stage) ? 332 mhd_CONN_CLOSE_HTTP_COMPLETED : 333 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY, 334 NULL); 335 return false; 336 } 337 } 338 339 mhd_assert ((! mhd_SCKT_NET_ST_HAS_FLAG (c->sk.ready, 340 mhd_SOCKET_NET_STATE_ERROR_READY)) 341 || (mhd_SOCKET_ERR_NO_ERROR == c->sk.state.discnt_err)); 342 343 if (mhd_SOCKET_ERR_NO_ERROR != c->sk.state.discnt_err) 344 { 345 mhd_assert (mhd_SOCKET_ERR_IS_HARD (c->sk.state.discnt_err)); 346 mhd_conn_start_closing_skt_err (c); 347 return false; 348 } 349 350 daemon_closing = (mhd_DAEMON_STATE_STOPPING == d->state); 351 #ifdef MHD_SUPPORT_THREADS 352 daemon_closing = daemon_closing || d->threading.stop_requested; 353 #endif /* MHD_SUPPORT_THREADS */ 354 if (daemon_closing) 355 { 356 mhd_conn_start_closing_d_shutdown (c); 357 return false; 358 } 359 360 mhd_assert (! c->suspended); 361 362 while (! 0) 363 { 364 #ifdef MHD_SUPPORT_HTTPS 365 mhd_assert (! mhd_C_HAS_TLS (c) || \ 366 (mhd_CONN_STATE_TLS_CONNECTED == c->conn_state)); 367 mhd_assert (mhd_C_HAS_TLS (c) || \ 368 (mhd_CONN_STATE_TCP_CONNECTED == c->conn_state)); 369 #endif /* MHD_SUPPORT_HTTPS */ 370 switch (c->stage) 371 { 372 case mhd_HTTP_STAGE_INIT: 373 case mhd_HTTP_STAGE_REQ_LINE_RECEIVING: 374 if (mhd_stream_get_request_line (c)) 375 { 376 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVING < c->stage); 377 mhd_assert ((MHD_HTTP_VERSION_IS_SUPPORTED (c->rq.http_ver)) \ 378 || (c->discard_request) 379 || (mhd_HTTP_STAGE_PRE_CLOSING <= c->stage)); 380 continue; 381 } 382 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVING >= c->stage); 383 break; 384 case mhd_HTTP_STAGE_REQ_LINE_RECEIVED: 385 mhd_stream_switch_to_rq_headers_proc (c); 386 mhd_assert (mhd_HTTP_STAGE_REQ_LINE_RECEIVED != c->stage); 387 continue; 388 case mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING: 389 if (mhd_stream_get_request_headers (c, false)) 390 { 391 mhd_assert (mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING < c->stage); 392 mhd_assert ((mhd_HTTP_STAGE_HEADERS_RECEIVED == c->stage) || \ 393 (c->discard_request)); 394 continue; 395 } 396 mhd_assert (mhd_HTTP_STAGE_REQ_HEADERS_RECEIVING == c->stage); 397 break; 398 case mhd_HTTP_STAGE_HEADERS_RECEIVED: 399 mhd_stream_parse_request_headers (c); 400 mhd_assert (c->stage != mhd_HTTP_STAGE_HEADERS_RECEIVED); 401 continue; 402 case mhd_HTTP_STAGE_HEADERS_PROCESSED: 403 if (mhd_stream_call_app_request_cb (c)) 404 { 405 mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED < c->stage); 406 continue; 407 } 408 // TODO: add assert 409 break; 410 case mhd_HTTP_STAGE_CONTINUE_SENDING: 411 if (c->continue_message_write_offset == 412 mhd_SSTR_LEN (mdh_HTTP_1_1_100_CONTINUE_REPLY)) 413 { 414 #ifdef MHD_SUPPORT_UPGRADE 415 c->rp.sent_100_cntn = true; 416 #endif /* MHD_SUPPORT_UPGRADE */ 417 c->stage = mhd_HTTP_STAGE_BODY_RECEIVING; 418 continue; 419 } 420 break; 421 case mhd_HTTP_STAGE_BODY_RECEIVING: 422 mhd_assert (c->rq.cntn.recv_size < c->rq.cntn.cntn_size); 423 mhd_assert (! c->discard_request); 424 mhd_assert (NULL == c->rp.response); 425 if (0 == c->read_buffer_offset) 426 break; /* Need more data to process */ 427 428 if (mhd_stream_process_request_body (c)) 429 continue; 430 mhd_assert (! c->discard_request); 431 mhd_assert (NULL == c->rp.response); 432 break; 433 case mhd_HTTP_STAGE_BODY_RECEIVED: 434 mhd_assert (! c->discard_request); 435 mhd_assert (NULL == c->rp.response); 436 mhd_assert (c->rq.have_chunked_upload); 437 /* Reset counter variables reused for footers */ 438 c->rq.num_cr_sp_replaced = 0; 439 c->rq.skipped_broken_lines = 0; 440 mhd_stream_reset_rq_hdr_proc_state (c); 441 c->stage = mhd_HTTP_STAGE_FOOTERS_RECEIVING; 442 continue; 443 case mhd_HTTP_STAGE_FOOTERS_RECEIVING: 444 mhd_assert (c->rq.have_chunked_upload); 445 if (mhd_stream_get_request_headers (c, true)) 446 { 447 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING < c->stage); 448 mhd_assert ((mhd_HTTP_STAGE_FOOTERS_RECEIVED == c->stage) || \ 449 (c->discard_request)); 450 continue; 451 } 452 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING == c->stage); 453 break; 454 case mhd_HTTP_STAGE_FOOTERS_RECEIVED: 455 mhd_assert (c->rq.have_chunked_upload); 456 c->stage = mhd_HTTP_STAGE_FULL_REQ_RECEIVED; 457 continue; 458 case mhd_HTTP_STAGE_FULL_REQ_RECEIVED: 459 if (mhd_stream_call_app_final_upload_cb (c)) 460 { 461 mhd_assert (mhd_HTTP_STAGE_FOOTERS_RECEIVING != c->stage); 462 continue; 463 } 464 break; 465 case mhd_HTTP_STAGE_REQ_RECV_FINISHED: 466 if (mhd_stream_process_req_recv_finished (c)) 467 continue; 468 break; 469 // TODO: add stage for setup and full request buffers cleanup 470 case mhd_HTTP_STAGE_START_REPLY: 471 mhd_assert (NULL != c->rp.response); 472 mhd_stream_switch_from_recv_to_send (c); 473 if (! mhd_stream_build_header_response (c)) 474 continue; 475 mhd_assert (mhd_HTTP_STAGE_START_REPLY != c->stage); 476 break; 477 case mhd_HTTP_STAGE_HEADERS_SENDING: 478 /* no default action, wait for sending all the headers */ 479 break; 480 case mhd_HTTP_STAGE_HEADERS_SENT: 481 if (c->rp.props.send_reply_body) 482 { 483 if (c->rp.props.chunked) 484 c->stage = mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY; 485 else 486 c->stage = mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY; 487 } 488 else 489 c->stage = mhd_HTTP_STAGE_FULL_REPLY_SENT; 490 continue; 491 #ifdef MHD_SUPPORT_UPGRADE 492 case mhd_HTTP_STAGE_UPGRADE_HEADERS_SENDING: 493 if (! mhd_upgrade_try_start_upgrading (c)) 494 break; 495 continue; 496 #endif /* MHD_SUPPORT_UPGRADE */ 497 case mhd_HTTP_STAGE_UNCHUNKED_BODY_READY: 498 mhd_assert (c->rp.props.send_reply_body); 499 mhd_assert (! c->rp.props.chunked); 500 /* nothing to do here, send the data */ 501 break; 502 case mhd_HTTP_STAGE_UNCHUNKED_BODY_UNREADY: 503 mhd_assert (c->rp.props.send_reply_body); 504 mhd_assert (! c->rp.props.chunked); 505 if (0 == c->rp.response->cntn_size) 506 { /* a shortcut */ 507 c->stage = mhd_HTTP_STAGE_FULL_REPLY_SENT; 508 continue; 509 } 510 if (mhd_stream_prep_unchunked_body (c)) 511 continue; 512 break; 513 case mhd_HTTP_STAGE_CHUNKED_BODY_READY: 514 mhd_assert (c->rp.props.send_reply_body); 515 mhd_assert (c->rp.props.chunked); 516 /* nothing to do here */ 517 break; 518 case mhd_HTTP_STAGE_CHUNKED_BODY_UNREADY: 519 mhd_assert (c->rp.props.send_reply_body); 520 mhd_assert (c->rp.props.chunked); 521 if ( (0 == c->rp.response->cntn_size) || 522 (c->rp.rsp_cntn_read_pos == 523 c->rp.response->cntn_size) ) 524 { 525 c->stage = mhd_HTTP_STAGE_CHUNKED_BODY_SENT; 526 continue; 527 } 528 if (mhd_stream_prep_chunked_body (c)) 529 continue; 530 break; 531 case mhd_HTTP_STAGE_CHUNKED_BODY_SENT: 532 mhd_assert (c->rp.props.send_reply_body); 533 mhd_assert (c->rp.props.chunked); 534 mhd_assert (c->write_buffer_send_offset <= \ 535 c->write_buffer_append_offset); 536 mhd_stream_call_dcc_cleanup_if_needed (c); 537 if (mhd_stream_prep_chunked_footer (c)) 538 continue; 539 break; 540 case mhd_HTTP_STAGE_FOOTERS_SENDING: 541 mhd_assert (c->rp.props.send_reply_body); 542 mhd_assert (c->rp.props.chunked); 543 /* no default action */ 544 break; 545 case mhd_HTTP_STAGE_FULL_REPLY_SENT: 546 // FIXME: support MHD_HTTP_STATUS_PROCESSING ? 547 /* Reset connection after complete reply */ 548 mhd_stream_finish_req_serving ( \ 549 c, 550 mhd_CONN_KEEPALIVE_POSSIBLE == c->conn_reuse 551 && ! c->discard_request 552 && ! c->sk.state.rmt_shut_wr); 553 continue; 554 #ifdef MHD_SUPPORT_UPGRADE 555 case mhd_HTTP_STAGE_UPGRADING: 556 if (mhd_upgrade_finish_switch_to_upgraded (c)) 557 return true; /* Do not close connection */ 558 mhd_assert (mhd_HTTP_STAGE_PRE_CLOSING == c->stage); 559 continue; 560 case mhd_HTTP_STAGE_UPGRADED: 561 mhd_assert (0 && "Should be unreachable"); 562 mhd_UNREACHABLE (); 563 break; 564 case mhd_HTTP_STAGE_UPGRADED_CLEANING: 565 mhd_assert (0 && "Should be unreachable"); 566 mhd_UNREACHABLE (); 567 break; 568 #endif /* MHD_SUPPORT_UPGRADE */ 569 case mhd_HTTP_STAGE_PRE_CLOSING: 570 return false; 571 case mhd_HTTP_STAGE_CLOSED: 572 mhd_assert (0 && "Should be unreachable"); 573 mhd_UNREACHABLE (); 574 break; 575 default: 576 mhd_assert (0 && "Impossible value"); 577 mhd_UNREACHABLE (); 578 break; 579 } 580 581 mhd_assert (mhd_HTTP_STAGE_CLOSED != c->stage); 582 583 if (mhd_HTTP_STAGE_PRE_CLOSING == c->stage) 584 { 585 mhd_assert (0 && "Pre-closing should be already caught in the loop"); 586 mhd_UNREACHABLE (); 587 return false; 588 } 589 590 if (c->suspended) 591 { 592 /* Do not perform any network activity while suspended */ 593 c->event_loop_info = MHD_EVENT_LOOP_INFO_PROCESS; 594 595 mhd_conn_mark_unready (c, d); 596 mhd_conn_deinit_activity_timeout (c); 597 #ifdef mhd_DEBUG_SUSPEND_RESUME 598 fprintf (stderr, 599 "%%%%%% Connection suspended, FD: %2llu\n", 600 (unsigned long long) c->sk.fd); 601 #endif /* mhd_DEBUG_SUSPEND_RESUME */ 602 return true; 603 } 604 605 if ((c->sk.state.rmt_shut_wr) && (mhd_HTTP_STAGE_START_REPLY > c->stage)) 606 { 607 mhd_conn_start_closing (c, 608 (mhd_HTTP_STAGE_INIT == c->stage) ? 609 mhd_CONN_CLOSE_HTTP_COMPLETED : 610 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY, 611 NULL); 612 return false; 613 } 614 615 if (0 != (c->sk.ready & mhd_SOCKET_NET_STATE_ERROR_READY)) 616 { 617 mhd_assert (0 && "Should be handled earlier"); 618 mhd_conn_start_closing_skt_err (c); 619 return false; 620 } 621 622 mhd_conn_event_loop_state_update (c); 623 624 if (0 != (MHD_EVENT_LOOP_INFO_RECV & c->event_loop_info)) 625 { 626 /* Check whether the space is available to receive data */ 627 switch (mhd_stream_check_and_grow_read_buffer_space (c)) 628 { 629 case mhd_CONN_BUFF_GROW_ERR_CONN_CLOSE: 630 mhd_assert (c->discard_request); 631 return false; 632 case mhd_CONN_BUFF_GROW_ERR_REPLY: 633 continue; /* Process error reply */ 634 case mhd_CONN_BUFF_GROW_OK: 635 break; 636 default: 637 mhd_UNREACHABLE (); 638 break; 639 } 640 } 641 642 /* Current MHD design assumes that data must be always processes when 643 * available. If it is not possible, connection must be suspended. */ 644 mhd_assert (MHD_EVENT_LOOP_INFO_PROCESS != c->event_loop_info); 645 646 /* Sockets errors must be already handled */ 647 mhd_assert (0 == (c->sk.ready & mhd_SOCKET_NET_STATE_ERROR_READY)); 648 649 mhd_conn_mark_ready_update (c); 650 651 break; 652 } 653 654 return true; 655 }