in support/ab.c [2992:3507]
int main(int argc, const char * const argv[])
{
char tmp[1024];
apr_status_t status;
apr_getopt_t *opt;
const char *opt_arg;
char c;
#ifdef USE_SSL
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
int max_prot = MAX_SSL_PROTO;
int min_prot = MIN_SSL_PROTO;
#endif /* #if OPENSSL_VERSION_NUMBER >= 0x10100000L */
AB_SSL_METHOD_CONST SSL_METHOD *meth = SSLv23_client_method();
#endif /* USE_SSL */
srand((unsigned int)apr_time_now());
/* table defaults */
tablestring = "";
trstring = "";
tdstring = "bgcolor=white";
cookie = "";
auth = "";
proxyhost = "";
hdrs = "";
apr_app_initialize(&argc, &argv, NULL);
if (apr_pool_create(&cntxt, NULL) != APR_SUCCESS) {
abort_on_oom(APR_ENOMEM);
}
apr_pool_abort_set(abort_on_oom, cntxt);
atexit(output_results_at_exit);
#ifdef NOT_ASCII
status = apr_xlate_open(&to_ascii, "ISO-8859-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, "ISO-8859-1", cntxt);
if (status) {
fprintf(stderr, "apr_xlate_open(from ASCII)->%d\n", status);
exit(1);
}
status = apr_base64init_ebcdic(to_ascii, from_ascii);
if (status) {
fprintf(stderr, "apr_base64init_ebcdic()->%d\n", status);
exit(1);
}
#endif
apr_getopt_init(&opt, cntxt, argc, argv);
while ((status = apr_getopt(opt, "n:c:t:s:b:T:p:u:v:lrkVhwiIx:y:z:C:H:P:A:g:X:de:SqQDB:m:R:o:"
#if APR_HAS_THREADS
"W:"
#endif
#ifdef USE_SSL
"Z:f:E:"
#endif
,&c, &opt_arg)) == APR_SUCCESS) {
switch (c) {
case 'n':
requests = atoi(opt_arg);
if (requests <= 0) {
fatal_error("Invalid number of requests\n");
}
break;
#if APR_HAS_THREADS
case 'W':
num_workers = atoi(opt_arg);
if (num_workers < 0) {
fatal_error("Invalid number of workers\n");
}
break;
#endif
case 'k':
keepalive = 1;
break;
case 'o':
src_address = strdup(opt_arg);
break;
case 'q':
heartbeatres = 0;
break;
case 'Q':
no_banner = 1;
break;
case 'D':
watchdog = 1;
break;
case 'c':
concurrency = atoi(opt_arg);
if (concurrency < 0) {
fatal_error("Invalid negative concurrency\n");
}
break;
case 'b':
windowsize = atoi(opt_arg);
break;
case 'i':
if (method != NO_METH)
fatal_error("Cannot mix HEAD with other methods\n");
method = HEAD;
break;
case 'g':
gnuplot = apr_pstrdup(cntxt, opt_arg);
break;
case 'd':
percentile = 0;
break;
case 'e':
csvperc = apr_pstrdup(cntxt, opt_arg);
break;
case 'S':
confidence = 0;
break;
case 's':
aprtimeout = apr_time_from_sec(atoi(opt_arg)); /* timeout value */
break;
case 'R':
ramp = apr_time_from_msec(atoi(opt_arg)); /* ramp delay */
break;
case 'p':
if (method != NO_METH)
fatal_error("Cannot mix POST with other methods\n");
if (open_postfile(opt_arg) != APR_SUCCESS) {
exit(1);
}
method = POST;
send_body = 1;
break;
case 'u':
if (method != NO_METH)
fatal_error("Cannot mix PUT with other methods\n");
if (open_postfile(opt_arg) != APR_SUCCESS) {
exit(1);
}
method = PUT;
send_body = 1;
break;
case 'l':
nolength = 1;
break;
case 'r':
recverrok = 1;
break;
case 'v':
verbosity = atoi(opt_arg);
break;
case 't':
tlimit = atoi(opt_arg);
if (tlimit < 0)
fatal_error("Invalid negative timelimit\n");
break;
case 'T':
content_type = apr_pstrdup(cntxt, opt_arg);
break;
case 'C':
cookie = apr_pstrcat(cntxt, "Cookie: ", opt_arg, "\r\n", NULL);
break;
case 'A':
/*
* assume username passwd already to be in colon separated form.
* Ready to be uu-encoded.
*/
while (apr_isspace(*opt_arg))
opt_arg++;
if (apr_base64_encode_len(strlen(opt_arg)) > sizeof(tmp)) {
fatal_error("Authentication credentials too long\n");
}
apr_base64_encode(tmp, opt_arg, strlen(opt_arg));
auth = apr_pstrcat(cntxt, auth, "Authorization: Basic ", tmp,
"\r\n", NULL);
break;
case 'P':
/*
* assume username passwd already to be in colon separated form.
*/
while (apr_isspace(*opt_arg))
opt_arg++;
if (apr_base64_encode_len(strlen(opt_arg)) > sizeof(tmp)) {
fatal_error("Proxy credentials too long\n");
}
apr_base64_encode(tmp, opt_arg, strlen(opt_arg));
auth = apr_pstrcat(cntxt, auth, "Proxy-Authorization: Basic ",
tmp, "\r\n", NULL);
break;
case 'H':
hdrs = apr_pstrcat(cntxt, hdrs, opt_arg, "\r\n", NULL);
/*
* allow override of some of the common headers that ab adds
*/
if (strncasecmp(opt_arg, "Host:", 5) == 0) {
char *host;
apr_size_t len;
opt_arg += 5;
while (apr_isspace(*opt_arg))
opt_arg++;
len = strlen(opt_arg);
host = strdup(opt_arg);
while (len && apr_isspace(host[len-1]))
host[--len] = '\0';
opt_host = host;
} else if (strncasecmp(opt_arg, "Accept:", 7) == 0) {
opt_accept = 1;
} else if (strncasecmp(opt_arg, "User-Agent:", 11) == 0) {
opt_useragent = 1;
}
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 = opt_arg;
break;
case 'X':
{
char *p;
/*
* assume proxy-name[:port]
*/
if ((p = strchr(opt_arg, ':'))) {
*p = '\0';
p++;
proxyport = atoi(p);
}
proxyhost = apr_pstrdup(cntxt, opt_arg);
isproxy = 1;
}
break;
case 'y':
use_html = 1;
trstring = opt_arg;
break;
case 'z':
use_html = 1;
tdstring = opt_arg;
break;
case 'h':
usage(argv[0]);
break;
case 'V':
copyright();
return 0;
case 'B':
{
const char *ptr, *end;
bind_count = 1;
for (ptr = opt_arg; (end = strchr(ptr, ',')); ptr = end + 1) {
bind_count++;
}
bind_hosts = apr_palloc(cntxt, bind_count * sizeof(char*));
bind_count = 0;
for (ptr = opt_arg; (end = strchr(ptr, ',')); ptr = end + 1) {
if (end > ptr) {
bind_hosts[bind_count++] = apr_pstrmemdup(cntxt, ptr, end - ptr);
}
}
if (*ptr) {
bind_hosts[bind_count++] = apr_pstrdup(cntxt, ptr);
}
if (!bind_count) {
fprintf(stderr, "%s: Invalid bind address[es]\n", argv[0]);
usage(argv[0]);
}
}
break;
case 'm':
method = CUSTOM_METHOD;
method_str[CUSTOM_METHOD] = strdup(opt_arg);
break;
#ifdef USE_SSL
case 'Z':
ssl_cipher = strdup(opt_arg);
break;
case 'E':
ssl_cert = strdup(opt_arg);
break;
case 'f':
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (strncasecmp(opt_arg, "ALL", 3) == 0) {
meth = SSLv23_client_method();
#ifndef OPENSSL_NO_SSL2
} else if (strncasecmp(opt_arg, "SSL2", 4) == 0) {
meth = SSLv2_client_method();
#ifdef HAVE_TLSEXT
tls_use_sni = 0;
#endif
#endif
#ifndef OPENSSL_NO_SSL3
} else if (strncasecmp(opt_arg, "SSL3", 4) == 0) {
meth = SSLv3_client_method();
#ifdef HAVE_TLSEXT
tls_use_sni = 0;
#endif
#endif
#ifdef HAVE_TLSV1_X
} else if (strncasecmp(opt_arg, "TLS1.1", 6) == 0) {
meth = TLSv1_1_client_method();
} else if (strncasecmp(opt_arg, "TLS1.2", 6) == 0) {
meth = TLSv1_2_client_method();
#endif
} else if (strncasecmp(opt_arg, "TLS1", 4) == 0) {
meth = TLSv1_client_method();
}
#else /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
meth = TLS_client_method();
if (strncasecmp(opt_arg, "ALL", 3) == 0) {
max_prot = MAX_SSL_PROTO;
min_prot = MIN_SSL_PROTO;
#ifndef OPENSSL_NO_SSL3
} else if (strncasecmp(opt_arg, "SSL3", 4) == 0) {
max_prot = SSL3_VERSION;
min_prot = SSL3_VERSION;
#endif
} else if (strncasecmp(opt_arg, "TLS1.1", 6) == 0) {
max_prot = TLS1_1_VERSION;
min_prot = TLS1_1_VERSION;
} else if (strncasecmp(opt_arg, "TLS1.2", 6) == 0) {
max_prot = TLS1_2_VERSION;
min_prot = TLS1_2_VERSION;
#ifdef TLS1_3_VERSION
} else if (strncasecmp(opt_arg, "TLS1.3", 6) == 0) {
max_prot = TLS1_3_VERSION;
min_prot = TLS1_3_VERSION;
#endif
} else if (strncasecmp(opt_arg, "TLS1", 4) == 0) {
max_prot = TLS1_VERSION;
min_prot = TLS1_VERSION;
}
#endif /* #if OPENSSL_VERSION_NUMBER < 0x10100000L */
break;
#ifdef HAVE_TLSEXT
case 'I':
tls_use_sni = 0;
break;
#endif
#endif /* USE_SSL */
}
}
if (status != APR_EOF || opt->ind != argc - 1) {
fprintf(stderr, "%s: Invalid or missing arguments\n", argv[0]);
usage(argv[0]);
}
if (method == NO_METH) {
method = GET;
}
if (parse_url(apr_pstrdup(cntxt, opt->argv[opt->ind++]))) {
fprintf(stderr, "%s: invalid URL\n", argv[0]);
usage(argv[0]);
}
rlimited = !tlimit || requests > 0;
if (requests == 0) {
requests = tlimit ? TIMED_REQUESTS : 1;
}
#if APR_HAS_THREADS
if (num_workers == 0) {
#ifdef _SC_NPROCESSORS_ONLN
num_workers = sysconf(_SC_NPROCESSORS_ONLN);
#else
fatal_error("-W0 not implemented on this platform\n");
#endif
}
if (num_workers > 1) {
requests = ROUND_UP(requests, num_workers);
concurrency = ROUND_UP(concurrency, num_workers);
}
else {
num_workers = 1;
}
#endif /* APR_HAS_THREADS */
if (concurrency == 0) {
concurrency = num_workers;
}
if (concurrency > ROUND_UP(MAX_CONCURRENCY, num_workers)) {
fprintf(stderr, "%s: Invalid Concurrency [Range 0..%d]\n",
argv[0], ROUND_UP(MAX_CONCURRENCY, num_workers));
usage(argv[0]);
}
if (concurrency > requests) {
fprintf(stderr, "%s: Cannot use concurrency level greater than "
"total number of requests\n", argv[0]);
usage(argv[0]);
}
if (tlimit) {
/* Print line every 10% of time */
hbperiod = apr_time_from_sec(tlimit) / 10;
if (hbperiod < apr_time_from_sec(1)) {
hbperiod = apr_time_from_sec(1);
}
else if (hbperiod > apr_time_from_sec(60)) {
hbperiod = apr_time_from_sec(60);
}
}
else if ((heartbeatres) && (requests > 150)) {
heartbeatres = requests / 10; /* Print line every 10% of requests */
if (heartbeatres < 100)
heartbeatres = 100; /* but never more often than once every 100
* connections. */
}
else
heartbeatres = 0;
#ifdef USE_SSL
#ifdef RSAREF
R_malloc_init();
#else
#if OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_malloc_init();
#endif
#endif
SSL_load_error_strings();
SSL_library_init();
if(!(bio_out = BIO_new_fp(stdout,BIO_NOCLOSE))) {
fprintf(stderr, "%s: Cannot allocate memory", argv[0]);
exit(1);
}
if(!(bio_err = BIO_new_fp(stderr,BIO_NOCLOSE))) {
fprintf(stderr, "%s: Cannot allocate memory", argv[0]);
exit(1);
}
#if OPENSSL_VERSION_NUMBER >= 0x10101000
if (RAND_status() == 0) {
fprintf(stderr, "%s: Error: Crypto library PRNG does not contain "
"sufficient randomness.\n"
"%s: Build the library with a suitable entropy source configured.\n",
argv[0], argv[0]);
exit(1);
}
#endif
if (!(ssl_ctx = SSL_CTX_new(meth))) {
BIO_printf(bio_err, "Could not initialize SSL Context.\n");
ERR_print_errors(bio_err);
fatal_error("SSL_CTX_new failed");
}
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
SSL_CTX_set_max_proto_version(ssl_ctx, max_prot);
SSL_CTX_set_min_proto_version(ssl_ctx, min_prot);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
/* Keep memory usage as low as possible */
SSL_CTX_set_mode (ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
if (ssl_cipher != NULL) {
int ok;
#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(TLS1_3_VERSION)
if (min_prot >= TLS1_3_VERSION)
ok = SSL_CTX_set_ciphersuites(ssl_ctx, ssl_cipher);
else
#endif
ok = SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher);
if (!ok) {
BIO_printf(bio_err, "error setting ciphersuite list [%s]\n",
ssl_cipher);
ERR_print_errors(bio_err);
fatal_error("SSL_CTX_set_cipher_list failed");
}
}
if (verbosity >= 3) {
SSL_CTX_set_info_callback(ssl_ctx, ssl_state_cb);
}
if (ssl_cert != NULL) {
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert) <= 0) {
BIO_printf(bio_err, "unable to get certificate from '%s'\n",
ssl_cert);
ERR_print_errors(bio_err);
fatal_error("SSL_CTX_use_certificate_chain_file failed");
}
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, ssl_cert, SSL_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "unable to get private key from '%s'\n",
ssl_cert);
ERR_print_errors(bio_err);
fatal_error("SSL_CTX_use_PrivateKey_file failed");
}
if (!SSL_CTX_check_private_key(ssl_ctx)) {
BIO_printf(bio_err,
"private key does not match the certificate public key in %s\n", ssl_cert);
ERR_print_errors(bio_err);
fatal_error("SSL_CTX_check_private_key failed");
}
}
#endif
#ifdef SIGPIPE
apr_signal(SIGPIPE, SIG_IGN); /* Ignore writes to connections that
* have been closed at the other end. */
#endif
if (!no_banner) {
copyright();
}
return test();
}