summaryrefslogtreecommitdiff
path: root/support/ab.c
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2016-12-05 22:19:16 +0300
committerIgor Pashev <pashev.igor@gmail.com>2016-12-05 22:19:16 +0300
commit89e9332e2bacdba1cf44aabfcfc082c0de62871c (patch)
tree156ad5e5b00e6966642b2d600dafa5f0cc1d43ac /support/ab.c
parentf51547f19e44fc1f511837443cb92ba28c189b9c (diff)
parentadb6f181257af28ee67af15fc49d2699a0080d4c (diff)
downloadapache2-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.c105
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>&lt;%s&gt;</i><br>\n", AP_AB_BASEREVISION, "$Revision: 1554214 $");
+ printf(" This is ApacheBench, Version %s <i>&lt;%s&gt;</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();