155714Skris/* crypto/threads/mttest.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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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#include <stdio.h>
6055714Skris#include <stdlib.h>
6155714Skris#include <string.h>
6255714Skris#include <errno.h>
6355714Skris#ifdef LINUX
64296465Sdelphij# include <typedefs.h>
6555714Skris#endif
66109998Smarkm#ifdef OPENSSL_SYS_WIN32
67296465Sdelphij# include <windows.h>
6855714Skris#endif
6955714Skris#ifdef SOLARIS
70296465Sdelphij# include <synch.h>
71296465Sdelphij# include <thread.h>
7255714Skris#endif
7355714Skris#ifdef IRIX
74296465Sdelphij# include <ulocks.h>
75296465Sdelphij# include <sys/prctl.h>
7655714Skris#endif
7759191Skris#ifdef PTHREADS
78296465Sdelphij# include <pthread.h>
7959191Skris#endif
80160814Ssimon#ifdef OPENSSL_SYS_NETWARE
81296465Sdelphij# if !defined __int64
82160814Ssimon#  define __int64 long long
83296465Sdelphij# endif
84296465Sdelphij# include <nwmpk.h>
85160814Ssimon#endif
8655714Skris#include <openssl/lhash.h>
8755714Skris#include <openssl/crypto.h>
8855714Skris#include <openssl/buffer.h>
8959191Skris#include "../../e_os.h"
9055714Skris#include <openssl/x509.h>
9155714Skris#include <openssl/ssl.h>
9255714Skris#include <openssl/err.h>
9359191Skris#include <openssl/rand.h>
9455714Skris
95160814Ssimon#ifdef OPENSSL_NO_FP_API
96296465Sdelphij# define APPS_WIN16
97296465Sdelphij# include "../buffer/bss_file.c"
98160814Ssimon#endif
99160814Ssimon
100160814Ssimon#ifdef OPENSSL_SYS_NETWARE
101296465Sdelphij# define TEST_SERVER_CERT "/openssl/apps/server.pem"
102296465Sdelphij# define TEST_CLIENT_CERT "/openssl/apps/client.pem"
103160814Ssimon#else
104296465Sdelphij# define TEST_SERVER_CERT "../../apps/server.pem"
105296465Sdelphij# define TEST_CLIENT_CERT "../../apps/client.pem"
106160814Ssimon#endif
10755714Skris
108296465Sdelphij#define MAX_THREAD_NUMBER       100
10955714Skris
11059191Skrisint MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *xs);
11155714Skrisvoid thread_setup(void);
11255714Skrisvoid thread_cleanup(void);
113296465Sdelphijvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx);
11455714Skris
115296465Sdelphijvoid irix_locking_callback(int mode, int type, char *file, int line);
116296465Sdelphijvoid solaris_locking_callback(int mode, int type, char *file, int line);
117296465Sdelphijvoid win32_locking_callback(int mode, int type, char *file, int line);
118296465Sdelphijvoid pthreads_locking_callback(int mode, int type, char *file, int line);
119296465Sdelphijvoid netware_locking_callback(int mode, int type, char *file, int line);
12055714Skris
121296465Sdelphijunsigned long irix_thread_id(void);
122296465Sdelphijunsigned long solaris_thread_id(void);
123296465Sdelphijunsigned long pthreads_thread_id(void);
124296465Sdelphijunsigned long netware_thread_id(void);
12555714Skris
126160814Ssimon#if defined(OPENSSL_SYS_NETWARE)
127160814Ssimonstatic MPKMutex *lock_cs;
128160814Ssimonstatic MPKSema ThreadSem;
129160814Ssimonstatic long *lock_count;
130160814Ssimon#endif
131160814Ssimon
132296465SdelphijBIO *bio_err = NULL;
133296465SdelphijBIO *bio_stdout = NULL;
13455714Skris
135296465Sdelphijstatic char *cipher = NULL;
136296465Sdelphijint verbose = 0;
13755714Skris#ifdef FIONBIO
138296465Sdelphijstatic int s_nbio = 0;
13955714Skris#endif
14055714Skris
141296465Sdelphijint thread_number = 10;
142296465Sdelphijint number_of_loops = 10;
143296465Sdelphijint reconnect = 0;
144296465Sdelphijint cache_stats = 0;
14555714Skris
146296465Sdelphijstatic const char rnd_seed[] =
147296465Sdelphij    "string to make the random number generator think it has entropy";
14859191Skris
14955714Skrisint doit(char *ctx[4]);
15055714Skrisstatic void print_stats(FILE *fp, SSL_CTX *ctx)
15155714Skris{
152296465Sdelphij    fprintf(fp, "%4ld items in the session cache\n",
153296465Sdelphij            SSL_CTX_sess_number(ctx));
154296465Sdelphij    fprintf(fp, "%4d client connects (SSL_connect())\n",
155296465Sdelphij            SSL_CTX_sess_connect(ctx));
156296465Sdelphij    fprintf(fp, "%4d client connects that finished\n",
157296465Sdelphij            SSL_CTX_sess_connect_good(ctx));
158296465Sdelphij    fprintf(fp, "%4d server connects (SSL_accept())\n",
159296465Sdelphij            SSL_CTX_sess_accept(ctx));
160296465Sdelphij    fprintf(fp, "%4d server connects that finished\n",
161296465Sdelphij            SSL_CTX_sess_accept_good(ctx));
162296465Sdelphij    fprintf(fp, "%4d session cache hits\n", SSL_CTX_sess_hits(ctx));
163296465Sdelphij    fprintf(fp, "%4d session cache misses\n", SSL_CTX_sess_misses(ctx));
164296465Sdelphij    fprintf(fp, "%4d session cache timeouts\n", SSL_CTX_sess_timeouts(ctx));
165296465Sdelphij}
16655714Skris
16755714Skrisstatic void sv_usage(void)
168296465Sdelphij{
169296465Sdelphij    fprintf(stderr, "usage: ssltest [args ...]\n");
170296465Sdelphij    fprintf(stderr, "\n");
171296465Sdelphij    fprintf(stderr, " -server_auth  - check server certificate\n");
172296465Sdelphij    fprintf(stderr, " -client_auth  - do client authentication\n");
173296465Sdelphij    fprintf(stderr, " -v            - more output\n");
174296465Sdelphij    fprintf(stderr, " -CApath arg   - PEM format directory of CA's\n");
175296465Sdelphij    fprintf(stderr, " -CAfile arg   - PEM format file of CA's\n");
176296465Sdelphij    fprintf(stderr, " -threads arg  - number of threads\n");
177296465Sdelphij    fprintf(stderr, " -loops arg    - number of 'connections', per thread\n");
178296465Sdelphij    fprintf(stderr, " -reconnect    - reuse session-id's\n");
179296465Sdelphij    fprintf(stderr, " -stats        - server session-id cache stats\n");
180296465Sdelphij    fprintf(stderr, " -cert arg     - server certificate/key\n");
181296465Sdelphij    fprintf(stderr, " -ccert arg    - client certificate/key\n");
182296465Sdelphij    fprintf(stderr, " -ssl3         - just SSLv3n\n");
183296465Sdelphij}
18455714Skris
18555714Skrisint main(int argc, char *argv[])
186296465Sdelphij{
187296465Sdelphij    char *CApath = NULL, *CAfile = NULL;
188296465Sdelphij    int badop = 0;
189296465Sdelphij    int ret = 1;
190296465Sdelphij    int client_auth = 0;
191296465Sdelphij    int server_auth = 0;
192296465Sdelphij    SSL_CTX *s_ctx = NULL;
193296465Sdelphij    SSL_CTX *c_ctx = NULL;
194296465Sdelphij    char *scert = TEST_SERVER_CERT;
195296465Sdelphij    char *ccert = TEST_CLIENT_CERT;
196296465Sdelphij    SSL_METHOD *ssl_method = SSLv23_method();
19755714Skris
198296465Sdelphij    RAND_seed(rnd_seed, sizeof rnd_seed);
19959191Skris
200296465Sdelphij    if (bio_err == NULL)
201296465Sdelphij        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
202296465Sdelphij    if (bio_stdout == NULL)
203296465Sdelphij        bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
204296465Sdelphij    argc--;
205296465Sdelphij    argv++;
20655714Skris
207296465Sdelphij    while (argc >= 1) {
208296465Sdelphij        if (strcmp(*argv, "-server_auth") == 0)
209296465Sdelphij            server_auth = 1;
210296465Sdelphij        else if (strcmp(*argv, "-client_auth") == 0)
211296465Sdelphij            client_auth = 1;
212296465Sdelphij        else if (strcmp(*argv, "-reconnect") == 0)
213296465Sdelphij            reconnect = 1;
214296465Sdelphij        else if (strcmp(*argv, "-stats") == 0)
215296465Sdelphij            cache_stats = 1;
216296465Sdelphij        else if (strcmp(*argv, "-ssl3") == 0)
217296465Sdelphij            ssl_method = SSLv3_method();
218296465Sdelphij        else if (strcmp(*argv, "-ssl2") == 0)
219296465Sdelphij            ssl_method = SSLv2_method();
220296465Sdelphij        else if (strcmp(*argv, "-CApath") == 0) {
221296465Sdelphij            if (--argc < 1)
222296465Sdelphij                goto bad;
223296465Sdelphij            CApath = *(++argv);
224296465Sdelphij        } else if (strcmp(*argv, "-CAfile") == 0) {
225296465Sdelphij            if (--argc < 1)
226296465Sdelphij                goto bad;
227296465Sdelphij            CAfile = *(++argv);
228296465Sdelphij        } else if (strcmp(*argv, "-cert") == 0) {
229296465Sdelphij            if (--argc < 1)
230296465Sdelphij                goto bad;
231296465Sdelphij            scert = *(++argv);
232296465Sdelphij        } else if (strcmp(*argv, "-ccert") == 0) {
233296465Sdelphij            if (--argc < 1)
234296465Sdelphij                goto bad;
235296465Sdelphij            ccert = *(++argv);
236296465Sdelphij        } else if (strcmp(*argv, "-threads") == 0) {
237296465Sdelphij            if (--argc < 1)
238296465Sdelphij                goto bad;
239296465Sdelphij            thread_number = atoi(*(++argv));
240296465Sdelphij            if (thread_number == 0)
241296465Sdelphij                thread_number = 1;
242296465Sdelphij            if (thread_number > MAX_THREAD_NUMBER)
243296465Sdelphij                thread_number = MAX_THREAD_NUMBER;
244296465Sdelphij        } else if (strcmp(*argv, "-loops") == 0) {
245296465Sdelphij            if (--argc < 1)
246296465Sdelphij                goto bad;
247296465Sdelphij            number_of_loops = atoi(*(++argv));
248296465Sdelphij            if (number_of_loops == 0)
249296465Sdelphij                number_of_loops = 1;
250296465Sdelphij        } else {
251296465Sdelphij            fprintf(stderr, "unknown option %s\n", *argv);
252296465Sdelphij            badop = 1;
253296465Sdelphij            break;
254296465Sdelphij        }
255296465Sdelphij        argc--;
256296465Sdelphij        argv++;
257296465Sdelphij    }
258296465Sdelphij    if (badop) {
259296465Sdelphij bad:
260296465Sdelphij        sv_usage();
261296465Sdelphij        goto end;
262296465Sdelphij    }
26355714Skris
264296465Sdelphij    if (cipher == NULL && OPENSSL_issetugid() == 0)
265296465Sdelphij        cipher = getenv("SSL_CIPHER");
26655714Skris
267296465Sdelphij    SSL_load_error_strings();
268296465Sdelphij    OpenSSL_add_ssl_algorithms();
26955714Skris
270296465Sdelphij    c_ctx = SSL_CTX_new(ssl_method);
271296465Sdelphij    s_ctx = SSL_CTX_new(ssl_method);
272296465Sdelphij    if ((c_ctx == NULL) || (s_ctx == NULL)) {
273296465Sdelphij        ERR_print_errors(bio_err);
274296465Sdelphij        goto end;
275296465Sdelphij    }
27655714Skris
277296465Sdelphij    SSL_CTX_set_session_cache_mode(s_ctx,
278296465Sdelphij                                   SSL_SESS_CACHE_NO_AUTO_CLEAR |
279296465Sdelphij                                   SSL_SESS_CACHE_SERVER);
280296465Sdelphij    SSL_CTX_set_session_cache_mode(c_ctx,
281296465Sdelphij                                   SSL_SESS_CACHE_NO_AUTO_CLEAR |
282296465Sdelphij                                   SSL_SESS_CACHE_SERVER);
28355714Skris
284296465Sdelphij    if (!SSL_CTX_use_certificate_file(s_ctx, scert, SSL_FILETYPE_PEM)) {
285296465Sdelphij        ERR_print_errors(bio_err);
286296465Sdelphij    } else
287296465Sdelphij        if (!SSL_CTX_use_RSAPrivateKey_file(s_ctx, scert, SSL_FILETYPE_PEM)) {
288296465Sdelphij        ERR_print_errors(bio_err);
289296465Sdelphij        goto end;
290296465Sdelphij    }
29155714Skris
292296465Sdelphij    if (client_auth) {
293296465Sdelphij        SSL_CTX_use_certificate_file(c_ctx, ccert, SSL_FILETYPE_PEM);
294296465Sdelphij        SSL_CTX_use_RSAPrivateKey_file(c_ctx, ccert, SSL_FILETYPE_PEM);
295296465Sdelphij    }
29655714Skris
297296465Sdelphij    if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) ||
298296465Sdelphij        (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
299296465Sdelphij        (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) ||
300296465Sdelphij        (!SSL_CTX_set_default_verify_paths(c_ctx))) {
301296465Sdelphij        fprintf(stderr, "SSL_load_verify_locations\n");
302296465Sdelphij        ERR_print_errors(bio_err);
303296465Sdelphij        goto end;
304296465Sdelphij    }
30555714Skris
306296465Sdelphij    if (client_auth) {
307296465Sdelphij        fprintf(stderr, "client authentication\n");
308296465Sdelphij        SSL_CTX_set_verify(s_ctx,
309296465Sdelphij                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
310296465Sdelphij                           verify_callback);
311296465Sdelphij    }
312296465Sdelphij    if (server_auth) {
313296465Sdelphij        fprintf(stderr, "server authentication\n");
314296465Sdelphij        SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, verify_callback);
315296465Sdelphij    }
31655714Skris
317296465Sdelphij    thread_setup();
318296465Sdelphij    do_threads(s_ctx, c_ctx);
319296465Sdelphij    thread_cleanup();
320296465Sdelphij end:
32155714Skris
322296465Sdelphij    if (c_ctx != NULL) {
323296465Sdelphij        fprintf(stderr, "Client SSL_CTX stats then free it\n");
324296465Sdelphij        print_stats(stderr, c_ctx);
325296465Sdelphij        SSL_CTX_free(c_ctx);
326296465Sdelphij    }
327296465Sdelphij    if (s_ctx != NULL) {
328296465Sdelphij        fprintf(stderr, "Server SSL_CTX stats then free it\n");
329296465Sdelphij        print_stats(stderr, s_ctx);
330296465Sdelphij        if (cache_stats) {
331296465Sdelphij            fprintf(stderr, "-----\n");
332296465Sdelphij            lh_stats(SSL_CTX_sessions(s_ctx), stderr);
333296465Sdelphij            fprintf(stderr, "-----\n");
334296465Sdelphij    /*-     lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
335296465Sdelphij            fprintf(stderr,"-----\n"); */
336296465Sdelphij            lh_node_usage_stats(SSL_CTX_sessions(s_ctx), stderr);
337296465Sdelphij            fprintf(stderr, "-----\n");
338296465Sdelphij        }
339296465Sdelphij        SSL_CTX_free(s_ctx);
340296465Sdelphij        fprintf(stderr, "done free\n");
341296465Sdelphij    }
342296465Sdelphij    exit(ret);
343296465Sdelphij    return (0);
344296465Sdelphij}
34555714Skris
346296465Sdelphij#define W_READ  1
347296465Sdelphij#define W_WRITE 2
348296465Sdelphij#define C_DONE  1
349296465Sdelphij#define S_DONE  2
350296465Sdelphij
35155714Skrisint ndoit(SSL_CTX *ssl_ctx[2])
352296465Sdelphij{
353296465Sdelphij    int i;
354296465Sdelphij    int ret;
355296465Sdelphij    char *ctx[4];
35655714Skris
357296465Sdelphij    ctx[0] = (char *)ssl_ctx[0];
358296465Sdelphij    ctx[1] = (char *)ssl_ctx[1];
35955714Skris
360296465Sdelphij    if (reconnect) {
361296465Sdelphij        ctx[2] = (char *)SSL_new(ssl_ctx[0]);
362296465Sdelphij        ctx[3] = (char *)SSL_new(ssl_ctx[1]);
363296465Sdelphij    } else {
364296465Sdelphij        ctx[2] = NULL;
365296465Sdelphij        ctx[3] = NULL;
366296465Sdelphij    }
36755714Skris
368296465Sdelphij    fprintf(stdout, "started thread %lu\n", CRYPTO_thread_id());
369296465Sdelphij    for (i = 0; i < number_of_loops; i++) {
370296465Sdelphij/*-     fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
371296465Sdelphij            CRYPTO_thread_id(),i,
372296465Sdelphij            ssl_ctx[0]->references,
373296465Sdelphij            ssl_ctx[1]->references); */
374296465Sdelphij/*      pthread_delay_np(&tm); */
37555714Skris
376296465Sdelphij        ret = doit(ctx);
377296465Sdelphij        if (ret != 0) {
378296465Sdelphij            fprintf(stdout, "error[%d] %lu - %d\n",
379296465Sdelphij                    i, CRYPTO_thread_id(), ret);
380296465Sdelphij            return (ret);
381296465Sdelphij        }
382296465Sdelphij    }
383296465Sdelphij    fprintf(stdout, "DONE %lu\n", CRYPTO_thread_id());
384296465Sdelphij    if (reconnect) {
385296465Sdelphij        SSL_free((SSL *)ctx[2]);
386296465Sdelphij        SSL_free((SSL *)ctx[3]);
387296465Sdelphij    }
388296465Sdelphij#ifdef OPENSSL_SYS_NETWARE
389296465Sdelphij    MPKSemaphoreSignal(ThreadSem);
390296465Sdelphij#endif
391296465Sdelphij    return (0);
392296465Sdelphij}
39355714Skris
39455714Skrisint doit(char *ctx[4])
395296465Sdelphij{
396296465Sdelphij    SSL_CTX *s_ctx, *c_ctx;
397296465Sdelphij    static char cbuf[200], sbuf[200];
398296465Sdelphij    SSL *c_ssl = NULL;
399296465Sdelphij    SSL *s_ssl = NULL;
400296465Sdelphij    BIO *c_to_s = NULL;
401296465Sdelphij    BIO *s_to_c = NULL;
402296465Sdelphij    BIO *c_bio = NULL;
403296465Sdelphij    BIO *s_bio = NULL;
404296465Sdelphij    int c_r, c_w, s_r, s_w;
405296465Sdelphij    int c_want, s_want;
406296465Sdelphij    int i;
407296465Sdelphij    int done = 0;
408296465Sdelphij    int c_write, s_write;
409296465Sdelphij    int do_server = 0, do_client = 0;
41055714Skris
411296465Sdelphij    s_ctx = (SSL_CTX *)ctx[0];
412296465Sdelphij    c_ctx = (SSL_CTX *)ctx[1];
41355714Skris
414296465Sdelphij    if (ctx[2] != NULL)
415296465Sdelphij        s_ssl = (SSL *)ctx[2];
416296465Sdelphij    else
417296465Sdelphij        s_ssl = SSL_new(s_ctx);
41855714Skris
419296465Sdelphij    if (ctx[3] != NULL)
420296465Sdelphij        c_ssl = (SSL *)ctx[3];
421296465Sdelphij    else
422296465Sdelphij        c_ssl = SSL_new(c_ctx);
42355714Skris
424296465Sdelphij    if ((s_ssl == NULL) || (c_ssl == NULL))
425296465Sdelphij        goto err;
42655714Skris
427296465Sdelphij    c_to_s = BIO_new(BIO_s_mem());
428296465Sdelphij    s_to_c = BIO_new(BIO_s_mem());
429296465Sdelphij    if ((s_to_c == NULL) || (c_to_s == NULL))
430296465Sdelphij        goto err;
43155714Skris
432296465Sdelphij    c_bio = BIO_new(BIO_f_ssl());
433296465Sdelphij    s_bio = BIO_new(BIO_f_ssl());
434296465Sdelphij    if ((c_bio == NULL) || (s_bio == NULL))
435296465Sdelphij        goto err;
43655714Skris
437296465Sdelphij    SSL_set_connect_state(c_ssl);
438296465Sdelphij    SSL_set_bio(c_ssl, s_to_c, c_to_s);
439296465Sdelphij    BIO_set_ssl(c_bio, c_ssl, (ctx[2] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
44055714Skris
441296465Sdelphij    SSL_set_accept_state(s_ssl);
442296465Sdelphij    SSL_set_bio(s_ssl, c_to_s, s_to_c);
443296465Sdelphij    BIO_set_ssl(s_bio, s_ssl, (ctx[3] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
44455714Skris
445296465Sdelphij    c_r = 0;
446296465Sdelphij    s_r = 1;
447296465Sdelphij    c_w = 1;
448296465Sdelphij    s_w = 0;
449296465Sdelphij    c_want = W_WRITE;
450296465Sdelphij    s_want = 0;
451296465Sdelphij    c_write = 1, s_write = 0;
45255714Skris
453296465Sdelphij    /* We can always do writes */
454296465Sdelphij    for (;;) {
455296465Sdelphij        do_server = 0;
456296465Sdelphij        do_client = 0;
45755714Skris
458296465Sdelphij        i = (int)BIO_pending(s_bio);
459296465Sdelphij        if ((i && s_r) || s_w)
460296465Sdelphij            do_server = 1;
46155714Skris
462296465Sdelphij        i = (int)BIO_pending(c_bio);
463296465Sdelphij        if ((i && c_r) || c_w)
464296465Sdelphij            do_client = 1;
46555714Skris
466296465Sdelphij        if (do_server && verbose) {
467296465Sdelphij            if (SSL_in_init(s_ssl))
468296465Sdelphij                printf("server waiting in SSL_accept - %s\n",
469296465Sdelphij                       SSL_state_string_long(s_ssl));
470296465Sdelphij            else if (s_write)
471296465Sdelphij                printf("server:SSL_write()\n");
472296465Sdelphij            else
473296465Sdelphij                printf("server:SSL_read()\n");
474296465Sdelphij        }
47555714Skris
476296465Sdelphij        if (do_client && verbose) {
477296465Sdelphij            if (SSL_in_init(c_ssl))
478296465Sdelphij                printf("client waiting in SSL_connect - %s\n",
479296465Sdelphij                       SSL_state_string_long(c_ssl));
480296465Sdelphij            else if (c_write)
481296465Sdelphij                printf("client:SSL_write()\n");
482296465Sdelphij            else
483296465Sdelphij                printf("client:SSL_read()\n");
484296465Sdelphij        }
48555714Skris
486296465Sdelphij        if (!do_client && !do_server) {
487296465Sdelphij            fprintf(stdout, "ERROR IN STARTUP\n");
488296465Sdelphij            break;
489296465Sdelphij        }
490296465Sdelphij        if (do_client && !(done & C_DONE)) {
491296465Sdelphij            if (c_write) {
492296465Sdelphij                i = BIO_write(c_bio, "hello from client\n", 18);
493296465Sdelphij                if (i < 0) {
494296465Sdelphij                    c_r = 0;
495296465Sdelphij                    c_w = 0;
496296465Sdelphij                    if (BIO_should_retry(c_bio)) {
497296465Sdelphij                        if (BIO_should_read(c_bio))
498296465Sdelphij                            c_r = 1;
499296465Sdelphij                        if (BIO_should_write(c_bio))
500296465Sdelphij                            c_w = 1;
501296465Sdelphij                    } else {
502296465Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
503296465Sdelphij                        ERR_print_errors_fp(stderr);
504296465Sdelphij                        return (1);
505296465Sdelphij                    }
506296465Sdelphij                } else if (i == 0) {
507296465Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
508296465Sdelphij                    return (1);
509296465Sdelphij                } else {
510296465Sdelphij                    /* ok */
511296465Sdelphij                    c_write = 0;
512296465Sdelphij                }
513296465Sdelphij            } else {
514296465Sdelphij                i = BIO_read(c_bio, cbuf, 100);
515296465Sdelphij                if (i < 0) {
516296465Sdelphij                    c_r = 0;
517296465Sdelphij                    c_w = 0;
518296465Sdelphij                    if (BIO_should_retry(c_bio)) {
519296465Sdelphij                        if (BIO_should_read(c_bio))
520296465Sdelphij                            c_r = 1;
521296465Sdelphij                        if (BIO_should_write(c_bio))
522296465Sdelphij                            c_w = 1;
523296465Sdelphij                    } else {
524296465Sdelphij                        fprintf(stderr, "ERROR in CLIENT\n");
525296465Sdelphij                        ERR_print_errors_fp(stderr);
526296465Sdelphij                        return (1);
527296465Sdelphij                    }
528296465Sdelphij                } else if (i == 0) {
529296465Sdelphij                    fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
530296465Sdelphij                    return (1);
531296465Sdelphij                } else {
532296465Sdelphij                    done |= C_DONE;
53355714Skris#ifdef undef
534296465Sdelphij                    fprintf(stdout, "CLIENT:from server:");
535296465Sdelphij                    fwrite(cbuf, 1, i, stdout);
536296465Sdelphij                    fflush(stdout);
53755714Skris#endif
538296465Sdelphij                }
539296465Sdelphij            }
540296465Sdelphij        }
54155714Skris
542296465Sdelphij        if (do_server && !(done & S_DONE)) {
543296465Sdelphij            if (!s_write) {
544296465Sdelphij                i = BIO_read(s_bio, sbuf, 100);
545296465Sdelphij                if (i < 0) {
546296465Sdelphij                    s_r = 0;
547296465Sdelphij                    s_w = 0;
548296465Sdelphij                    if (BIO_should_retry(s_bio)) {
549296465Sdelphij                        if (BIO_should_read(s_bio))
550296465Sdelphij                            s_r = 1;
551296465Sdelphij                        if (BIO_should_write(s_bio))
552296465Sdelphij                            s_w = 1;
553296465Sdelphij                    } else {
554296465Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
555296465Sdelphij                        ERR_print_errors_fp(stderr);
556296465Sdelphij                        return (1);
557296465Sdelphij                    }
558296465Sdelphij                } else if (i == 0) {
559296465Sdelphij                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
560296465Sdelphij                    return (1);
561296465Sdelphij                } else {
562296465Sdelphij                    s_write = 1;
563296465Sdelphij                    s_w = 1;
56455714Skris#ifdef undef
565296465Sdelphij                    fprintf(stdout, "SERVER:from client:");
566296465Sdelphij                    fwrite(sbuf, 1, i, stdout);
567296465Sdelphij                    fflush(stdout);
56855714Skris#endif
569296465Sdelphij                }
570296465Sdelphij            } else {
571296465Sdelphij                i = BIO_write(s_bio, "hello from server\n", 18);
572296465Sdelphij                if (i < 0) {
573296465Sdelphij                    s_r = 0;
574296465Sdelphij                    s_w = 0;
575296465Sdelphij                    if (BIO_should_retry(s_bio)) {
576296465Sdelphij                        if (BIO_should_read(s_bio))
577296465Sdelphij                            s_r = 1;
578296465Sdelphij                        if (BIO_should_write(s_bio))
579296465Sdelphij                            s_w = 1;
580296465Sdelphij                    } else {
581296465Sdelphij                        fprintf(stderr, "ERROR in SERVER\n");
582296465Sdelphij                        ERR_print_errors_fp(stderr);
583296465Sdelphij                        return (1);
584296465Sdelphij                    }
585296465Sdelphij                } else if (i == 0) {
586296465Sdelphij                    fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
587296465Sdelphij                    return (1);
588296465Sdelphij                } else {
589296465Sdelphij                    s_write = 0;
590296465Sdelphij                    s_r = 1;
591296465Sdelphij                    done |= S_DONE;
592296465Sdelphij                }
593296465Sdelphij            }
594296465Sdelphij        }
59555714Skris
596296465Sdelphij        if ((done & S_DONE) && (done & C_DONE))
597296465Sdelphij            break;
598296465Sdelphij#if defined(OPENSSL_SYS_NETWARE)
599160814Ssimon        ThreadSwitchWithDelay();
600296465Sdelphij#endif
601296465Sdelphij    }
60255714Skris
603296465Sdelphij    SSL_set_shutdown(c_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
604296465Sdelphij    SSL_set_shutdown(s_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
60555714Skris
60655714Skris#ifdef undef
607296465Sdelphij    fprintf(stdout, "DONE\n");
60855714Skris#endif
609296465Sdelphij err:
610296465Sdelphij    /*
611296465Sdelphij     * We have to set the BIO's to NULL otherwise they will be free()ed
612296465Sdelphij     * twice.  Once when th s_ssl is SSL_free()ed and again when c_ssl is
613296465Sdelphij     * SSL_free()ed. This is a hack required because s_ssl and c_ssl are
614296465Sdelphij     * sharing the same BIO structure and SSL_set_bio() and SSL_free()
615296465Sdelphij     * automatically BIO_free non NULL entries. You should not normally do
616296465Sdelphij     * this or be required to do this
617296465Sdelphij     */
61855714Skris
619296465Sdelphij    if (s_ssl != NULL) {
620296465Sdelphij        s_ssl->rbio = NULL;
621296465Sdelphij        s_ssl->wbio = NULL;
622296465Sdelphij    }
623296465Sdelphij    if (c_ssl != NULL) {
624296465Sdelphij        c_ssl->rbio = NULL;
625296465Sdelphij        c_ssl->wbio = NULL;
626296465Sdelphij    }
62755714Skris
628296465Sdelphij    /* The SSL's are optionally freed in the following calls */
629296465Sdelphij    if (c_to_s != NULL)
630296465Sdelphij        BIO_free(c_to_s);
631296465Sdelphij    if (s_to_c != NULL)
632296465Sdelphij        BIO_free(s_to_c);
63355714Skris
634296465Sdelphij    if (c_bio != NULL)
635296465Sdelphij        BIO_free(c_bio);
636296465Sdelphij    if (s_bio != NULL)
637296465Sdelphij        BIO_free(s_bio);
638296465Sdelphij    return (0);
639296465Sdelphij}
64055714Skris
64159191Skrisint MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
642296465Sdelphij{
643296465Sdelphij    char *s, buf[256];
64455714Skris
645296465Sdelphij    if (verbose) {
646296465Sdelphij        s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
647296465Sdelphij                              buf, 256);
648296465Sdelphij        if (s != NULL) {
649296465Sdelphij            if (ok)
650296465Sdelphij                fprintf(stderr, "depth=%d %s\n", ctx->error_depth, buf);
651296465Sdelphij            else
652296465Sdelphij                fprintf(stderr, "depth=%d error=%d %s\n",
653296465Sdelphij                        ctx->error_depth, ctx->error, buf);
654296465Sdelphij        }
655296465Sdelphij    }
656296465Sdelphij    return (ok);
657296465Sdelphij}
65855714Skris
65955714Skris#define THREAD_STACK_SIZE (16*1024)
66055714Skris
661109998Smarkm#ifdef OPENSSL_SYS_WIN32
66255714Skris
66359191Skrisstatic HANDLE *lock_cs;
66455714Skris
66555714Skrisvoid thread_setup(void)
666296465Sdelphij{
667296465Sdelphij    int i;
66855714Skris
669296465Sdelphij    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
670296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
671296465Sdelphij        lock_cs[i] = CreateMutex(NULL, FALSE, NULL);
672296465Sdelphij    }
67355714Skris
674296465Sdelphij    CRYPTO_set_locking_callback((void (*)(int, int, char *, int))
675296465Sdelphij                                win32_locking_callback);
676296465Sdelphij    /* id callback defined */
677296465Sdelphij}
67855714Skris
67955714Skrisvoid thread_cleanup(void)
680296465Sdelphij{
681296465Sdelphij    int i;
68255714Skris
683296465Sdelphij    CRYPTO_set_locking_callback(NULL);
684296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++)
685296465Sdelphij        CloseHandle(lock_cs[i]);
686296465Sdelphij    OPENSSL_free(lock_cs);
687296465Sdelphij}
68855714Skris
68955714Skrisvoid win32_locking_callback(int mode, int type, char *file, int line)
690296465Sdelphij{
691296465Sdelphij    if (mode & CRYPTO_LOCK) {
692296465Sdelphij        WaitForSingleObject(lock_cs[type], INFINITE);
693296465Sdelphij    } else {
694296465Sdelphij        ReleaseMutex(lock_cs[type]);
695296465Sdelphij    }
696296465Sdelphij}
69755714Skris
69855714Skrisvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
699296465Sdelphij{
700296465Sdelphij    double ret;
701296465Sdelphij    SSL_CTX *ssl_ctx[2];
702296465Sdelphij    DWORD thread_id[MAX_THREAD_NUMBER];
703296465Sdelphij    HANDLE thread_handle[MAX_THREAD_NUMBER];
704296465Sdelphij    int i;
705296465Sdelphij    SYSTEMTIME start, end;
70655714Skris
707296465Sdelphij    ssl_ctx[0] = s_ctx;
708296465Sdelphij    ssl_ctx[1] = c_ctx;
70955714Skris
710296465Sdelphij    GetSystemTime(&start);
711296465Sdelphij    for (i = 0; i < thread_number; i++) {
712296465Sdelphij        thread_handle[i] = CreateThread(NULL,
713296465Sdelphij                                        THREAD_STACK_SIZE,
714296465Sdelphij                                        (LPTHREAD_START_ROUTINE) ndoit,
715296465Sdelphij                                        (void *)ssl_ctx, 0L, &(thread_id[i]));
716296465Sdelphij    }
71755714Skris
718296465Sdelphij    printf("reaping\n");
719296465Sdelphij    for (i = 0; i < thread_number; i += 50) {
720296465Sdelphij        int j;
72155714Skris
722296465Sdelphij        j = (thread_number < (i + 50)) ? (thread_number - i) : 50;
72355714Skris
724296465Sdelphij        if (WaitForMultipleObjects(j,
725296465Sdelphij                                   (CONST HANDLE *) & (thread_handle[i]),
726296465Sdelphij                                   TRUE, INFINITE)
727296465Sdelphij            == WAIT_FAILED) {
728296465Sdelphij            fprintf(stderr, "WaitForMultipleObjects failed:%d\n",
729296465Sdelphij                    GetLastError());
730296465Sdelphij            exit(1);
731296465Sdelphij        }
732296465Sdelphij    }
733296465Sdelphij    GetSystemTime(&end);
73455714Skris
735296465Sdelphij    if (start.wDayOfWeek > end.wDayOfWeek)
736296465Sdelphij        end.wDayOfWeek += 7;
737296465Sdelphij    ret = (end.wDayOfWeek - start.wDayOfWeek) * 24;
73855714Skris
739296465Sdelphij    ret = (ret + end.wHour - start.wHour) * 60;
740296465Sdelphij    ret = (ret + end.wMinute - start.wMinute) * 60;
741296465Sdelphij    ret = (ret + end.wSecond - start.wSecond);
742296465Sdelphij    ret += (end.wMilliseconds - start.wMilliseconds) / 1000.0;
74355714Skris
744296465Sdelphij    printf("win32 threads done - %.3f seconds\n", ret);
745296465Sdelphij}
74655714Skris
747296465Sdelphij#endif                          /* OPENSSL_SYS_WIN32 */
74855714Skris
74955714Skris#ifdef SOLARIS
75055714Skris
75159191Skrisstatic mutex_t *lock_cs;
752296465Sdelphij/*
753296465Sdelphij * static rwlock_t *lock_cs;
754296465Sdelphij */
75559191Skrisstatic long *lock_count;
75655714Skris
75755714Skrisvoid thread_setup(void)
758296465Sdelphij{
759296465Sdelphij    int i;
76055714Skris
761296465Sdelphij    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
762296465Sdelphij    lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
763296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
764296465Sdelphij        lock_count[i] = 0;
765296465Sdelphij        /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
766296465Sdelphij        mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
767296465Sdelphij    }
76855714Skris
769296465Sdelphij    CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
770296465Sdelphij    CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
771296465Sdelphij}
77255714Skris
77355714Skrisvoid thread_cleanup(void)
774296465Sdelphij{
775296465Sdelphij    int i;
77655714Skris
777296465Sdelphij    CRYPTO_set_locking_callback(NULL);
77859191Skris
779296465Sdelphij    fprintf(stderr, "cleanup\n");
78059191Skris
781296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
782296465Sdelphij        /* rwlock_destroy(&(lock_cs[i])); */
783296465Sdelphij        mutex_destroy(&(lock_cs[i]));
784296465Sdelphij        fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
785296465Sdelphij    }
786296465Sdelphij    OPENSSL_free(lock_cs);
787296465Sdelphij    OPENSSL_free(lock_count);
78859191Skris
789296465Sdelphij    fprintf(stderr, "done cleanup\n");
79059191Skris
791296465Sdelphij}
79255714Skris
79355714Skrisvoid solaris_locking_callback(int mode, int type, char *file, int line)
794296465Sdelphij{
795296465Sdelphij# ifdef undef
796296465Sdelphij    fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
797296465Sdelphij            CRYPTO_thread_id(),
798296465Sdelphij            (mode & CRYPTO_LOCK) ? "l" : "u",
799296465Sdelphij            (type & CRYPTO_READ) ? "r" : "w", file, line);
800296465Sdelphij# endif
80155714Skris
802296465Sdelphij    /*-
803296465Sdelphij    if (CRYPTO_LOCK_SSL_CERT == type)
804296465Sdelphij    fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
805296465Sdelphij            CRYPTO_thread_id(),
806296465Sdelphij            mode,file,line);
807296465Sdelphij    */
808296465Sdelphij    if (mode & CRYPTO_LOCK) {
809296465Sdelphij        /*-
810296465Sdelphij        if (mode & CRYPTO_READ)
811296465Sdelphij                rw_rdlock(&(lock_cs[type]));
812296465Sdelphij        else
813296465Sdelphij                rw_wrlock(&(lock_cs[type])); */
81455714Skris
815296465Sdelphij        mutex_lock(&(lock_cs[type]));
816296465Sdelphij        lock_count[type]++;
817296465Sdelphij    } else {
818296465Sdelphij/*      rw_unlock(&(lock_cs[type]));  */
819296465Sdelphij        mutex_unlock(&(lock_cs[type]));
820296465Sdelphij    }
821296465Sdelphij}
82255714Skris
82355714Skrisvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
824296465Sdelphij{
825296465Sdelphij    SSL_CTX *ssl_ctx[2];
826296465Sdelphij    thread_t thread_ctx[MAX_THREAD_NUMBER];
827296465Sdelphij    int i;
82855714Skris
829296465Sdelphij    ssl_ctx[0] = s_ctx;
830296465Sdelphij    ssl_ctx[1] = c_ctx;
83155714Skris
832296465Sdelphij    thr_setconcurrency(thread_number);
833296465Sdelphij    for (i = 0; i < thread_number; i++) {
834296465Sdelphij        thr_create(NULL, THREAD_STACK_SIZE,
835296465Sdelphij                   (void *(*)())ndoit, (void *)ssl_ctx, 0L, &(thread_ctx[i]));
836296465Sdelphij    }
83755714Skris
838296465Sdelphij    printf("reaping\n");
839296465Sdelphij    for (i = 0; i < thread_number; i++) {
840296465Sdelphij        thr_join(thread_ctx[i], NULL, NULL);
841296465Sdelphij    }
84255714Skris
843296465Sdelphij    printf("solaris threads done (%d,%d)\n",
844296465Sdelphij           s_ctx->references, c_ctx->references);
845296465Sdelphij}
84655714Skris
84755714Skrisunsigned long solaris_thread_id(void)
848296465Sdelphij{
849296465Sdelphij    unsigned long ret;
85055714Skris
851296465Sdelphij    ret = (unsigned long)thr_self();
852296465Sdelphij    return (ret);
853296465Sdelphij}
854296465Sdelphij#endif                          /* SOLARIS */
85555714Skris
85655714Skris#ifdef IRIX
85755714Skris
85855714Skrisstatic usptr_t *arena;
85959191Skrisstatic usema_t **lock_cs;
86055714Skris
86155714Skrisvoid thread_setup(void)
862296465Sdelphij{
863296465Sdelphij    int i;
864296465Sdelphij    char filename[20];
86555714Skris
866296465Sdelphij    strcpy(filename, "/tmp/mttest.XXXXXX");
867296465Sdelphij    mktemp(filename);
86855714Skris
869296465Sdelphij    usconfig(CONF_STHREADIOOFF);
870296465Sdelphij    usconfig(CONF_STHREADMALLOCOFF);
871296465Sdelphij    usconfig(CONF_INITUSERS, 100);
872296465Sdelphij    usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
873296465Sdelphij    arena = usinit(filename);
874296465Sdelphij    unlink(filename);
87555714Skris
876296465Sdelphij    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *));
877296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
878296465Sdelphij        lock_cs[i] = usnewsema(arena, 1);
879296465Sdelphij    }
88055714Skris
881296465Sdelphij    CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
882296465Sdelphij    CRYPTO_set_locking_callback((void (*)())irix_locking_callback);
883296465Sdelphij}
88455714Skris
88555714Skrisvoid thread_cleanup(void)
886296465Sdelphij{
887296465Sdelphij    int i;
88855714Skris
889296465Sdelphij    CRYPTO_set_locking_callback(NULL);
890296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
891296465Sdelphij        char buf[10];
89255714Skris
893296465Sdelphij        sprintf(buf, "%2d:", i);
894296465Sdelphij        usdumpsema(lock_cs[i], stdout, buf);
895296465Sdelphij        usfreesema(lock_cs[i], arena);
896296465Sdelphij    }
897296465Sdelphij    OPENSSL_free(lock_cs);
898296465Sdelphij}
89955714Skris
90055714Skrisvoid irix_locking_callback(int mode, int type, char *file, int line)
901296465Sdelphij{
902296465Sdelphij    if (mode & CRYPTO_LOCK) {
903296465Sdelphij        printf("lock %d\n", type);
904296465Sdelphij        uspsema(lock_cs[type]);
905296465Sdelphij    } else {
906296465Sdelphij        printf("unlock %d\n", type);
907296465Sdelphij        usvsema(lock_cs[type]);
908296465Sdelphij    }
909296465Sdelphij}
91055714Skris
91155714Skrisvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
912296465Sdelphij{
913296465Sdelphij    SSL_CTX *ssl_ctx[2];
914296465Sdelphij    int thread_ctx[MAX_THREAD_NUMBER];
915296465Sdelphij    int i;
91655714Skris
917296465Sdelphij    ssl_ctx[0] = s_ctx;
918296465Sdelphij    ssl_ctx[1] = c_ctx;
91955714Skris
920296465Sdelphij    for (i = 0; i < thread_number; i++) {
921296465Sdelphij        thread_ctx[i] = sproc((void (*)())ndoit,
922296465Sdelphij                              PR_SADDR | PR_SFDS, (void *)ssl_ctx);
923296465Sdelphij    }
92455714Skris
925296465Sdelphij    printf("reaping\n");
926296465Sdelphij    for (i = 0; i < thread_number; i++) {
927296465Sdelphij        wait(NULL);
928296465Sdelphij    }
92955714Skris
930296465Sdelphij    printf("irix threads done (%d,%d)\n",
931296465Sdelphij           s_ctx->references, c_ctx->references);
932296465Sdelphij}
93355714Skris
93455714Skrisunsigned long irix_thread_id(void)
935296465Sdelphij{
936296465Sdelphij    unsigned long ret;
93755714Skris
938296465Sdelphij    ret = (unsigned long)getpid();
939296465Sdelphij    return (ret);
940296465Sdelphij}
941296465Sdelphij#endif                          /* IRIX */
94255714Skris
94355714Skris#ifdef PTHREADS
94455714Skris
94559191Skrisstatic pthread_mutex_t *lock_cs;
94659191Skrisstatic long *lock_count;
94755714Skris
94855714Skrisvoid thread_setup(void)
949296465Sdelphij{
950296465Sdelphij    int i;
95155714Skris
952296465Sdelphij    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
953296465Sdelphij    lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
954296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
955296465Sdelphij        lock_count[i] = 0;
956296465Sdelphij        pthread_mutex_init(&(lock_cs[i]), NULL);
957296465Sdelphij    }
95855714Skris
959296465Sdelphij    CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
960296465Sdelphij    CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
961296465Sdelphij}
96255714Skris
96355714Skrisvoid thread_cleanup(void)
964296465Sdelphij{
965296465Sdelphij    int i;
96655714Skris
967296465Sdelphij    CRYPTO_set_locking_callback(NULL);
968296465Sdelphij    fprintf(stderr, "cleanup\n");
969296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
970296465Sdelphij        pthread_mutex_destroy(&(lock_cs[i]));
971296465Sdelphij        fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
972296465Sdelphij    }
973296465Sdelphij    OPENSSL_free(lock_cs);
974296465Sdelphij    OPENSSL_free(lock_count);
97559191Skris
976296465Sdelphij    fprintf(stderr, "done cleanup\n");
977296465Sdelphij}
97855714Skris
979296465Sdelphijvoid pthreads_locking_callback(int mode, int type, char *file, int line)
980296465Sdelphij{
981296465Sdelphij# ifdef undef
982296465Sdelphij    fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
983296465Sdelphij            CRYPTO_thread_id(),
984296465Sdelphij            (mode & CRYPTO_LOCK) ? "l" : "u",
985296465Sdelphij            (type & CRYPTO_READ) ? "r" : "w", file, line);
986296465Sdelphij# endif
987296465Sdelphij/*-
988296465Sdelphij    if (CRYPTO_LOCK_SSL_CERT == type)
989296465Sdelphij            fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
990296465Sdelphij            CRYPTO_thread_id(),
991296465Sdelphij            mode,file,line);
99255714Skris*/
993296465Sdelphij    if (mode & CRYPTO_LOCK) {
994296465Sdelphij        pthread_mutex_lock(&(lock_cs[type]));
995296465Sdelphij        lock_count[type]++;
996296465Sdelphij    } else {
997296465Sdelphij        pthread_mutex_unlock(&(lock_cs[type]));
998296465Sdelphij    }
999296465Sdelphij}
100055714Skris
100155714Skrisvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1002296465Sdelphij{
1003296465Sdelphij    SSL_CTX *ssl_ctx[2];
1004296465Sdelphij    pthread_t thread_ctx[MAX_THREAD_NUMBER];
1005296465Sdelphij    int i;
100655714Skris
1007296465Sdelphij    ssl_ctx[0] = s_ctx;
1008296465Sdelphij    ssl_ctx[1] = c_ctx;
100955714Skris
1010296465Sdelphij    /*
1011296465Sdelphij     * thr_setconcurrency(thread_number);
1012296465Sdelphij     */
1013296465Sdelphij    for (i = 0; i < thread_number; i++) {
1014296465Sdelphij        pthread_create(&(thread_ctx[i]), NULL,
1015296465Sdelphij                       (void *(*)())ndoit, (void *)ssl_ctx);
1016296465Sdelphij    }
101755714Skris
1018296465Sdelphij    printf("reaping\n");
1019296465Sdelphij    for (i = 0; i < thread_number; i++) {
1020296465Sdelphij        pthread_join(thread_ctx[i], NULL);
1021296465Sdelphij    }
102255714Skris
1023296465Sdelphij    printf("pthreads threads done (%d,%d)\n",
1024296465Sdelphij           s_ctx->references, c_ctx->references);
1025296465Sdelphij}
102655714Skris
102755714Skrisunsigned long pthreads_thread_id(void)
1028296465Sdelphij{
1029296465Sdelphij    unsigned long ret;
103055714Skris
1031296465Sdelphij    ret = (unsigned long)pthread_self();
1032296465Sdelphij    return (ret);
1033296465Sdelphij}
103455714Skris
1035296465Sdelphij#endif                          /* PTHREADS */
103655714Skris
1037160814Ssimon#ifdef OPENSSL_SYS_NETWARE
1038160814Ssimon
1039160814Ssimonvoid thread_setup(void)
1040160814Ssimon{
1041296465Sdelphij    int i;
1042160814Ssimon
1043296465Sdelphij    lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(MPKMutex));
1044296465Sdelphij    lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1045296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
1046296465Sdelphij        lock_count[i] = 0;
1047296465Sdelphij        lock_cs[i] = MPKMutexAlloc("OpenSSL mutex");
1048296465Sdelphij    }
1049160814Ssimon
1050296465Sdelphij    ThreadSem = MPKSemaphoreAlloc("OpenSSL mttest semaphore", 0);
1051160814Ssimon
1052296465Sdelphij    CRYPTO_set_id_callback((unsigned long (*)())netware_thread_id);
1053296465Sdelphij    CRYPTO_set_locking_callback((void (*)())netware_locking_callback);
1054160814Ssimon}
1055160814Ssimon
1056160814Ssimonvoid thread_cleanup(void)
1057160814Ssimon{
1058296465Sdelphij    int i;
1059160814Ssimon
1060296465Sdelphij    CRYPTO_set_locking_callback(NULL);
1061160814Ssimon
1062296465Sdelphij    fprintf(stdout, "thread_cleanup\n");
1063160814Ssimon
1064296465Sdelphij    for (i = 0; i < CRYPTO_num_locks(); i++) {
1065296465Sdelphij        MPKMutexFree(lock_cs[i]);
1066296465Sdelphij        fprintf(stdout, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
1067296465Sdelphij    }
1068296465Sdelphij    OPENSSL_free(lock_cs);
1069296465Sdelphij    OPENSSL_free(lock_count);
1070160814Ssimon
1071296465Sdelphij    MPKSemaphoreFree(ThreadSem);
1072160814Ssimon
1073296465Sdelphij    fprintf(stdout, "done cleanup\n");
1074160814Ssimon}
1075160814Ssimon
1076160814Ssimonvoid netware_locking_callback(int mode, int type, char *file, int line)
1077160814Ssimon{
1078296465Sdelphij    if (mode & CRYPTO_LOCK) {
1079296465Sdelphij        MPKMutexLock(lock_cs[type]);
1080296465Sdelphij        lock_count[type]++;
1081296465Sdelphij    } else
1082296465Sdelphij        MPKMutexUnlock(lock_cs[type]);
1083160814Ssimon}
1084160814Ssimon
1085160814Ssimonvoid do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1086160814Ssimon{
1087296465Sdelphij    SSL_CTX *ssl_ctx[2];
1088296465Sdelphij    int i;
1089296465Sdelphij    ssl_ctx[0] = s_ctx;
1090296465Sdelphij    ssl_ctx[1] = c_ctx;
1091160814Ssimon
1092296465Sdelphij    for (i = 0; i < thread_number; i++) {
1093296465Sdelphij        BeginThread((void (*)(void *))ndoit, NULL, THREAD_STACK_SIZE,
1094296465Sdelphij                    (void *)ssl_ctx);
1095296465Sdelphij        ThreadSwitchWithDelay();
1096296465Sdelphij    }
1097160814Ssimon
1098296465Sdelphij    printf("reaping\n");
1099160814Ssimon
1100296465Sdelphij    /* loop until all threads have signaled the semaphore */
1101296465Sdelphij    for (i = 0; i < thread_number; i++) {
1102296465Sdelphij        MPKSemaphoreWait(ThreadSem);
1103296465Sdelphij    }
1104296465Sdelphij    printf("netware threads done (%d,%d)\n",
1105296465Sdelphij           s_ctx->references, c_ctx->references);
1106160814Ssimon}
1107160814Ssimon
1108160814Ssimonunsigned long netware_thread_id(void)
1109160814Ssimon{
1110296465Sdelphij    unsigned long ret;
1111160814Ssimon
1112296465Sdelphij    ret = (unsigned long)GetThreadID();
1113296465Sdelphij    return (ret);
1114160814Ssimon}
1115296465Sdelphij#endif                          /* NETWARE */
1116