ab.c revision 5e48e0ef81c0736649fd7d2884837b32ed678750
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd/* Licensed to the Apache Software Foundation (ASF) under one or more
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd * contributor license agreements. See the NOTICE file distributed with
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * this work for additional information regarding copyright ownership.
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * The ASF licenses this file to You under the Apache License, Version 2.0
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * (the "License"); you may not use this file except in compliance with
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd * the License. You may obtain a copy of the License at
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * Unless required by applicable law or agreed to in writing, software
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd * distributed under the License is distributed on an "AS IS" BASIS,
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
2e545ce2450a9953665f701bb05350f0d3f26275nd * limitations under the License.
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** This program is based on ZeusBench V1.0 written by Adam Twiss
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** This software is provided "as is" and any express or implied waranties,
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** including but not limited to, the implied warranties of merchantability and
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** fitness for a particular purpose are disclaimed. In no event shall
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd ** exemplary, or consequential damaged (including, but not limited to,
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen ** procurement of substitute good or services; loss of use, data, or profits;
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen ** or business interruption) however caused and on theory of liability. Whether
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd ** in contract, strict liability or tort (including negligence or otherwise)
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd ** arising in any way out of the use of this software, even if advised of the
4eb0f4031876c60c0ba2035666579dac07304b9drbowen ** possibility of such damage.
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** HISTORY:
4eb0f4031876c60c0ba2035666579dac07304b9drbowen ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** with input from Mike Belshe <mbelshe@netscape.com> and
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** Michael Campanella <campanella@stevms.enet.dec.com>
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Added Cookie, Arbitrary header and auth support. <dirkx@webweaving.org>, April 1999
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** Version 1.3d
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Increased version number - as some of the socket/error handling has
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** fundamentally changed - and will give fundamentally different results
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** in situations where a server is dropping requests. Therefore you can
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** no longer compare results of AB as easily. Hence the inc of the version.
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** They should be closer to the truth though. Sander & <dirkx@covalent.net>, End 2000.
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** - Fixed proxy functionality, added median/mean statistics, added gnuplot
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** output option, added _experimental/rudimentary_ SSL support. Added
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** confidence guestimators and warnings. Sander & <dirkx@covalent.net>, End 2000
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Fixed serious int overflow issues which would cause realistic (longer
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** than a few minutes) run's to have wrong (but believable) results. Added
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** trapping of connection errors which influenced measurements.
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** Contributed by Sander Temme, Early 2001
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** Version 1.3e
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** - Changed timeout behavour during write to work whilst the sockets
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** are filling up and apr_write() does writes a few - but not all.
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** This will potentially change results. <dirkx@webweaving.org>, April 2001
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** Version 2.0.36-dev
c40959d803d2d8328b2ead89dd975ac88ba946f6humbedooh ** Improvements to concurrent processing:
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Enabled non-blocking connect()s.
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** - Prevent blocking calls to apr_socket_recv() (thereby allowing AB to
4eb0f4031876c60c0ba2035666579dac07304b9drbowen ** manage its entire set of socket descriptors).
d05d0eb4ae6d2a5e513fc3bf2555ce33da416634nd ** - Any error returned from apr_socket_recv() that is not EAGAIN or EOF
d05d0eb4ae6d2a5e513fc3bf2555ce33da416634nd ** is now treated as fatal.
d05d0eb4ae6d2a5e513fc3bf2555ce33da416634nd ** Contributed by Aaron Bannert, April 24, 2002
d05d0eb4ae6d2a5e513fc3bf2555ce33da416634nd ** Version 2.0.36-2
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** Internalized the version string - this string is part
fc056b4d564cebe1d186a536e9d21fb661a2f5c5humbedooh ** of the Agent: header and the result output.
d05d0eb4ae6d2a5e513fc3bf2555ce33da416634nd ** Version 2.0.37-dev
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** Adopted SSL code by Madhu Mathihalli <madhusudan_mathihalli@hp.com>
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd ** [PATCH] ab with SSL support Posted Wed, 15 Aug 2001 20:55:06 GMT
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd ** Introduces four 'if (int == value)' tests per non-ssl request.
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen ** Version 2.0.40-dev
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd ** Switched to the new abstract pollset API, allowing ab to
205f749042ed530040a4f0080dbcb47ceae8a374rjung ** take advantage of future apr_pollset_t scalability improvements.
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen ** Contributed by Brian Pane, August 31, 2002
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ** Version 2.3
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ** SIGINT now triggers output_results().
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ** Contributed by colm, March 30, 2006
#define NOT_ASCII
#define BSD_COMP
#include "apr.h"
#include "apr_signal.h"
#include "apr_strings.h"
#include "apr_network_io.h"
#include "apr_file_io.h"
#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;
int err_response = 0;
#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;
float timetaken;
if (sig) {
#ifdef USE_SSL
if (bad)
if (err_response)
if (keepalive)
if (posting > 0)
if (timetaken) {
if (posting > 0) {
if (requests) {
for (i = 0; i < requests; i++) {
for (i = 0; i < requests; i++) {
sdtot += a * a;
sdcon += a * a;
sdd += a * a;
sdwait += a * a;
if (gnuplot) {
if (!out) {
for (i = 0; i < requests; i++) {
fprintf(out, "%s\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\t%" APR_TIME_T_FMT "\n",
diff,
(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 " %4d %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) {
apr_time_t t;
if (sig) {
static void output_html_results(void)
long timetaken;
if (bad)
if (err_response)
if (keepalive)
if (posting > 0)
if (timetaken) {
if (posting > 0) {
for (i = 0; i < requests; 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++;
struct data s;
#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++;
struct data s;
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) {
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();