From 0491ab9ceda95207db8a8b52a836b8c87d56d877 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Fri, 4 Sep 2015 08:52:15 +0000 Subject: [PATCH] improvements in ap_select_protocol(), supplied by yann ylavic git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1701178 13f79535-47bb-0310-9956-ffa450edef68 --- include/http_protocol.h | 2 +- server/protocol.c | 87 +++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 47 deletions(-) diff --git a/include/http_protocol.h b/include/http_protocol.h index 3867b3458d..64ed01362c 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -800,7 +800,7 @@ AP_DECLARE_HOOK(const char *,protocol_get,(const conn_rec *c)) */ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, server_rec *s, - apr_array_header_t *choices); + const apr_array_header_t *choices); /** * Perform the actual protocol switch. The protocol given must have been diff --git a/server/protocol.c b/server/protocol.c index d2ae6e3886..26ce24a8f2 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -1951,7 +1951,7 @@ AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers) * Compare two protocol identifier. Result is similar to strcmp(): * 0 gives same precedence, >0 means proto1 is preferred. */ -static int protocol_cmp(apr_array_header_t *preferences, +static int protocol_cmp(const apr_array_header_t *preferences, const char *proto1, const char *proto2) { @@ -1979,47 +1979,57 @@ AP_DECLARE(const char *) ap_get_protocol(conn_rec *c) AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, server_rec *s, - apr_array_header_t *choices) + const apr_array_header_t *choices) { apr_pool_t *pool = r? r->pool : c->pool; core_server_config *conf = ap_get_core_module_config(s->module_config); - const char *protocol = NULL, *existing = ap_get_protocol(c); + const char *protocol = NULL, *existing; apr_array_header_t *proposals; if (APLOGcdebug(c)) { const char *p = apr_array_pstrcat(pool, conf->protocols, ','); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "select protocol from %s, choices=%s for server %s", - p, choices? - apr_array_pstrcat(pool, choices, ',') : "NULL", + p, apr_array_pstrcat(pool, choices, ','), s->server_hostname); } - - proposals = apr_array_make(pool, choices? choices->nelts+1 : 5, - sizeof(char *)); + + if (conf->protocols->nelts <= 0) { + /* nothing configured, by default, we only allow http/1.1 here. + * For now... + */ + if (ap_array_str_contains(choices, AP_PROTOCOL_HTTP1)) { + return AP_PROTOCOL_HTTP1; + } + else { + return NULL; + } + } + + proposals = apr_array_make(pool, choices->nelts + 1, sizeof(char *)); ap_run_protocol_propose(c, r, s, choices, proposals); - + + /* If the existing protocol has not been proposed, but is a choice, + * add it to the proposals implicitly. + */ + existing = ap_get_protocol(c); + if (!ap_array_str_contains(proposals, existing) + && ap_array_str_contains(choices, existing)) { + APR_ARRAY_PUSH(proposals, const char*) = existing; + } + if (proposals->nelts > 0) { int i; - apr_array_header_t *prefs = NULL; - + const apr_array_header_t *prefs = NULL; + /* Default for protocols_honor_order is 'on' or != 0 */ - if (conf->protocols_honor_order == 0 && choices && choices->nelts > 0) { + if (conf->protocols_honor_order == 0 && choices->nelts > 0) { prefs = choices; } else { prefs = conf->protocols; } - /* If the existing protocol has not been proposed, but is a choice, - * add it to the proposals implicitly. - */ - if (choices - && !ap_array_str_contains(proposals, existing) - && ap_array_str_contains(choices, existing)) { - APR_ARRAY_PUSH(proposals, const char*) = existing; - } - /* Select the most preferred protocol */ if (APLOGcdebug(c)) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, @@ -2028,31 +2038,16 @@ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, apr_array_pstrcat(pool, prefs, ','), apr_array_pstrcat(pool, conf->protocols, ',')); } - if (conf->protocols->nelts <= 0) { - /* nothing configured, by default, we only allow http/1.1 here. - * For now... - */ - return (ap_array_str_contains(proposals, AP_PROTOCOL_HTTP1)? - AP_PROTOCOL_HTTP1 : NULL); - } - else { - for (i = 0; i < proposals->nelts; ++i) { - const char *p = APR_ARRAY_IDX(proposals, i, const char *); - if (conf->protocols->nelts <= 0 && !strcmp(AP_PROTOCOL_HTTP1, p)) { - /* nothing configured, by default, we only allow http/1.1 here. - * For now... - */ - continue; - } - if (!ap_array_str_contains(conf->protocols, p)) { - /* not a configured protocol here */ - continue; - } - else if (!protocol - || (protocol_cmp(prefs, protocol, p) < 0)) { - /* none selected yet or this one has preference */ - protocol = p; - } + for (i = 0; i < proposals->nelts; ++i) { + const char *p = APR_ARRAY_IDX(proposals, i, const char *); + if (!ap_array_str_contains(conf->protocols, p)) { + /* not a configured protocol here */ + continue; + } + else if (!protocol + || (protocol_cmp(prefs, protocol, p) < 0)) { + /* none selected yet or this one has preference */ + protocol = p; } } } -- 2.40.0