155714Skris/* apps/s_time.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8280304Sjkim *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15280304Sjkim *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22280304Sjkim *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40280304Sjkim *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52280304Sjkim *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#define NO_SHUTDOWN
6055714Skris
61280304Sjkim/* ----------------------------------------
6255714Skris   s_time - SSL client connection timer program
6355714Skris   Written and donated by Larry Streepy <streepy@healthcare.com>
6455714Skris  -----------------------------------------*/
6555714Skris
6655714Skris#include <stdio.h>
6755714Skris#include <stdlib.h>
6855714Skris#include <string.h>
6955714Skris
70109998Smarkm#define USE_SOCKETS
71109998Smarkm#include "apps.h"
72109998Smarkm#ifdef OPENSSL_NO_STDIO
73280304Sjkim# define APPS_WIN16
7455714Skris#endif
7555714Skris#include <openssl/x509.h>
7655714Skris#include <openssl/ssl.h>
7755714Skris#include <openssl/pem.h>
7855714Skris#include "s_apps.h"
7955714Skris#include <openssl/err.h>
8055714Skris#ifdef WIN32_STUFF
81280304Sjkim# include "winmain.h"
82280304Sjkim# include "wintext.h"
8355714Skris#endif
84109998Smarkm#if !defined(OPENSSL_SYS_MSDOS)
85280304Sjkim# include OPENSSL_UNISTD
86109998Smarkm#endif
8755714Skris
8855714Skris#undef PROG
8955714Skris#define PROG s_time_main
9055714Skris
9155714Skris#undef ioctl
9255714Skris#define ioctl ioctlsocket
9355714Skris
94280304Sjkim#define SSL_CONNECT_NAME        "localhost:4433"
9555714Skris
96280304Sjkim/* no default cert. */
97280304Sjkim/*
98280304Sjkim * #define TEST_CERT "client.pem"
99280304Sjkim */
10055714Skris
10155714Skris#undef BUFSIZZ
10255714Skris#define BUFSIZZ 1024*10
10355714Skris
104109998Smarkm#define MYBUFSIZ 1024*8
105109998Smarkm
106100928Snectar#undef min
107100928Snectar#undef max
10855714Skris#define min(a,b) (((a) < (b)) ? (a) : (b))
10955714Skris#define max(a,b) (((a) > (b)) ? (a) : (b))
11055714Skris
11155714Skris#undef SECONDS
112280304Sjkim#define SECONDS 30
11355714Skrisextern int verify_depth;
11455714Skrisextern int verify_error;
11555714Skris
11655714Skrisstatic void s_time_usage(void);
117280304Sjkimstatic int parseArgs(int argc, char **argv);
118280304Sjkimstatic SSL *doConnection(SSL *scon);
11955714Skrisstatic void s_time_init(void);
12055714Skris
12155714Skris/***********************************************************************
12255714Skris * Static data declarations
12355714Skris */
12455714Skris
12555714Skris/* static char *port=PORT_STR;*/
126280304Sjkimstatic char *host = SSL_CONNECT_NAME;
127280304Sjkimstatic char *t_cert_file = NULL;
128280304Sjkimstatic char *t_key_file = NULL;
129280304Sjkimstatic char *CApath = NULL;
130280304Sjkimstatic char *CAfile = NULL;
131280304Sjkimstatic char *tm_cipher = NULL;
13255714Skrisstatic int tm_verify = SSL_VERIFY_NONE;
13355714Skrisstatic int maxTime = SECONDS;
134280304Sjkimstatic SSL_CTX *tm_ctx = NULL;
135280304Sjkimstatic const SSL_METHOD *s_time_meth = NULL;
136280304Sjkimstatic char *s_www_path = NULL;
137280304Sjkimstatic long bytes_read = 0;
138280304Sjkimstatic int st_bugs = 0;
139280304Sjkimstatic int perform = 0;
14055714Skris#ifdef FIONBIO
141280304Sjkimstatic int t_nbio = 0;
14255714Skris#endif
143109998Smarkm#ifdef OPENSSL_SYS_WIN32
144280304Sjkimstatic int exitNow = 0;         /* Set when it's time to exit main */
14555714Skris#endif
14655714Skris
14755714Skrisstatic void s_time_init(void)
148280304Sjkim{
149280304Sjkim    host = SSL_CONNECT_NAME;
150280304Sjkim    t_cert_file = NULL;
151280304Sjkim    t_key_file = NULL;
152280304Sjkim    CApath = NULL;
153280304Sjkim    CAfile = NULL;
154280304Sjkim    tm_cipher = NULL;
155280304Sjkim    tm_verify = SSL_VERIFY_NONE;
156280304Sjkim    maxTime = SECONDS;
157280304Sjkim    tm_ctx = NULL;
158280304Sjkim    s_time_meth = NULL;
159280304Sjkim    s_www_path = NULL;
160280304Sjkim    bytes_read = 0;
161280304Sjkim    st_bugs = 0;
162280304Sjkim    perform = 0;
16355714Skris
16455714Skris#ifdef FIONBIO
165280304Sjkim    t_nbio = 0;
16655714Skris#endif
167109998Smarkm#ifdef OPENSSL_SYS_WIN32
168280304Sjkim    exitNow = 0;                /* Set when it's time to exit main */
16955714Skris#endif
170280304Sjkim}
17155714Skris
17255714Skris/***********************************************************************
17355714Skris * usage - display usage message
17455714Skris */
17555714Skrisstatic void s_time_usage(void)
17655714Skris{
177280304Sjkim    static char umsg[] = "\
17855714Skris-time arg     - max number of seconds to collect data, default %d\n\
17955714Skris-verify arg   - turn on peer certificate verification, arg == depth\n\
18055714Skris-cert arg     - certificate file to use, PEM format assumed\n\
18155714Skris-key arg      - RSA file to use, PEM format assumed, key is in cert file\n\
18255714Skris                file if not specified by this option\n\
18355714Skris-CApath arg   - PEM format directory of CA's\n\
18455714Skris-CAfile arg   - PEM format file of CA's\n\
18559191Skris-cipher       - preferred cipher to use, play with 'openssl ciphers'\n\n";
18655714Skris
187280304Sjkim    printf("usage: s_time <args>\n\n");
18855714Skris
189280304Sjkim    printf("-connect host:port - host:port to connect to (default is %s)\n",
190280304Sjkim           SSL_CONNECT_NAME);
19155714Skris#ifdef FIONBIO
192280304Sjkim    printf("-nbio         - Run with non-blocking IO\n");
193280304Sjkim    printf("-ssl2         - Just use SSLv2\n");
194280304Sjkim    printf("-ssl3         - Just use SSLv3\n");
195280304Sjkim    printf("-bugs         - Turn on SSL bug compatibility\n");
196280304Sjkim    printf("-new          - Just time new connections\n");
197280304Sjkim    printf("-reuse        - Just time connection reuse\n");
198280304Sjkim    printf("-www page     - Retrieve 'page' from the site\n");
19955714Skris#endif
200280304Sjkim    printf(umsg, SECONDS);
20155714Skris}
20255714Skris
20355714Skris/***********************************************************************
20455714Skris * parseArgs - Parse command line arguments and initialize data
20555714Skris *
20655714Skris * Returns 0 if ok, -1 on bad args
20755714Skris */
20855714Skrisstatic int parseArgs(int argc, char **argv)
20955714Skris{
21055714Skris    int badop = 0;
21155714Skris
212280304Sjkim    verify_depth = 0;
213280304Sjkim    verify_error = X509_V_OK;
21455714Skris
21555714Skris    argc--;
21655714Skris    argv++;
21755714Skris
21855714Skris    while (argc >= 1) {
219280304Sjkim        if (strcmp(*argv, "-connect") == 0) {
220280304Sjkim            if (--argc < 1)
221280304Sjkim                goto bad;
222280304Sjkim            host = *(++argv);
223280304Sjkim        }
22455714Skris#if 0
225280304Sjkim        else if (strcmp(*argv, "-host") == 0) {
226280304Sjkim            if (--argc < 1)
227280304Sjkim                goto bad;
228280304Sjkim            host = *(++argv);
229280304Sjkim        } else if (strcmp(*argv, "-port") == 0) {
230280304Sjkim            if (--argc < 1)
231280304Sjkim                goto bad;
232280304Sjkim            port = *(++argv);
233280304Sjkim        }
23455714Skris#endif
235280304Sjkim        else if (strcmp(*argv, "-reuse") == 0)
236280304Sjkim            perform = 2;
237280304Sjkim        else if (strcmp(*argv, "-new") == 0)
238280304Sjkim            perform = 1;
239280304Sjkim        else if (strcmp(*argv, "-verify") == 0) {
24055714Skris
241280304Sjkim            tm_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
242280304Sjkim            if (--argc < 1)
243280304Sjkim                goto bad;
244280304Sjkim            verify_depth = atoi(*(++argv));
245280304Sjkim            BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
24655714Skris
247280304Sjkim        } else if (strcmp(*argv, "-cert") == 0) {
24855714Skris
249280304Sjkim            if (--argc < 1)
250280304Sjkim                goto bad;
251280304Sjkim            t_cert_file = *(++argv);
25255714Skris
253280304Sjkim        } else if (strcmp(*argv, "-key") == 0) {
25455714Skris
255280304Sjkim            if (--argc < 1)
256280304Sjkim                goto bad;
257280304Sjkim            t_key_file = *(++argv);
25855714Skris
259280304Sjkim        } else if (strcmp(*argv, "-CApath") == 0) {
26055714Skris
261280304Sjkim            if (--argc < 1)
262280304Sjkim                goto bad;
263280304Sjkim            CApath = *(++argv);
26455714Skris
265280304Sjkim        } else if (strcmp(*argv, "-CAfile") == 0) {
26655714Skris
267280304Sjkim            if (--argc < 1)
268280304Sjkim                goto bad;
269280304Sjkim            CAfile = *(++argv);
27055714Skris
271280304Sjkim        } else if (strcmp(*argv, "-cipher") == 0) {
27255714Skris
273280304Sjkim            if (--argc < 1)
274280304Sjkim                goto bad;
275280304Sjkim            tm_cipher = *(++argv);
276280304Sjkim        }
27755714Skris#ifdef FIONBIO
278280304Sjkim        else if (strcmp(*argv, "-nbio") == 0) {
279280304Sjkim            t_nbio = 1;
280280304Sjkim        }
28155714Skris#endif
282280304Sjkim        else if (strcmp(*argv, "-www") == 0) {
283280304Sjkim            if (--argc < 1)
284280304Sjkim                goto bad;
285280304Sjkim            s_www_path = *(++argv);
286280304Sjkim            if (strlen(s_www_path) > MYBUFSIZ - 100) {
287280304Sjkim                BIO_printf(bio_err, "-www option too long\n");
288280304Sjkim                badop = 1;
289280304Sjkim            }
290280304Sjkim        } else if (strcmp(*argv, "-bugs") == 0)
291280304Sjkim            st_bugs = 1;
292109998Smarkm#ifndef OPENSSL_NO_SSL2
293280304Sjkim        else if (strcmp(*argv, "-ssl2") == 0)
294280304Sjkim            s_time_meth = SSLv2_client_method();
29555714Skris#endif
296109998Smarkm#ifndef OPENSSL_NO_SSL3
297280304Sjkim        else if (strcmp(*argv, "-ssl3") == 0)
298280304Sjkim            s_time_meth = SSLv3_client_method();
29955714Skris#endif
300280304Sjkim        else if (strcmp(*argv, "-time") == 0) {
30155714Skris
302280304Sjkim            if (--argc < 1)
303280304Sjkim                goto bad;
304280304Sjkim            maxTime = atoi(*(++argv));
305284285Sjkim            if (maxTime <= 0) {
306280304Sjkim                BIO_printf(bio_err, "time must be > 0\n");
307280304Sjkim                badop = 1;
308280304Sjkim            }
309280304Sjkim        } else {
310280304Sjkim            BIO_printf(bio_err, "unknown option %s\n", *argv);
311280304Sjkim            badop = 1;
312280304Sjkim            break;
313280304Sjkim        }
31455714Skris
315280304Sjkim        argc--;
316280304Sjkim        argv++;
31755714Skris    }
31855714Skris
319280304Sjkim    if (perform == 0)
320280304Sjkim        perform = 3;
32155714Skris
322280304Sjkim    if (badop) {
323280304Sjkim bad:
324280304Sjkim        s_time_usage();
325280304Sjkim        return -1;
32655714Skris    }
32755714Skris
328280304Sjkim    return 0;                   /* Valid args */
32955714Skris}
33055714Skris
33155714Skris/***********************************************************************
33255714Skris * TIME - time functions
33355714Skris */
334280304Sjkim#define START   0
335280304Sjkim#define STOP    1
33655714Skris
33755714Skrisstatic double tm_Time_F(int s)
338280304Sjkim{
339280304Sjkim    return app_tminterval(s, 1);
340280304Sjkim}
341160814Ssimon
34255714Skris/***********************************************************************
34355714Skris * MAIN - main processing area for client
344280304Sjkim *                      real name depends on MONOLITH
34555714Skris */
34659191Skrisint MAIN(int, char **);
34759191Skris
34855714Skrisint MAIN(int argc, char **argv)
349280304Sjkim{
350280304Sjkim    double totalTime = 0.0;
351280304Sjkim    int nConn = 0;
352280304Sjkim    SSL *scon = NULL;
353280304Sjkim    long finishtime = 0;
354280304Sjkim    int ret = 1, i;
355280304Sjkim    MS_STATIC char buf[1024 * 8];
356280304Sjkim    int ver;
35755714Skris
358280304Sjkim    apps_startup();
359280304Sjkim    s_time_init();
36059191Skris
361280304Sjkim    if (bio_err == NULL)
362280304Sjkim        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
36359191Skris
364280304Sjkim    s_time_meth = SSLv23_client_method();
36555714Skris
366280304Sjkim    /* parse the command line arguments */
367280304Sjkim    if (parseArgs(argc, argv) < 0)
368280304Sjkim        goto end;
36955714Skris
370280304Sjkim    OpenSSL_add_ssl_algorithms();
371280304Sjkim    if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
372280304Sjkim        return (1);
37355714Skris
374280304Sjkim    SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
37555714Skris
376280304Sjkim    if (st_bugs)
377280304Sjkim        SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
378280304Sjkim    SSL_CTX_set_cipher_list(tm_ctx, tm_cipher);
379280304Sjkim    if (!set_cert_stuff(tm_ctx, t_cert_file, t_key_file))
380280304Sjkim        goto end;
38155714Skris
382280304Sjkim    SSL_load_error_strings();
38355714Skris
384280304Sjkim    if ((!SSL_CTX_load_verify_locations(tm_ctx, CAfile, CApath)) ||
385280304Sjkim        (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
386280304Sjkim        /*
387280304Sjkim         * BIO_printf(bio_err,"error setting default verify locations\n");
388280304Sjkim         */
389280304Sjkim        ERR_print_errors(bio_err);
390280304Sjkim        /* goto end; */
391280304Sjkim    }
39255714Skris
393280304Sjkim    if (tm_cipher == NULL)
394280304Sjkim        tm_cipher = getenv("SSL_CIPHER");
39555714Skris
396280304Sjkim    if (tm_cipher == NULL) {
397280304Sjkim        fprintf(stderr, "No CIPHER specified\n");
398280304Sjkim    }
39955714Skris
400280304Sjkim    if (!(perform & 1))
401280304Sjkim        goto next;
402280304Sjkim    printf("Collecting connection statistics for %d seconds\n", maxTime);
40355714Skris
404280304Sjkim    /* Loop and time how long it takes to make connections */
40555714Skris
406280304Sjkim    bytes_read = 0;
407280304Sjkim    finishtime = (long)time(NULL) + maxTime;
408280304Sjkim    tm_Time_F(START);
409280304Sjkim    for (;;) {
410280304Sjkim        if (finishtime < (long)time(NULL))
411280304Sjkim            break;
41255714Skris#ifdef WIN32_STUFF
41355714Skris
414280304Sjkim        if (flushWinMsgs(0) == -1)
415280304Sjkim            goto end;
41655714Skris
417280304Sjkim        if (waitingToDie || exitNow) /* we're dead */
418280304Sjkim            goto end;
41955714Skris#endif
42055714Skris
421280304Sjkim        if ((scon = doConnection(NULL)) == NULL)
422280304Sjkim            goto end;
42355714Skris
424280304Sjkim        if (s_www_path != NULL) {
425280304Sjkim            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
426280304Sjkim                         s_www_path);
427280304Sjkim            SSL_write(scon, buf, strlen(buf));
428280304Sjkim            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
429280304Sjkim                bytes_read += i;
430280304Sjkim        }
43155714Skris#ifdef NO_SHUTDOWN
432280304Sjkim        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
43355714Skris#else
434280304Sjkim        SSL_shutdown(scon);
43555714Skris#endif
436280304Sjkim        SHUTDOWN2(SSL_get_fd(scon));
43755714Skris
438280304Sjkim        nConn += 1;
439280304Sjkim        if (SSL_session_reused(scon))
440280304Sjkim            ver = 'r';
441280304Sjkim        else {
442280304Sjkim            ver = SSL_version(scon);
443280304Sjkim            if (ver == TLS1_VERSION)
444280304Sjkim                ver = 't';
445280304Sjkim            else if (ver == SSL3_VERSION)
446280304Sjkim                ver = '3';
447280304Sjkim            else if (ver == SSL2_VERSION)
448280304Sjkim                ver = '2';
449280304Sjkim            else
450280304Sjkim                ver = '*';
451280304Sjkim        }
452280304Sjkim        fputc(ver, stdout);
453280304Sjkim        fflush(stdout);
45455714Skris
455280304Sjkim        SSL_free(scon);
456280304Sjkim        scon = NULL;
457280304Sjkim    }
458280304Sjkim    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
45955714Skris
460280304Sjkim    i = (int)((long)time(NULL) - finishtime + maxTime);
461280304Sjkim    printf
462280304Sjkim        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
463280304Sjkim         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
464280304Sjkim    printf
465280304Sjkim        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
466280304Sjkim         nConn, (long)time(NULL) - finishtime + maxTime, bytes_read / nConn);
46755714Skris
468280304Sjkim    /*
469280304Sjkim     * Now loop and time connections using the same session id over and over
470280304Sjkim     */
47155714Skris
472280304Sjkim next:
473280304Sjkim    if (!(perform & 2))
474280304Sjkim        goto end;
475280304Sjkim    printf("\n\nNow timing with session id reuse.\n");
47655714Skris
477280304Sjkim    /* Get an SSL object so we can reuse the session id */
478280304Sjkim    if ((scon = doConnection(NULL)) == NULL) {
479280304Sjkim        fprintf(stderr, "Unable to get connection\n");
480280304Sjkim        goto end;
481280304Sjkim    }
48255714Skris
483280304Sjkim    if (s_www_path != NULL) {
484280304Sjkim        BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", s_www_path);
485280304Sjkim        SSL_write(scon, buf, strlen(buf));
486280304Sjkim        while (SSL_read(scon, buf, sizeof(buf)) > 0) ;
487280304Sjkim    }
48855714Skris#ifdef NO_SHUTDOWN
489280304Sjkim    SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
49055714Skris#else
491280304Sjkim    SSL_shutdown(scon);
49255714Skris#endif
493280304Sjkim    SHUTDOWN2(SSL_get_fd(scon));
49455714Skris
495280304Sjkim    nConn = 0;
496280304Sjkim    totalTime = 0.0;
49755714Skris
498280304Sjkim    finishtime = (long)time(NULL) + maxTime;
49955714Skris
500280304Sjkim    printf("starting\n");
501280304Sjkim    bytes_read = 0;
502280304Sjkim    tm_Time_F(START);
50355714Skris
504280304Sjkim    for (;;) {
505280304Sjkim        if (finishtime < (long)time(NULL))
506280304Sjkim            break;
507280304Sjkim
50855714Skris#ifdef WIN32_STUFF
509280304Sjkim        if (flushWinMsgs(0) == -1)
510280304Sjkim            goto end;
51155714Skris
512280304Sjkim        if (waitingToDie || exitNow) /* we're dead */
513280304Sjkim            goto end;
51455714Skris#endif
51555714Skris
516280304Sjkim        if ((doConnection(scon)) == NULL)
517280304Sjkim            goto end;
51855714Skris
519280304Sjkim        if (s_www_path) {
520280304Sjkim            BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n",
521280304Sjkim                         s_www_path);
522280304Sjkim            SSL_write(scon, buf, strlen(buf));
523280304Sjkim            while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
524280304Sjkim                bytes_read += i;
525280304Sjkim        }
52655714Skris#ifdef NO_SHUTDOWN
527280304Sjkim        SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
52855714Skris#else
529280304Sjkim        SSL_shutdown(scon);
53055714Skris#endif
531280304Sjkim        SHUTDOWN2(SSL_get_fd(scon));
53255714Skris
533280304Sjkim        nConn += 1;
534280304Sjkim        if (SSL_session_reused(scon))
535280304Sjkim            ver = 'r';
536280304Sjkim        else {
537280304Sjkim            ver = SSL_version(scon);
538280304Sjkim            if (ver == TLS1_VERSION)
539280304Sjkim                ver = 't';
540280304Sjkim            else if (ver == SSL3_VERSION)
541280304Sjkim                ver = '3';
542280304Sjkim            else if (ver == SSL2_VERSION)
543280304Sjkim                ver = '2';
544280304Sjkim            else
545280304Sjkim                ver = '*';
546280304Sjkim        }
547280304Sjkim        fputc(ver, stdout);
548280304Sjkim        fflush(stdout);
549280304Sjkim    }
550280304Sjkim    totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
55155714Skris
552280304Sjkim    printf
553280304Sjkim        ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
554280304Sjkim         nConn, totalTime, ((double)nConn / totalTime), bytes_read);
555280304Sjkim    printf
556280304Sjkim        ("%d connections in %ld real seconds, %ld bytes read per connection\n",
557280304Sjkim         nConn, (long)time(NULL) - finishtime + maxTime,
558280304Sjkim         bytes_read / (nConn?nConn:1));
55955714Skris
560280304Sjkim    ret = 0;
561280304Sjkim end:
562280304Sjkim    if (scon != NULL)
563280304Sjkim        SSL_free(scon);
56455714Skris
565280304Sjkim    if (tm_ctx != NULL) {
566280304Sjkim        SSL_CTX_free(tm_ctx);
567280304Sjkim        tm_ctx = NULL;
568280304Sjkim    }
569280304Sjkim    apps_shutdown();
570280304Sjkim    OPENSSL_EXIT(ret);
571280304Sjkim}
57255714Skris
573280304Sjkim/*-
57455714Skris * doConnection - make a connection
57555714Skris * Args:
576280304Sjkim *              scon    = earlier ssl connection for session id, or NULL
57755714Skris * Returns:
578280304Sjkim *              SSL *   = the connection pointer.
57955714Skris */
58055714Skrisstatic SSL *doConnection(SSL *scon)
581280304Sjkim{
582280304Sjkim    BIO *conn;
583280304Sjkim    SSL *serverCon;
584280304Sjkim    int width, i;
585280304Sjkim    fd_set readfds;
58655714Skris
587280304Sjkim    if ((conn = BIO_new(BIO_s_connect())) == NULL)
588280304Sjkim        return (NULL);
58955714Skris
590280304Sjkim/*      BIO_set_conn_port(conn,port);*/
591280304Sjkim    BIO_set_conn_hostname(conn, host);
59255714Skris
593280304Sjkim    if (scon == NULL)
594280304Sjkim        serverCon = SSL_new(tm_ctx);
595280304Sjkim    else {
596280304Sjkim        serverCon = scon;
597280304Sjkim        SSL_set_connect_state(serverCon);
598280304Sjkim    }
59955714Skris
600280304Sjkim    SSL_set_bio(serverCon, conn, conn);
60155714Skris
60255714Skris#if 0
603280304Sjkim    if (scon != NULL)
604280304Sjkim        SSL_set_session(serverCon, SSL_get_session(scon));
60555714Skris#endif
60655714Skris
607280304Sjkim    /* ok, lets connect */
608280304Sjkim    for (;;) {
609280304Sjkim        i = SSL_connect(serverCon);
610280304Sjkim        if (BIO_sock_should_retry(i)) {
611280304Sjkim            BIO_printf(bio_err, "DELAY\n");
61255714Skris
613280304Sjkim            i = SSL_get_fd(serverCon);
614280304Sjkim            width = i + 1;
615280304Sjkim            FD_ZERO(&readfds);
616280304Sjkim            openssl_fdset(i, &readfds);
617280304Sjkim            /*
618280304Sjkim             * Note: under VMS with SOCKETSHR the 2nd parameter is currently
619280304Sjkim             * of type (int *) whereas under other systems it is (void *) if
620280304Sjkim             * you don't have a cast it will choke the compiler: if you do
621280304Sjkim             * have a cast then you can either go for (int *) or (void *).
622280304Sjkim             */
623280304Sjkim            select(width, (void *)&readfds, NULL, NULL, NULL);
624280304Sjkim            continue;
625280304Sjkim        }
626280304Sjkim        break;
627280304Sjkim    }
628280304Sjkim    if (i <= 0) {
629280304Sjkim        BIO_printf(bio_err, "ERROR\n");
630280304Sjkim        if (verify_error != X509_V_OK)
631280304Sjkim            BIO_printf(bio_err, "verify error:%s\n",
632280304Sjkim                       X509_verify_cert_error_string(verify_error));
633280304Sjkim        else
634280304Sjkim            ERR_print_errors(bio_err);
635280304Sjkim        if (scon == NULL)
636280304Sjkim            SSL_free(serverCon);
637280304Sjkim        return NULL;
638280304Sjkim    }
63955714Skris
640280304Sjkim    return serverCon;
641280304Sjkim}
642