ab.c revision cbe23d0a0ff097b3d544d714657452abc80e3c87
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere/* Licensed to the Apache Software Foundation (ASF) under one or more
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * contributor license agreements. See the NOTICE file distributed with
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * this work for additional information regarding copyright ownership.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * The ASF licenses this file to You under the Apache License, Version 2.0
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * (the "License"); you may not use this file except in compliance with
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * the License. You may obtain a copy of the License at
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * Unless required by applicable law or agreed to in writing, software
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * distributed under the License is distributed on an "AS IS" BASIS,
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * See the License for the specific language governing permissions and
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * limitations under the License.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** This program is based on ZeusBench V1.0 written by Adam Twiss
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** This software is provided "as is" and any express or implied waranties,
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** including but not limited to, the implied warranties of merchantability and
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** fitness for a particular purpose are disclaimed. In no event shall
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** exemplary, or consequential damaged (including, but not limited to,
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** procurement of substitute good or services; loss of use, data, or profits;
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** or business interruption) however caused and on theory of liability. Whether
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** in contract, strict liability or tort (including negligence or otherwise)
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** arising in any way out of the use of this software, even if advised of the
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** possibility of such damage.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** HISTORY:
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** with input from Mike Belshe <mbelshe@netscape.com> and
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Michael Campanella <campanella@stevms.enet.dec.com>
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Added Cookie, Arbitrary header and auth support. <dirkx@webweaving.org>, April 1999
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 1.3d
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Increased version number - as some of the socket/error handling has
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** fundamentally changed - and will give fundamentally different results
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** in situations where a server is dropping requests. Therefore you can
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** no longer compare results of AB as easily. Hence the inc of the version.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** They should be closer to the truth though. Sander & <dirkx@covalent.net>, End 2000.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Fixed proxy functionality, added median/mean statistics, added gnuplot
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** output option, added _experimental/rudimentary_ SSL support. Added
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** confidence guestimators and warnings. Sander & <dirkx@covalent.net>, End 2000
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Fixed serious int overflow issues which would cause realistic (longer
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** than a few minutes) run's to have wrong (but believable) results. Added
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** trapping of connection errors which influenced measurements.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Contributed by Sander Temme, Early 2001
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 1.3e
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Changed timeout behavour during write to work whilst the sockets
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** are filling up and apr_write() does writes a few - but not all.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** This will potentially change results. <dirkx@webweaving.org>, April 2001
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 2.0.36-dev
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Improvements to concurrent processing:
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Enabled non-blocking connect()s.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Prevent blocking calls to apr_socket_recv() (thereby allowing AB to
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** manage its entire set of socket descriptors).
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** - Any error returned from apr_socket_recv() that is not EAGAIN or EOF
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** is now treated as fatal.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Contributed by Aaron Bannert, April 24, 2002
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 2.0.36-2
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Internalized the version string - this string is part
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** of the Agent: header and the result output.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 2.0.37-dev
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Adopted SSL code by Madhu Mathihalli <madhusudan_mathihalli@hp.com>
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** [PATCH] ab with SSL support Posted Wed, 15 Aug 2001 20:55:06 GMT
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Introduces four 'if (int == value)' tests per non-ssl request.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 2.0.40-dev
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Switched to the new abstract pollset API, allowing ab to
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** take advantage of future apr_pollset_t scalability improvements.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Contributed by Brian Pane, August 31, 2002
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Version 2.3
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** SIGINT now triggers output_results().
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere ** Contributed by colm, March 30, 2006
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere/* Note: this version string should start with \d+[\d\.]* and be a valid
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * string for an HTTP Agent: header when prefixed with 'ApacheBench/'.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * It should reflect the version of AB - and not that of the apache server
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * it happens to accompany. And it should be updated or changed whenever
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * the results are no longer fundamentally comparable to the results of
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * a previous version of ab. Either due to a change in the logic of
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * ab - or to due to a change in the distribution it is compiled with
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * (such as an APR change in for example blocking).
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * - has various other poor buffer attacks related to the lazy parsing of
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * response headers from the server
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * - doesn't implement much of HTTP/1.x, only accepts certain forms of
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * responses
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * - (performance problem) heavy use of strstr shows up top in profile
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * only an issue for loopback usage
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere/* -------------------------------------------------------------------- */
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere/* Hmmm... This source code isn't being compiled in ASCII.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * In order for data that flows over the network to make
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere * sense, we need to translate to/from ASCII.
e3659090e9bb9934465dbb6c6212ba4c512190b0jfclere/* affects include files on Solaris */
#include "apr_time.h"
#include "apr_getopt.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "apr_portable.h"
#include "ap_release.h"
#include "apr_poll.h"
#define APR_WANT_STRFUNC
#include "apr_want.h"
#include "apr_base64.h"
#ifdef NOT_ASCII
#include "apr_xlate.h"
#if APR_HAVE_STDIO_H
#include <stdio.h>
#include <stdlib.h>
#include "ap_config_auto.h"
#if defined(HAVE_SSLC)
#include <rsa.h>
#include <x509.h>
#include <pem.h>
#include <err.h>
#include <ssl.h>
#include <r_rand.h>
#include <sslc.h>
#define USE_SSL
#define RSAREF
#define USE_SSL
#include <math.h>
#if APR_HAVE_CTYPE_H
#include <ctype.h>
#ifndef LLONG_MAX
#define STATE_UNCONNECTED 0
struct connection {
int state;
int socknum;
#ifdef USE_SSL
struct data {
#define ap_min(a,b) ((a)<(b))?(a):(b)
#define ap_max(a,b) ((a)>(b))?(a):(b)
char *connecthost;
int isproxy = 0;
const char *tablestring;
const char *trstring;
const char *tdstring;
#ifdef USE_SSL
int is_ssl;
#ifdef NOT_ASCII
static void err(char *s)
if (done)
if (done)
#ifdef USE_SSL
return(ret);
return ret;
if (w & SSL_CB_ALERT) {
} else if (w & SSL_CB_LOOP) {
#ifndef RAND_MAX
#include <limits.h>
static int ssl_rand_choosenum(int l, int h)
static void ssl_rand_seed(void)
int nDone = 0;
time_t t;
l = sizeof(time_t);
RAND_seed((unsigned char *)&t, l);
nDone += l;
l = sizeof(pid_t);
nDone += l;
SSL_CIPHER *c;
int count;
while (do_next) {
switch (ecode) {
case SSL_ERROR_NONE:
ssl_print_info(c);
if (cert)
write_request(c);
do_next = 0;
case SSL_ERROR_WANT_READ:
do_next = 0;
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_SSL:
case SSL_ERROR_SYSCALL:
close_connection(c);
do_next = 0;
if (c->rwrite == 0) {
c->rwrote = 0;
if (posting)
close_connection(c);
#ifdef USE_SSL
if (c->ssl) {
if (e_ssl != l) {
close_connection (c);
l = e_ssl;
e = APR_SUCCESS;
if (l == c->rwrite)
if (e != APR_SUCCESS) {
if (!APR_STATUS_IS_EAGAIN(e)) {
epipe++;
close_connection(c);
c->rwrote += l;
c->rwrite -= l;
double timetaken;
if (sig) {
#ifdef USE_SSL
if (bad)
if (err_response)
if (keepalive)
if (posting > 0)
if (posting > 0) {
if (done > 0) {
for (i = 0; i < done; i++) {
for (i = 0; i < done; i++) {
sdtot += a * a;
sdcon += a * a;
sdd += a * a;
sdwait += a * a;
(int (*) (const void *, const void *)) compradre);
(int (*) (const void *, const void *)) compri);
(int (*) (const void *, const void *)) compwait);
(int (*) (const void *, const void *)) comprando);
if (confidence) {
#define CONF_FMT_STRING "%5" APR_TIME_T_FMT " %4" APR_TIME_T_FMT " %5.1f %6" APR_TIME_T_FMT " %7" APR_TIME_T_FMT "\n"
else if (d > sd ) \
for (i = 0; i < sizeof(percs) / sizeof(int); i++) {
if (percs[i] <= 0)
if (csvperc) {
if (!out) {
if (gnuplot) {
if (!out) {
for (i = 0; i < done; i++) {
if (sig) {
static void output_html_results(void)
if (bad)
if (err_response)
if (keepalive)
if (posting > 0)
if (timetaken) {
if (posting > 0) {
for (i = 0; i < done; i++) {
c->read = 0;
c->bread = 0;
c->keepalive = 0;
c->cbx = 0;
c->gotheader = 0;
c->rwrite = 0;
if (c->ctx)
!= APR_SUCCESS) {
if (windowsize != 0) {
#ifdef USE_SSL
if (is_ssl) {
c->rwrite = 0;
err_conn++;
start_connect(c);
started++;
#ifdef USE_SSL
if (c->ssl) {
write_request(c);
if (good)
bad++;
err_length++;
#ifdef USE_SSL
if (c->ssl) {
start_connect(c);
apr_size_t r;
char *part;
r = sizeof(buffer);
#ifdef USE_SSL
if (c->ssl) {
if (status <= 0) {
good++;
close_connection(c);
c->read = 0;
close_connection(c);
r = status;
good++;
close_connection(c);
err_recv++;
if (recverrok) {
bad++;
close_connection(c);
totalread += r;
if (c->read == 0) {
c->read += r;
if (!c->gotheader) {
#ifdef NOT_ASCII
if (space) {
err_response++;
start_connect(c);
if (!good) {
q = servername;
err_response++;
if (keepalive &&
char *cl;
if (!cl)
if (cl) {
if (!cl) {
c->length = 0;
c->bread += r;
totalbread += r;
good++;
bad++;
err_length++;
doneka++;
c->keepalive = 0;
c->length = 0;
c->gotheader = 0;
c->cbx = 0;
write_request(c);
static void test(void)
int snprintf_res = 0;
#ifdef NOT_ASCII
if (isproxy) {
if (!use_html) {
if (isproxy)
if (!opt_host) {
if (!opt_useragent) {
if (!opt_accept) {
if (posting <= 0) {
if (!buff) {
#ifdef NOT_ASCII
!= APR_SUCCESS) {
#ifdef SIGINT
for (i = 0; i < concurrency; i++) {
apr_int32_t n;
n = concurrency;
struct connection *c;
#ifdef USE_SSL
read_connection(c);
bad++;
err_except++;
start_connect(c);
err_conn++;
start_connect(c);
started++;
#ifdef USE_SSL
if (c->ssl)
write_request(c);
write_request(c);
if (heartbeatres)
if (use_html)
output_results(0);
static void copyright(void)
if (!use_html) {
printf(" This is ApacheBench, Version %s <i><%s></i><br>\n", AP_AB_BASEREVISION, "$Revision$");
#ifdef USE_SSL
/* 80 column ruler: ********************************************************************************
#ifdef USE_SSL
char *cp;
char *scope_id;
#ifdef USE_SSL
is_ssl = 0;
#ifdef USE_SSL
#ifdef USE_SSL
if (is_ssl)
#ifdef USE_SSL
return rv;
if (!postdata) {
return APR_ENOMEM;
return rv;
const char *optarg;
#ifdef USE_SSL
#ifdef NOT_ASCII
if (status) {
if (status) {
if (status) {
#ifdef USE_SSL
if (requests <= 0) {
heartbeatres = 0;
percentile = 0;
confidence = 0;
if (posting != 0)
else if (postdata) {
exit(r);
optarg++;
optarg++;
copyright();
#ifdef USE_SSL
heartbeatres = 0;
#ifdef USE_SSL
#ifdef RSAREF
#ifdef SIGPIPE
copyright();
test();