diff options
-rw-r--r-- | src/include/microhttpd2.h | 156 | ||||
-rw-r--r-- | src/include/microhttpd_tls.h | 4 | ||||
-rw-r--r-- | src/lib/connection_call_handlers.c | 715 |
3 files changed, 630 insertions, 245 deletions
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h index 8d89a807..f54d16b2 100644 --- a/src/include/microhttpd2.h +++ b/src/include/microhttpd2.h | |||
@@ -333,37 +333,51 @@ struct MHD_Connection; | |||
333 | enum MHD_StatusCode | 333 | enum MHD_StatusCode |
334 | { | 334 | { |
335 | 335 | ||
336 | /* 00000-level status codes indicate return values | ||
337 | the application must act on. */ | ||
338 | |||
336 | /** | 339 | /** |
337 | * Successful operation (not used for logging). | 340 | * Successful operation (not used for logging). |
338 | */ | 341 | */ |
339 | MHD_SC_OK = 0, | 342 | MHD_SC_OK = 0, |
340 | 343 | ||
341 | /** | 344 | /** |
342 | * Informational event, MHD started. | 345 | * We were asked to return a timeout, but, there is no timeout. |
343 | */ | 346 | */ |
344 | MHD_SC_DAEMON_STARTED = 10000, | 347 | MHD_SC_NO_TIMEOUT = 1, |
345 | 348 | ||
349 | |||
350 | /* 10000-level status codes indicate intermediate | ||
351 | results of some kind. */ | ||
352 | |||
346 | /** | 353 | /** |
347 | * Informational event, there is no timeout. | 354 | * Informational event, MHD started. |
348 | */ | 355 | */ |
349 | MHD_SC_NO_TIMEOUT = 10001, | 356 | MHD_SC_DAEMON_STARTED = 10000, |
350 | 357 | ||
351 | /** | 358 | /** |
352 | * Informational event, we accepted a connection. | 359 | * Informational event, we accepted a connection. |
353 | */ | 360 | */ |
354 | MHD_SC_CONNECTION_ACCEPTED = 10002, | 361 | MHD_SC_CONNECTION_ACCEPTED = 10001, |
355 | 362 | ||
356 | /** | 363 | /** |
357 | * Informational event, thread processing connection termiantes. | 364 | * Informational event, thread processing connection termiantes. |
358 | */ | 365 | */ |
359 | MHD_SC_THREAD_TERMINATING = 10003, | 366 | MHD_SC_THREAD_TERMINATING = 10002, |
360 | 367 | ||
361 | /** | 368 | /** |
362 | * Informational event, state machine status for a connection. | 369 | * Informational event, state machine status for a connection. |
363 | */ | 370 | */ |
364 | MHD_SC_STATE_MACHINE_STATUS_REPORT = 10004, | 371 | MHD_SC_STATE_MACHINE_STATUS_REPORT = 10003, |
372 | |||
373 | /** | ||
374 | * accept() returned transient error. | ||
375 | */ | ||
376 | MHD_SC_ACCEPT_FAILED_EAGAIN = 10004, | ||
365 | 377 | ||
366 | 378 | ||
379 | /* 20000-level status codes indicate success of some kind. */ | ||
380 | |||
367 | /** | 381 | /** |
368 | * MHD is closing a connection after the client closed it | 382 | * MHD is closing a connection after the client closed it |
369 | * (perfectly normal end). | 383 | * (perfectly normal end). |
@@ -375,6 +389,11 @@ enum MHD_StatusCode | |||
375 | * logic to generate the response data completed. | 389 | * logic to generate the response data completed. |
376 | */ | 390 | */ |
377 | MHD_SC_APPLICATION_DATA_GENERATION_FINISHED = 20001, | 391 | MHD_SC_APPLICATION_DATA_GENERATION_FINISHED = 20001, |
392 | |||
393 | |||
394 | /* 30000-level status codes indicate transient failures | ||
395 | that might go away if the client tries again. */ | ||
396 | |||
378 | 397 | ||
379 | /** | 398 | /** |
380 | * Resource limit in terms of number of parallel connections | 399 | * Resource limit in terms of number of parallel connections |
@@ -383,129 +402,103 @@ enum MHD_StatusCode | |||
383 | MHD_SC_LIMIT_CONNECTIONS_REACHED = 30000, | 402 | MHD_SC_LIMIT_CONNECTIONS_REACHED = 30000, |
384 | 403 | ||
385 | /** | 404 | /** |
386 | * accept() returned transient error. | ||
387 | */ | ||
388 | MHD_SC_ACCEPT_FAILED_EAGAIN = 30001, | ||
389 | |||
390 | /** | ||
391 | * We failed to allocate memory for poll() syscall. | 405 | * We failed to allocate memory for poll() syscall. |
392 | * (May be transient.) | 406 | * (May be transient.) |
393 | */ | 407 | */ |
394 | MHD_SC_POLL_MALLOC_FAILURE = 30002, | 408 | MHD_SC_POLL_MALLOC_FAILURE = 30001, |
395 | 409 | ||
396 | /** | 410 | /** |
397 | * The operation failed because the respective | 411 | * The operation failed because the respective |
398 | * daemon is already too deep inside of the shutdown | 412 | * daemon is already too deep inside of the shutdown |
399 | * activity. | 413 | * activity. |
400 | */ | 414 | */ |
401 | MHD_SC_DAEMON_ALREADY_SHUTDOWN = 30003, | 415 | MHD_SC_DAEMON_ALREADY_SHUTDOWN = 30002, |
402 | 416 | ||
403 | /** | 417 | /** |
404 | * We failed to start a thread. | 418 | * We failed to start a thread. |
405 | */ | 419 | */ |
406 | MHD_SC_THREAD_LAUNCH_FAILURE = 30004, | 420 | MHD_SC_THREAD_LAUNCH_FAILURE = 30003, |
407 | 421 | ||
408 | /** | 422 | /** |
409 | * The operation failed because we either have no | 423 | * The operation failed because we either have no |
410 | * listen socket or were already quiesced. | 424 | * listen socket or were already quiesced. |
411 | */ | 425 | */ |
412 | MHD_SC_DAEMON_ALREADY_QUIESCED = 30005, | 426 | MHD_SC_DAEMON_ALREADY_QUIESCED = 30004, |
413 | 427 | ||
414 | /** | 428 | /** |
415 | * The operation failed because client disconnected | 429 | * The operation failed because client disconnected |
416 | * faster than we could accept(). | 430 | * faster than we could accept(). |
417 | */ | 431 | */ |
418 | MHD_SC_ACCEPT_FAST_DISCONNECT = 30006, | 432 | MHD_SC_ACCEPT_FAST_DISCONNECT = 30005, |
419 | 433 | ||
420 | /** | 434 | /** |
421 | * Operating resource limits hit on accept(). | 435 | * Operating resource limits hit on accept(). |
422 | */ | 436 | */ |
423 | MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED = 30007, | 437 | MHD_SC_ACCEPT_SYSTEM_LIMIT_REACHED = 30006, |
424 | 438 | ||
425 | /** | 439 | /** |
426 | * Connection was refused by accept policy callback. | 440 | * Connection was refused by accept policy callback. |
427 | */ | 441 | */ |
428 | MHD_SC_ACCEPT_POLICY_REJECTED = 30008, | 442 | MHD_SC_ACCEPT_POLICY_REJECTED = 30007, |
429 | 443 | ||
430 | /** | 444 | /** |
431 | * We failed to allocate memory for the connection. | 445 | * We failed to allocate memory for the connection. |
432 | * (May be transient.) | 446 | * (May be transient.) |
433 | */ | 447 | */ |
434 | MHD_SC_CONNECTION_MALLOC_FAILURE = 30009, | 448 | MHD_SC_CONNECTION_MALLOC_FAILURE = 30008, |
435 | 449 | ||
436 | /** | 450 | /** |
437 | * We failed to allocate memory for the connection's memory pool. | 451 | * We failed to allocate memory for the connection's memory pool. |
438 | * (May be transient.) | 452 | * (May be transient.) |
439 | */ | 453 | */ |
440 | MHD_SC_POOL_MALLOC_FAILURE = 30010, | 454 | MHD_SC_POOL_MALLOC_FAILURE = 30009, |
441 | 455 | ||
442 | /** | 456 | /** |
443 | * We failed to forward data from a Web socket to the | 457 | * We failed to forward data from a Web socket to the |
444 | * application to the remote side due to the socket | 458 | * application to the remote side due to the socket |
445 | * being closed prematurely. (May be transient.) | 459 | * being closed prematurely. (May be transient.) |
446 | */ | 460 | */ |
447 | MHD_SC_UPGRADE_FORWARD_INCOMPLETE = 30011, | 461 | MHD_SC_UPGRADE_FORWARD_INCOMPLETE = 30010, |
448 | |||
449 | /** | ||
450 | * MHD is closing a connection because it was reset. | ||
451 | */ | ||
452 | MHD_SC_CONNECTION_RESET_CLOSED = 30012, | ||
453 | |||
454 | /** | ||
455 | * MHD is closing a connection because reading the | ||
456 | * request failed. | ||
457 | */ | ||
458 | MHD_SC_CONNECTION_READ_FAIL_CLOSED = 30013, | ||
459 | |||
460 | /** | ||
461 | * MHD is closing a connection because writing the response failed. | ||
462 | */ | ||
463 | MHD_SC_CONNECTION_WRITE_FAIL_CLOSED = 30014, | ||
464 | |||
465 | /** | ||
466 | * MHD is closing a connection because the application | ||
467 | * logic to generate the response data failed. | ||
468 | */ | ||
469 | MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 30015, | ||
470 | 462 | ||
471 | /** | 463 | /** |
472 | * We failed to allocate memory for generatig the response from our | 464 | * We failed to allocate memory for generatig the response from our |
473 | * memory pool. Likely the request header was too large to leave | 465 | * memory pool. Likely the request header was too large to leave |
474 | * enough room. | 466 | * enough room. |
475 | */ | 467 | */ |
476 | MHD_SC_CONNECTION_POOL_MALLOC_FAILURE = 30016, | 468 | MHD_SC_CONNECTION_POOL_MALLOC_FAILURE = 30011, |
477 | 469 | ||
478 | 470 | ||
471 | /* 40000-level errors are caused by the HTTP client | ||
472 | (or the network) */ | ||
479 | 473 | ||
480 | /** | 474 | /** |
481 | * MHD does not support the requested combination of | 475 | * MHD is closing a connection because parsing the |
482 | * EPOLL with thread-per-connection mode. | 476 | * request failed. |
483 | */ | ||
484 | MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID = 40000, | ||
485 | |||
486 | /** | ||
487 | * MHD does not support quiescing if ITC was disabled | ||
488 | * and threads are used. | ||
489 | */ | 477 | */ |
490 | MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 40001, | 478 | MHD_SC_CONNECTION_PARSE_FAIL_CLOSED = 40000, |
491 | 479 | ||
492 | /** | 480 | /** |
493 | * We failed to bind the listen socket. | 481 | * MHD is closing a connection because it was reset. |
494 | */ | 482 | */ |
495 | MHD_SC_LISTEN_SOCKET_BIND_FAILED = 40002, | 483 | MHD_SC_CONNECTION_RESET_CLOSED = 40001, |
496 | 484 | ||
497 | /** | 485 | /** |
498 | * The application requested an unsupported TLS backend to be used. | 486 | * MHD is closing a connection because reading the |
487 | * request failed. | ||
499 | */ | 488 | */ |
500 | MHD_SC_TLS_BACKEND_UNSUPPORTED = 40003, | 489 | MHD_SC_CONNECTION_READ_FAIL_CLOSED = 40002, |
501 | 490 | ||
502 | /** | 491 | /** |
503 | * The application requested a TLS cipher suite which is not | 492 | * MHD is closing a connection because writing the response failed. |
504 | * supported by the selected backend. | ||
505 | */ | 493 | */ |
506 | MHD_SC_TLS_CIPHERS_INVALID = 40004, | 494 | MHD_SC_CONNECTION_WRITE_FAIL_CLOSED = 40003, |
507 | 495 | ||
508 | 496 | ||
497 | |||
498 | /* 50000-level errors are because of an error internal | ||
499 | to the MHD logic, possibly including our interaction | ||
500 | with the operating system (but not the application) */ | ||
501 | |||
509 | /** | 502 | /** |
510 | * This build of MHD does not support TLS, but the application | 503 | * This build of MHD does not support TLS, but the application |
511 | * requested TLS. | 504 | * requested TLS. |
@@ -788,7 +781,46 @@ enum MHD_StatusCode | |||
788 | * state machine, we closed the connection. | 781 | * state machine, we closed the connection. |
789 | */ | 782 | */ |
790 | MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED = 50054, | 783 | MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED = 50054, |
791 | 784 | ||
785 | |||
786 | /* 60000-level errors are because the application | ||
787 | logic did something wrong or generated an error. */ | ||
788 | |||
789 | /** | ||
790 | * MHD does not support the requested combination of | ||
791 | * EPOLL with thread-per-connection mode. | ||
792 | */ | ||
793 | MHD_SC_SYSCALL_THREAD_COMBINATION_INVALID = 60000, | ||
794 | |||
795 | /** | ||
796 | * MHD does not support quiescing if ITC was disabled | ||
797 | * and threads are used. | ||
798 | */ | ||
799 | MHD_SC_SYSCALL_QUIESCE_REQUIRES_ITC = 60001, | ||
800 | |||
801 | /** | ||
802 | * We failed to bind the listen socket. | ||
803 | */ | ||
804 | MHD_SC_LISTEN_SOCKET_BIND_FAILED = 60002, | ||
805 | |||
806 | /** | ||
807 | * The application requested an unsupported TLS backend to be used. | ||
808 | */ | ||
809 | MHD_SC_TLS_BACKEND_UNSUPPORTED = 60003, | ||
810 | |||
811 | /** | ||
812 | * The application requested a TLS cipher suite which is not | ||
813 | * supported by the selected backend. | ||
814 | */ | ||
815 | MHD_SC_TLS_CIPHERS_INVALID = 60004, | ||
816 | |||
817 | /** | ||
818 | * MHD is closing a connection because the application | ||
819 | * logic to generate the response data failed. | ||
820 | */ | ||
821 | MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED = 60005, | ||
822 | |||
823 | |||
792 | }; | 824 | }; |
793 | 825 | ||
794 | 826 | ||
diff --git a/src/include/microhttpd_tls.h b/src/include/microhttpd_tls.h index c0a5c66b..85862a45 100644 --- a/src/include/microhttpd_tls.h +++ b/src/include/microhttpd_tls.h | |||
@@ -96,6 +96,10 @@ struct MHD_TLS_Plugin | |||
96 | (*handshake)(void *cls, | 96 | (*handshake)(void *cls, |
97 | struct MHD_TLS_ConnectionState *cs); | 97 | struct MHD_TLS_ConnectionState *cs); |
98 | 98 | ||
99 | |||
100 | enum MHD_Bool | ||
101 | (*idle_ready)(void *cls, | ||
102 | struct MHD_TLS_ConnectionState *cs); | ||
99 | 103 | ||
100 | ssize_t | 104 | ssize_t |
101 | (*send)(void *cls, | 105 | (*send)(void *cls, |
diff --git a/src/lib/connection_call_handlers.c b/src/lib/connection_call_handlers.c index 1eac9c10..346089a2 100644 --- a/src/lib/connection_call_handlers.c +++ b/src/lib/connection_call_handlers.c | |||
@@ -935,48 +935,405 @@ MHD_request_handle_write_ (struct MHD_Request *request) | |||
935 | } | 935 | } |
936 | 936 | ||
937 | 937 | ||
938 | #if COMMENTED_OUT_FOR_REWRITE | 938 | /** |
939 | * Convert @a method to the respective enum value. | ||
940 | * | ||
941 | * @param method the method string to look up enum value for | ||
942 | * @return resulting enum, or generic value for "unknown" | ||
943 | */ | ||
944 | static enum MHD_Method | ||
945 | method_string_to_enum (const char *method) | ||
946 | { | ||
947 | static const struct { | ||
948 | const char *key; | ||
949 | enum MHD_Method value; | ||
950 | } methods[] = { | ||
951 | { "OPTIONS", MHD_METHOD_OPTIONS }, | ||
952 | { "GET", MHD_METHOD_GET }, | ||
953 | { "HEAD", MHD_METHOD_HEAD }, | ||
954 | { "POST", MHD_METHOD_POST }, | ||
955 | { "PUT", MHD_METHOD_PUT }, | ||
956 | { "DELETE", MHD_METHOD_DELETE }, | ||
957 | { "TRACE", MHD_METHOD_TRACE }, | ||
958 | { "CONNECT", MHD_METHOD_CONNECT }, | ||
959 | { "ACL", MHD_METHOD_ACL }, | ||
960 | { "BASELINE_CONTROL", MHD_METHOD_BASELINE_CONTROL }, | ||
961 | { "BIND", MHD_METHOD_BIND }, | ||
962 | { "CHECKIN", MHD_METHOD_CHECKIN }, | ||
963 | { "CHECKOUT", MHD_METHOD_CHECKOUT }, | ||
964 | { "COPY", MHD_METHOD_COPY }, | ||
965 | { "LABEL", MHD_METHOD_LABEL }, | ||
966 | { "LINK", MHD_METHOD_LINK }, | ||
967 | { "LOCK", MHD_METHOD_LOCK }, | ||
968 | { "MERGE", MHD_METHOD_MERGE }, | ||
969 | { "MKACTIVITY", MHD_METHOD_MKACTIVITY }, | ||
970 | { "MKCOL", MHD_METHOD_MKCOL }, | ||
971 | { "MKREDIRECTREF", MHD_METHOD_MKREDIRECTREF }, | ||
972 | { "MKWORKSPACE", MHD_METHOD_MKWORKSPACE }, | ||
973 | { "MOVE", MHD_METHOD_MOVE }, | ||
974 | { "ORDERPATCH", MHD_METHOD_ORDERPATCH }, | ||
975 | { "PRI", MHD_METHOD_PRI }, | ||
976 | { "PROPFIND", MHD_METHOD_PROPFIND }, | ||
977 | { "PROPPATCH", MHD_METHOD_PROPPATCH }, | ||
978 | { "REBIND", MHD_METHOD_REBIND }, | ||
979 | { "REPORT", MHD_METHOD_REPORT }, | ||
980 | { "SEARCH", MHD_METHOD_SEARCH }, | ||
981 | { "UNBIND", MHD_METHOD_UNBIND }, | ||
982 | { "UNCHECKOUT", MHD_METHOD_UNCHECKOUT }, | ||
983 | { "UNLINK", MHD_METHOD_UNLINK }, | ||
984 | { "UNLOCK", MHD_METHOD_UNLOCK }, | ||
985 | { "UPDATE", MHD_METHOD_UPDATE }, | ||
986 | { "UPDATEDIRECTREF", MHD_METHOD_UPDATEDIRECTREF }, | ||
987 | { "VERSION-CONTROL", MHD_METHOD_VERSION_CONTROL }, | ||
988 | { NULL, MHD_METHOD_UNKNOWN } /* must be last! */ | ||
989 | }; | ||
990 | unsigned int i; | ||
991 | |||
992 | for (i=0;NULL != methods[i].key;i++) | ||
993 | if (0 == | ||
994 | MHD_str_equal_caseless_ (method, | ||
995 | methods[i].key)) | ||
996 | return methods[i].value; | ||
997 | return MHD_METHOD_UNKNOWN; | ||
998 | } | ||
999 | |||
1000 | |||
1001 | /** | ||
1002 | * Parse the first line of the HTTP HEADER. | ||
1003 | * | ||
1004 | * @param connection the connection (updated) | ||
1005 | * @param line the first line, not 0-terminated | ||
1006 | * @param line_len length of the first @a line | ||
1007 | * @return true if the line is ok, false if it is malformed | ||
1008 | */ | ||
1009 | static bool | ||
1010 | parse_initial_message_line (struct MHD_Request *request, | ||
1011 | char *line, | ||
1012 | size_t line_len) | ||
1013 | { | ||
1014 | struct MHD_Connection *connection = request->connection; | ||
1015 | struct MHD_Daemon *daemon = request->daemon; | ||
1016 | const char *curi; | ||
1017 | char *uri; | ||
1018 | char *http_version; | ||
1019 | char *args; | ||
1020 | unsigned int unused_num_headers; | ||
1021 | |||
1022 | if (NULL == (uri = memchr (line, | ||
1023 | ' ', | ||
1024 | line_len))) | ||
1025 | return false; /* serious error */ | ||
1026 | uri[0] = '\0'; | ||
1027 | request->method_s = line; | ||
1028 | request->method = method_string_to_enum (line); | ||
1029 | uri++; | ||
1030 | /* Skip any spaces. Not required by standard but allow | ||
1031 | to be more tolerant. */ | ||
1032 | while ( (' ' == uri[0]) && | ||
1033 | ( (size_t)(uri - line) < line_len) ) | ||
1034 | uri++; | ||
1035 | if ((size_t)(uri - line) == line_len) | ||
1036 | { | ||
1037 | curi = ""; | ||
1038 | uri = NULL; | ||
1039 | request->version = ""; | ||
1040 | args = NULL; | ||
1041 | } | ||
1042 | else | ||
1043 | { | ||
1044 | curi = uri; | ||
1045 | /* Search from back to accept misformed URI with space */ | ||
1046 | http_version = line + line_len - 1; | ||
1047 | /* Skip any trailing spaces */ | ||
1048 | while ( (' ' == http_version[0]) && | ||
1049 | (http_version > uri) ) | ||
1050 | http_version--; | ||
1051 | /* Find first space in reverse direction */ | ||
1052 | while ( (' ' != http_version[0]) && | ||
1053 | (http_version > uri) ) | ||
1054 | http_version--; | ||
1055 | if (http_version > uri) | ||
1056 | { | ||
1057 | http_version[0] = '\0'; | ||
1058 | request->version = http_version + 1; | ||
1059 | args = memchr (uri, | ||
1060 | '?', | ||
1061 | http_version - uri); | ||
1062 | } | ||
1063 | else | ||
1064 | { | ||
1065 | request->version = ""; | ||
1066 | args = memchr (uri, | ||
1067 | '?', | ||
1068 | line_len - (uri - line)); | ||
1069 | } | ||
1070 | } | ||
1071 | if (NULL != daemon->uri_log_callback) | ||
1072 | { | ||
1073 | request->client_aware = true; | ||
1074 | request->client_context | ||
1075 | = daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls, | ||
1076 | curi, | ||
1077 | request); | ||
1078 | } | ||
1079 | if (NULL != args) | ||
1080 | { | ||
1081 | args[0] = '\0'; | ||
1082 | args++; | ||
1083 | /* note that this call clobbers 'args' */ | ||
1084 | MHD_parse_arguments_ (connection, | ||
1085 | MHD_GET_ARGUMENT_KIND, | ||
1086 | args, | ||
1087 | &connection_add_header, | ||
1088 | &unused_num_headers); | ||
1089 | } | ||
1090 | if (NULL != uri) | ||
1091 | daemon->unescape_cb (daemon->unescape_cb_cls, | ||
1092 | request, | ||
1093 | uri); | ||
1094 | request->url = curi; | ||
1095 | return MHD_YES; | ||
1096 | } | ||
1097 | |||
1098 | |||
1099 | /** | ||
1100 | * Add an entry to the HTTP headers of a request. If this fails, | ||
1101 | * transmit an error response (request too big). | ||
1102 | * | ||
1103 | * @param request the request for which a value should be set | ||
1104 | * @param kind kind of the value | ||
1105 | * @param key key for the value | ||
1106 | * @param value the value itself | ||
1107 | * @return false on failure (out of memory), true for success | ||
1108 | */ | ||
1109 | static bool | ||
1110 | connection_add_header (struct MHD_Request *request, | ||
1111 | const char *key, | ||
1112 | const char *value, | ||
1113 | enum MHD_ValueKind kind) | ||
1114 | { | ||
1115 | if (MHD_NO == | ||
1116 | MHD_request_set_value (request, | ||
1117 | kind, | ||
1118 | key, | ||
1119 | value)) | ||
1120 | { | ||
1121 | #ifdef HAVE_MESSAGES | ||
1122 | MHD_DLOG (request->daemon, | ||
1123 | _("Not enough memory in pool to allocate header record!\n")); | ||
1124 | #endif | ||
1125 | transmit_error_response (request->connection, | ||
1126 | MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, | ||
1127 | REQUEST_TOO_BIG); | ||
1128 | return false; | ||
1129 | } | ||
1130 | return true; | ||
1131 | } | ||
1132 | |||
1133 | |||
1134 | /** | ||
1135 | * We have received (possibly the beginning of) a line in the | ||
1136 | * header (or footer). Validate (check for ":") and prepare | ||
1137 | * to process. | ||
1138 | * | ||
1139 | * @param request the request we're processing | ||
1140 | * @param line line from the header to process | ||
1141 | * @return true on success, false on error (malformed @a line) | ||
1142 | */ | ||
1143 | static bool | ||
1144 | process_header_line (struct MHD_Request *request, | ||
1145 | char *line) | ||
1146 | { | ||
1147 | struct MHD_Connection *connection = request->connection; | ||
1148 | char *colon; | ||
1149 | |||
1150 | /* line should be normal header line, find colon */ | ||
1151 | colon = strchr (line, ':'); | ||
1152 | if (NULL == colon) | ||
1153 | { | ||
1154 | /* error in header line, die hard */ | ||
1155 | CONNECTION_CLOSE_ERROR (connection, | ||
1156 | MHD_SC_CONNECTION_PARSE_FAIL_CLOSED, | ||
1157 | _("Received malformed line (no colon). Closing connection.\n")); | ||
1158 | return false; | ||
1159 | } | ||
1160 | if (-1 >= request->daemon->strict_for_client) | ||
1161 | { | ||
1162 | /* check for whitespace before colon, which is not allowed | ||
1163 | by RFC 7230 section 3.2.4; we count space ' ' and | ||
1164 | tab '\t', but not '\r\n' as those would have ended the line. */ | ||
1165 | const char *white; | ||
1166 | |||
1167 | white = strchr (line, | ||
1168 | (unsigned char) ' '); | ||
1169 | if ( (NULL != white) && | ||
1170 | (white < colon) ) | ||
1171 | { | ||
1172 | CONNECTION_CLOSE_ERROR (connection, | ||
1173 | MHD_SC_CONNECTION_PARSE_FAIL_CLOSED, | ||
1174 | _("Whitespace before colon forbidden by RFC 7230. Closing connection.\n")); | ||
1175 | return false; | ||
1176 | } | ||
1177 | white = strchr (line, | ||
1178 | (unsigned char) '\t'); | ||
1179 | if ( (NULL != white) && | ||
1180 | (white < colon) ) | ||
1181 | { | ||
1182 | CONNECTION_CLOSE_ERROR (connection, | ||
1183 | MHD_SC_CONNECTION_PARSE_FAIL_CLOSED, | ||
1184 | _("Tab before colon forbidden by RFC 7230. Closing connection.\n")); | ||
1185 | return false; | ||
1186 | } | ||
1187 | } | ||
1188 | /* zero-terminate header */ | ||
1189 | colon[0] = '\0'; | ||
1190 | colon++; /* advance to value */ | ||
1191 | while ( ('\0' != colon[0]) && | ||
1192 | ( (' ' == colon[0]) || | ||
1193 | ('\t' == colon[0]) ) ) | ||
1194 | colon++; | ||
1195 | /* we do the actual adding of the connection | ||
1196 | header at the beginning of the while | ||
1197 | loop since we need to be able to inspect | ||
1198 | the *next* header line (in case it starts | ||
1199 | with a space...) */ | ||
1200 | request->last = line; | ||
1201 | request->colon = colon; | ||
1202 | return true; | ||
1203 | } | ||
939 | 1204 | ||
940 | 1205 | ||
941 | /** | 1206 | /** |
942 | * This function was created to handle per-connection processing that | 1207 | * Process a header value that spans multiple lines. |
1208 | * The previous line(s) are in connection->last. | ||
1209 | * | ||
1210 | * @param request the request we're processing | ||
1211 | * @param line the current input line | ||
1212 | * @param kind if the line is complete, add a header | ||
1213 | * of the given kind | ||
1214 | * @return true if the line was processed successfully | ||
1215 | */ | ||
1216 | static bool | ||
1217 | process_broken_line (struct MHD_Request *request, | ||
1218 | char *line, | ||
1219 | enum MHD_ValueKind kind) | ||
1220 | { | ||
1221 | struct MHD_Connection *connection = request->connection; | ||
1222 | char *last; | ||
1223 | char *tmp; | ||
1224 | size_t last_len; | ||
1225 | size_t tmp_len; | ||
1226 | |||
1227 | last = request->last; | ||
1228 | if ( (' ' == line[0]) || | ||
1229 | ('\t' == line[0]) ) | ||
1230 | { | ||
1231 | /* value was continued on the next line, see | ||
1232 | http://www.jmarshall.com/easy/http/ */ | ||
1233 | last_len = strlen (last); | ||
1234 | /* skip whitespace at start of 2nd line */ | ||
1235 | tmp = line; | ||
1236 | while ( (' ' == tmp[0]) || | ||
1237 | ('\t' == tmp[0]) ) | ||
1238 | tmp++; | ||
1239 | tmp_len = strlen (tmp); | ||
1240 | /* FIXME: we might be able to do this better (faster!), as most | ||
1241 | likely 'last' and 'line' should already be adjacent in | ||
1242 | memory; however, doing this right gets tricky if we have a | ||
1243 | value continued over multiple lines (in which case we need to | ||
1244 | record how often we have done this so we can check for | ||
1245 | adjacency); also, in the case where these are not adjacent | ||
1246 | (not sure how it can happen!), we would want to allocate from | ||
1247 | the end of the pool, so as to not destroy the read-buffer's | ||
1248 | ability to grow nicely. */ | ||
1249 | last = MHD_pool_reallocate (connection->pool, | ||
1250 | last, | ||
1251 | last_len + 1, | ||
1252 | last_len + tmp_len + 1); | ||
1253 | if (NULL == last) | ||
1254 | { | ||
1255 | transmit_error_response (connection, | ||
1256 | MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, | ||
1257 | REQUEST_TOO_BIG); | ||
1258 | return MHD_NO; | ||
1259 | } | ||
1260 | memcpy (&last[last_len], | ||
1261 | tmp, | ||
1262 | tmp_len + 1); | ||
1263 | request->last = last; | ||
1264 | return MHD_YES; /* possibly more than 2 lines... */ | ||
1265 | } | ||
1266 | mhd_assert ( (NULL != last) && | ||
1267 | (NULL != request->colon) ); | ||
1268 | if (! request_add_header (request, | ||
1269 | last, | ||
1270 | request->colon, | ||
1271 | kind)) | ||
1272 | { | ||
1273 | transmit_error_response (connection, | ||
1274 | MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, | ||
1275 | REQUEST_TOO_BIG); | ||
1276 | return false; | ||
1277 | } | ||
1278 | /* we still have the current line to deal with... */ | ||
1279 | if ('\0' != line[0]) | ||
1280 | { | ||
1281 | if (! process_header_line (request, | ||
1282 | line)) | ||
1283 | { | ||
1284 | transmit_error_response (connection, | ||
1285 | MHD_HTTP_BAD_REQUEST, | ||
1286 | REQUEST_MALFORMED); | ||
1287 | return false; | ||
1288 | } | ||
1289 | } | ||
1290 | return true; | ||
1291 | } | ||
1292 | |||
1293 | |||
1294 | #ifdef REWRITE_IN_PROGRESS | ||
1295 | |||
1296 | /** | ||
1297 | * This function was created to handle per-request processing that | ||
943 | * has to happen even if the socket cannot be read or written to. | 1298 | * has to happen even if the socket cannot be read or written to. |
944 | * @remark To be called only from thread that process connection's | 1299 | * @remark To be called only from thread that process request's |
945 | * recv(), send() and response. | 1300 | * recv(), send() and response. |
946 | * | 1301 | * |
947 | * @param connection connection to handle | 1302 | * @param request the request to handle |
948 | * @return #MHD_YES if we should continue to process the | 1303 | * @return true if we should continue to process the |
949 | * connection (not dead yet), #MHD_NO if it died | 1304 | * request (not dead yet), false if it died |
950 | */ | 1305 | */ |
951 | int | 1306 | bool |
952 | MHD_connection_handle_idle (struct MHD_Connection *connection) | 1307 | MHD_request_handle_idle (struct MHD_Request *request) |
953 | { | 1308 | { |
954 | struct MHD_Daemon *daemon = connection->daemon; | 1309 | struct MHD_Daemon *daemon = request->daemon; |
1310 | struct MHD_Connection *connection = request->connection; | ||
955 | char *line; | 1311 | char *line; |
956 | size_t line_len; | 1312 | size_t line_len; |
957 | int ret; | 1313 | int ret; |
958 | 1314 | ||
959 | connection->in_idle = true; | 1315 | request->in_idle = true; |
960 | while (! connection->suspended) | 1316 | while (! connection->suspended) |
961 | { | 1317 | { |
962 | #ifdef HTTPS_SUPPORT | 1318 | #ifdef HTTPS_SUPPORT |
963 | if (MHD_TLS_CONN_NO_TLS != connection->tls_state) | 1319 | struct MHD_TLS_Plugin *tls; |
964 | { /* HTTPS connection. */ | 1320 | |
965 | if ((MHD_TLS_CONN_INIT <= connection->tls_state) && | 1321 | if ( (NULL != (tls = daemon->tls_api)) && |
966 | (MHD_TLS_CONN_CONNECTED > connection->tls_state)) | 1322 | (! tls->idle_ready (tls->cls, |
967 | break; | 1323 | connection->tls_cs)) ) |
968 | } | 1324 | break; |
969 | #endif /* HTTPS_SUPPORT */ | 1325 | #endif /* HTTPS_SUPPORT */ |
970 | #if DEBUG_STATES | 1326 | #if DEBUG_STATES |
971 | MHD_DLOG (daemon, | 1327 | MHD_DLOG (daemon, |
1328 | MHD_SC_STATE_MACHINE_STATUS_REPORT, | ||
972 | _("In function %s handling connection at state: %s\n"), | 1329 | _("In function %s handling connection at state: %s\n"), |
973 | __FUNCTION__, | 1330 | __FUNCTION__, |
974 | MHD_state_to_string (connection->state)); | 1331 | MHD_state_to_string (request->state)); |
975 | #endif | 1332 | #endif |
976 | switch (connection->state) | 1333 | switch (request->state) |
977 | { | 1334 | { |
978 | case MHD_CONNECTION_INIT: | 1335 | case MHD_REQUEST_INIT: |
979 | line = get_next_header_line (connection, | 1336 | line = get_next_header_line (request, |
980 | &line_len); | 1337 | &line_len); |
981 | /* Check for empty string, as we might want | 1338 | /* Check for empty string, as we might want |
982 | to tolerate 'spurious' empty lines; also | 1339 | to tolerate 'spurious' empty lines; also |
@@ -985,34 +1342,37 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
985 | if ( (NULL == line) || | 1342 | if ( (NULL == line) || |
986 | (0 == line[0]) ) | 1343 | (0 == line[0]) ) |
987 | { | 1344 | { |
988 | if (MHD_CONNECTION_INIT != connection->state) | 1345 | if (MHD_REQUEST_INIT != request->state) |
989 | continue; | 1346 | continue; |
990 | if (connection->read_closed) | 1347 | if (connection->read_closed) |
991 | { | 1348 | { |
992 | CONNECTION_CLOSE_ERROR (connection, | 1349 | CONNECTION_CLOSE_ERROR (connection, |
1350 | MHD_SC_CONNECTION_READ_FAIL_CLOSED, | ||
993 | NULL); | 1351 | NULL); |
994 | continue; | 1352 | continue; |
995 | } | 1353 | } |
996 | break; | 1354 | break; |
997 | } | 1355 | } |
998 | if (MHD_NO == parse_initial_message_line (connection, | 1356 | if (MHD_NO == |
999 | line, | 1357 | parse_initial_message_line (request, |
1000 | line_len)) | 1358 | line, |
1359 | line_len)) | ||
1001 | CONNECTION_CLOSE_ERROR (connection, | 1360 | CONNECTION_CLOSE_ERROR (connection, |
1002 | NULL); | 1361 | NULL); |
1003 | else | 1362 | else |
1004 | connection->state = MHD_CONNECTION_URL_RECEIVED; | 1363 | request->state = MHD_REQUEST_URL_RECEIVED; |
1005 | continue; | 1364 | continue; |
1006 | case MHD_CONNECTION_URL_RECEIVED: | 1365 | case MHD_REQUEST_URL_RECEIVED: |
1007 | line = get_next_header_line (connection, | 1366 | line = get_next_header_line (request, |
1008 | NULL); | 1367 | NULL); |
1009 | if (NULL == line) | 1368 | if (NULL == line) |
1010 | { | 1369 | { |
1011 | if (MHD_CONNECTION_URL_RECEIVED != connection->state) | 1370 | if (MHD_REQUEST_URL_RECEIVED != request->state) |
1012 | continue; | 1371 | continue; |
1013 | if (connection->read_closed) | 1372 | if (connection->read_closed) |
1014 | { | 1373 | { |
1015 | CONNECTION_CLOSE_ERROR (connection, | 1374 | CONNECTION_CLOSE_ERROR (connection, |
1375 | MHD_SC_CONNECTION_READ_FAIL_CLOSED, | ||
1016 | NULL); | 1376 | NULL); |
1017 | continue; | 1377 | continue; |
1018 | } | 1378 | } |
@@ -1020,126 +1380,126 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1020 | } | 1380 | } |
1021 | if (0 == line[0]) | 1381 | if (0 == line[0]) |
1022 | { | 1382 | { |
1023 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; | 1383 | request->state = MHD_REQUEST_HEADERS_RECEIVED; |
1024 | connection->header_size = (size_t) (line - connection->read_buffer); | 1384 | request->header_size = (size_t) (line - request->read_buffer); |
1025 | continue; | 1385 | continue; |
1026 | } | 1386 | } |
1027 | if (MHD_NO == process_header_line (connection, | 1387 | if (! process_header_line (request, |
1028 | line)) | 1388 | line)) |
1029 | { | 1389 | { |
1030 | transmit_error_response (connection, | 1390 | transmit_error_response (connection, |
1031 | MHD_HTTP_BAD_REQUEST, | 1391 | MHD_HTTP_BAD_REQUEST, |
1032 | REQUEST_MALFORMED); | 1392 | REQUEST_MALFORMED); |
1033 | break; | 1393 | break; |
1034 | } | 1394 | } |
1035 | connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED; | 1395 | request->state = MHD_REQUEST_HEADER_PART_RECEIVED; |
1036 | continue; | 1396 | continue; |
1037 | case MHD_CONNECTION_HEADER_PART_RECEIVED: | 1397 | case MHD_REQUEST_HEADER_PART_RECEIVED: |
1038 | line = get_next_header_line (connection, | 1398 | line = get_next_header_line (request, |
1039 | NULL); | 1399 | NULL); |
1040 | if (NULL == line) | 1400 | if (NULL == line) |
1041 | { | 1401 | { |
1042 | if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED) | 1402 | if (request->state != MHD_REQUEST_HEADER_PART_RECEIVED) |
1043 | continue; | 1403 | continue; |
1044 | if (connection->read_closed) | 1404 | if (connection->read_closed) |
1045 | { | 1405 | { |
1046 | CONNECTION_CLOSE_ERROR (connection, | 1406 | CONNECTION_CLOSE_ERROR (connection, |
1407 | MHD_SC_CONNECTION_READ_FAIL_CLOSED, | ||
1047 | NULL); | 1408 | NULL); |
1048 | continue; | 1409 | continue; |
1049 | } | 1410 | } |
1050 | break; | 1411 | break; |
1051 | } | 1412 | } |
1052 | if (MHD_NO == | 1413 | if (MHD_NO == |
1053 | process_broken_line (connection, | 1414 | process_broken_line (request, |
1054 | line, | 1415 | line, |
1055 | MHD_HEADER_KIND)) | 1416 | MHD_HEADER_KIND)) |
1056 | continue; | 1417 | continue; |
1057 | if (0 == line[0]) | 1418 | if (0 == line[0]) |
1058 | { | 1419 | { |
1059 | connection->state = MHD_CONNECTION_HEADERS_RECEIVED; | 1420 | request->state = MHD_REQUEST_HEADERS_RECEIVED; |
1060 | connection->header_size = (size_t) (line - connection->read_buffer); | 1421 | request->header_size = (size_t) (line - request->read_buffer); |
1061 | continue; | 1422 | continue; |
1062 | } | 1423 | } |
1063 | continue; | 1424 | continue; |
1064 | case MHD_CONNECTION_HEADERS_RECEIVED: | 1425 | case MHD_REQUEST_HEADERS_RECEIVED: |
1065 | parse_connection_headers (connection); | 1426 | parse_request_headers (request); |
1066 | if (MHD_CONNECTION_CLOSED == connection->state) | 1427 | if (MHD_REQUEST_CLOSED == request->state) |
1067 | continue; | 1428 | continue; |
1068 | connection->state = MHD_CONNECTION_HEADERS_PROCESSED; | 1429 | request->state = MHD_REQUEST_HEADERS_PROCESSED; |
1069 | if (connection->suspended) | 1430 | if (connection->suspended) |
1070 | break; | 1431 | break; |
1071 | continue; | 1432 | continue; |
1072 | case MHD_CONNECTION_HEADERS_PROCESSED: | 1433 | case MHD_REQUEST_HEADERS_PROCESSED: |
1073 | call_connection_handler (connection); /* first call */ | 1434 | call_request_handler (request); /* first call */ |
1074 | if (MHD_CONNECTION_CLOSED == connection->state) | 1435 | if (MHD_REQUEST_CLOSED == request->state) |
1075 | continue; | 1436 | continue; |
1076 | if (need_100_continue (connection)) | 1437 | if (need_100_continue (request)) |
1077 | { | 1438 | { |
1078 | connection->state = MHD_CONNECTION_CONTINUE_SENDING; | 1439 | request->state = MHD_REQUEST_CONTINUE_SENDING; |
1079 | if (MHD_NO != socket_flush_possible (connection)) | 1440 | if (socket_flush_possible (connection)) |
1080 | socket_start_extra_buffering (connection); | 1441 | socket_start_extra_buffering (connection); |
1081 | else | 1442 | else |
1082 | socket_start_no_buffering (connection); | 1443 | socket_start_no_buffering (connection); |
1083 | |||
1084 | break; | 1444 | break; |
1085 | } | 1445 | } |
1086 | if ( (NULL != connection->response) && | 1446 | if ( (NULL != request->response) && |
1087 | ( (MHD_str_equal_caseless_ (connection->method, | 1447 | ( (MHD_str_equal_caseless_ (request->method, |
1088 | MHD_HTTP_METHOD_POST)) || | 1448 | MHD_HTTP_METHOD_POST)) || |
1089 | (MHD_str_equal_caseless_ (connection->method, | 1449 | (MHD_str_equal_caseless_ (request->method, |
1090 | MHD_HTTP_METHOD_PUT))) ) | 1450 | MHD_HTTP_METHOD_PUT))) ) |
1091 | { | 1451 | { |
1092 | /* we refused (no upload allowed!) */ | 1452 | /* we refused (no upload allowed!) */ |
1093 | connection->remaining_upload_size = 0; | 1453 | request->remaining_upload_size = 0; |
1094 | /* force close, in case client still tries to upload... */ | 1454 | /* force close, in case client still tries to upload... */ |
1095 | connection->read_closed = true; | 1455 | connection->read_closed = true; |
1096 | } | 1456 | } |
1097 | connection->state = (0 == connection->remaining_upload_size) | 1457 | request->state = (0 == request->remaining_upload_size) |
1098 | ? MHD_CONNECTION_FOOTERS_RECEIVED : MHD_CONNECTION_CONTINUE_SENT; | 1458 | ? MHD_REQUEST_FOOTERS_RECEIVED : MHD_REQUEST_CONTINUE_SENT; |
1099 | if (connection->suspended) | 1459 | if (connection->suspended) |
1100 | break; | 1460 | break; |
1101 | continue; | 1461 | continue; |
1102 | case MHD_CONNECTION_CONTINUE_SENDING: | 1462 | case MHD_REQUEST_CONTINUE_SENDING: |
1103 | if (connection->continue_message_write_offset == | 1463 | if (request->continue_message_write_offset == |
1104 | MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) | 1464 | MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) |
1105 | { | 1465 | { |
1106 | connection->state = MHD_CONNECTION_CONTINUE_SENT; | 1466 | request->state = MHD_REQUEST_CONTINUE_SENT; |
1107 | if (MHD_NO != socket_flush_possible (connection)) | 1467 | if (MHD_NO != socket_flush_possible (request)) |
1108 | socket_start_no_buffering_flush (connection); | 1468 | socket_start_no_buffering_flush (request); |
1109 | else | 1469 | else |
1110 | socket_start_normal_buffering (connection); | 1470 | socket_start_normal_buffering (request); |
1111 | 1471 | ||
1112 | continue; | 1472 | continue; |
1113 | } | 1473 | } |
1114 | break; | 1474 | break; |
1115 | case MHD_CONNECTION_CONTINUE_SENT: | 1475 | case MHD_REQUEST_CONTINUE_SENT: |
1116 | if (0 != connection->read_buffer_offset) | 1476 | if (0 != request->read_buffer_offset) |
1117 | { | 1477 | { |
1118 | process_request_body (connection); /* loop call */ | 1478 | process_request_body (request); /* loop call */ |
1119 | if (MHD_CONNECTION_CLOSED == connection->state) | 1479 | if (MHD_REQUEST_CLOSED == request->state) |
1120 | continue; | 1480 | continue; |
1121 | } | 1481 | } |
1122 | if ( (0 == connection->remaining_upload_size) || | 1482 | if ( (0 == request->remaining_upload_size) || |
1123 | ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) && | 1483 | ( (MHD_SIZE_UNKNOWN == request->remaining_upload_size) && |
1124 | (0 == connection->read_buffer_offset) && | 1484 | (0 == request->read_buffer_offset) && |
1125 | (connection->read_closed) ) ) | 1485 | (request->read_closed) ) ) |
1126 | { | 1486 | { |
1127 | if ( (connection->have_chunked_upload) && | 1487 | if ( (request->have_chunked_upload) && |
1128 | (! connection->read_closed) ) | 1488 | (! request->read_closed) ) |
1129 | connection->state = MHD_CONNECTION_BODY_RECEIVED; | 1489 | request->state = MHD_REQUEST_BODY_RECEIVED; |
1130 | else | 1490 | else |
1131 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 1491 | request->state = MHD_REQUEST_FOOTERS_RECEIVED; |
1132 | if (connection->suspended) | 1492 | if (connection->suspended) |
1133 | break; | 1493 | break; |
1134 | continue; | 1494 | continue; |
1135 | } | 1495 | } |
1136 | break; | 1496 | break; |
1137 | case MHD_CONNECTION_BODY_RECEIVED: | 1497 | case MHD_REQUEST_BODY_RECEIVED: |
1138 | line = get_next_header_line (connection, | 1498 | line = get_next_header_line (request, |
1139 | NULL); | 1499 | NULL); |
1140 | if (NULL == line) | 1500 | if (NULL == line) |
1141 | { | 1501 | { |
1142 | if (connection->state != MHD_CONNECTION_BODY_RECEIVED) | 1502 | if (request->state != MHD_REQUEST_BODY_RECEIVED) |
1143 | continue; | 1503 | continue; |
1144 | if (connection->read_closed) | 1504 | if (connection->read_closed) |
1145 | { | 1505 | { |
@@ -1151,12 +1511,12 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1151 | } | 1511 | } |
1152 | if (0 == line[0]) | 1512 | if (0 == line[0]) |
1153 | { | 1513 | { |
1154 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 1514 | request->state = MHD_REQUEST_FOOTERS_RECEIVED; |
1155 | if (connection->suspended) | 1515 | if (connection->suspended) |
1156 | break; | 1516 | break; |
1157 | continue; | 1517 | continue; |
1158 | } | 1518 | } |
1159 | if (MHD_NO == process_header_line (connection, | 1519 | if (MHD_NO == process_header_line (request, |
1160 | line)) | 1520 | line)) |
1161 | { | 1521 | { |
1162 | transmit_error_response (connection, | 1522 | transmit_error_response (connection, |
@@ -1164,14 +1524,14 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1164 | REQUEST_MALFORMED); | 1524 | REQUEST_MALFORMED); |
1165 | break; | 1525 | break; |
1166 | } | 1526 | } |
1167 | connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED; | 1527 | request->state = MHD_REQUEST_FOOTER_PART_RECEIVED; |
1168 | continue; | 1528 | continue; |
1169 | case MHD_CONNECTION_FOOTER_PART_RECEIVED: | 1529 | case MHD_REQUEST_FOOTER_PART_RECEIVED: |
1170 | line = get_next_header_line (connection, | 1530 | line = get_next_header_line (request, |
1171 | NULL); | 1531 | NULL); |
1172 | if (NULL == line) | 1532 | if (NULL == line) |
1173 | { | 1533 | { |
1174 | if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED) | 1534 | if (request->state != MHD_REQUEST_FOOTER_PART_RECEIVED) |
1175 | continue; | 1535 | continue; |
1176 | if (connection->read_closed) | 1536 | if (connection->read_closed) |
1177 | { | 1537 | { |
@@ -1182,66 +1542,66 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1182 | break; | 1542 | break; |
1183 | } | 1543 | } |
1184 | if (MHD_NO == | 1544 | if (MHD_NO == |
1185 | process_broken_line (connection, | 1545 | process_broken_line (request, |
1186 | line, | 1546 | line, |
1187 | MHD_FOOTER_KIND)) | 1547 | MHD_FOOTER_KIND)) |
1188 | continue; | 1548 | continue; |
1189 | if (0 == line[0]) | 1549 | if (0 == line[0]) |
1190 | { | 1550 | { |
1191 | connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; | 1551 | request->state = MHD_REQUEST_FOOTERS_RECEIVED; |
1192 | if (connection->suspended) | 1552 | if (connection->suspended) |
1193 | break; | 1553 | break; |
1194 | continue; | 1554 | continue; |
1195 | } | 1555 | } |
1196 | continue; | 1556 | continue; |
1197 | case MHD_CONNECTION_FOOTERS_RECEIVED: | 1557 | case MHD_REQUEST_FOOTERS_RECEIVED: |
1198 | call_connection_handler (connection); /* "final" call */ | 1558 | call_request_handler (request); /* "final" call */ |
1199 | if (connection->state == MHD_CONNECTION_CLOSED) | 1559 | if (request->state == MHD_REQUEST_CLOSED) |
1200 | continue; | 1560 | continue; |
1201 | if (NULL == connection->response) | 1561 | if (NULL == request->response) |
1202 | break; /* try again next time */ | 1562 | break; /* try again next time */ |
1203 | if (MHD_NO == build_header_response (connection)) | 1563 | if (MHD_NO == build_header_response (request)) |
1204 | { | 1564 | { |
1205 | /* oops - close! */ | 1565 | /* oops - close! */ |
1206 | CONNECTION_CLOSE_ERROR (connection, | 1566 | CONNECTION_CLOSE_ERROR (connection, |
1207 | _("Closing connection (failed to create response header)\n")); | 1567 | _("Closing connection (failed to create response header)\n")); |
1208 | continue; | 1568 | continue; |
1209 | } | 1569 | } |
1210 | connection->state = MHD_CONNECTION_HEADERS_SENDING; | 1570 | request->state = MHD_REQUEST_HEADERS_SENDING; |
1211 | if (MHD_NO != socket_flush_possible (connection)) | 1571 | if (MHD_NO != socket_flush_possible (connection)) |
1212 | socket_start_extra_buffering (connection); | 1572 | socket_start_extra_buffering (connection); |
1213 | else | 1573 | else |
1214 | socket_start_no_buffering (connection); | 1574 | socket_start_no_buffering (connection); |
1215 | 1575 | ||
1216 | break; | 1576 | break; |
1217 | case MHD_CONNECTION_HEADERS_SENDING: | 1577 | case MHD_REQUEST_HEADERS_SENDING: |
1218 | /* no default action */ | 1578 | /* no default action */ |
1219 | break; | 1579 | break; |
1220 | case MHD_CONNECTION_HEADERS_SENT: | 1580 | case MHD_REQUEST_HEADERS_SENT: |
1221 | /* Some clients may take some actions right after header receive */ | 1581 | /* Some clients may take some actions right after header receive */ |
1222 | if (MHD_NO != socket_flush_possible (connection)) | 1582 | if (MHD_NO != socket_flush_possible (connection)) |
1223 | socket_start_no_buffering_flush (connection); | 1583 | socket_start_no_buffering_flush (connection); |
1224 | 1584 | ||
1225 | #ifdef UPGRADE_SUPPORT | 1585 | #ifdef UPGRADE_SUPPORT |
1226 | if (NULL != connection->response->upgrade_handler) | 1586 | if (NULL != request->response->upgrade_handler) |
1227 | { | 1587 | { |
1228 | socket_start_normal_buffering (connection); | 1588 | socket_start_normal_buffering (connection); |
1229 | connection->state = MHD_CONNECTION_UPGRADE; | 1589 | request->state = MHD_REQUEST_UPGRADE; |
1230 | /* This connection is "upgraded". Pass socket to application. */ | 1590 | /* This request is "upgraded". Pass socket to application. */ |
1231 | if (MHD_YES != | 1591 | if (MHD_YES != |
1232 | MHD_response_execute_upgrade_ (connection->response, | 1592 | MHD_response_execute_upgrade_ (request->response, |
1233 | connection)) | 1593 | request)) |
1234 | { | 1594 | { |
1235 | /* upgrade failed, fail hard */ | 1595 | /* upgrade failed, fail hard */ |
1236 | CONNECTION_CLOSE_ERROR (connection, | 1596 | CONNECTION_CLOSE_ERROR (connection, |
1237 | NULL); | 1597 | NULL); |
1238 | continue; | 1598 | continue; |
1239 | } | 1599 | } |
1240 | /* Response is not required anymore for this connection. */ | 1600 | /* Response is not required anymore for this request. */ |
1241 | if (NULL != connection->response) | 1601 | if (NULL != request->response) |
1242 | { | 1602 | { |
1243 | struct MHD_Response * const resp = connection->response; | 1603 | struct MHD_Response * const resp = request->response; |
1244 | connection->response = NULL; | 1604 | request->response = NULL; |
1245 | MHD_destroy_response (resp); | 1605 | MHD_destroy_response (resp); |
1246 | } | 1606 | } |
1247 | continue; | 1607 | continue; |
@@ -1252,29 +1612,29 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1252 | else | 1612 | else |
1253 | socket_start_normal_buffering (connection); | 1613 | socket_start_normal_buffering (connection); |
1254 | 1614 | ||
1255 | if (connection->have_chunked_upload) | 1615 | if (request->have_chunked_upload) |
1256 | connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY; | 1616 | request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY; |
1257 | else | 1617 | else |
1258 | connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY; | 1618 | request->state = MHD_REQUEST_NORMAL_BODY_UNREADY; |
1259 | continue; | 1619 | continue; |
1260 | case MHD_CONNECTION_NORMAL_BODY_READY: | 1620 | case MHD_REQUEST_NORMAL_BODY_READY: |
1261 | /* nothing to do here */ | 1621 | /* nothing to do here */ |
1262 | break; | 1622 | break; |
1263 | case MHD_CONNECTION_NORMAL_BODY_UNREADY: | 1623 | case MHD_REQUEST_NORMAL_BODY_UNREADY: |
1264 | if (NULL != connection->response->crc) | 1624 | if (NULL != request->response->crc) |
1265 | MHD_mutex_lock_chk_ (&connection->response->mutex); | 1625 | MHD_mutex_lock_chk_ (&request->response->mutex); |
1266 | if (0 == connection->response->total_size) | 1626 | if (0 == request->response->total_size) |
1267 | { | 1627 | { |
1268 | if (NULL != connection->response->crc) | 1628 | if (NULL != request->response->crc) |
1269 | MHD_mutex_unlock_chk_ (&connection->response->mutex); | 1629 | MHD_mutex_unlock_chk_ (&request->response->mutex); |
1270 | connection->state = MHD_CONNECTION_BODY_SENT; | 1630 | request->state = MHD_REQUEST_BODY_SENT; |
1271 | continue; | 1631 | continue; |
1272 | } | 1632 | } |
1273 | if (try_ready_normal_body (connection)) | 1633 | if (try_ready_normal_body (request)) |
1274 | { | 1634 | { |
1275 | if (NULL != connection->response->crc) | 1635 | if (NULL != request->response->crc) |
1276 | MHD_mutex_unlock_chk_ (&connection->response->mutex); | 1636 | MHD_mutex_unlock_chk_ (&request->response->mutex); |
1277 | connection->state = MHD_CONNECTION_NORMAL_BODY_READY; | 1637 | request->state = MHD_REQUEST_NORMAL_BODY_READY; |
1278 | /* Buffering for flushable socket was already enabled*/ | 1638 | /* Buffering for flushable socket was already enabled*/ |
1279 | if (MHD_NO == socket_flush_possible (connection)) | 1639 | if (MHD_NO == socket_flush_possible (connection)) |
1280 | socket_start_no_buffering (connection); | 1640 | socket_start_no_buffering (connection); |
@@ -1283,26 +1643,26 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1283 | /* mutex was already unlocked by "try_ready_normal_body */ | 1643 | /* mutex was already unlocked by "try_ready_normal_body */ |
1284 | /* not ready, no socket action */ | 1644 | /* not ready, no socket action */ |
1285 | break; | 1645 | break; |
1286 | case MHD_CONNECTION_CHUNKED_BODY_READY: | 1646 | case MHD_REQUEST_CHUNKED_BODY_READY: |
1287 | /* nothing to do here */ | 1647 | /* nothing to do here */ |
1288 | break; | 1648 | break; |
1289 | case MHD_CONNECTION_CHUNKED_BODY_UNREADY: | 1649 | case MHD_REQUEST_CHUNKED_BODY_UNREADY: |
1290 | if (NULL != connection->response->crc) | 1650 | if (NULL != request->response->crc) |
1291 | MHD_mutex_lock_chk_ (&connection->response->mutex); | 1651 | MHD_mutex_lock_chk_ (&request->response->mutex); |
1292 | if ( (0 == connection->response->total_size) || | 1652 | if ( (0 == request->response->total_size) || |
1293 | (connection->response_write_position == | 1653 | (request->response_write_position == |
1294 | connection->response->total_size) ) | 1654 | request->response->total_size) ) |
1295 | { | 1655 | { |
1296 | if (NULL != connection->response->crc) | 1656 | if (NULL != request->response->crc) |
1297 | MHD_mutex_unlock_chk_ (&connection->response->mutex); | 1657 | MHD_mutex_unlock_chk_ (&request->response->mutex); |
1298 | connection->state = MHD_CONNECTION_BODY_SENT; | 1658 | request->state = MHD_REQUEST_BODY_SENT; |
1299 | continue; | 1659 | continue; |
1300 | } | 1660 | } |
1301 | if (try_ready_chunked_body (connection)) | 1661 | if (try_ready_chunked_body (request)) |
1302 | { | 1662 | { |
1303 | if (NULL != connection->response->crc) | 1663 | if (NULL != request->response->crc) |
1304 | MHD_mutex_unlock_chk_ (&connection->response->mutex); | 1664 | MHD_mutex_unlock_chk_ (&request->response->mutex); |
1305 | connection->state = MHD_CONNECTION_CHUNKED_BODY_READY; | 1665 | request->state = MHD_REQUEST_CHUNKED_BODY_READY; |
1306 | /* Buffering for flushable socket was already enabled */ | 1666 | /* Buffering for flushable socket was already enabled */ |
1307 | if (MHD_NO == socket_flush_possible (connection)) | 1667 | if (MHD_NO == socket_flush_possible (connection)) |
1308 | socket_start_no_buffering (connection); | 1668 | socket_start_no_buffering (connection); |
@@ -1310,31 +1670,31 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1310 | } | 1670 | } |
1311 | /* mutex was already unlocked by try_ready_chunked_body */ | 1671 | /* mutex was already unlocked by try_ready_chunked_body */ |
1312 | break; | 1672 | break; |
1313 | case MHD_CONNECTION_BODY_SENT: | 1673 | case MHD_REQUEST_BODY_SENT: |
1314 | if (MHD_NO == build_header_response (connection)) | 1674 | if (MHD_NO == build_header_response (request)) |
1315 | { | 1675 | { |
1316 | /* oops - close! */ | 1676 | /* oops - close! */ |
1317 | CONNECTION_CLOSE_ERROR (connection, | 1677 | CONNECTION_CLOSE_ERROR (connection, |
1318 | _("Closing connection (failed to create response header)\n")); | 1678 | _("Closing connection (failed to create response header)\n")); |
1319 | continue; | 1679 | continue; |
1320 | } | 1680 | } |
1321 | if ( (! connection->have_chunked_upload) || | 1681 | if ( (! request->have_chunked_upload) || |
1322 | (connection->write_buffer_send_offset == | 1682 | (request->write_buffer_send_offset == |
1323 | connection->write_buffer_append_offset) ) | 1683 | request->write_buffer_append_offset) ) |
1324 | connection->state = MHD_CONNECTION_FOOTERS_SENT; | 1684 | request->state = MHD_REQUEST_FOOTERS_SENT; |
1325 | else | 1685 | else |
1326 | connection->state = MHD_CONNECTION_FOOTERS_SENDING; | 1686 | request->state = MHD_REQUEST_FOOTERS_SENDING; |
1327 | continue; | 1687 | continue; |
1328 | case MHD_CONNECTION_FOOTERS_SENDING: | 1688 | case MHD_REQUEST_FOOTERS_SENDING: |
1329 | /* no default action */ | 1689 | /* no default action */ |
1330 | break; | 1690 | break; |
1331 | case MHD_CONNECTION_FOOTERS_SENT: | 1691 | case MHD_REQUEST_FOOTERS_SENT: |
1332 | if (MHD_HTTP_PROCESSING == connection->responseCode) | 1692 | if (MHD_HTTP_PROCESSING == request->responseCode) |
1333 | { | 1693 | { |
1334 | /* After this type of response, we allow sending another! */ | 1694 | /* After this type of response, we allow sending another! */ |
1335 | connection->state = MHD_CONNECTION_HEADERS_PROCESSED; | 1695 | request->state = MHD_REQUEST_HEADERS_PROCESSED; |
1336 | MHD_destroy_response (connection->response); | 1696 | MHD_destroy_response (request->response); |
1337 | connection->response = NULL; | 1697 | request->response = NULL; |
1338 | /* FIXME: maybe partially reset memory pool? */ | 1698 | /* FIXME: maybe partially reset memory pool? */ |
1339 | continue; | 1699 | continue; |
1340 | } | 1700 | } |
@@ -1343,7 +1703,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1343 | else | 1703 | else |
1344 | socket_start_normal_buffering (connection); | 1704 | socket_start_normal_buffering (connection); |
1345 | 1705 | ||
1346 | MHD_destroy_response (connection->response); | 1706 | MHD_destroy_response (request->response); |
1347 | connection->response = NULL; | 1707 | connection->response = NULL; |
1348 | if ( (NULL != daemon->notify_completed) && | 1708 | if ( (NULL != daemon->notify_completed) && |
1349 | (connection->client_aware) ) | 1709 | (connection->client_aware) ) |
@@ -1354,7 +1714,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1354 | &connection->client_context, | 1714 | &connection->client_context, |
1355 | MHD_REQUEST_TERMINATED_COMPLETED_OK); | 1715 | MHD_REQUEST_TERMINATED_COMPLETED_OK); |
1356 | } | 1716 | } |
1357 | if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) || | 1717 | if ( (MHD_CONN_USE_KEEPALIVE != request->keepalive) || |
1358 | (connection->read_closed) ) | 1718 | (connection->read_closed) ) |
1359 | { | 1719 | { |
1360 | /* have to close for some reason */ | 1720 | /* have to close for some reason */ |
@@ -1362,55 +1722,44 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1362 | MHD_REQUEST_TERMINATED_COMPLETED_OK); | 1722 | MHD_REQUEST_TERMINATED_COMPLETED_OK); |
1363 | MHD_pool_destroy (connection->pool); | 1723 | MHD_pool_destroy (connection->pool); |
1364 | connection->pool = NULL; | 1724 | connection->pool = NULL; |
1365 | connection->read_buffer = NULL; | 1725 | request->read_buffer = NULL; |
1366 | connection->read_buffer_size = 0; | 1726 | request->read_buffer_size = 0; |
1367 | connection->read_buffer_offset = 0; | 1727 | request->read_buffer_offset = 0; |
1368 | } | 1728 | } |
1369 | else | 1729 | else |
1370 | { | 1730 | { |
1371 | /* can try to keep-alive */ | 1731 | /* can try to keep-alive */ |
1372 | if (MHD_NO != socket_flush_possible (connection)) | 1732 | if (MHD_NO != socket_flush_possible (connection)) |
1373 | socket_start_normal_buffering (connection); | 1733 | socket_start_normal_buffering (connection); |
1374 | connection->version = NULL; | 1734 | request->version = NULL; |
1375 | connection->state = MHD_CONNECTION_INIT; | 1735 | request->state = MHD_REQUEST_INIT; |
1376 | connection->last = NULL; | 1736 | request->last = NULL; |
1377 | connection->colon = NULL; | 1737 | request->colon = NULL; |
1378 | connection->header_size = 0; | 1738 | request->header_size = 0; |
1379 | connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN; | 1739 | request->keepalive = MHD_CONN_KEEPALIVE_UNKOWN; |
1380 | /* Reset the read buffer to the starting size, | 1740 | /* Reset the read buffer to the starting size, |
1381 | preserving the bytes we have already read. */ | 1741 | preserving the bytes we have already read. */ |
1382 | connection->read_buffer | 1742 | request->read_buffer |
1383 | = MHD_pool_reset (connection->pool, | 1743 | = MHD_pool_reset (connection->pool, |
1384 | connection->read_buffer, | 1744 | request->read_buffer, |
1385 | connection->read_buffer_offset, | 1745 | request->read_buffer_offset, |
1386 | connection->daemon->pool_size / 2); | 1746 | daemon->pool_size / 2); |
1387 | connection->read_buffer_size | 1747 | request->read_buffer_size |
1388 | = connection->daemon->pool_size / 2; | 1748 | = daemon->pool_size / 2; |
1389 | } | 1749 | } |
1390 | connection->client_aware = false; | 1750 | memset (&request, |
1391 | connection->client_context = NULL; | 1751 | 0, |
1392 | connection->continue_message_write_offset = 0; | 1752 | sizeof (struct MHD_Request)); |
1393 | connection->responseCode = 0; | 1753 | request->daemon = daemon; |
1394 | connection->headers_received = NULL; | 1754 | request->connection = connection; |
1395 | connection->headers_received_tail = NULL; | ||
1396 | connection->response_write_position = 0; | ||
1397 | connection->have_chunked_upload = false; | ||
1398 | connection->current_chunk_size = 0; | ||
1399 | connection->current_chunk_offset = 0; | ||
1400 | connection->method = NULL; | ||
1401 | connection->url = NULL; | ||
1402 | connection->write_buffer = NULL; | ||
1403 | connection->write_buffer_size = 0; | ||
1404 | connection->write_buffer_send_offset = 0; | ||
1405 | connection->write_buffer_append_offset = 0; | ||
1406 | continue; | 1755 | continue; |
1407 | case MHD_CONNECTION_CLOSED: | 1756 | case MHD_REQUEST_CLOSED: |
1408 | cleanup_connection (connection); | 1757 | cleanup_connection (connection); |
1409 | connection->in_idle = false; | 1758 | request->in_idle = false; |
1410 | return MHD_NO; | 1759 | return MHD_NO; |
1411 | #ifdef UPGRADE_SUPPORT | 1760 | #ifdef UPGRADE_SUPPORT |
1412 | case MHD_CONNECTION_UPGRADE: | 1761 | case MHD_REQUEST_UPGRADE: |
1413 | connection->in_idle = false; | 1762 | request->in_idle = false; |
1414 | return MHD_YES; /* keep open */ | 1763 | return MHD_YES; /* keep open */ |
1415 | #endif /* UPGRADE_SUPPORT */ | 1764 | #endif /* UPGRADE_SUPPORT */ |
1416 | default: | 1765 | default: |
@@ -1428,7 +1777,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1428 | { | 1777 | { |
1429 | MHD_connection_close_ (connection, | 1778 | MHD_connection_close_ (connection, |
1430 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); | 1779 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); |
1431 | connection->in_idle = false; | 1780 | request->in_idle = false; |
1432 | return MHD_YES; | 1781 | return MHD_YES; |
1433 | } | 1782 | } |
1434 | } | 1783 | } |
@@ -1441,7 +1790,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
1441 | ret = MHD_connection_epoll_update_ (connection); | 1790 | ret = MHD_connection_epoll_update_ (connection); |
1442 | } | 1791 | } |
1443 | #endif /* EPOLL_SUPPORT */ | 1792 | #endif /* EPOLL_SUPPORT */ |
1444 | connection->in_idle = false; | 1793 | request->in_idle = false; |
1445 | return ret; | 1794 | return ret; |
1446 | } | 1795 | } |
1447 | 1796 | ||