summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSammy Kaye Powers <sammyk@sammykmedia.com>2017-03-29 09:27:18 -0500
committerAnatol Belski <ab@php.net>2017-11-14 20:00:45 +0100
commit3bc5c9f118d994dbeabd5b2ab3ae025c960a0c65 (patch)
treeeed758fe1ab0bdc3b4c94846577d4b5fb38c6177
parentdf615f47bddfc4c2edb78f74e6935f013c1512f2 (diff)
downloadphp-git-3bc5c9f118d994dbeabd5b2ab3ae025c960a0c65.tar.gz
Fix bug 60471 by correctly identifying unused speculative preconnections
* Correctly identify unused speculative preconnections from browsers like Chrome and Firefox * Add a new message to the debug level that is emitted when a TCP connection is closed without sending any request (a preconnection) * Fix an issue where the existing debug messages were not being displayed even when debug mode was enabled
-rw-r--r--sapi/cli/php_cli_server.c16
-rw-r--r--sapi/cli/php_http_parser.c69
-rw-r--r--sapi/cli/php_http_parser.h67
3 files changed, 79 insertions, 73 deletions
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 48480bb1e2..4c1d443d61 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -213,6 +213,8 @@ static php_cli_server_http_response_status_code_pair template_map[] = {
static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
#endif
+static const char php_cli_server_request_error_unexpected_eof[] = "Unexpected EOF";
+
static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len);
static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len);
static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk);
@@ -1743,7 +1745,7 @@ static int php_cli_server_client_read_request(php_cli_server_client *client, cha
*errstr = php_socket_strerror(err, NULL, 0);
return -1;
} else if (nbytes_read == 0) {
- *errstr = estrdup("Unexpected EOF");
+ *errstr = estrdup(php_cli_server_request_error_unexpected_eof);
return -1;
}
client->parser.data = client;
@@ -1880,7 +1882,7 @@ static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */
static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client) /* {{{ */
{
-#ifdef DEBUG
+#if PHP_DEBUG
php_cli_server_logf("%s Closing", client->addr_str);
#endif
zend_hash_index_del(&server->clients, client->sock);
@@ -2369,7 +2371,13 @@ static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cl
char *errstr = NULL;
int status = php_cli_server_client_read_request(client, &errstr);
if (status < 0) {
- php_cli_server_logf("%s Invalid request (%s)", client->addr_str, errstr);
+ if (strcmp(errstr, php_cli_server_request_error_unexpected_eof) == 0 && client->parser.state == s_start_req) {
+#if PHP_DEBUG
+ php_cli_server_logf("%s Closed without sending a request; it was probably just an unused speculative preconnection", client->addr_str);
+#endif
+ } else {
+ php_cli_server_logf("%s Invalid request (%s)", client->addr_str, errstr);
+ }
efree(errstr);
php_cli_server_close_connection(server, client);
return FAILURE;
@@ -2453,7 +2461,7 @@ static int php_cli_server_do_event_for_each_fd_callback(void *_params, php_socke
closesocket(client_sock);
return SUCCESS;
}
-#ifdef DEBUG
+#if PHP_DEBUG
php_cli_server_logf("%s Accepted", client->addr_str);
#endif
zend_hash_index_update_ptr(&server->clients, client_sock, client);
diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c
index 5f8eb3ce0b..82c74e93c2 100644
--- a/sapi/cli/php_http_parser.c
+++ b/sapi/cli/php_http_parser.c
@@ -195,75 +195,6 @@ static const uint8_t normal_url_char[256] = {
1, 1, 1, 1, 1, 1, 1, 0 };
-enum state
- { s_dead = 1 /* important that this is > 0 */
-
- , s_start_req_or_res
- , s_res_or_resp_H
- , s_start_res
- , s_res_H
- , s_res_HT
- , s_res_HTT
- , s_res_HTTP
- , s_res_first_http_major
- , s_res_http_major
- , s_res_first_http_minor
- , s_res_http_minor
- , s_res_first_status_code
- , s_res_status_code
- , s_res_status
- , s_res_line_almost_done
-
- , s_start_req
-
- , s_req_method
- , s_req_spaces_before_url
- , s_req_schema
- , s_req_schema_slash
- , s_req_schema_slash_slash
- , s_req_host
- , s_req_port
- , s_req_path
- , s_req_query_string_start
- , s_req_query_string
- , s_req_fragment_start
- , s_req_fragment
- , s_req_http_start
- , s_req_http_H
- , s_req_http_HT
- , s_req_http_HTT
- , s_req_http_HTTP
- , s_req_first_http_major
- , s_req_http_major
- , s_req_first_http_minor
- , s_req_http_minor
- , s_req_line_almost_done
-
- , s_header_field_start
- , s_header_field
- , s_header_value_start
- , s_header_value
-
- , s_header_almost_done
-
- , s_headers_almost_done
- /* Important: 's_headers_almost_done' must be the last 'header' state. All
- * states beyond this must be 'body' states. It is used for overflow
- * checking. See the PARSING_HEADER() macro.
- */
- , s_chunk_size_start
- , s_chunk_size
- , s_chunk_size_almost_done
- , s_chunk_parameters
- , s_chunk_data
- , s_chunk_data_almost_done
- , s_chunk_data_done
-
- , s_body_identity
- , s_body_identity_eof
- };
-
-
#define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
diff --git a/sapi/cli/php_http_parser.h b/sapi/cli/php_http_parser.h
index fa4873abeb..d2fa69b757 100644
--- a/sapi/cli/php_http_parser.h
+++ b/sapi/cli/php_http_parser.h
@@ -110,6 +110,73 @@ enum php_http_method
enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
+enum state
+ { s_dead = 1 /* important that this is > 0 */
+
+ , s_start_req_or_res
+ , s_res_or_resp_H
+ , s_start_res
+ , s_res_H
+ , s_res_HT
+ , s_res_HTT
+ , s_res_HTTP
+ , s_res_first_http_major
+ , s_res_http_major
+ , s_res_first_http_minor
+ , s_res_http_minor
+ , s_res_first_status_code
+ , s_res_status_code
+ , s_res_status
+ , s_res_line_almost_done
+
+ , s_start_req
+
+ , s_req_method
+ , s_req_spaces_before_url
+ , s_req_schema
+ , s_req_schema_slash
+ , s_req_schema_slash_slash
+ , s_req_host
+ , s_req_port
+ , s_req_path
+ , s_req_query_string_start
+ , s_req_query_string
+ , s_req_fragment_start
+ , s_req_fragment
+ , s_req_http_start
+ , s_req_http_H
+ , s_req_http_HT
+ , s_req_http_HTT
+ , s_req_http_HTTP
+ , s_req_first_http_major
+ , s_req_http_major
+ , s_req_first_http_minor
+ , s_req_http_minor
+ , s_req_line_almost_done
+
+ , s_header_field_start
+ , s_header_field
+ , s_header_value_start
+ , s_header_value
+
+ , s_header_almost_done
+
+ , s_headers_almost_done
+ /* Important: 's_headers_almost_done' must be the last 'header' state. All
+ * states beyond this must be 'body' states. It is used for overflow
+ * checking. See the PARSING_HEADER() macro.
+ */
+ , s_chunk_size_start
+ , s_chunk_size
+ , s_chunk_size_almost_done
+ , s_chunk_parameters
+ , s_chunk_data
+ , s_chunk_data_almost_done
+ , s_chunk_data_done
+
+ , s_body_identity
+ , s_body_identity_eof
+ };
struct php_http_parser {
/** PRIVATE **/