From 0296354880b10865be039d64d0154b66f7b03995 Mon Sep 17 00:00:00 2001 From: Bill Stoddard Date: Fri, 16 Mar 2001 04:17:38 +0000 Subject: [PATCH] Avoid using sscanf to determine the HTTP protocol number in the common case because sscanf is a performance hog. From Mike Abbot's Accelerating Apache patch number 6. Submitted by: Mike Abbot Reviewed by: Bill Stoddard git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88523 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ server/protocol.c | 33 +++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 0f3944086e..3824250e0b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ Changes with Apache 2.0.15-dev + *) Avoid using sscanf to determine the HTTP protocol number in + the common case because sscanf is a performance hog. From + Mike Abbot's Accelerating Apache patch number 6. + [Mike Abbot , Bill Stoddard] *) Fix a security exposure in mod_access. Previously when IPv6 listening sockets were used, allow/deny-from-IPv4-address rules diff --git a/server/protocol.c b/server/protocol.c index b6838b4424..aa8308e05d 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -664,6 +664,8 @@ static int read_request_line(request_rec *r) char l[DEFAULT_LIMIT_REQUEST_LINE + 2]; /* getline's two extra for \n\0 */ const char *ll = l; const char *uri; + const char *pro; + #if 0 conn_rec *conn = r->connection; #endif @@ -739,16 +741,27 @@ static int read_request_line(request_rec *r) return 0; } - r->assbackwards = (ll[0] == '\0'); - r->protocol = apr_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9"); -/* XXX If we want to keep track of the Method, the protocol module should do - * it. That support isn't in the scoreboard yet. Hopefully next week - * sometime. rbb - ap_update_connection_status(conn->id, "Protocol", r->protocol); - */ - - if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor) - && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */ + if (ll[0]) { + r->assbackwards = 0; + pro = ll; + len = strlen(ll); + } else { + r->assbackwards = 1; + pro = "HTTP/0.9"; + len = 8; + } + r->protocol = apr_pstrndup(r->pool, pro, len); + + /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */ + + /* Avoid sscanf in the common case */ + if (len == 8 && + pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' && + pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' && + apr_isdigit(pro[7])) { + r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0'); + } else if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor) + && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */ r->proto_num = HTTP_VERSION(major, minor); else r->proto_num = HTTP_VERSION(1,0); -- 2.40.0