OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
mttest.c
Go to the documentation of this file.
1 /* crypto/threads/mttest.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 OPENSSL_SYS_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 #ifdef PTHREADS
78 #include <pthread.h>
79 #endif
80 #ifdef OPENSSL_SYS_NETWARE
81 #if !defined __int64
82 # define __int64 long long
83 #endif
84 #include <nwmpk.h>
85 #endif
86 #include <openssl/lhash.h>
87 #include <openssl/crypto.h>
88 #include <openssl/buffer.h>
89 #include "../../e_os.h"
90 #include <openssl/x509.h>
91 #include <openssl/ssl.h>
92 #include <openssl/err.h>
93 #include <openssl/rand.h>
94 
95 #ifdef OPENSSL_NO_FP_API
96 #define APPS_WIN16
97 #include "../buffer/bss_file.c"
98 #endif
99 
100 #ifdef OPENSSL_SYS_NETWARE
101 #define TEST_SERVER_CERT "/openssl/apps/server.pem"
102 #define TEST_CLIENT_CERT "/openssl/apps/client.pem"
103 #else
104 #define TEST_SERVER_CERT "../../apps/server.pem"
105 #define TEST_CLIENT_CERT "../../apps/client.pem"
106 #endif
107 
108 #define MAX_THREAD_NUMBER 100
109 
111 void thread_setup(void);
112 void thread_cleanup(void);
113 void do_threads(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
114 
115 void irix_locking_callback(int mode,int type,char *file,int line);
116 void solaris_locking_callback(int mode,int type,char *file,int line);
117 void win32_locking_callback(int mode,int type,char *file,int line);
118 void pthreads_locking_callback(int mode,int type,char *file,int line);
119 void netware_locking_callback(int mode,int type,char *file,int line);
120 void beos_locking_callback(int mode,int type,const char *file,int line);
121 
122 unsigned long irix_thread_id(void );
123 unsigned long solaris_thread_id(void );
124 unsigned long pthreads_thread_id(void );
125 unsigned long netware_thread_id(void );
126 unsigned long beos_thread_id(void );
127 
128 #if defined(OPENSSL_SYS_NETWARE)
129 static MPKMutex *lock_cs;
130 static MPKSema ThreadSem;
131 static long *lock_count;
132 #endif
133 
134 BIO *bio_err=NULL;
136 
137 static char *cipher=NULL;
138 int verbose=0;
139 #ifdef FIONBIO
140 static int s_nbio=0;
141 #endif
142 
145 int reconnect=0;
147 
148 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
149 
150 int doit(char *ctx[4]);
151 static void print_stats(FILE *fp, SSL_CTX *ctx)
152 {
153  fprintf(fp,"%4ld items in the session cache\n",
154  SSL_CTX_sess_number(ctx));
155  fprintf(fp,"%4d client connects (SSL_connect())\n",
156  SSL_CTX_sess_connect(ctx));
157  fprintf(fp,"%4d client connects that finished\n",
159  fprintf(fp,"%4d server connects (SSL_accept())\n",
160  SSL_CTX_sess_accept(ctx));
161  fprintf(fp,"%4d server connects that finished\n",
163  fprintf(fp,"%4d session cache hits\n",SSL_CTX_sess_hits(ctx));
164  fprintf(fp,"%4d session cache misses\n",SSL_CTX_sess_misses(ctx));
165  fprintf(fp,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ctx));
166  }
167 
168 static void sv_usage(void)
169  {
170  fprintf(stderr,"usage: ssltest [args ...]\n");
171  fprintf(stderr,"\n");
172  fprintf(stderr," -server_auth - check server certificate\n");
173  fprintf(stderr," -client_auth - do client authentication\n");
174  fprintf(stderr," -v - more output\n");
175  fprintf(stderr," -CApath arg - PEM format directory of CA's\n");
176  fprintf(stderr," -CAfile arg - PEM format file of CA's\n");
177  fprintf(stderr," -threads arg - number of threads\n");
178  fprintf(stderr," -loops arg - number of 'connections', per thread\n");
179  fprintf(stderr," -reconnect - reuse session-id's\n");
180  fprintf(stderr," -stats - server session-id cache stats\n");
181  fprintf(stderr," -cert arg - server certificate/key\n");
182  fprintf(stderr," -ccert arg - client certificate/key\n");
183  fprintf(stderr," -ssl3 - just SSLv3n\n");
184  }
185 
186 int main(int argc, char *argv[])
187  {
188  char *CApath=NULL,*CAfile=NULL;
189  int badop=0;
190  int ret=1;
191  int client_auth=0;
192  int server_auth=0;
193  SSL_CTX *s_ctx=NULL;
194  SSL_CTX *c_ctx=NULL;
195  char *scert=TEST_SERVER_CERT;
196  char *ccert=TEST_CLIENT_CERT;
197  SSL_METHOD *ssl_method=SSLv23_method();
198 
199  RAND_seed(rnd_seed, sizeof rnd_seed);
200 
201  if (bio_err == NULL)
202  bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
203  if (bio_stdout == NULL)
204  bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
205  argc--;
206  argv++;
207 
208  while (argc >= 1)
209  {
210  if (strcmp(*argv,"-server_auth") == 0)
211  server_auth=1;
212  else if (strcmp(*argv,"-client_auth") == 0)
213  client_auth=1;
214  else if (strcmp(*argv,"-reconnect") == 0)
215  reconnect=1;
216  else if (strcmp(*argv,"-stats") == 0)
217  cache_stats=1;
218  else if (strcmp(*argv,"-ssl3") == 0)
219  ssl_method=SSLv3_method();
220  else if (strcmp(*argv,"-ssl2") == 0)
221  ssl_method=SSLv2_method();
222  else if (strcmp(*argv,"-CApath") == 0)
223  {
224  if (--argc < 1) goto bad;
225  CApath= *(++argv);
226  }
227  else if (strcmp(*argv,"-CAfile") == 0)
228  {
229  if (--argc < 1) goto bad;
230  CAfile= *(++argv);
231  }
232  else if (strcmp(*argv,"-cert") == 0)
233  {
234  if (--argc < 1) goto bad;
235  scert= *(++argv);
236  }
237  else if (strcmp(*argv,"-ccert") == 0)
238  {
239  if (--argc < 1) goto bad;
240  ccert= *(++argv);
241  }
242  else if (strcmp(*argv,"-threads") == 0)
243  {
244  if (--argc < 1) goto bad;
245  thread_number= atoi(*(++argv));
246  if (thread_number == 0) thread_number=1;
249  }
250  else if (strcmp(*argv,"-loops") == 0)
251  {
252  if (--argc < 1) goto bad;
253  number_of_loops= atoi(*(++argv));
254  if (number_of_loops == 0) number_of_loops=1;
255  }
256  else
257  {
258  fprintf(stderr,"unknown option %s\n",*argv);
259  badop=1;
260  break;
261  }
262  argc--;
263  argv++;
264  }
265  if (badop)
266  {
267 bad:
268  sv_usage();
269  goto end;
270  }
271 
272  if (cipher == NULL && OPENSSL_issetugid() == 0)
273  cipher=getenv("SSL_CIPHER");
274 
277 
278  c_ctx=SSL_CTX_new(ssl_method);
279  s_ctx=SSL_CTX_new(ssl_method);
280  if ((c_ctx == NULL) || (s_ctx == NULL))
281  {
282  ERR_print_errors(bio_err);
283  goto end;
284  }
285 
290 
292  {
293  ERR_print_errors(bio_err);
294  }
295  else if (!SSL_CTX_use_RSAPrivateKey_file(s_ctx,scert,SSL_FILETYPE_PEM))
296  {
297  ERR_print_errors(bio_err);
298  goto end;
299  }
300 
301  if (client_auth)
302  {
303  SSL_CTX_use_certificate_file(c_ctx,ccert,
305  SSL_CTX_use_RSAPrivateKey_file(c_ctx,ccert,
307  }
308 
309  if ( (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
311  (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
313  {
314  fprintf(stderr,"SSL_load_verify_locations\n");
315  ERR_print_errors(bio_err);
316  goto end;
317  }
318 
319  if (client_auth)
320  {
321  fprintf(stderr,"client authentication\n");
322  SSL_CTX_set_verify(s_ctx,
325  }
326  if (server_auth)
327  {
328  fprintf(stderr,"server authentication\n");
331  }
332 
333  thread_setup();
334  do_threads(s_ctx,c_ctx);
335  thread_cleanup();
336 end:
337 
338  if (c_ctx != NULL)
339  {
340  fprintf(stderr,"Client SSL_CTX stats then free it\n");
341  print_stats(stderr,c_ctx);
342  SSL_CTX_free(c_ctx);
343  }
344  if (s_ctx != NULL)
345  {
346  fprintf(stderr,"Server SSL_CTX stats then free it\n");
347  print_stats(stderr,s_ctx);
348  if (cache_stats)
349  {
350  fprintf(stderr,"-----\n");
351  lh_stats(SSL_CTX_sessions(s_ctx),stderr);
352  fprintf(stderr,"-----\n");
353  /* lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
354  fprintf(stderr,"-----\n"); */
355  lh_node_usage_stats(SSL_CTX_sessions(s_ctx),stderr);
356  fprintf(stderr,"-----\n");
357  }
358  SSL_CTX_free(s_ctx);
359  fprintf(stderr,"done free\n");
360  }
361  exit(ret);
362  return(0);
363  }
364 
365 #define W_READ 1
366 #define W_WRITE 2
367 #define C_DONE 1
368 #define S_DONE 2
369 
370 int ndoit(SSL_CTX *ssl_ctx[2])
371  {
372  int i;
373  int ret;
374  char *ctx[4];
375 
376  ctx[0]=(char *)ssl_ctx[0];
377  ctx[1]=(char *)ssl_ctx[1];
378 
379  if (reconnect)
380  {
381  ctx[2]=(char *)SSL_new(ssl_ctx[0]);
382  ctx[3]=(char *)SSL_new(ssl_ctx[1]);
383  }
384  else
385  {
386  ctx[2]=NULL;
387  ctx[3]=NULL;
388  }
389 
390  fprintf(stdout,"started thread %lu\n",CRYPTO_thread_id());
391  for (i=0; i<number_of_loops; i++)
392  {
393 /* fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
394  CRYPTO_thread_id(),i,
395  ssl_ctx[0]->references,
396  ssl_ctx[1]->references); */
397  /* pthread_delay_np(&tm);*/
398 
399  ret=doit(ctx);
400  if (ret != 0)
401  {
402  fprintf(stdout,"error[%d] %lu - %d\n",
403  i,CRYPTO_thread_id(),ret);
404  return(ret);
405  }
406  }
407  fprintf(stdout,"DONE %lu\n",CRYPTO_thread_id());
408  if (reconnect)
409  {
410  SSL_free((SSL *)ctx[2]);
411  SSL_free((SSL *)ctx[3]);
412  }
413 # ifdef OPENSSL_SYS_NETWARE
414  MPKSemaphoreSignal(ThreadSem);
415 # endif
416  return(0);
417  }
418 
419 int doit(char *ctx[4])
420  {
421  SSL_CTX *s_ctx,*c_ctx;
422  static char cbuf[200],sbuf[200];
423  SSL *c_ssl=NULL;
424  SSL *s_ssl=NULL;
425  BIO *c_to_s=NULL;
426  BIO *s_to_c=NULL;
427  BIO *c_bio=NULL;
428  BIO *s_bio=NULL;
429  int c_r,c_w,s_r,s_w;
430  int c_want,s_want;
431  int i;
432  int done=0;
433  int c_write,s_write;
434  int do_server=0,do_client=0;
435 
436  s_ctx=(SSL_CTX *)ctx[0];
437  c_ctx=(SSL_CTX *)ctx[1];
438 
439  if (ctx[2] != NULL)
440  s_ssl=(SSL *)ctx[2];
441  else
442  s_ssl=SSL_new(s_ctx);
443 
444  if (ctx[3] != NULL)
445  c_ssl=(SSL *)ctx[3];
446  else
447  c_ssl=SSL_new(c_ctx);
448 
449  if ((s_ssl == NULL) || (c_ssl == NULL)) goto err;
450 
451  c_to_s=BIO_new(BIO_s_mem());
452  s_to_c=BIO_new(BIO_s_mem());
453  if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;
454 
455  c_bio=BIO_new(BIO_f_ssl());
456  s_bio=BIO_new(BIO_f_ssl());
457  if ((c_bio == NULL) || (s_bio == NULL)) goto err;
458 
459  SSL_set_connect_state(c_ssl);
460  SSL_set_bio(c_ssl,s_to_c,c_to_s);
461  BIO_set_ssl(c_bio,c_ssl,(ctx[2] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
462 
463  SSL_set_accept_state(s_ssl);
464  SSL_set_bio(s_ssl,c_to_s,s_to_c);
465  BIO_set_ssl(s_bio,s_ssl,(ctx[3] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
466 
467  c_r=0; s_r=1;
468  c_w=1; s_w=0;
469  c_want=W_WRITE;
470  s_want=0;
471  c_write=1,s_write=0;
472 
473  /* We can always do writes */
474  for (;;)
475  {
476  do_server=0;
477  do_client=0;
478 
479  i=(int)BIO_pending(s_bio);
480  if ((i && s_r) || s_w) do_server=1;
481 
482  i=(int)BIO_pending(c_bio);
483  if ((i && c_r) || c_w) do_client=1;
484 
485  if (do_server && verbose)
486  {
487  if (SSL_in_init(s_ssl))
488  printf("server waiting in SSL_accept - %s\n",
489  SSL_state_string_long(s_ssl));
490  else if (s_write)
491  printf("server:SSL_write()\n");
492  else
493  printf("server:SSL_read()\n");
494  }
495 
496  if (do_client && verbose)
497  {
498  if (SSL_in_init(c_ssl))
499  printf("client waiting in SSL_connect - %s\n",
500  SSL_state_string_long(c_ssl));
501  else if (c_write)
502  printf("client:SSL_write()\n");
503  else
504  printf("client:SSL_read()\n");
505  }
506 
507  if (!do_client && !do_server)
508  {
509  fprintf(stdout,"ERROR IN STARTUP\n");
510  break;
511  }
512  if (do_client && !(done & C_DONE))
513  {
514  if (c_write)
515  {
516  i=BIO_write(c_bio,"hello from client\n",18);
517  if (i < 0)
518  {
519  c_r=0;
520  c_w=0;
521  if (BIO_should_retry(c_bio))
522  {
523  if (BIO_should_read(c_bio))
524  c_r=1;
525  if (BIO_should_write(c_bio))
526  c_w=1;
527  }
528  else
529  {
530  fprintf(stderr,"ERROR in CLIENT\n");
531  ERR_print_errors_fp(stderr);
532  return(1);
533  }
534  }
535  else if (i == 0)
536  {
537  fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
538  return(1);
539  }
540  else
541  {
542  /* ok */
543  c_write=0;
544  }
545  }
546  else
547  {
548  i=BIO_read(c_bio,cbuf,100);
549  if (i < 0)
550  {
551  c_r=0;
552  c_w=0;
553  if (BIO_should_retry(c_bio))
554  {
555  if (BIO_should_read(c_bio))
556  c_r=1;
557  if (BIO_should_write(c_bio))
558  c_w=1;
559  }
560  else
561  {
562  fprintf(stderr,"ERROR in CLIENT\n");
563  ERR_print_errors_fp(stderr);
564  return(1);
565  }
566  }
567  else if (i == 0)
568  {
569  fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
570  return(1);
571  }
572  else
573  {
574  done|=C_DONE;
575 #ifdef undef
576  fprintf(stdout,"CLIENT:from server:");
577  fwrite(cbuf,1,i,stdout);
578  fflush(stdout);
579 #endif
580  }
581  }
582  }
583 
584  if (do_server && !(done & S_DONE))
585  {
586  if (!s_write)
587  {
588  i=BIO_read(s_bio,sbuf,100);
589  if (i < 0)
590  {
591  s_r=0;
592  s_w=0;
593  if (BIO_should_retry(s_bio))
594  {
595  if (BIO_should_read(s_bio))
596  s_r=1;
597  if (BIO_should_write(s_bio))
598  s_w=1;
599  }
600  else
601  {
602  fprintf(stderr,"ERROR in SERVER\n");
603  ERR_print_errors_fp(stderr);
604  return(1);
605  }
606  }
607  else if (i == 0)
608  {
609  fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
610  return(1);
611  }
612  else
613  {
614  s_write=1;
615  s_w=1;
616 #ifdef undef
617  fprintf(stdout,"SERVER:from client:");
618  fwrite(sbuf,1,i,stdout);
619  fflush(stdout);
620 #endif
621  }
622  }
623  else
624  {
625  i=BIO_write(s_bio,"hello from server\n",18);
626  if (i < 0)
627  {
628  s_r=0;
629  s_w=0;
630  if (BIO_should_retry(s_bio))
631  {
632  if (BIO_should_read(s_bio))
633  s_r=1;
634  if (BIO_should_write(s_bio))
635  s_w=1;
636  }
637  else
638  {
639  fprintf(stderr,"ERROR in SERVER\n");
640  ERR_print_errors_fp(stderr);
641  return(1);
642  }
643  }
644  else if (i == 0)
645  {
646  fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
647  return(1);
648  }
649  else
650  {
651  s_write=0;
652  s_r=1;
653  done|=S_DONE;
654  }
655  }
656  }
657 
658  if ((done & S_DONE) && (done & C_DONE)) break;
659 # if defined(OPENSSL_SYS_NETWARE)
660  ThreadSwitchWithDelay();
661 # endif
662  }
663 
666 
667 #ifdef undef
668  fprintf(stdout,"DONE\n");
669 #endif
670 err:
671  /* We have to set the BIO's to NULL otherwise they will be
672  * free()ed twice. Once when th s_ssl is SSL_free()ed and
673  * again when c_ssl is SSL_free()ed.
674  * This is a hack required because s_ssl and c_ssl are sharing the same
675  * BIO structure and SSL_set_bio() and SSL_free() automatically
676  * BIO_free non NULL entries.
677  * You should not normally do this or be required to do this */
678 
679  if (s_ssl != NULL)
680  {
681  s_ssl->rbio=NULL;
682  s_ssl->wbio=NULL;
683  }
684  if (c_ssl != NULL)
685  {
686  c_ssl->rbio=NULL;
687  c_ssl->wbio=NULL;
688  }
689 
690  /* The SSL's are optionally freed in the following calls */
691  if (c_to_s != NULL) BIO_free(c_to_s);
692  if (s_to_c != NULL) BIO_free(s_to_c);
693 
694  if (c_bio != NULL) BIO_free(c_bio);
695  if (s_bio != NULL) BIO_free(s_bio);
696  return(0);
697  }
698 
700  {
701  char *s, buf[256];
702 
703  if (verbose)
704  {
706  buf,256);
707  if (s != NULL)
708  {
709  if (ok)
710  fprintf(stderr,"depth=%d %s\n",
711  ctx->error_depth,buf);
712  else
713  fprintf(stderr,"depth=%d error=%d %s\n",
714  ctx->error_depth,ctx->error,buf);
715  }
716  }
717  return(ok);
718  }
719 
720 #define THREAD_STACK_SIZE (16*1024)
721 
722 #ifdef OPENSSL_SYS_WIN32
723 
724 static HANDLE *lock_cs;
725 
726 void thread_setup(void)
727  {
728  int i;
729 
730  lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
731  for (i=0; i<CRYPTO_num_locks(); i++)
732  {
733  lock_cs[i]=CreateMutex(NULL,FALSE,NULL);
734  }
735 
736  CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback);
737  /* id callback defined */
738  }
739 
740 void thread_cleanup(void)
741  {
742  int i;
743 
745  for (i=0; i<CRYPTO_num_locks(); i++)
746  CloseHandle(lock_cs[i]);
747  OPENSSL_free(lock_cs);
748  }
749 
750 void win32_locking_callback(int mode, int type, char *file, int line)
751  {
752  if (mode & CRYPTO_LOCK)
753  {
754  WaitForSingleObject(lock_cs[type],INFINITE);
755  }
756  else
757  {
758  ReleaseMutex(lock_cs[type]);
759  }
760  }
761 
762 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
763  {
764  double ret;
765  SSL_CTX *ssl_ctx[2];
766  DWORD thread_id[MAX_THREAD_NUMBER];
767  HANDLE thread_handle[MAX_THREAD_NUMBER];
768  int i;
769  SYSTEMTIME start,end;
770 
771  ssl_ctx[0]=s_ctx;
772  ssl_ctx[1]=c_ctx;
773 
774  GetSystemTime(&start);
775  for (i=0; i<thread_number; i++)
776  {
777  thread_handle[i]=CreateThread(NULL,
779  (LPTHREAD_START_ROUTINE)ndoit,
780  (void *)ssl_ctx,
781  0L,
782  &(thread_id[i]));
783  }
784 
785  printf("reaping\n");
786  for (i=0; i<thread_number; i+=50)
787  {
788  int j;
789 
790  j=(thread_number < (i+50))?(thread_number-i):50;
791 
792  if (WaitForMultipleObjects(j,
793  (CONST HANDLE *)&(thread_handle[i]),TRUE,INFINITE)
794  == WAIT_FAILED)
795  {
796  fprintf(stderr,"WaitForMultipleObjects failed:%d\n",GetLastError());
797  exit(1);
798  }
799  }
800  GetSystemTime(&end);
801 
802  if (start.wDayOfWeek > end.wDayOfWeek) end.wDayOfWeek+=7;
803  ret=(end.wDayOfWeek-start.wDayOfWeek)*24;
804 
805  ret=(ret+end.wHour-start.wHour)*60;
806  ret=(ret+end.wMinute-start.wMinute)*60;
807  ret=(ret+end.wSecond-start.wSecond);
808  ret+=(end.wMilliseconds-start.wMilliseconds)/1000.0;
809 
810  printf("win32 threads done - %.3f seconds\n",ret);
811  }
812 
813 #endif /* OPENSSL_SYS_WIN32 */
814 
815 #ifdef SOLARIS
816 
817 static mutex_t *lock_cs;
818 /*static rwlock_t *lock_cs; */
819 static long *lock_count;
820 
821 void thread_setup(void)
822  {
823  int i;
824 
825  lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
826  lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
827  for (i=0; i<CRYPTO_num_locks(); i++)
828  {
829  lock_count[i]=0;
830  /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
831  mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL);
832  }
833 
834  CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
836  }
837 
838 void thread_cleanup(void)
839  {
840  int i;
841 
843 
844  fprintf(stderr,"cleanup\n");
845 
846  for (i=0; i<CRYPTO_num_locks(); i++)
847  {
848  /* rwlock_destroy(&(lock_cs[i])); */
849  mutex_destroy(&(lock_cs[i]));
850  fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
851  }
852  OPENSSL_free(lock_cs);
853  OPENSSL_free(lock_count);
854 
855  fprintf(stderr,"done cleanup\n");
856 
857  }
858 
859 void solaris_locking_callback(int mode, int type, char *file, int line)
860  {
861 #ifdef undef
862  fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
864  (mode&CRYPTO_LOCK)?"l":"u",
865  (type&CRYPTO_READ)?"r":"w",file,line);
866 #endif
867 
868  /*
869  if (CRYPTO_LOCK_SSL_CERT == type)
870  fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
871  CRYPTO_thread_id(),
872  mode,file,line);
873  */
874  if (mode & CRYPTO_LOCK)
875  {
876  /* if (mode & CRYPTO_READ)
877  rw_rdlock(&(lock_cs[type]));
878  else
879  rw_wrlock(&(lock_cs[type])); */
880 
881  mutex_lock(&(lock_cs[type]));
882  lock_count[type]++;
883  }
884  else
885  {
886 /* rw_unlock(&(lock_cs[type])); */
887  mutex_unlock(&(lock_cs[type]));
888  }
889  }
890 
891 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
892  {
893  SSL_CTX *ssl_ctx[2];
894  thread_t thread_ctx[MAX_THREAD_NUMBER];
895  int i;
896 
897  ssl_ctx[0]=s_ctx;
898  ssl_ctx[1]=c_ctx;
899 
900  thr_setconcurrency(thread_number);
901  for (i=0; i<thread_number; i++)
902  {
903  thr_create(NULL, THREAD_STACK_SIZE,
904  (void *(*)())ndoit,
905  (void *)ssl_ctx,
906  0L,
907  &(thread_ctx[i]));
908  }
909 
910  printf("reaping\n");
911  for (i=0; i<thread_number; i++)
912  {
913  thr_join(thread_ctx[i],NULL,NULL);
914  }
915 
916  printf("solaris threads done (%d,%d)\n",
917  s_ctx->references,c_ctx->references);
918  }
919 
920 unsigned long solaris_thread_id(void)
921  {
922  unsigned long ret;
923 
924  ret=(unsigned long)thr_self();
925  return(ret);
926  }
927 #endif /* SOLARIS */
928 
929 #ifdef IRIX
930 
931 
932 static usptr_t *arena;
933 static usema_t **lock_cs;
934 
935 void thread_setup(void)
936  {
937  int i;
938  char filename[20];
939 
940  strcpy(filename,"/tmp/mttest.XXXXXX");
941  mktemp(filename);
942 
943  usconfig(CONF_STHREADIOOFF);
944  usconfig(CONF_STHREADMALLOCOFF);
945  usconfig(CONF_INITUSERS,100);
946  usconfig(CONF_LOCKTYPE,US_DEBUGPLUS);
947  arena=usinit(filename);
948  unlink(filename);
949 
950  lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *));
951  for (i=0; i<CRYPTO_num_locks(); i++)
952  {
953  lock_cs[i]=usnewsema(arena,1);
954  }
955 
956  CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
958  }
959 
960 void thread_cleanup(void)
961  {
962  int i;
963 
965  for (i=0; i<CRYPTO_num_locks(); i++)
966  {
967  char buf[10];
968 
969  sprintf(buf,"%2d:",i);
970  usdumpsema(lock_cs[i],stdout,buf);
971  usfreesema(lock_cs[i],arena);
972  }
973  OPENSSL_free(lock_cs);
974  }
975 
976 void irix_locking_callback(int mode, int type, char *file, int line)
977  {
978  if (mode & CRYPTO_LOCK)
979  {
980  printf("lock %d\n",type);
981  uspsema(lock_cs[type]);
982  }
983  else
984  {
985  printf("unlock %d\n",type);
986  usvsema(lock_cs[type]);
987  }
988  }
989 
990 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
991  {
992  SSL_CTX *ssl_ctx[2];
993  int thread_ctx[MAX_THREAD_NUMBER];
994  int i;
995 
996  ssl_ctx[0]=s_ctx;
997  ssl_ctx[1]=c_ctx;
998 
999  for (i=0; i<thread_number; i++)
1000  {
1001  thread_ctx[i]=sproc((void (*)())ndoit,
1002  PR_SADDR|PR_SFDS,(void *)ssl_ctx);
1003  }
1004 
1005  printf("reaping\n");
1006  for (i=0; i<thread_number; i++)
1007  {
1008  wait(NULL);
1009  }
1010 
1011  printf("irix threads done (%d,%d)\n",
1012  s_ctx->references,c_ctx->references);
1013  }
1014 
1015 unsigned long irix_thread_id(void)
1016  {
1017  unsigned long ret;
1018 
1019  ret=(unsigned long)getpid();
1020  return(ret);
1021  }
1022 #endif /* IRIX */
1023 
1024 #ifdef PTHREADS
1025 
1026 static pthread_mutex_t *lock_cs;
1027 static long *lock_count;
1028 
1029 void thread_setup(void)
1030  {
1031  int i;
1032 
1033  lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
1034  lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1035  for (i=0; i<CRYPTO_num_locks(); i++)
1036  {
1037  lock_count[i]=0;
1038  pthread_mutex_init(&(lock_cs[i]),NULL);
1039  }
1040 
1041  CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
1043  }
1044 
1045 void thread_cleanup(void)
1046  {
1047  int i;
1048 
1050  fprintf(stderr,"cleanup\n");
1051  for (i=0; i<CRYPTO_num_locks(); i++)
1052  {
1053  pthread_mutex_destroy(&(lock_cs[i]));
1054  fprintf(stderr,"%8ld:%s\n",lock_count[i],
1056  }
1057  OPENSSL_free(lock_cs);
1058  OPENSSL_free(lock_count);
1059 
1060  fprintf(stderr,"done cleanup\n");
1061  }
1062 
1063 void pthreads_locking_callback(int mode, int type, char *file,
1064  int line)
1065  {
1066 #ifdef undef
1067  fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
1068  CRYPTO_thread_id(),
1069  (mode&CRYPTO_LOCK)?"l":"u",
1070  (type&CRYPTO_READ)?"r":"w",file,line);
1071 #endif
1072 /*
1073  if (CRYPTO_LOCK_SSL_CERT == type)
1074  fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
1075  CRYPTO_thread_id(),
1076  mode,file,line);
1077 */
1078  if (mode & CRYPTO_LOCK)
1079  {
1080  pthread_mutex_lock(&(lock_cs[type]));
1081  lock_count[type]++;
1082  }
1083  else
1084  {
1085  pthread_mutex_unlock(&(lock_cs[type]));
1086  }
1087  }
1088 
1089 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1090  {
1091  SSL_CTX *ssl_ctx[2];
1092  pthread_t thread_ctx[MAX_THREAD_NUMBER];
1093  int i;
1094 
1095  ssl_ctx[0]=s_ctx;
1096  ssl_ctx[1]=c_ctx;
1097 
1098  /*
1099  thr_setconcurrency(thread_number);
1100  */
1101  for (i=0; i<thread_number; i++)
1102  {
1103  pthread_create(&(thread_ctx[i]), NULL,
1104  (void *(*)())ndoit, (void *)ssl_ctx);
1105  }
1106 
1107  printf("reaping\n");
1108  for (i=0; i<thread_number; i++)
1109  {
1110  pthread_join(thread_ctx[i],NULL);
1111  }
1112 
1113  printf("pthreads threads done (%d,%d)\n",
1114  s_ctx->references,c_ctx->references);
1115  }
1116 
1117 unsigned long pthreads_thread_id(void)
1118  {
1119  unsigned long ret;
1120 
1121  ret=(unsigned long)pthread_self();
1122  return(ret);
1123  }
1124 
1125 #endif /* PTHREADS */
1126 
1127 
1128 
1129 #ifdef OPENSSL_SYS_NETWARE
1130 
1131 void thread_setup(void)
1132 {
1133  int i;
1134 
1135  lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(MPKMutex));
1136  lock_count=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1137  for (i=0; i<CRYPTO_num_locks(); i++)
1138  {
1139  lock_count[i]=0;
1140  lock_cs[i]=MPKMutexAlloc("OpenSSL mutex");
1141  }
1142 
1143  ThreadSem = MPKSemaphoreAlloc("OpenSSL mttest semaphore", 0 );
1144 
1145  CRYPTO_set_id_callback((unsigned long (*)())netware_thread_id);
1147 }
1148 
1149 void thread_cleanup(void)
1150 {
1151  int i;
1152 
1154 
1155  fprintf(stdout,"thread_cleanup\n");
1156 
1157  for (i=0; i<CRYPTO_num_locks(); i++)
1158  {
1159  MPKMutexFree(lock_cs[i]);
1160  fprintf(stdout,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
1161  }
1162  OPENSSL_free(lock_cs);
1163  OPENSSL_free(lock_count);
1164 
1165  MPKSemaphoreFree(ThreadSem);
1166 
1167  fprintf(stdout,"done cleanup\n");
1168 }
1169 
1170 void netware_locking_callback(int mode, int type, char *file, int line)
1171 {
1172  if (mode & CRYPTO_LOCK)
1173  {
1174  MPKMutexLock(lock_cs[type]);
1175  lock_count[type]++;
1176  }
1177  else
1178  MPKMutexUnlock(lock_cs[type]);
1179 }
1180 
1181 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1182 {
1183  SSL_CTX *ssl_ctx[2];
1184  int i;
1185  ssl_ctx[0]=s_ctx;
1186  ssl_ctx[1]=c_ctx;
1187 
1188  for (i=0; i<thread_number; i++)
1189  {
1190  BeginThread( (void(*)(void*))ndoit, NULL, THREAD_STACK_SIZE,
1191  (void*)ssl_ctx);
1192  ThreadSwitchWithDelay();
1193  }
1194 
1195  printf("reaping\n");
1196 
1197  /* loop until all threads have signaled the semaphore */
1198  for (i=0; i<thread_number; i++)
1199  {
1200  MPKSemaphoreWait(ThreadSem);
1201  }
1202  printf("netware threads done (%d,%d)\n",
1203  s_ctx->references,c_ctx->references);
1204 }
1205 
1206 unsigned long netware_thread_id(void)
1207 {
1208  unsigned long ret;
1209 
1210  ret=(unsigned long)GetThreadID();
1211  return(ret);
1212 }
1213 #endif /* NETWARE */
1214 
1215 #ifdef BEOS_THREADS
1216 
1217 #include <Locker.h>
1218 
1219 static BLocker** lock_cs;
1220 static long* lock_count;
1221 
1222 void thread_setup(void)
1223  {
1224  int i;
1225 
1226  lock_cs=(BLocker**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(BLocker*));
1227  lock_count=(long*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1228  for (i=0; i<CRYPTO_num_locks(); i++)
1229  {
1230  lock_count[i]=0;
1231  lock_cs[i] = new BLocker(CRYPTO_get_lock_name(i));
1232  }
1233 
1234  CRYPTO_set_id_callback((unsigned long (*)())beos_thread_id);
1236  }
1237 
1238 void thread_cleanup(void)
1239  {
1240  int i;
1241 
1243  fprintf(stderr,"cleanup\n");
1244  for (i=0; i<CRYPTO_num_locks(); i++)
1245  {
1246  delete lock_cs[i];
1247  fprintf(stderr,"%8ld:%s\n",lock_count[i],
1249  }
1250  OPENSSL_free(lock_cs);
1251  OPENSSL_free(lock_count);
1252 
1253  fprintf(stderr,"done cleanup\n");
1254  }
1255 
1256 void beos_locking_callback(int mode, int type, const char *file, int line)
1257  {
1258 #if 0
1259  fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
1260  CRYPTO_thread_id(),
1261  (mode&CRYPTO_LOCK)?"l":"u",
1262  (type&CRYPTO_READ)?"r":"w",file,line);
1263 #endif
1264  if (mode & CRYPTO_LOCK)
1265  {
1266  lock_cs[type]->Lock();
1267  lock_count[type]++;
1268  }
1269  else
1270  {
1271  lock_cs[type]->Unlock();
1272  }
1273  }
1274 
1275 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1276  {
1277  SSL_CTX *ssl_ctx[2];
1278  thread_id thread_ctx[MAX_THREAD_NUMBER];
1279  int i;
1280 
1281  ssl_ctx[0]=s_ctx;
1282  ssl_ctx[1]=c_ctx;
1283 
1284  for (i=0; i<thread_number; i++)
1285  {
1286  thread_ctx[i] = spawn_thread((thread_func)ndoit,
1287  NULL, B_NORMAL_PRIORITY, (void *)ssl_ctx);
1288  resume_thread(thread_ctx[i]);
1289  }
1290 
1291  printf("waiting...\n");
1292  for (i=0; i<thread_number; i++)
1293  {
1294  status_t result;
1295  wait_for_thread(thread_ctx[i], &result);
1296  }
1297 
1298  printf("beos threads done (%d,%d)\n",
1299  s_ctx->references,c_ctx->references);
1300  }
1301 
1302 unsigned long beos_thread_id(void)
1303  {
1304  unsigned long ret;
1305 
1306  ret=(unsigned long)find_thread(NULL);
1307  return(ret);
1308  }
1309 
1310 #endif /* BEOS_THREADS */