mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
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
This commit is contained in:
parent
8121cb5046
commit
fd0e71d001
3 changed files with 80 additions and 74 deletions
|
@ -211,6 +211,8 @@ static php_cli_server_http_response_status_code_pair template_map[] = {
|
||||||
static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
|
static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
|
||||||
#endif
|
#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 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 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);
|
static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk);
|
||||||
|
@ -1462,7 +1464,7 @@ static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath
|
||||||
#ifdef PHP_WIN32
|
#ifdef PHP_WIN32
|
||||||
{
|
{
|
||||||
char *p = decoded_vpath;
|
char *p = decoded_vpath;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (*p == '\\') {
|
if (*p == '\\') {
|
||||||
*p = '/';
|
*p = '/';
|
||||||
|
@ -1677,7 +1679,7 @@ static int php_cli_server_client_read_request(php_cli_server_client *client, cha
|
||||||
*errstr = php_socket_strerror(err, NULL, 0);
|
*errstr = php_socket_strerror(err, NULL, 0);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (nbytes_read == 0) {
|
} else if (nbytes_read == 0) {
|
||||||
*errstr = estrdup("Unexpected EOF");
|
*errstr = estrdup(php_cli_server_request_error_unexpected_eof);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
client->parser.data = client;
|
client->parser.data = client;
|
||||||
|
@ -1806,7 +1808,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) /* {{{ */
|
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);
|
php_cli_server_logf("%s Closing", client->addr_str);
|
||||||
#endif
|
#endif
|
||||||
zend_hash_index_del(&server->clients, client->sock);
|
zend_hash_index_del(&server->clients, client->sock);
|
||||||
|
@ -2297,7 +2299,13 @@ static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cl
|
||||||
char *errstr = NULL;
|
char *errstr = NULL;
|
||||||
int status = php_cli_server_client_read_request(client, &errstr);
|
int status = php_cli_server_client_read_request(client, &errstr);
|
||||||
if (status < 0) {
|
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);
|
efree(errstr);
|
||||||
php_cli_server_close_connection(server, client);
|
php_cli_server_close_connection(server, client);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
|
@ -2379,7 +2387,7 @@ static int php_cli_server_do_event_for_each_fd_callback(void *_params, php_socke
|
||||||
closesocket(client_sock);
|
closesocket(client_sock);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#if PHP_DEBUG
|
||||||
php_cli_server_logf("%s Accepted", client->addr_str);
|
php_cli_server_logf("%s Accepted", client->addr_str);
|
||||||
#endif
|
#endif
|
||||||
zend_hash_index_update_ptr(&server->clients, client_sock, client);
|
zend_hash_index_update_ptr(&server->clients, client_sock, client);
|
||||||
|
|
|
@ -195,75 +195,6 @@ static const uint8_t normal_url_char[256] = {
|
||||||
1, 1, 1, 1, 1, 1, 1, 0 };
|
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))
|
#define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,73 @@ enum php_http_method
|
||||||
|
|
||||||
enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
|
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 {
|
struct php_http_parser {
|
||||||
/** PRIVATE **/
|
/** PRIVATE **/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue