diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2016-12-05 22:19:16 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2016-12-05 22:19:16 +0300 |
commit | 89e9332e2bacdba1cf44aabfcfc082c0de62871c (patch) | |
tree | 156ad5e5b00e6966642b2d600dafa5f0cc1d43ac /support/ab.c | |
parent | f51547f19e44fc1f511837443cb92ba28c189b9c (diff) | |
parent | adb6f181257af28ee67af15fc49d2699a0080d4c (diff) | |
download | apache2-89e9332e2bacdba1cf44aabfcfc082c0de62871c.tar.gz |
Merge branch 'master' of git://anonscm.debian.org/pkg-apache/apache2
Diffstat (limited to 'support/ab.c')
-rw-r--r-- | support/ab.c | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/support/ab.c b/support/ab.c index 13041505..902b1023 100644 --- a/support/ab.c +++ b/support/ab.c @@ -170,6 +170,14 @@ #define SK_VALUE(x,y) sk_X509_value(x,y) typedef STACK_OF(X509) X509_STACK_TYPE; +#if defined(_MSC_VER) +/* The following logic ensures we correctly glue FILE* within one CRT used + * by the OpenSSL library build to another CRT used by the ab.exe build. + * This became especially problematic with Visual Studio 2015. + */ +#include <openssl/applink.c> +#endif + #endif #if defined(USE_SSL) @@ -220,7 +228,7 @@ typedef enum { STATE_READ } connect_state_e; -#define CBUFFSIZE (2048) +#define CBUFFSIZE (8192) struct connection { apr_pool_t *ctx; @@ -266,14 +274,14 @@ struct data { int verbosity = 0; /* no verbosity by default */ int recverrok = 0; /* ok to proceed after socket receive errors */ -enum {NO_METH = 0, GET, HEAD, PUT, POST} method = NO_METH; -const char *method_str[] = {"bug", "GET", "HEAD", "PUT", "POST"}; +enum {NO_METH = 0, GET, HEAD, PUT, POST, CUSTOM_METHOD} method = NO_METH; +const char *method_str[] = {"bug", "GET", "HEAD", "PUT", "POST", ""}; int send_body = 0; /* non-zero if sending body with request */ int requests = 1; /* Number of requests to make */ int heartbeatres = 100; /* How often do we say we're alive */ int concurrency = 1; /* Number of multiple requests to make */ int percentile = 1; /* Show percentile served */ -int nolength = 0; /* Accept variable document length */ +int nolength = 0; /* Accept variable document length */ int confidence = 1; /* Show confidence estimator and warnings */ int tlimit = 0; /* time limit in secs */ int keepalive = 0; /* try and do keepalive connections */ @@ -340,7 +348,7 @@ BIO *bio_out,*bio_err; apr_time_t start, lasttime, stoptime; /* global request (and its length) */ -char _request[2048]; +char _request[8192]; char *request = _request; apr_size_t reqlen; @@ -425,6 +433,41 @@ static char *xstrdup(const char *s) return ret; } +/* + * Similar to standard strstr() but we ignore case in this version. + * Copied from ap_strcasestr(). + */ +static char *xstrcasestr(const char *s1, const char *s2) +{ + char *p1, *p2; + if (*s2 == '\0') { + /* an empty s2 */ + return((char *)s1); + } + while(1) { + for ( ; (*s1 != '\0') && (apr_tolower(*s1) != apr_tolower(*s2)); s1++); + if (*s1 == '\0') { + return(NULL); + } + /* found first character of s2, see if the rest matches */ + p1 = (char *)s1; + p2 = (char *)s2; + for (++p1, ++p2; apr_tolower(*p1) == apr_tolower(*p2); ++p1, ++p2) { + if (*p1 == '\0') { + /* both strings ended together */ + return((char *)s1); + } + } + if (*p2 == '\0') { + /* second string ended, a match */ + break; + } + /* didn't find a match here, try starting at next character in s1 */ + s1++; + } + return((char *)s1); +} + /* pool abort function */ static int abort_on_oom(int retcode) { @@ -1038,7 +1081,7 @@ static void output_results(int sig) exit(1); } fprintf(out, "" "Percentage served" "," "Time in ms" "\n"); - for (i = 0; i < 100; i++) { + for (i = 0; i <= 100; i++) { double t; if (i == 0) t = ap_double_ms(stats[0].time); @@ -1222,7 +1265,7 @@ static void start_connect(struct connection * c) apr_status_t rv; if (!(started < requests)) - return; + return; c->read = 0; c->bread = 0; @@ -1515,12 +1558,14 @@ static void read_connection(struct connection * c) * this is first time, extract some interesting info */ char *p, *q; - p = strstr(c->cbuff, "Server:"); + size_t len = 0; + p = xstrcasestr(c->cbuff, "Server:"); q = servername; if (p) { p += 8; - while (*p > 32) - *q++ = *p++; + /* -1 to not overwrite last '\0' byte */ + while (*p > 32 && len++ < sizeof(servername) - 1) + *q++ = *p++; } *q = 0; } @@ -1551,22 +1596,15 @@ static void read_connection(struct connection * c) } c->gotheader = 1; *s = 0; /* terminate at end of header */ - if (keepalive && - (strstr(c->cbuff, "Keep-Alive") - || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */ + if (keepalive && xstrcasestr(c->cbuff, "Keep-Alive")) { char *cl; - cl = strstr(c->cbuff, "Content-Length:"); - /* handle NCSA, which sends Content-length: */ - if (!cl) - cl = strstr(c->cbuff, "Content-length:"); - if (cl) { - c->keepalive = 1; + c->keepalive = 1; + cl = xstrcasestr(c->cbuff, "Content-Length:"); + if (cl && method != HEAD) { /* response to HEAD doesn't have entity body */ - c->length = method != HEAD ? atoi(cl + 16) : 0; + c->length = atoi(cl + 16); } - /* The response may not have a Content-Length header */ - if (!cl) { - c->keepalive = 1; + else { c->length = 0; } } @@ -1888,14 +1926,14 @@ static void test(void) static void copyright(void) { if (!use_html) { - printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision: 1554214 $>"); + printf("This is ApacheBench, Version %s\n", AP_AB_BASEREVISION " <$Revision: 1748469 $>"); printf("Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); printf("Licensed to The Apache Software Foundation, http://www.apache.org/\n"); printf("\n"); } else { printf("<p>\n"); - printf(" This is ApacheBench, Version %s <i><%s></i><br>\n", AP_AB_BASEREVISION, "$Revision: 1554214 $"); + printf(" This is ApacheBench, Version %s <i><%s></i><br>\n", AP_AB_BASEREVISION, "$Revision: 1748469 $"); printf(" Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n"); printf(" Licensed to The Apache Software Foundation, http://www.apache.org/<br>\n"); printf("</p>\n<p>\n"); @@ -1949,6 +1987,7 @@ static void usage(const char *progname) fprintf(stderr, " -g filename Output collected data to gnuplot format file.\n"); fprintf(stderr, " -e filename Output CSV file with percentages served\n"); fprintf(stderr, " -r Don't exit on socket receive errors.\n"); + fprintf(stderr, " -m method Method name\n"); fprintf(stderr, " -h Display usage information (this message)\n"); #ifdef USE_SSL @@ -1958,6 +1997,12 @@ static void usage(const char *progname) #define SSL2_HELP_MSG "" #endif +#ifndef OPENSSL_NO_SSL3 +#define SSL3_HELP_MSG "SSL3, " +#else +#define SSL3_HELP_MSG "" +#endif + #ifdef HAVE_TLSV1_X #define TLS1_X_HELP_MSG ", TLS1.1, TLS1.2" #else @@ -1966,7 +2011,7 @@ static void usage(const char *progname) fprintf(stderr, " -Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)\n"); fprintf(stderr, " -f protocol Specify SSL/TLS protocol\n"); - fprintf(stderr, " (" SSL2_HELP_MSG "SSL3, TLS1" TLS1_X_HELP_MSG " or ALL)\n"); + fprintf(stderr, " (" SSL2_HELP_MSG SSL3_HELP_MSG "TLS1" TLS1_X_HELP_MSG " or ALL)\n"); #endif exit(EINVAL); } @@ -2127,7 +2172,7 @@ int main(int argc, const char * const argv[]) myhost = NULL; /* 0.0.0.0 or :: */ apr_getopt_init(&opt, cntxt, argc, argv); - while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwix:y:z:C:H:P:A:g:X:de:SqB:" + while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwix:y:z:C:H:P:A:g:X:de:SqB:m:" #ifdef USE_SSL "Z:f:" #endif @@ -2300,6 +2345,10 @@ int main(int argc, const char * const argv[]) case 'Z': ssl_cipher = strdup(opt_arg); break; + case 'm': + method = CUSTOM_METHOD; + method_str[CUSTOM_METHOD] = strdup(opt_arg); + break; case 'f': if (strncasecmp(opt_arg, "ALL", 3) == 0) { meth = SSLv23_client_method(); @@ -2307,8 +2356,10 @@ int main(int argc, const char * const argv[]) } else if (strncasecmp(opt_arg, "SSL2", 4) == 0) { meth = SSLv2_client_method(); #endif +#ifndef OPENSSL_NO_SSL3 } else if (strncasecmp(opt_arg, "SSL3", 4) == 0) { meth = SSLv3_client_method(); +#endif #ifdef HAVE_TLSV1_X } else if (strncasecmp(opt_arg, "TLS1.1", 6) == 0) { meth = TLSv1_1_client_method(); |