ab.c revision c9c04228fc004c5ab2e739100f9d95804c28d23d
2d2eda71267231c2526be701fe655db125852c1ffielding/* ====================================================================
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * The Apache Software License, Version 1.1
f062ed7bd262a37a909dd77ce5fc23b446818823fielding *
bc8fd1b0b1afdf89b8d28eefa8cd74e26ba97986fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * reserved.
2d2eda71267231c2526be701fe655db125852c1ffielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * Redistribution and use in source and binary forms, with or without
2d2eda71267231c2526be701fe655db125852c1ffielding * modification, are permitted provided that the following conditions
2d2eda71267231c2526be701fe655db125852c1ffielding * are met:
2d2eda71267231c2526be701fe655db125852c1ffielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * 1. Redistributions of source code must retain the above copyright
2d2eda71267231c2526be701fe655db125852c1ffielding * notice, this list of conditions and the following disclaimer.
2d2eda71267231c2526be701fe655db125852c1ffielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * 2. Redistributions in binary form must reproduce the above copyright
2d2eda71267231c2526be701fe655db125852c1ffielding * notice, this list of conditions and the following disclaimer in
2d2eda71267231c2526be701fe655db125852c1ffielding * the documentation and/or other materials provided with the
2d2eda71267231c2526be701fe655db125852c1ffielding * distribution.
2d2eda71267231c2526be701fe655db125852c1ffielding *
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * 3. The end-user documentation included with the redistribution,
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * if any, must include the following acknowledgment:
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * "This product includes software developed by the
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * Apache Software Foundation (http://www.apache.org/)."
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * Alternately, this acknowledgment may appear in the software itself,
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * if and wherever such third-party acknowledgments normally appear.
2d2eda71267231c2526be701fe655db125852c1ffielding *
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * 4. The names "Apache" and "Apache Software Foundation" must
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * not be used to endorse or promote products derived from this
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * software without prior written permission. For written
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * permission, please contact apache@apache.org.
2d2eda71267231c2526be701fe655db125852c1ffielding *
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * 5. Products derived from this software may not be called "Apache",
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * nor may "Apache" appear in their name, without prior written
64185f9824e42f21ca7b9ae6c004484215c031a7rbb * permission of the Apache Software Foundation.
2d2eda71267231c2526be701fe655db125852c1ffielding *
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
2d2eda71267231c2526be701fe655db125852c1ffielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * SUCH DAMAGE.
2d2eda71267231c2526be701fe655db125852c1ffielding * ====================================================================
2d2eda71267231c2526be701fe655db125852c1ffielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * This software consists of voluntary contributions made by many
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * individuals on behalf of the Apache Software Foundation. For more
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * information on the Apache Software Foundation, please see
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * <http://www.apache.org/>.
2d2eda71267231c2526be701fe655db125852c1ffielding *
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * Portions of this software are based upon public domain software
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * originally written at the National Center for Supercomputing Applications,
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * University of Illinois, Urbana-Champaign.
2d2eda71267231c2526be701fe655db125852c1ffielding */
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding/*
2d2eda71267231c2526be701fe655db125852c1ffielding ** This program is based on ZeusBench V1.0 written by Adam Twiss
2d2eda71267231c2526be701fe655db125852c1ffielding ** which is Copyright (c) 1996 by Zeus Technology Ltd. http://www.zeustech.net/
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb **
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe ** This software is provided "as is" and any express or implied waranties,
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb ** including but not limited to, the implied warranties of merchantability and
92f3af936ce61f25358a3ee4f28df2f6d62040dfdreid ** fitness for a particular purpose are disclaimed. In no event shall
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** Zeus Technology Ltd. be liable for any direct, indirect, incidental, special,
c9a95767fbf0f5fb0976a06b97a256033925e433rbb ** exemplary, or consequential damaged (including, but not limited to,
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding ** procurement of substitute good or services; loss of use, data, or profits;
2d2eda71267231c2526be701fe655db125852c1ffielding ** or business interruption) however caused and on theory of liability. Whether
2d2eda71267231c2526be701fe655db125852c1ffielding ** in contract, strict liability or tort (including negligence or otherwise)
2d2eda71267231c2526be701fe655db125852c1ffielding ** arising in any way out of the use of this software, even if advised of the
2d2eda71267231c2526be701fe655db125852c1ffielding ** possibility of such damage.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb **
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb ** HISTORY:
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb ** - Originally written by Adam Twiss <adam@zeus.co.uk>, March 1996
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb ** with input from Mike Belshe <mbelshe@netscape.com> and
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb ** Michael Campanella <campanella@stevms.enet.dec.com>
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb ** - Enhanced by Dean Gaudet <dgaudet@apache.org>, November 1997
2d2eda71267231c2526be701fe655db125852c1ffielding ** - Cleaned up by Ralf S. Engelschall <rse@apache.org>, March 1998
2d2eda71267231c2526be701fe655db125852c1ffielding ** - POST and verbosity by Kurt Sussman <kls@merlot.com>, August 1998
2d2eda71267231c2526be701fe655db125852c1ffielding ** - HTML table output added by David N. Welton <davidw@prosa.it>, January 1999
2d2eda71267231c2526be701fe655db125852c1ffielding ** - Added Cookie, Arbitrary header and auth support. <dirkx@webweaving.org>, April 1999
2d2eda71267231c2526be701fe655db125852c1ffielding **
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * BUGS:
61fd0cab072a05b855cbef9c585702401ac5ae29rbb *
2d2eda71267231c2526be701fe655db125852c1ffielding * - uses strcpy/etc.
2d2eda71267231c2526be701fe655db125852c1ffielding * - has various other poor buffer attacks related to the lazy parsing of
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz * response headers from the server
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz * - doesn't implement much of HTTP/1.x, only accepts certain forms of
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz * responses
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz * - (performance problem) heavy use of strstr shows up top in profile
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz * only an issue for loopback usage
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz */
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb#define AB_VERSION "1.3c"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* -------------------------------------------------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#if 'A' != 0x41
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* Hmmm... This source code isn't being compiled in ASCII.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * In order for data that flows over the network to make
3d96ee83babeec32482c9082c9426340cee8c44dwrowe * sense, we need to translate to/from ASCII.
2d2eda71267231c2526be701fe655db125852c1ffielding */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define NOT_ASCII
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* affects include files on Solaris */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define BSD_COMP
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include "apr.h"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include "apr_strings.h"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include "apr_network_io.h"
2d2eda71267231c2526be701fe655db125852c1ffielding#include "apr_file_io.h"
3d96ee83babeec32482c9082c9426340cee8c44dwrowe#include "apr_time.h"
2d2eda71267231c2526be701fe655db125852c1ffielding#include "apr_getopt.h"
2d2eda71267231c2526be701fe655db125852c1ffielding#include "apr_general.h"
2d2eda71267231c2526be701fe655db125852c1ffielding#include "apr_lib.h"
2d2eda71267231c2526be701fe655db125852c1ffielding
000b67449410515eac43e76ef6667915bfd4d2abgstein#if APR_HAVE_STDIO_H
2d2eda71267231c2526be701fe655db125852c1ffielding#include <stdio.h> /* for EOF */
2d2eda71267231c2526be701fe655db125852c1ffielding#endif
2d2eda71267231c2526be701fe655db125852c1ffielding#if APR_HAVE_STDLIB_H
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include <stdlib.h>
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include "ap_base64.h"
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein#ifdef NOT_ASCII
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include "apr_xlate.h"
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein#endif
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein#if APR_HAVE_STRING_H
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include <string.h>
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#if APR_HAVE_STDIO_H
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include <stdio.h>
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#if APR_HAVE_STDLIB_H
3d96ee83babeec32482c9082c9426340cee8c44dwrowe#include <stdlib.h>
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#if APR_HAVE_CTYPE_H
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#include <ctype.h>
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* ------------------- DEFINITIONS -------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* maximum number of requests on a time limited test */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define MAX_REQUESTS 50000
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein/* good old state hostname */
c9a95767fbf0f5fb0976a06b97a256033925e433rbb#define STATE_UNCONNECTED 0
c9a95767fbf0f5fb0976a06b97a256033925e433rbb#define STATE_CONNECTING 1
c9a95767fbf0f5fb0976a06b97a256033925e433rbb#define STATE_READ 2
c9a95767fbf0f5fb0976a06b97a256033925e433rbb
c9a95767fbf0f5fb0976a06b97a256033925e433rbb#define CBUFFSIZE 2048
c9a95767fbf0f5fb0976a06b97a256033925e433rbb
c9a95767fbf0f5fb0976a06b97a256033925e433rbbstruct connection {
c9a95767fbf0f5fb0976a06b97a256033925e433rbb apr_socket_t *aprsock;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb int state;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb int read; /* amount of bytes read */
c9a95767fbf0f5fb0976a06b97a256033925e433rbb int bread; /* amount of body read */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp int length; /* Content-Length value used for keep-alive */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp char cbuff[CBUFFSIZE]; /* a buffer to store server response header */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp int cbx; /* offset in cbuffer */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp int keepalive; /* non-zero if a keep-alive request */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp int gotheader; /* non-zero if we have the entire header in
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp * cbuff */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp apr_time_t start, connect, done;
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp int socknum;
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp};
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianpstruct data {
c9a95767fbf0f5fb0976a06b97a256033925e433rbb int read; /* number of bytes read */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int ctime; /* time in ms to connect */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int time; /* time in ms for connection */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb};
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define ap_min(a,b) ((a)<(b))?(a):(b)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#define ap_max(a,b) ((a)>(b))?(a):(b)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* --------------------- GLOBALS ---------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
3d96ee83babeec32482c9082c9426340cee8c44dwroweint verbosity = 0; /* no verbosity by default */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgsteinint posting = 0; /* GET by default */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint requests = 1; /* Number of requests to make */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint concurrency = 1; /* Number of multiple requests to make */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint tlimit = 0; /* time limit in cs */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint keepalive = 0; /* try and do keepalive connections */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar servername[1024]; /* name that server reports */
3d96ee83babeec32482c9082c9426340cee8c44dwrowechar *hostname; /* host name from URL */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgsteinchar *host_field; /* value of "Host:" header field */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar path[1024]; /* path name */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar postfile[1024]; /* name of file containing post data */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar *postdata; /* *buffer containing data from postfile */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_size_t postlen = 0; /* length of data to be POSTed */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar content_type[1024]; /* content type to put in POST header */
3d96ee83babeec32482c9082c9426340cee8c44dwrowechar cookie[1024], /* optional cookie line */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein auth[1024], /* optional (basic/uuencoded)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * authentification */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb hdrs[4096]; /* optional arbitrary headers */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_port_t port; /* port number */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_time_t aprtimeout = 30 * APR_USEC_PER_SEC; /* timeout value */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint use_html = 0; /* use html in the report */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbconst char *tablestring;
61fd0cab072a05b855cbef9c585702401ac5ae29rbbconst char *trstring;
3d96ee83babeec32482c9082c9426340cee8c44dwroweconst char *tdstring;
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffieldingint doclen = 0; /* the length the document should be */
2d2eda71267231c2526be701fe655db125852c1ffieldingint totalread = 0; /* total number of bytes read */
2d2eda71267231c2526be701fe655db125852c1ffieldingint totalbread = 0; /* totoal amount of entity body read */
2d2eda71267231c2526be701fe655db125852c1ffieldingint totalposted = 0; /* total number of bytes posted, inc. headers */
2d2eda71267231c2526be701fe655db125852c1ffieldingint done = 0; /* number of requests we have done */
2d2eda71267231c2526be701fe655db125852c1ffieldingint doneka = 0; /* number of keep alive connections done */
2d2eda71267231c2526be701fe655db125852c1ffieldingint started = 0; /* number of requests started, so no excess */
2d2eda71267231c2526be701fe655db125852c1ffieldingint good = 0, bad = 0; /* number of good and bad requests */
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding/* store error cases */
2d2eda71267231c2526be701fe655db125852c1ffieldingint err_length = 0, err_conn = 0, err_except = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbbint err_response = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_time_t start, endtime;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* global request (and its length) */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar request[512];
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_size_t reqlen;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* one global throw-away buffer to read stuff into */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbchar buffer[8192];
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstruct connection *con; /* connection array */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgsteinstruct data *stats; /* date for each request */
23ff73a56371e21f16744cb94d06399b877829f1rbbapr_pool_t *cntxt;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_pollfd_t *readbits;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#ifdef NOT_ASCII
61fd0cab072a05b855cbef9c585702401ac5ae29rbbapr_xlate_t *from_ascii, *to_ascii;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* --------------------------------------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
3d96ee83babeec32482c9082c9426340cee8c44dwrowe/* simple little function to write an error string and exit */
2d2eda71267231c2526be701fe655db125852c1ffielding
23ff73a56371e21f16744cb94d06399b877829f1rbbstatic void err(char *s)
2d2eda71267231c2526be701fe655db125852c1ffielding{
62db15de4c1f335a64d45821796ae197cff94ef8rbb fprintf(stderr, "%s", s);
62db15de4c1f335a64d45821796ae197cff94ef8rbb exit(1);
62db15de4c1f335a64d45821796ae197cff94ef8rbb}
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbb/* simple little function to write an APR error string and exit */
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbbstatic void apr_err(char *s, apr_status_t rv)
62db15de4c1f335a64d45821796ae197cff94ef8rbb{
62db15de4c1f335a64d45821796ae197cff94ef8rbb char buf[120];
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbb fprintf(stderr,
62db15de4c1f335a64d45821796ae197cff94ef8rbb "%s: %s (%d)\n",
62db15de4c1f335a64d45821796ae197cff94ef8rbb s, apr_strerror(rv, buf, sizeof buf), rv);
62db15de4c1f335a64d45821796ae197cff94ef8rbb exit(rv);
62db15de4c1f335a64d45821796ae197cff94ef8rbb}
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbb/* --------------------------------------------------------- */
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbb/* write out request to a connection - assumes we can write
62db15de4c1f335a64d45821796ae197cff94ef8rbb (small) request out in one go into our new socket buffer */
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbbstatic void write_request(struct connection *c)
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb{
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb apr_size_t len = reqlen;
62db15de4c1f335a64d45821796ae197cff94ef8rbb c->connect = apr_now();
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar apr_setsocketopt(c->aprsock, APR_SO_TIMEOUT, aprtimeout);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (apr_send(c->aprsock, request, &reqlen) != APR_SUCCESS ||
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar reqlen != len) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Send request failed!\n");
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (posting) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar apr_send(c->aprsock, postdata, &postlen);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar totalposted += (reqlen + postlen);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
3d96ee83babeec32482c9082c9426340cee8c44dwrowe c->state = STATE_READ;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe apr_add_poll_socket(readbits, c->aprsock, APR_POLLIN);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar}
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick/* --------------------------------------------------------- */
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick/* calculate and output results */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coarstatic void output_results(void)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar{
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar int timetaken;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar endtime = apr_now();
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar timetaken = (endtime - start) / 1000;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("\r \r");
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Server Software: %s\n", servername);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Server Hostname: %s\n", hostname);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Server Port: %hd\n", port);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("\n");
3d96ee83babeec32482c9082c9426340cee8c44dwrowe printf("Document Path: %s\n", path);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Document Length: %d bytes\n", doclen);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("\n");
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Concurrency Level: %d\n", concurrency);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Time taken for tests: %d.%03d seconds\n",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar timetaken / 1000, timetaken % 1000);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Complete requests: %d\n", done);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Failed requests: %d\n", bad);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (bad)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf(" (Connect: %d, Length: %d, Exceptions: %d)\n",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar err_conn, err_length, err_except);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (err_response)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Non-2xx responses: %d\n", err_response);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (keepalive)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Keep-Alive requests: %d\n", doneka);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Total transferred: %d bytes\n", totalread);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (posting)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Total POSTed: %d\n", totalposted);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("HTML transferred: %d bytes\n", totalbread);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /* avoid divide by zero */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (timetaken) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf("Transfer rate: %.2f kb/s received\n",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar (float) (totalread) / timetaken);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (posting>0) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf(" %.2f kb/s sent\n",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar (float) (totalposted) / timetaken);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar printf(" %.2f kb/s total\n",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar (float) (totalread + totalposted) / timetaken);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
2864362ca8266097928e84f101010bdf814ffa08stoddard {
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard /* work out connection times */
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard int i;
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard int totalcon = 0, total = 0;
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard int mincon = 9999999, mintot = 999999;
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard int maxcon = 0, maxtot = 0;
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard for (i = 0; i < requests; i++) {
2864362ca8266097928e84f101010bdf814ffa08stoddard struct data s = stats[i];
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard mincon = ap_min(mincon, s.ctime);
2864362ca8266097928e84f101010bdf814ffa08stoddard mintot = ap_min(mintot, s.time);
2d2eda71267231c2526be701fe655db125852c1ffielding maxcon = ap_max(maxcon, s.ctime);
2d2eda71267231c2526be701fe655db125852c1ffielding maxtot = ap_max(maxtot, s.time);
2d2eda71267231c2526be701fe655db125852c1ffielding totalcon += s.ctime;
2d2eda71267231c2526be701fe655db125852c1ffielding total += s.time;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (requests > 0) { /* avoid division by zero (if 0 requests) */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("\nConnnection Times (ms)\n");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf(" min avg max\n");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("Processing: %5d %5d %5d\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb mintot - mincon, (total / requests) - (totalcon / requests),
3d96ee83babeec32482c9082c9426340cee8c44dwrowe maxtot - maxcon);
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* --------------------------------------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* calculate and output results in HTML */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgsteinstatic void output_html_results(void)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int timetaken;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb endtime = apr_now();
61fd0cab072a05b855cbef9c585702401ac5ae29rbb timetaken = (endtime - start) / 1000;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("\n\n<table %s>\n", tablestring);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Server Software:</th>"
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "<td colspan=2 %s>%s</td></tr>\n",
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein trstring, tdstring, tdstring, servername);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Server Hostname:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%s</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, hostname);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Server Port:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%hd</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, port);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Document Path:</th>"
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "<td colspan=2 %s>%s</td></tr>\n",
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein trstring, tdstring, tdstring, path);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Document Length:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d bytes</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, doclen);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Concurrency Level:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, concurrency);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Time taken for tests:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d.%03d seconds</td></tr>\n",
3d96ee83babeec32482c9082c9426340cee8c44dwrowe trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000);
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein printf("<tr %s><th colspan=2 %s>Complete requests:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, done);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Failed requests:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, bad);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (bad)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><td colspan=4 %s > (Connect: %d, Length: %d, Exceptions: %d)</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, err_conn, err_length, err_except);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (err_response)
2d2eda71267231c2526be701fe655db125852c1ffielding printf("<tr %s><th colspan=2 %s>Non-2xx responses:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, err_response);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (keepalive)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Keep-Alive requests:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, doneka);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe printf("<tr %s><th colspan=2 %s>Total transferred:</th>"
2d2eda71267231c2526be701fe655db125852c1ffielding "<td colspan=2 %s>%d bytes</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, totalread);
2d2eda71267231c2526be701fe655db125852c1ffielding if (posting>0)
2d2eda71267231c2526be701fe655db125852c1ffielding printf("<tr %s><th colspan=2 %s>Total POSTed:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, totalposted);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>HTML transferred:</th>"
2d2eda71267231c2526be701fe655db125852c1ffielding "<td colspan=2 %s>%d bytes</td></tr>\n",
3d96ee83babeec32482c9082c9426340cee8c44dwrowe trstring, tdstring, tdstring, totalbread);
2d2eda71267231c2526be701fe655db125852c1ffielding
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* avoid divide by zero */
d839a9822ee53ce00da24c15f2d9fe054233d342gstein if (timetaken) {
d839a9822ee53ce00da24c15f2d9fe054233d342gstein printf("<tr %s><th colspan=2 %s>Requests per second:</th>"
d839a9822ee53ce00da24c15f2d9fe054233d342gstein "<td colspan=2 %s>%.2f</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th colspan=2 %s>Transfer rate:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%.2f kb/s received</td></tr>\n",
d839a9822ee53ce00da24c15f2d9fe054233d342gstein trstring, tdstring, tdstring, (float) (totalread) / timetaken);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (posting>0) {
d839a9822ee53ce00da24c15f2d9fe054233d342gstein printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
2d2eda71267231c2526be701fe655db125852c1ffielding "<td colspan=2 %s>%.2f kb/s sent</td></tr>\n",
2d2eda71267231c2526be701fe655db125852c1ffielding trstring, tdstring, tdstring,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb (float) (totalposted) / timetaken);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><td colspan=2 %s>&nbsp;</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td colspan=2 %s>%.2f kb/s total</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring,
346029f34d03eb20d84fc35664426d3874b00f9ewrowe (float) (totalread + totalposted) / timetaken);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
346029f34d03eb20d84fc35664426d3874b00f9ewrowe {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* work out connection times */
eda25307d712abd132e100e2b40ae1de5497d3e2trawick int i;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int totalcon = 0, total = 0;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe int mincon = 9999999, mintot = 999999;
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein int maxcon = 0, maxtot = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb for (i = 0; i < requests; i++) {
face099b681c052cb1f52176a5499661c44b2982trawick struct data s = stats[i];
61fd0cab072a05b855cbef9c585702401ac5ae29rbb mincon = ap_min(mincon, s.ctime);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb mintot = ap_min(mintot, s.time);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb maxcon = ap_max(maxcon, s.ctime);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb maxtot = ap_max(maxtot, s.time);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb totalcon += s.ctime;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb total += s.time;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (requests > 0) { /* avoid division by zero (if 0 requests) */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th %s colspan=4>Connnection Times (ms)</th></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th %s>&nbsp;</th> <th %s>min</th> <th %s>avg</th> <th %s>max</th></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, tdstring, tdstring);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th %s>Connect:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td>"
11a7b0dff22d26770b532c174d1cf2e7b56ec244wrowe "<td %s>%5d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon);
11a7b0dff22d26770b532c174d1cf2e7b56ec244wrowe printf("<tr %s><th %s>Processing:</th>"
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "<td %s>%5d</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, mintot - mincon, tdstring,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("<tr %s><th %s>Total:</th>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td>"
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<td %s>%5d</td></tr>\n",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("</table>\n");
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
2d2eda71267231c2526be701fe655db125852c1ffielding}
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* --------------------------------------------------------- */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* start asnchronous non-blocking connection */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic void start_connect(struct connection *c)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_status_t rv;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe apr_sockaddr_t *destsa;
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if(!(started < requests)) return;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->read = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->bread = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->keepalive = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->cbx = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->gotheader = 0;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein if ((rv = apr_getaddrinfo(&destsa, hostname, APR_UNSPEC, port, 0, cntxt))
61fd0cab072a05b855cbef9c585702401ac5ae29rbb != APR_SUCCESS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb char buf[120];
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_snprintf(buf, sizeof(buf),
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "apr_getaddrinfo() for %s", hostname);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_err(buf, rv);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if ((rv = apr_create_socket(&c->aprsock, destsa->sa.sin.sin_family,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein SOCK_STREAM, cntxt)) != APR_SUCCESS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_err("socket", rv);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->start = apr_now();
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((rv = apr_connect(c->aprsock, destsa)) != APR_SUCCESS) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (APR_STATUS_IS_EINPROGRESS(rv)) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->state = STATE_CONNECTING;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_add_poll_socket(readbits, c->aprsock, APR_POLLOUT);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb else {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_remove_poll_socket(readbits, c->aprsock);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_close_socket(c->aprsock);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb err_conn++;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (bad++ > 10) {
2d2eda71267231c2526be701fe655db125852c1ffielding fprintf(stderr,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "\nTest aborted after 10 failures\n\n");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_err("apr_connect()", rv);
346029f34d03eb20d84fc35664426d3874b00f9ewrowe }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->state = STATE_UNCONNECTED;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb start_connect(c);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return;
346029f34d03eb20d84fc35664426d3874b00f9ewrowe }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* connected first time */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb started++;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe write_request(c);
2d2eda71267231c2526be701fe655db125852c1ffielding}
fd8b91502bc200ed4cca3810560a2a570522b3debrianp
fd8b91502bc200ed4cca3810560a2a570522b3debrianp/* --------------------------------------------------------- */
fd8b91502bc200ed4cca3810560a2a570522b3debrianp
fd8b91502bc200ed4cca3810560a2a570522b3debrianp/* close down connection and save stats */
fd8b91502bc200ed4cca3810560a2a570522b3debrianp
fd8b91502bc200ed4cca3810560a2a570522b3debrianpstatic void close_connection(struct connection *c)
fd8b91502bc200ed4cca3810560a2a570522b3debrianp{
fd8b91502bc200ed4cca3810560a2a570522b3debrianp if (c->read == 0 && c->keepalive) {
fd8b91502bc200ed4cca3810560a2a570522b3debrianp /* server has legitimately shut down an idle keep alive request */
fd8b91502bc200ed4cca3810560a2a570522b3debrianp if (good) good--; /* connection never happened */
fd8b91502bc200ed4cca3810560a2a570522b3debrianp }
aa4af3da5c68fe5dbd9d2c3fd7b2fe7103daa2b7dougm else {
e351a4349a3dcc2e8d9c27bcdf72414bdde0942frbb if (good == 1) {
fd8b91502bc200ed4cca3810560a2a570522b3debrianp /* first time here */
fd8b91502bc200ed4cca3810560a2a570522b3debrianp doclen = c->bread;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames }
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames else if (c->bread != doclen) {
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames bad ++;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames err_length++;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames }
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames /* save out time */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames if (done < requests) {
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames struct data s;
fd8b91502bc200ed4cca3810560a2a570522b3debrianp c->done = apr_now();
fd8b91502bc200ed4cca3810560a2a570522b3debrianp s.read = c->read;
fd8b91502bc200ed4cca3810560a2a570522b3debrianp s.ctime = (c->connect - c->start) / 1000;
fd8b91502bc200ed4cca3810560a2a570522b3debrianp s.time = (c->done - c->start) / 1000;
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz stats[done++] = s;
fd8b91502bc200ed4cca3810560a2a570522b3debrianp }
fd8b91502bc200ed4cca3810560a2a570522b3debrianp }
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz apr_remove_poll_socket(readbits, c->aprsock);
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz apr_close_socket(c->aprsock);
fd8b91502bc200ed4cca3810560a2a570522b3debrianp c->state = STATE_UNCONNECTED;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames /* connect again */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames start_connect(c);
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz return;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames}
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames/* --------------------------------------------------------- */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames/* read data from connection */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregamesstatic void read_connection(struct connection *c)
5a9667916c79d8c699b069068e5570aa1c331c80gstein{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_size_t r;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_status_t status;
2d2eda71267231c2526be701fe655db125852c1ffielding char *part;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb char respcode[4]; /* 3 digits and null */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
2d2eda71267231c2526be701fe655db125852c1ffielding r = sizeof(buffer);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe apr_setsocketopt(c->aprsock, APR_SO_TIMEOUT, aprtimeout);
2d2eda71267231c2526be701fe655db125852c1ffielding status = apr_recv(c->aprsock, buffer, &r);
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar if (r == 0 || (status != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(status))) {
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar good++;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar close_connection(c);
5a9667916c79d8c699b069068e5570aa1c331c80gstein return;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar }
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar if (APR_STATUS_IS_EAGAIN(status))
5a9667916c79d8c699b069068e5570aa1c331c80gstein return;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar
d5df46b7972c0c4a5ca0ba5068e238f6053c2e6ftrawick c->read += r;
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding totalread += r;
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding if (!c->gotheader) {
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding char *s;
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding int l = 4;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int space = CBUFFSIZE - c->cbx - 1; /* -1 to allow for 0 terminator */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int tocopy = (space < r) ? space : r;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#ifdef NOT_ASCII
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_size_t inbytes_left = space, outbytes_left = space;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb status = apr_xlate_conv_buffer(from_ascii, buffer, &inbytes_left,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->cbuff + c->cbx, &outbytes_left);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (status || inbytes_left || outbytes_left) {
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n",
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein status, inbytes_left, outbytes_left);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb exit(1);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#else
61fd0cab072a05b855cbef9c585702401ac5ae29rbb memcpy(c->cbuff + c->cbx, buffer, space);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#endif /*NOT_ASCII */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb c->cbx += tocopy;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb space -= tocopy;
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm c->cbuff[c->cbx] = 0; /* terminate for benefit of strstr */
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein if (verbosity >= 4) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb printf("LOG: header received:\n%s\n", c->cbuff);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb s = strstr(c->cbuff, "\r\n\r\n");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* this next line is so that we talk to NCSA 1.5 which blatantly
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * breaks the http specifaction
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!s) {
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm s = strstr(c->cbuff, "\n\n");
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein l = 2;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (!s) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* read rest next time */
dad234382d8424e1c5a30af2838e172aec9d6d1bdreid if (space) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return;
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm }
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding else {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* header is in invalid or too big - close connection */
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein apr_remove_poll_socket(readbits, c->aprsock);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb apr_close_socket(c->aprsock);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb err_response++;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (bad++ > 10) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb err("\nTest aborted after 10 failures\n\n");
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb start_connect(c);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
8b7047e519340545e6807c9749576a40a76b6d3frbb else {
8b7047e519340545e6807c9749576a40a76b6d3frbb /* have full header */
8b7047e519340545e6807c9749576a40a76b6d3frbb if (!good) {
6d00a43be9ab145c89e8cc22bad59e3aa746f761jwoolley /* this is first time, extract some interesting info */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb char *p, *q;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb p = strstr(c->cbuff, "Server:");
9484ae61c7cc5fa8d8d9a836efdbdb1e88d3036dwrowe q = servername;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (p) {
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz p += 8;
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz while (*p > 32)
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz *q++ = *p++;
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz }
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz *q = 0;
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz }
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* XXX: this parsing isn't even remotely HTTP compliant...
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * but in the interest of speed it doesn't totally have to be,
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * it just needs to be extended to handle whatever servers
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * folks want to test against. -djg */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* check response code */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb part = strstr(c->cbuff, "HTTP"); /* really HTTP/1.x_ */
561e5f16a2f9fb397aac4c283aaa87a752520a4ddougm strncpy(respcode, (part + strlen("HTTP/1.x_")), 3);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb respcode[3] = '\0';
561e5f16a2f9fb397aac4c283aaa87a752520a4ddougm if (respcode[0] != '2') {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb err_response++;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (verbosity >= 2)
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb printf("WARNING: Response code not 2xx (%s)\n", respcode);
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb else if (verbosity >= 3) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb printf("LOG: Response code = %s\n", respcode);
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley }
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb c->gotheader = 1;
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley *s = 0; /* terminate at end of header */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (keepalive &&
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley (strstr(c->cbuff, "Keep-Alive")
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley || strstr(c->cbuff, "keep-alive"))) { /* for benefit of MSIIS */
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley char *cl;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb cl = strstr(c->cbuff, "Content-Length:");
c9a95767fbf0f5fb0976a06b97a256033925e433rbb /* handle NCSA, which sends Content-length: */
c9a95767fbf0f5fb0976a06b97a256033925e433rbb if (!cl)
c9a95767fbf0f5fb0976a06b97a256033925e433rbb cl = strstr(c->cbuff, "Content-length:");
c9a95767fbf0f5fb0976a06b97a256033925e433rbb if (cl) {
c9a95767fbf0f5fb0976a06b97a256033925e433rbb c->keepalive = 1;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb c->length = atoi(cl + 16);
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb c->bread += c->cbx - (s + l - c->cbuff) + r - tocopy;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb totalbread += c->bread;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb else {
2d2eda71267231c2526be701fe655db125852c1ffielding /* outside header, everything we have read is entity body */
2d2eda71267231c2526be701fe655db125852c1ffielding c->bread += r;
2d2eda71267231c2526be701fe655db125852c1ffielding totalbread += r;
2d2eda71267231c2526be701fe655db125852c1ffielding }
2d2eda71267231c2526be701fe655db125852c1ffielding
if (c->keepalive && (c->bread >= c->length)) {
/* finished a keep-alive connection */
good++;
doneka++;
/* save out time */
if (good == 1) {
/* first time here */
doclen = c->bread;
}
else if (c->bread != doclen) {
bad++;
err_length++;
}
if (done < requests) {
struct data s;
c->done = apr_now();
s.read = c->read;
s.ctime = (c->connect - c->start) / 1000;
s.time = (c->done - c->start) / 1000;
stats[done++] = s;
}
c->keepalive = 0;
c->length = 0;
c->gotheader = 0;
c->cbx = 0;
c->read = c->bread = 0;
write_request(c);
c->start = c->connect; /* zero connect time with keep-alive */
}
}
/* --------------------------------------------------------- */
/* run the tests */
static void test(void)
{
apr_time_t now;
apr_int16_t rv;
int i;
apr_status_t status;
#ifdef NOT_ASCII
apr_size_t inbytes_left, outbytes_left;
#endif
if (!use_html) {
printf("Benchmarking %s (be patient)...", hostname);
fflush(stdout);
}
now = apr_now();
con = malloc(concurrency * sizeof(struct connection));
memset(con, 0, concurrency * sizeof(struct connection));
stats = malloc(requests * sizeof(struct data));
apr_setup_poll(&readbits, concurrency, cntxt);
/* setup request */
if (!posting) {
sprintf(request, "%s %s HTTP/1.0\r\n"
"User-Agent: ApacheBench/%s\r\n"
"%s" "%s" "%s"
"Host: %s\r\n"
"Accept: */*\r\n"
"%s" "\r\n",
(posting == 0) ? "GET" : "HEAD",
path,
AB_VERSION,
keepalive ? "Connection: Keep-Alive\r\n" : "",
cookie, auth, host_field, hdrs);
}
else {
sprintf(request, "POST %s HTTP/1.0\r\n"
"User-Agent: ApacheBench/%s\r\n"
"%s" "%s" "%s"
"Host: %s\r\n"
"Accept: */*\r\n"
"Content-length: %" APR_SIZE_T_FMT "\r\n"
"Content-type: %s\r\n"
"%s"
"\r\n",
path,
AB_VERSION,
keepalive ? "Connection: Keep-Alive\r\n" : "",
cookie, auth,
host_field, postlen,
(content_type[0]) ? content_type : "text/plain", hdrs);
}
if (verbosity >= 2)
printf("INFO: POST header == \n---\n%s\n---\n", request);
reqlen = strlen(request);
#ifdef NOT_ASCII
inbytes_left = outbytes_left = reqlen;
status = apr_xlate_conv_buffer(to_ascii, request, &inbytes_left,
request, &outbytes_left);
if (status || inbytes_left || outbytes_left) {
fprintf(stderr, "only simple translation is supported (%d/%u/%u)\n",
status, inbytes_left, outbytes_left);
exit(1);
}
#endif /*NOT_ASCII*/
/* ok - lets start */
start = apr_now();
/* initialise lots of requests */
for (i = 0; i < concurrency; i++) {
con[i].socknum = i;
start_connect(&con[i]);
}
while (done < requests) {
apr_int32_t n;
apr_int32_t timed;
/* check for time limit expiry */
now = apr_now();
timed = (now - start) / APR_USEC_PER_SEC;
if (tlimit && timed > (tlimit * 1000)) {
requests = done; /* so stats are correct */
}
n = concurrency;
status = apr_poll(readbits, &n, aprtimeout);
if (status != APR_SUCCESS)
apr_err("apr_poll", status);
if (!n) {
err("\nServer timed out\n\n");
}
for (i = 0; i < concurrency; i++) {
/* If the connection isn't connected how can we check it?
*/
if (con[i].state == STATE_UNCONNECTED)
continue;
apr_get_revents(&rv, con[i].aprsock, readbits);
/* Notes: APR_POLLHUP is set after FIN is received on some
* systems, so treat that like APR_POLLIN so that we try
* to read again.
*
* Some systems return APR_POLLERR with APR_POLLHUP. We
* need to call read_connection() for APR_POLLHUP, so
* check for APR_POLLHUP first so that a closed connection
* isn't treated like an I/O error. If it is, we never
* figure out that the connection is done and we loop
* here endlessly calling apr_poll().
*/
if ((rv & APR_POLLIN) || (rv & APR_POLLPRI) || (rv & APR_POLLHUP))
read_connection(&con[i]);
if ((rv & APR_POLLERR) || (rv & APR_POLLNVAL)) {
bad++;
err_except++;
start_connect(&con[i]);
continue;
}
if (rv & APR_POLLOUT)
write_request(&con[i]);
/* When using a select based poll every time we check the bits
* are reset. In 1.3's ab we copied the FD_SET's each time through,
* but here we're going to check the state and if the connection
* is in STATE_READ or STATE_CONNECTING we'll add the socket back
* in as APR_POLLIN.
*/
if (con[i].state == STATE_READ || con[i].state == STATE_CONNECTING)
apr_add_poll_socket(readbits, con[i].aprsock, APR_POLLIN);
}
}
if (use_html)
output_html_results();
else
output_results();
}
/* ------------------------------------------------------- */
/* display copyright information */
static void copyright(void)
{
if (!use_html) {
printf("This is ApacheBench, Version %s\n", AB_VERSION " <$Revision: 1.50 $> apache-2.0");
printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n");
printf("Copyright (c) 1998-2000 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> apache-2.0<br>\n", AB_VERSION, "$Revision: 1.50 $");
printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br>\n");
printf(" Copyright (c) 1998-2000 The Apache Software Foundation, http://www.apache.org/<br>\n");
printf("</p>\n<p>\n");
}
}
/* display usage information */
static void usage(const char *progname)
{
fprintf(stderr, "Usage: %s [options] [http://]hostname[:port]/path\n", progname);
fprintf(stderr, "Options are:\n");
fprintf(stderr, " -n requests Number of requests to perform\n");
fprintf(stderr, " -c concurrency Number of multiple requests to make\n");
fprintf(stderr, " -t timelimit Seconds to max. wait for responses\n");
fprintf(stderr, " -p postfile File containg data to POST\n");
fprintf(stderr, " -T content-type Content-type header for POSTing\n");
fprintf(stderr, " -v verbosity How much troubleshooting info to print\n");
fprintf(stderr, " -w Print out results in HTML tables\n");
fprintf(stderr, " -i Use HEAD instead of GET\n");
fprintf(stderr, " -x attributes String to insert as table attributes\n");
fprintf(stderr, " -y attributes String to insert as tr attributes\n");
fprintf(stderr, " -z attributes String to insert as td or th attributes\n");
fprintf(stderr, " -C attribute Add cookie, eg. 'Apache=1234. (repeatable)\n");
fprintf(stderr, " -H attribute Add Arbitrary header line, eg. 'Accept-Encoding: zop'\n");
fprintf(stderr, " Inserted after all normal header lines. (repeatable)\n");
fprintf(stderr, " -A attribute Add Basic WWW Authentication, the attributes\n");
fprintf(stderr, " are a colon separated username and password.\n");
fprintf(stderr, " -p attribute Add Basic Proxy Authentication, the attributes\n");
fprintf(stderr, " are a colon separated username and password.\n");
fprintf(stderr, " -V Print version number and exit\n");
fprintf(stderr, " -k Use HTTP KeepAlive feature\n");
fprintf(stderr, " -h Display usage information (this message)\n");
exit(EINVAL);
}
/* ------------------------------------------------------- */
/* split URL into parts */
static int parse_url(char *url)
{
char *cp;
char *h;
char *scope_id;
apr_status_t rv;
if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0)
url += 7;
if ((cp = strchr(url, '/')) == NULL)
return 1;
h = apr_palloc(cntxt, cp - url + 1);
memcpy(h, url, cp - url);
h[cp - url] = '\0';
rv = apr_parse_addr_port(&hostname, &scope_id, &port, h, cntxt);
if (rv != APR_SUCCESS || !hostname || scope_id) {
return 1;
}
strcpy(path, cp);
*cp = '\0';
if (*url == '[') { /* IPv6 numeric address string */
host_field = apr_psprintf(cntxt, "[%s]", hostname);
}
else {
host_field = hostname;
}
if (port == 0) { /* no port specified */
port = 80;
}
return 0;
}
/* ------------------------------------------------------- */
/* read data to POST from file, save contents and length */
static int open_postfile(const char *pfile)
{
apr_file_t *postfd = NULL;
apr_finfo_t finfo;
apr_fileperms_t mode = APR_OS_DEFAULT;
apr_size_t length;
apr_status_t rv;
char errmsg[120];
rv = apr_open(&postfd, pfile, APR_READ, mode, cntxt);
if (rv != APR_SUCCESS) {
printf("Invalid postfile name (%s): %s\n", pfile,
apr_strerror(rv, errmsg, sizeof errmsg));
return rv;
}
apr_getfileinfo(&finfo, postfd);
postlen = finfo.size;
postdata = (char *)malloc(postlen);
if (!postdata) {
printf("Can\'t alloc postfile buffer\n");
return APR_ENOMEM;
}
length = postlen;
rv = apr_read(postfd, postdata, &length);
if (rv != APR_SUCCESS) {
printf("error reading postfile: %s\n",
apr_strerror(rv, errmsg, sizeof errmsg));
return rv;
}
if (length != postlen) {
printf("error reading postfile: read only %"
APR_SIZE_T_FMT " bytes",
length);
return APR_EINVAL;
}
return 0;
}
/* ------------------------------------------------------- */
/* sort out command-line args and call test */
int main(int argc, const char * const argv[])
{
int r, l;
char tmp[1024];
apr_status_t status;
apr_getopt_t *opt;
const char *optarg;
char c;
/* table defaults */
tablestring = "";
trstring = "";
tdstring = "bgcolor=white";
cookie[0] = '\0';
auth[0] = '\0';
hdrs[0] = '\0';
apr_initialize();
atexit(apr_terminate);
apr_create_pool(&cntxt, NULL);
#ifdef NOT_ASCII
status = apr_xlate_open(&to_ascii, "ISO8859-1", APR_DEFAULT_CHARSET, cntxt);
if (status) {
fprintf(stderr, "apr_xlate_open(to ASCII)->%d\n", status);
exit(1);
}
status = apr_xlate_open(&from_ascii, APR_DEFAULT_CHARSET, "ISO8859-1", cntxt);
if (status) {
fprintf(stderr, "apr_xlate_open(from ASCII)->%d\n", status);
exit(1);
}
status = ap_base64init_ebcdic(to_ascii, from_ascii);
if (status) {
fprintf(stderr, "ap_base64init_ebcdic()->%d\n", status);
exit(1);
}
#endif
apr_initopt(&opt, cntxt, argc, argv);
while ((status = apr_getopt(opt, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:", &c, &optarg)) == APR_SUCCESS) {
switch (c) {
case 'n':
requests = atoi(optarg);
if (!requests) {
err("Invalid number of requests\n");
}
break;
case 'k':
keepalive = 1;
break;
case 'c':
concurrency = atoi(optarg);
break;
case 'i':
if (posting == 1)
err("Cannot mix POST and HEAD\n");
posting = -1;
break;
case 'p':
if (posting != 0)
err("Cannot mix POST and HEAD\n");
if (0 == (r = open_postfile(optarg))) {
posting = 1;
}
else if (postdata) {
exit(r);
}
break;
case 'v':
verbosity = atoi(optarg);
break;
case 't':
tlimit = atoi(optarg);
requests = MAX_REQUESTS; /* need to size data array on something */
break;
case 'T':
strcpy(content_type, optarg);
break;
case 'C':
strncat(cookie, "Cookie: ", sizeof(cookie));
strncat(cookie, optarg, sizeof(cookie));
strncat(cookie, "\r\n", sizeof(cookie));
break;
case 'A':
/* assume username passwd already to be in colon separated form.
* Ready to be uu-encoded.
*/
while(apr_isspace(*optarg))
optarg++;
l=ap_base64encode(tmp, optarg, strlen(optarg));
tmp[l]='\0';
strncat(auth, "Authorization: basic ", sizeof(auth));
strncat(auth, tmp, sizeof(auth));
strncat(auth, "\r\n", sizeof(auth));
break;
case 'P':
/*
* assume username passwd already to be in colon separated form.
*/
while(apr_isspace(*optarg))
optarg++;
l=ap_base64encode(tmp, optarg, strlen(optarg));
tmp[l]='\0';
strncat(auth, "Proxy-Authorization: basic ", sizeof(auth));
strncat(auth, tmp, sizeof(auth));
strncat(auth, "\r\n", sizeof(auth));
break;
case 'H':
strncat(hdrs, optarg, sizeof(hdrs));
strncat(hdrs, "\r\n", sizeof(hdrs));
break;
case 'w':
use_html = 1;
break;
/*
* if any of the following three are used, turn on html output
* automatically
*/
case 'x':
use_html = 1;
tablestring = optarg;
break;
case 'y':
use_html = 1;
trstring = optarg;
break;
case 'z':
use_html = 1;
tdstring = optarg;
break;
case 'h':
usage(argv[0]);
break;
case 'V':
copyright();
return 0;
}
}
if (opt->ind != argc - 1) {
fprintf(stderr, "%s: wrong number of arguments\n", argv[0]);
usage(argv[0]);
}
if (parse_url(apr_pstrdup(cntxt, opt->argv[opt->ind++]))) {
fprintf(stderr, "%s: invalid URL\n", argv[0]);
usage(argv[0]);
}
copyright();
test();
return 0;
}