Change #include filenames from <foo.h> to <openssl.h>.
[openssl.git] / crypto / threads / mttest.c
1 /* crypto/threads/mttest.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <errno.h>
63 #ifdef LINUX
64 #include <typedefs.h>
65 #endif
66 #ifdef WIN32
67 #include <windows.h>
68 #endif
69 #ifdef SOLARIS
70 #include <synch.h>
71 #include <thread.h>
72 #endif
73 #ifdef IRIX
74 #include <ulocks.h>
75 #include <sys/prctl.h>
76 #endif
77 #include <openssl/lhash.h>
78 #include <openssl/crypto.h>
79 #include <openssl/buffer.h>
80 #include "../e_os.h"
81 #include <openssl/x509.h>
82 #include <openssl/ssl.h>
83 #include <openssl/err.h>
84
85 #ifdef NO_FP_API
86 #define APPS_WIN16
87 #include "../crypto/buffer/bss_file.c"
88 #endif
89
90 #define TEST_SERVER_CERT "../apps/server.pem"
91 #define TEST_CLIENT_CERT "../apps/client.pem"
92
93 #define MAX_THREAD_NUMBER       100
94
95 #ifndef NOPROTO
96 int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth,
97         int error,char *arg);
98 void thread_setup(void);
99 void thread_cleanup(void);
100 void do_threads(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
101
102 void irix_locking_callback(int mode,int type,char *file,int line);
103 void solaris_locking_callback(int mode,int type,char *file,int line);
104 void win32_locking_callback(int mode,int type,char *file,int line);
105 void pthreads_locking_callback(int mode,int type,char *file,int line);
106
107 unsigned long irix_thread_id(void );
108 unsigned long solaris_thread_id(void );
109 unsigned long pthreads_thread_id(void );
110
111 #else
112 int MS_CALLBACK verify_callback();
113 void thread_setup();
114 void thread_cleanup();
115 void do_threads();
116
117 void irix_locking_callback();
118 void solaris_locking_callback();
119 void win32_locking_callback();
120 void pthreads_locking_callback();
121
122 unsigned long irix_thread_id();
123 unsigned long solaris_thread_id();
124 unsigned long pthreads_thread_id();
125
126 #endif
127
128 BIO *bio_err=NULL;
129 BIO *bio_stdout=NULL;
130
131 static char *cipher=NULL;
132 int verbose=0;
133 #ifdef FIONBIO
134 static int s_nbio=0;
135 #endif
136
137 int thread_number=10;
138 int number_of_loops=10;
139 int reconnect=0;
140 int cache_stats=0;
141
142 #ifndef  NOPROTO
143 int doit(char *ctx[4]);
144 #else
145 int doit();
146 #endif
147
148 static void print_stats(FILE *fp, SSL_CTX *ctx)
149 {
150         fprintf(fp,"%4ld items in the session cache\n",
151                 SSL_CTX_sess_number(ctx));
152         fprintf(fp,"%4d client connects (SSL_connect())\n",
153                 SSL_CTX_sess_connect(ctx));
154         fprintf(fp,"%4d client connects that finished\n",
155                 SSL_CTX_sess_connect_good(ctx));
156         fprintf(fp,"%4d server connects (SSL_accept())\n",
157                 SSL_CTX_sess_accept(ctx));
158         fprintf(fp,"%4d server connects that finished\n",
159                 SSL_CTX_sess_accept_good(ctx));
160         fprintf(fp,"%4d session cache hits\n",SSL_CTX_sess_hits(ctx));
161         fprintf(fp,"%4d session cache misses\n",SSL_CTX_sess_misses(ctx));
162         fprintf(fp,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ctx));
163         }
164
165 static void sv_usage(void)
166         {
167         fprintf(stderr,"usage: ssltest [args ...]\n");
168         fprintf(stderr,"\n");
169         fprintf(stderr," -server_auth  - check server certificate\n");
170         fprintf(stderr," -client_auth  - do client authentication\n");
171         fprintf(stderr," -v            - more output\n");
172         fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
173         fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
174         fprintf(stderr," -threads arg  - number of threads\n");
175         fprintf(stderr," -loops arg    - number of 'connections', per thread\n");
176         fprintf(stderr," -reconnect    - reuse session-id's\n");
177         fprintf(stderr," -stats        - server session-id cache stats\n");
178         fprintf(stderr," -cert arg     - server certificate/key\n");
179         fprintf(stderr," -ccert arg    - client certificate/key\n");
180         fprintf(stderr," -ssl3         - just SSLv3n\n");
181         }
182
183 int main(int argc, char *argv[])
184         {
185         char *CApath=NULL,*CAfile=NULL;
186         int badop=0;
187         int ret=1;
188         int client_auth=0;
189         int server_auth=0;
190         SSL_CTX *s_ctx=NULL;
191         SSL_CTX *c_ctx=NULL;
192         char *scert=TEST_SERVER_CERT;
193         char *ccert=TEST_CLIENT_CERT;
194         SSL_METHOD *ssl_method=SSLv23_method();
195
196         if (bio_err == NULL)
197                 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
198         if (bio_stdout == NULL)
199                 bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
200         argc--;
201         argv++;
202
203         while (argc >= 1)
204                 {
205                 if      (strcmp(*argv,"-server_auth") == 0)
206                         server_auth=1;
207                 else if (strcmp(*argv,"-client_auth") == 0)
208                         client_auth=1;
209                 else if (strcmp(*argv,"-reconnect") == 0)
210                         reconnect=1;
211                 else if (strcmp(*argv,"-stats") == 0)
212                         cache_stats=1;
213                 else if (strcmp(*argv,"-ssl3") == 0)
214                         ssl_method=SSLv3_method();
215                 else if (strcmp(*argv,"-ssl2") == 0)
216                         ssl_method=SSLv2_method();
217                 else if (strcmp(*argv,"-CApath") == 0)
218                         {
219                         if (--argc < 1) goto bad;
220                         CApath= *(++argv);
221                         }
222                 else if (strcmp(*argv,"-CAfile") == 0)
223                         {
224                         if (--argc < 1) goto bad;
225                         CAfile= *(++argv);
226                         }
227                 else if (strcmp(*argv,"-cert") == 0)
228                         {
229                         if (--argc < 1) goto bad;
230                         scert= *(++argv);
231                         }
232                 else if (strcmp(*argv,"-ccert") == 0)
233                         {
234                         if (--argc < 1) goto bad;
235                         ccert= *(++argv);
236                         }
237                 else if (strcmp(*argv,"-threads") == 0)
238                         {
239                         if (--argc < 1) goto bad;
240                         thread_number= atoi(*(++argv));
241                         if (thread_number == 0) thread_number=1;
242                         if (thread_number > MAX_THREAD_NUMBER)
243                                 thread_number=MAX_THREAD_NUMBER;
244                         }
245                 else if (strcmp(*argv,"-loops") == 0)
246                         {
247                         if (--argc < 1) goto bad;
248                         number_of_loops= atoi(*(++argv));
249                         if (number_of_loops == 0) number_of_loops=1;
250                         }
251                 else
252                         {
253                         fprintf(stderr,"unknown option %s\n",*argv);
254                         badop=1;
255                         break;
256                         }
257                 argc--;
258                 argv++;
259                 }
260         if (badop)
261                 {
262 bad:
263                 sv_usage();
264                 goto end;
265                 }
266
267         if (cipher == NULL) cipher=getenv("SSL_CIPHER");
268
269         SSL_load_error_strings();
270         SSLeay_add_ssl_algorithms();
271
272         c_ctx=SSL_CTX_new(ssl_method);
273         s_ctx=SSL_CTX_new(ssl_method);
274         if ((c_ctx == NULL) || (s_ctx == NULL))
275                 {
276                 ERR_print_errors(bio_err);
277                 goto end;
278                 }
279
280         SSL_CTX_set_session_cache_mode(s_ctx,
281                 SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
282         SSL_CTX_set_session_cache_mode(c_ctx,
283                 SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
284
285         SSL_CTX_use_certificate_file(s_ctx,scert,SSL_FILETYPE_PEM);
286         SSL_CTX_use_RSAPrivateKey_file(s_ctx,scert,SSL_FILETYPE_PEM);
287
288         if (client_auth)
289                 {
290                 SSL_CTX_use_certificate_file(c_ctx,ccert,
291                         SSL_FILETYPE_PEM);
292                 SSL_CTX_use_RSAPrivateKey_file(c_ctx,ccert,
293                         SSL_FILETYPE_PEM);
294                 }
295
296         if (    (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
297                 (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
298                 (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
299                 (!SSL_CTX_set_default_verify_paths(c_ctx)))
300                 {
301                 fprintf(stderr,"SSL_load_verify_locations\n");
302                 ERR_print_errors(bio_err);
303                 goto end;
304                 }
305
306         if (client_auth)
307                 {
308                 fprintf(stderr,"client authentication\n");
309                 SSL_CTX_set_verify(s_ctx,
310                         SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
311                         verify_callback);
312                 }
313         if (server_auth)
314                 {
315                 fprintf(stderr,"server authentication\n");
316                 SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
317                         verify_callback);
318                 }
319
320         thread_setup();
321         do_threads(s_ctx,c_ctx);
322         thread_cleanup();
323 end:
324         
325         if (c_ctx != NULL) 
326                 {
327                 fprintf(stderr,"Client SSL_CTX stats then free it\n");
328                 print_stats(stderr,c_ctx);
329                 SSL_CTX_free(c_ctx);
330                 }
331         if (s_ctx != NULL)
332                 {
333                 fprintf(stderr,"Server SSL_CTX stats then free it\n");
334                 print_stats(stderr,s_ctx);
335                 if (cache_stats)
336                         {
337                         fprintf(stderr,"-----\n");
338                         lh_stats(SSL_CTX_sessions(s_ctx),stderr);
339                         fprintf(stderr,"-----\n");
340                 /*      lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
341                         fprintf(stderr,"-----\n"); */
342                         lh_node_usage_stats(SSL_CTX_sessions(s_ctx),stderr);
343                         fprintf(stderr,"-----\n");
344                         }
345                 SSL_CTX_free(s_ctx);
346                 fprintf(stderr,"done free\n");
347                 }
348         exit(ret);
349         return(0);
350         }
351
352 #define W_READ  1
353 #define W_WRITE 2
354 #define C_DONE  1
355 #define S_DONE  2
356
357 int ndoit(SSL_CTX *ssl_ctx[2])
358         {
359         int i;
360         int ret;
361         char *ctx[4];
362
363         ctx[0]=(char *)ssl_ctx[0];
364         ctx[1]=(char *)ssl_ctx[1];
365
366         if (reconnect)
367                 {
368                 ctx[2]=(char *)SSL_new(ssl_ctx[0]);
369                 ctx[3]=(char *)SSL_new(ssl_ctx[1]);
370                 }
371         else
372                 {
373                 ctx[2]=NULL;
374                 ctx[3]=NULL;
375                 }
376
377         fprintf(stdout,"started thread %lu\n",CRYPTO_thread_id());
378         for (i=0; i<number_of_loops; i++)
379                 {
380 /*              fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
381                         CRYPTO_thread_id(),i,
382                         ssl_ctx[0]->references,
383                         ssl_ctx[1]->references); */
384         /*      pthread_delay_np(&tm);*/
385
386                 ret=doit(ctx);
387                 if (ret != 0)
388                         {
389                         fprintf(stdout,"error[%d] %lu - %d\n",
390                                 i,CRYPTO_thread_id(),ret);
391                         return(ret);
392                         }
393                 }
394         fprintf(stdout,"DONE %lu\n",CRYPTO_thread_id());
395         if (reconnect)
396                 {
397                 SSL_free((SSL *)ctx[2]);
398                 SSL_free((SSL *)ctx[3]);
399                 }
400         return(0);
401         }
402
403 int doit(char *ctx[4])
404         {
405         SSL_CTX *s_ctx,*c_ctx;
406         static char cbuf[200],sbuf[200];
407         SSL *c_ssl=NULL;
408         SSL *s_ssl=NULL;
409         BIO *c_to_s=NULL;
410         BIO *s_to_c=NULL;
411         BIO *c_bio=NULL;
412         BIO *s_bio=NULL;
413         int c_r,c_w,s_r,s_w;
414         int c_want,s_want;
415         int i;
416         int done=0;
417         int c_write,s_write;
418         int do_server=0,do_client=0;
419
420         s_ctx=(SSL_CTX *)ctx[0];
421         c_ctx=(SSL_CTX *)ctx[1];
422
423         if (ctx[2] != NULL)
424                 s_ssl=(SSL *)ctx[2];
425         else
426                 s_ssl=SSL_new(s_ctx);
427
428         if (ctx[3] != NULL)
429                 c_ssl=(SSL *)ctx[3];
430         else
431                 c_ssl=SSL_new(c_ctx);
432
433         if ((s_ssl == NULL) || (c_ssl == NULL)) goto err;
434
435         c_to_s=BIO_new(BIO_s_mem());
436         s_to_c=BIO_new(BIO_s_mem());
437         if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;
438
439         c_bio=BIO_new(BIO_f_ssl());
440         s_bio=BIO_new(BIO_f_ssl());
441         if ((c_bio == NULL) || (s_bio == NULL)) goto err;
442
443         SSL_set_connect_state(c_ssl);
444         SSL_set_bio(c_ssl,s_to_c,c_to_s);
445         BIO_set_ssl(c_bio,c_ssl,(ctx[2] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
446
447         SSL_set_accept_state(s_ssl);
448         SSL_set_bio(s_ssl,c_to_s,s_to_c);
449         BIO_set_ssl(s_bio,s_ssl,(ctx[3] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
450
451         c_r=0; s_r=1;
452         c_w=1; s_w=0;
453         c_want=W_WRITE;
454         s_want=0;
455         c_write=1,s_write=0;
456
457         /* We can always do writes */
458         for (;;)
459                 {
460                 do_server=0;
461                 do_client=0;
462
463                 i=(int)BIO_pending(s_bio);
464                 if ((i && s_r) || s_w) do_server=1;
465
466                 i=(int)BIO_pending(c_bio);
467                 if ((i && c_r) || c_w) do_client=1;
468
469                 if (do_server && verbose)
470                         {
471                         if (SSL_in_init(s_ssl))
472                                 printf("server waiting in SSL_accept - %s\n",
473                                         SSL_state_string_long(s_ssl));
474                         else if (s_write)
475                                 printf("server:SSL_write()\n");
476                         else 
477                                 printf("server:SSL_read()\n");
478                         }
479
480                 if (do_client && verbose)
481                         {
482                         if (SSL_in_init(c_ssl))
483                                 printf("client waiting in SSL_connect - %s\n",
484                                         SSL_state_string_long(c_ssl));
485                         else if (c_write)
486                                 printf("client:SSL_write()\n");
487                         else
488                                 printf("client:SSL_read()\n");
489                         }
490
491                 if (!do_client && !do_server)
492                         {
493                         fprintf(stdout,"ERROR IN STARTUP\n");
494                         break;
495                         }
496                 if (do_client && !(done & C_DONE))
497                         {
498                         if (c_write)
499                                 {
500                                 i=BIO_write(c_bio,"hello from client\n",18);
501                                 if (i < 0)
502                                         {
503                                         c_r=0;
504                                         c_w=0;
505                                         if (BIO_should_retry(c_bio))
506                                                 {
507                                                 if (BIO_should_read(c_bio))
508                                                         c_r=1;
509                                                 if (BIO_should_write(c_bio))
510                                                         c_w=1;
511                                                 }
512                                         else
513                                                 {
514                                                 fprintf(stderr,"ERROR in CLIENT\n");
515                                                 return(1);
516                                                 }
517                                         }
518                                 else if (i == 0)
519                                         {
520                                         fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
521                                         return(1);
522                                         }
523                                 else
524                                         {
525                                         /* ok */
526                                         c_write=0;
527                                         }
528                                 }
529                         else
530                                 {
531                                 i=BIO_read(c_bio,cbuf,100);
532                                 if (i < 0)
533                                         {
534                                         c_r=0;
535                                         c_w=0;
536                                         if (BIO_should_retry(c_bio))
537                                                 {
538                                                 if (BIO_should_read(c_bio))
539                                                         c_r=1;
540                                                 if (BIO_should_write(c_bio))
541                                                         c_w=1;
542                                                 }
543                                         else
544                                                 {
545                                                 fprintf(stderr,"ERROR in CLIENT\n");
546                                                 return(1);
547                                                 }
548                                         }
549                                 else if (i == 0)
550                                         {
551                                         fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
552                                         return(1);
553                                         }
554                                 else
555                                         {
556                                         done|=C_DONE;
557 #ifdef undef
558                                         fprintf(stdout,"CLIENT:from server:");
559                                         fwrite(cbuf,1,i,stdout);
560                                         fflush(stdout);
561 #endif
562                                         }
563                                 }
564                         }
565
566                 if (do_server && !(done & S_DONE))
567                         {
568                         if (!s_write)
569                                 {
570                                 i=BIO_read(s_bio,sbuf,100);
571                                 if (i < 0)
572                                         {
573                                         s_r=0;
574                                         s_w=0;
575                                         if (BIO_should_retry(s_bio))
576                                                 {
577                                                 if (BIO_should_read(s_bio))
578                                                         s_r=1;
579                                                 if (BIO_should_write(s_bio))
580                                                         s_w=1;
581                                                 }
582                                         else
583                                                 {
584                                                 fprintf(stderr,"ERROR in SERVER\n");
585                                                 ERR_print_errors_fp(stderr);
586                                                 return(1);
587                                                 }
588                                         }
589                                 else if (i == 0)
590                                         {
591                                         fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
592                                         return(1);
593                                         }
594                                 else
595                                         {
596                                         s_write=1;
597                                         s_w=1;
598 #ifdef undef
599                                         fprintf(stdout,"SERVER:from client:");
600                                         fwrite(sbuf,1,i,stdout);
601                                         fflush(stdout);
602 #endif
603                                         }
604                                 }
605                         else
606                                 {
607                                 i=BIO_write(s_bio,"hello from server\n",18);
608                                 if (i < 0)
609                                         {
610                                         s_r=0;
611                                         s_w=0;
612                                         if (BIO_should_retry(s_bio))
613                                                 {
614                                                 if (BIO_should_read(s_bio))
615                                                         s_r=1;
616                                                 if (BIO_should_write(s_bio))
617                                                         s_w=1;
618                                                 }
619                                         else
620                                                 {
621                                                 fprintf(stderr,"ERROR in SERVER\n");
622                                                 ERR_print_errors_fp(stderr);
623                                                 return(1);
624                                                 }
625                                         }
626                                 else if (i == 0)
627                                         {
628                                         fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
629                                         return(1);
630                                         }
631                                 else
632                                         {
633                                         s_write=0;
634                                         s_r=1;
635                                         done|=S_DONE;
636                                         }
637                                 }
638                         }
639
640                 if ((done & S_DONE) && (done & C_DONE)) break;
641                 }
642
643         SSL_set_shutdown(c_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
644         SSL_set_shutdown(s_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
645
646 #ifdef undef
647         fprintf(stdout,"DONE\n");
648 #endif
649 err:
650         /* We have to set the BIO's to NULL otherwise they will be
651          * free()ed twice.  Once when th s_ssl is SSL_free()ed and
652          * again when c_ssl is SSL_free()ed.
653          * This is a hack required because s_ssl and c_ssl are sharing the same
654          * BIO structure and SSL_set_bio() and SSL_free() automatically
655          * BIO_free non NULL entries.
656          * You should not normally do this or be required to do this */
657
658         if (s_ssl != NULL)
659                 {
660                 s_ssl->rbio=NULL;
661                 s_ssl->wbio=NULL;
662                 }
663         if (c_ssl != NULL)
664                 {
665                 c_ssl->rbio=NULL;
666                 c_ssl->wbio=NULL;
667                 }
668
669         /* The SSL's are optionally freed in the following calls */
670         if (c_to_s != NULL) BIO_free(c_to_s);
671         if (s_to_c != NULL) BIO_free(s_to_c);
672
673         if (c_bio != NULL) BIO_free(c_bio);
674         if (s_bio != NULL) BIO_free(s_bio);
675         return(0);
676         }
677
678 int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth,
679              int error, char *arg)
680         {
681         char buf[256];
682
683         if (verbose)
684                 {
685                 X509_NAME_oneline(X509_get_subject_name(xs),buf,256);
686                 if (ok)
687                         fprintf(stderr,"depth=%d %s\n",depth,buf);
688                 else
689                         fprintf(stderr,"depth=%d error=%d %s\n",depth,error,buf);
690                 }
691         return(ok);
692         }
693
694 #define THREAD_STACK_SIZE (16*1024)
695
696 #ifdef WIN32
697
698 static HANDLE lock_cs[CRYPTO_NUM_LOCKS];
699
700 void thread_setup(void)
701         {
702         int i;
703
704         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
705                 {
706                 lock_cs[i]=CreateMutex(NULL,FALSE,NULL);
707                 }
708
709         CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback);
710         /* id callback defined */
711         }
712
713 void thread_cleanup(void)
714         {
715         int i;
716
717         CRYPTO_set_locking_callback(NULL);
718         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
719                 CloseHandle(lock_cs[i]);
720         }
721
722 void win32_locking_callback(int mode, int type, char *file, int line)
723         {
724         if (mode & CRYPTO_LOCK)
725                 {
726                 WaitForSingleObject(lock_cs[type],INFINITE);
727                 }
728         else
729                 {
730                 ReleaseMutex(lock_cs[type]);
731                 }
732         }
733
734 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
735         {
736         double ret;
737         SSL_CTX *ssl_ctx[2];
738         DWORD thread_id[MAX_THREAD_NUMBER];
739         HANDLE thread_handle[MAX_THREAD_NUMBER];
740         int i;
741         SYSTEMTIME start,end;
742
743         ssl_ctx[0]=s_ctx;
744         ssl_ctx[1]=c_ctx;
745
746         GetSystemTime(&start);
747         for (i=0; i<thread_number; i++)
748                 {
749                 thread_handle[i]=CreateThread(NULL,
750                         THREAD_STACK_SIZE,
751                         (LPTHREAD_START_ROUTINE)ndoit,
752                         (void *)ssl_ctx,
753                         0L,
754                         &(thread_id[i]));
755                 }
756
757         printf("reaping\n");
758         for (i=0; i<thread_number; i+=50)
759                 {
760                 int j;
761
762                 j=(thread_number < (i+50))?(thread_number-i):50;
763
764                 if (WaitForMultipleObjects(j,
765                         (CONST HANDLE *)&(thread_handle[i]),TRUE,INFINITE)
766                         == WAIT_FAILED)
767                         {
768                         fprintf(stderr,"WaitForMultipleObjects failed:%d\n",GetLastError());
769                         exit(1);
770                         }
771                 }
772         GetSystemTime(&end);
773
774         if (start.wDayOfWeek > end.wDayOfWeek) end.wDayOfWeek+=7;
775         ret=(end.wDayOfWeek-start.wDayOfWeek)*24;
776
777         ret=(ret+end.wHour-start.wHour)*60;
778         ret=(ret+end.wMinute-start.wMinute)*60;
779         ret=(ret+end.wSecond-start.wSecond);
780         ret+=(end.wMilliseconds-start.wMilliseconds)/1000.0;
781
782         printf("win32 threads done - %.3f seconds\n",ret);
783         }
784
785 #endif /* WIN32 */
786
787 #ifdef SOLARIS
788
789 static mutex_t lock_cs[CRYPTO_NUM_LOCKS];
790 /*static rwlock_t lock_cs[CRYPTO_NUM_LOCKS]; */
791 static long lock_count[CRYPTO_NUM_LOCKS];
792
793 void thread_setup(void)
794         {
795         int i;
796
797         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
798                 {
799                 lock_count[i]=0;
800                 /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
801                 mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL);
802                 }
803
804         CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
805         CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
806         }
807
808 void thread_cleanup(void)
809         {
810         int i;
811
812         CRYPTO_set_locking_callback(NULL);
813 fprintf(stderr,"cleanup\n");
814         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
815                 {
816                 /* rwlock_destroy(&(lock_cs[i])); */
817                 mutex_destroy(&(lock_cs[i]));
818                 fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
819                 }
820 fprintf(stderr,"done cleanup\n");
821         }
822
823 void solaris_locking_callback(int mode, int type, char *file, int line)
824         {
825 #ifdef undef
826 fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
827         CRYPTO_thread_id(),
828         (mode&CRYPTO_LOCK)?"l":"u",
829         (type&CRYPTO_READ)?"r":"w",file,line);
830 #endif
831
832 /*
833 if (CRYPTO_LOCK_SSL_CERT == type)
834         fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
835                 CRYPTO_thread_id(),
836                 mode,file,line);
837 */
838         if (mode & CRYPTO_LOCK)
839                 {
840         /*      if (mode & CRYPTO_READ)
841                         rw_rdlock(&(lock_cs[type]));
842                 else
843                         rw_wrlock(&(lock_cs[type])); */
844
845                 mutex_lock(&(lock_cs[type]));
846                 lock_count[type]++;
847                 }
848         else
849                 {
850 /*              rw_unlock(&(lock_cs[type]));  */
851                 mutex_unlock(&(lock_cs[type]));
852                 }
853         }
854
855 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
856         {
857         SSL_CTX *ssl_ctx[2];
858         thread_t thread_ctx[MAX_THREAD_NUMBER];
859         int i;
860
861         ssl_ctx[0]=s_ctx;
862         ssl_ctx[1]=c_ctx;
863
864         thr_setconcurrency(thread_number);
865         for (i=0; i<thread_number; i++)
866                 {
867                 thr_create(NULL, THREAD_STACK_SIZE,
868                         (void *(*)())ndoit,
869                         (void *)ssl_ctx,
870                         0L,
871                         &(thread_ctx[i]));
872                 }
873
874         printf("reaping\n");
875         for (i=0; i<thread_number; i++)
876                 {
877                 thr_join(thread_ctx[i],NULL,NULL);
878                 }
879
880         printf("solaris threads done (%d,%d)\n",
881                 s_ctx->references,c_ctx->references);
882         }
883
884 unsigned long solaris_thread_id(void)
885         {
886         unsigned long ret;
887
888         ret=(unsigned long)thr_self();
889         return(ret);
890         }
891 #endif /* SOLARIS */
892
893 #ifdef IRIX
894
895
896 static usptr_t *arena;
897 static usema_t *lock_cs[CRYPTO_NUM_LOCKS];
898
899 void thread_setup(void)
900         {
901         int i;
902         char filename[20];
903
904         strcpy(filename,"/tmp/mttest.XXXXXX");
905         mktemp(filename);
906
907         usconfig(CONF_STHREADIOOFF);
908         usconfig(CONF_STHREADMALLOCOFF);
909         usconfig(CONF_INITUSERS,100);
910         usconfig(CONF_LOCKTYPE,US_DEBUGPLUS);
911         arena=usinit(filename);
912         unlink(filename);
913
914         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
915                 {
916                 lock_cs[i]=usnewsema(arena,1);
917                 }
918
919         CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
920         CRYPTO_set_locking_callback((void (*)())irix_locking_callback);
921         }
922
923 void thread_cleanup(void)
924         {
925         int i;
926
927         CRYPTO_set_locking_callback(NULL);
928         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
929                 {
930                 char buf[10];
931
932                 sprintf(buf,"%2d:",i);
933                 usdumpsema(lock_cs[i],stdout,buf);
934                 usfreesema(lock_cs[i],arena);
935                 }
936         }
937
938 void irix_locking_callback(int mode, int type, char *file, int line)
939         {
940         if (mode & CRYPTO_LOCK)
941                 {
942                 printf("lock %d\n",type);
943                 uspsema(lock_cs[type]);
944                 }
945         else
946                 {
947                 printf("unlock %d\n",type);
948                 usvsema(lock_cs[type]);
949                 }
950         }
951
952 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
953         {
954         SSL_CTX *ssl_ctx[2];
955         int thread_ctx[MAX_THREAD_NUMBER];
956         int i;
957
958         ssl_ctx[0]=s_ctx;
959         ssl_ctx[1]=c_ctx;
960
961         for (i=0; i<thread_number; i++)
962                 {
963                 thread_ctx[i]=sproc((void (*)())ndoit,
964                         PR_SADDR|PR_SFDS,(void *)ssl_ctx);
965                 }
966
967         printf("reaping\n");
968         for (i=0; i<thread_number; i++)
969                 {
970                 wait(NULL);
971                 }
972
973         printf("irix threads done (%d,%d)\n",
974                 s_ctx->references,c_ctx->references);
975         }
976
977 unsigned long irix_thread_id(void)
978         {
979         unsigned long ret;
980
981         ret=(unsigned long)getpid();
982         return(ret);
983         }
984 #endif /* IRIX */
985
986 #ifdef PTHREADS
987
988 static pthread_mutex_t lock_cs[CRYPTO_NUM_LOCKS];
989 static long lock_count[CRYPTO_NUM_LOCKS];
990
991 void thread_setup(void)
992         {
993         int i;
994
995         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
996                 {
997                 lock_count[i]=0;
998                 pthread_mutex_init(&(lock_cs[i]),NULL);
999                 }
1000
1001         CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
1002         CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
1003         }
1004
1005 void thread_cleanup(void)
1006         {
1007         int i;
1008
1009         CRYPTO_set_locking_callback(NULL);
1010         fprintf(stderr,"cleanup\n");
1011         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
1012                 {
1013                 pthread_mutex_destroy(&(lock_cs[i]));
1014                 fprintf(stderr,"%8ld:%s\n",lock_count[i],
1015                         CRYPTO_get_lock_name(i));
1016                 }
1017         fprintf(stderr,"done cleanup\n");
1018         }
1019
1020 void pthreads_locking_callback(int mode, int type, char *file,
1021              int line)
1022       {
1023 #ifdef undef
1024         fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
1025                 CRYPTO_thread_id(),
1026                 (mode&CRYPTO_LOCK)?"l":"u",
1027                 (type&CRYPTO_READ)?"r":"w",file,line);
1028 #endif
1029 /*
1030         if (CRYPTO_LOCK_SSL_CERT == type)
1031                 fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
1032                 CRYPTO_thread_id(),
1033                 mode,file,line);
1034 */
1035         if (mode & CRYPTO_LOCK)
1036                 {
1037                 pthread_mutex_lock(&(lock_cs[type]));
1038                 lock_count[type]++;
1039                 }
1040         else
1041                 {
1042                 pthread_mutex_unlock(&(lock_cs[type]));
1043                 }
1044         }
1045
1046 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1047         {
1048         SSL_CTX *ssl_ctx[2];
1049         pthread_t thread_ctx[MAX_THREAD_NUMBER];
1050         int i;
1051
1052         ssl_ctx[0]=s_ctx;
1053         ssl_ctx[1]=c_ctx;
1054
1055         /*
1056         thr_setconcurrency(thread_number);
1057         */
1058         for (i=0; i<thread_number; i++)
1059                 {
1060                 pthread_create(&(thread_ctx[i]), NULL,
1061                         (void *(*)())ndoit, (void *)ssl_ctx);
1062                 }
1063
1064         printf("reaping\n");
1065         for (i=0; i<thread_number; i++)
1066                 {
1067                 pthread_join(thread_ctx[i],NULL);
1068                 }
1069
1070         printf("pthreads threads done (%d,%d)\n",
1071         s_ctx->references,c_ctx->references);
1072         }
1073
1074 unsigned long pthreads_thread_id(void)
1075         {
1076         unsigned long ret;
1077
1078         ret=(unsigned long)pthread_self();
1079         return(ret);
1080         }
1081
1082 #endif /* PTHREADS */
1083
1084
1085