]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/IDE/MDK5-ARM/Projects/CyaSSL-Full/client.c
Update CyaSSL to latest version.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / IDE / MDK5-ARM / Projects / CyaSSL-Full / client.c
1 /* client.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * CyaSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23         #include <config.h>
24 #endif
25  #define CYASSL_MDK_ARM
26 #if defined(CYASSL_MDK_ARM)
27         #include <stdio.h>
28         #include <string.h>
29
30         #if defined(CYASSL_MDK5)
31             #include "cmsis_os.h"
32             #include "rl_fs.h" 
33             #include "rl_net.h" 
34         #else
35             #include "rtl.h"
36         #endif
37
38         #include "cyassl_MDK_ARM.h"
39 #endif
40
41 #include <cyassl/ctaocrypt/settings.h>
42
43 #if !defined(CYASSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
44     /* in case memory tracker wants stats */
45     #define CYASSL_TRACK_MEMORY
46 #endif
47
48 #include <cyassl/ssl.h>
49 #include <cyassl/test.h>
50 #include "examples/client/client.h"
51
52
53 #ifdef CYASSL_CALLBACKS
54     int handShakeCB(HandShakeInfo*);
55     int timeoutCB(TimeoutInfo*);
56     Timeval timeout;
57 #endif
58
59
60 static void NonBlockingSSL_Connect(CYASSL* ssl)
61 {
62 #ifndef CYASSL_CALLBACKS
63     int ret = CyaSSL_connect(ssl);
64 #else
65     int ret = CyaSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
66 #endif
67     int error = CyaSSL_get_error(ssl, 0);
68     SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl);
69     int select_ret;
70
71     while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
72                                   error == SSL_ERROR_WANT_WRITE)) {
73         int currTimeout = 1;
74
75         if (error == SSL_ERROR_WANT_READ)
76             printf("... client would read block\n");
77         else
78             printf("... client would write block\n");
79
80 #ifdef CYASSL_DTLS
81         currTimeout = CyaSSL_dtls_get_current_timeout(ssl);
82 #endif
83         select_ret = tcp_select(sockfd, currTimeout);
84
85         if ((select_ret == TEST_RECV_READY) ||
86                                         (select_ret == TEST_ERROR_READY)) {
87             #ifndef CYASSL_CALLBACKS
88                     ret = CyaSSL_connect(ssl);
89             #else
90                 ret = CyaSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout);
91             #endif
92             error = CyaSSL_get_error(ssl, 0);
93         }
94         else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) {
95             error = SSL_ERROR_WANT_READ;
96         }
97 #ifdef CYASSL_DTLS
98         else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) &&
99                                             CyaSSL_dtls_got_timeout(ssl) >= 0) {
100             error = SSL_ERROR_WANT_READ;
101         }
102 #endif
103         else {
104             error = SSL_FATAL_ERROR;
105         }
106     }
107     if (ret != SSL_SUCCESS)
108         err_sys("SSL_connect failed");
109 }
110
111
112 static void Usage(void)
113 {
114     printf("client "    LIBCYASSL_VERSION_STRING
115            " NOTE: All files relative to CyaSSL home dir\n");
116     printf("-?          Help, print this usage\n");
117     printf("-h <host>   Host to connect to, default %s\n", yasslIP);
118     printf("-p <num>    Port to connect on, not 0, default %d\n", yasslPort);
119     printf("-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n",
120                                  CLIENT_DEFAULT_VERSION);
121     printf("-l <str>    Cipher list\n");
122     printf("-c <file>   Certificate file,           default %s\n", cliCert);
123     printf("-k <file>   Key file,                   default %s\n", cliKey);
124     printf("-A <file>   Certificate Authority file, default %s\n", caCert);
125     printf("-b <num>    Benchmark <num> connections and print stats\n");
126     printf("-s          Use pre Shared keys\n");
127     printf("-t          Track CyaSSL memory use\n");
128     printf("-d          Disable peer checks\n");
129     printf("-g          Send server HTTP GET\n");
130     printf("-u          Use UDP DTLS,"
131            " add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n");
132     printf("-m          Match domain name in cert\n");
133     printf("-N          Use Non-blocking sockets\n");
134     printf("-r          Resume session\n");
135     printf("-f          Fewer packets/group messages\n");
136     printf("-x          Disable client cert/key loading\n");
137 #ifdef SHOW_SIZES
138     printf("-z          Print structure sizes\n");
139 #endif
140 #ifdef HAVE_SNI
141     printf("-S <str>    Use Host Name Indication\n");
142 #endif
143 #ifdef HAVE_MAX_FRAGMENT
144     printf("-L <num>    Use Maximum Fragment Length [1-5]\n");
145 #endif
146 #ifdef HAVE_TRUNCATED_HMAC
147     printf("-T          Use Truncated HMAC\n");
148 #endif
149 #ifdef HAVE_OCSP
150     printf("-o          Perform OCSP lookup on peer certificate\n");
151     printf("-O <url>    Perform OCSP lookup using <url> as responder\n");
152 #endif
153 #ifdef ATOMIC_USER
154     printf("-U          Atomic User Record Layer Callbacks\n");
155 #endif
156 #ifdef HAVE_PK_CALLBACKS 
157     printf("-P          Public Key Callbacks\n");
158 #endif
159 }
160
161
162 #ifdef CYASSL_MDK_SHELL
163     #define exit(code) return(code)
164 #endif
165
166
167 THREAD_RETURN CYASSL_THREAD client_test(void* args)
168 {
169     SOCKET_T sockfd = 0;
170
171     CYASSL_METHOD*  method  = 0;
172     CYASSL_CTX*     ctx     = 0;
173     CYASSL*         ssl     = 0;
174     
175     CYASSL*         sslResume = 0;
176     CYASSL_SESSION* session = 0;
177     char         resumeMsg[] = "resuming cyassl!";
178     int          resumeSz    = sizeof(resumeMsg);
179
180     char msg[32] = "hello cyassl!";   /* GET may make bigger */
181     char reply[80];
182     int  input;
183     int  msgSz = (int)strlen(msg);
184
185     word16 port   = yasslPort;
186     char* host   = (char*)yasslIP;
187     char* domain = (char*)"www.yassl.com";
188
189     int    ch;
190     int    version = CLIENT_INVALID_VERSION;
191     int    usePsk   = 0;
192     int    sendGET  = 0;
193     int    benchmark = 0;
194     int    doDTLS    = 0;
195     int    matchName = 0;
196     int    doPeerCheck = 1;
197     int    nonBlocking = 0;
198     int    resumeSession = 0;
199     int    trackMemory   = 0;
200     int    useClientCert = 1;
201     int    fewerPackets  = 0;
202     int    atomicUser    = 0;
203     int    pkCallbacks   = 0;
204     char*  cipherList = NULL;
205     char*  verifyCert = (char*)caCert;
206     char*  ourCert    = (char*)cliCert;
207     char*  ourKey     = (char*)cliKey;
208
209 #ifdef HAVE_SNI
210     char*  sniHostName = NULL;
211 #endif
212 #ifdef HAVE_MAX_FRAGMENT
213     byte maxFragment = 0;
214 #endif
215 #ifdef HAVE_TRUNCATED_HMAC
216     byte  truncatedHMAC = 0;
217 #endif
218
219
220 #ifdef HAVE_OCSP
221     int    useOcsp  = 0;
222     char*  ocspUrl  = NULL;
223 #endif
224
225     int     argc = ((func_args*)args)->argc;
226     char**  argv = ((func_args*)args)->argv;
227
228     ((func_args*)args)->return_code = -1; /* error state */
229
230 #ifdef NO_RSA
231     verifyCert = (char*)eccCert;
232     ourCert    = (char*)cliEccCert;
233     ourKey     = (char*)cliEccKey;
234 #endif
235     (void)resumeSz;
236     (void)session;
237     (void)sslResume;
238     (void)trackMemory;
239     (void)atomicUser;
240     (void)pkCallbacks;
241
242     StackTrap();
243
244     while ((ch = mygetopt(argc, argv,
245                           "?gdusmNrtfxUPh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) {
246         switch (ch) {
247             case '?' :
248                 Usage();
249                 exit(EXIT_SUCCESS);
250
251             case 'g' :
252                 sendGET = 1;
253                 break;
254
255             case 'd' :
256                 doPeerCheck = 0;
257                 break;
258
259             case 'u' :
260                 doDTLS  = 1;
261                 break;
262
263             case 's' :
264                 usePsk = 1;
265                 break;
266
267             case 't' :
268             #ifdef USE_CYASSL_MEMORY
269                 trackMemory = 1;
270             #endif
271                 break;
272
273             case 'm' :
274                 matchName = 1;
275                 break;
276
277             case 'x' :
278                 useClientCert = 0;
279                 break;
280
281             case 'f' :
282                 fewerPackets = 1;
283                 break;
284
285             case 'U' :
286             #ifdef ATOMIC_USER
287                 atomicUser = 1;
288             #endif
289                 break;
290
291             case 'P' :
292             #ifdef HAVE_PK_CALLBACKS 
293                 pkCallbacks = 1;
294             #endif
295                 break;
296
297             case 'h' :
298                 host   = myoptarg;
299                 domain = myoptarg;
300                 break;
301
302             case 'p' :
303                 port = (word16)atoi(myoptarg);
304                 #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
305                     if (port == 0)
306                         err_sys("port number cannot be 0");
307                 #endif
308                 break;
309
310             case 'v' :
311                 version = atoi(myoptarg);
312                 if (version < 0 || version > 3) {
313                     Usage();
314                     exit(MY_EX_USAGE);
315                 }
316                 break;
317
318             case 'l' :
319                 cipherList = myoptarg;
320                 break;
321
322             case 'A' :
323                 verifyCert = myoptarg;
324                 break;
325
326             case 'c' :
327                 ourCert = myoptarg;
328                 break;
329
330             case 'k' :
331                 ourKey = myoptarg;
332                 break;
333
334             case 'b' :
335                 benchmark = atoi(myoptarg);
336                 if (benchmark < 0 || benchmark > 1000000) {
337                     Usage();
338                     exit(MY_EX_USAGE);
339                 }
340                 break;
341
342             case 'N' :
343                 nonBlocking = 1;
344                 break;
345
346             case 'r' :
347                 resumeSession = 1;
348                 break;
349
350             case 'z' :
351                 #ifndef CYASSL_LEANPSK
352                     CyaSSL_GetObjectSize();
353                 #endif
354                 break;
355
356             case 'S' :
357                 #ifdef HAVE_SNI
358                     sniHostName = myoptarg;
359                 #endif
360                 break;
361
362             case 'L' :
363                 #ifdef HAVE_MAX_FRAGMENT
364                     maxFragment = atoi(myoptarg);
365                     if (maxFragment < CYASSL_MFL_2_9 ||
366                                                 maxFragment > CYASSL_MFL_2_13) {
367                         Usage();
368                         exit(MY_EX_USAGE);
369                     }
370                 #endif
371                 break;
372
373             case 'T' :
374                 #ifdef HAVE_TRUNCATED_HMAC
375                     truncatedHMAC = 1;
376                 #endif
377                 break;
378
379             case 'o' :
380                 #ifdef HAVE_OCSP
381                     useOcsp = 1;
382                 #endif
383                 break;
384
385             case 'O' :
386                 #ifdef HAVE_OCSP
387                     useOcsp = 1;
388                     ocspUrl = myoptarg;
389                 #endif
390                 break;
391
392             default:
393                 Usage();
394                 exit(MY_EX_USAGE);
395         }
396     }
397
398     myoptind = 0;      /* reset for test cases */
399
400     /* sort out DTLS versus TLS versions */
401     if (version == CLIENT_INVALID_VERSION) {
402         if (doDTLS)
403             version = CLIENT_DTLS_DEFAULT_VERSION;
404         else
405             version = CLIENT_DEFAULT_VERSION;
406     }
407     else {
408         if (doDTLS) {
409             if (version == 3)
410                 version = -2;
411             else
412                 version = -1;
413         }
414     }
415
416 #ifdef USE_CYASSL_MEMORY
417     if (trackMemory)
418         InitMemoryTracker(); 
419 #endif
420
421     switch (version) {
422 #ifndef NO_OLD_TLS
423         case 0:
424             method = CyaSSLv3_client_method();
425             break;
426                 
427                 
428     #ifndef NO_TLS
429         case 1:
430             method = CyaTLSv1_client_method();
431             break;
432
433         case 2:
434             method = CyaTLSv1_1_client_method();
435             break;
436     #endif /* NO_TLS */
437                 
438 #endif  /* NO_OLD_TLS */
439                 
440 #ifndef NO_TLS
441         case 3:
442             method = CyaTLSv1_2_client_method();
443             break;
444 #endif
445
446 #ifdef CYASSL_DTLS
447         case -1:
448             method = CyaDTLSv1_client_method();
449             break;
450
451         case -2:
452             method = CyaDTLSv1_2_client_method();
453             break;
454 #endif
455
456         default:
457             err_sys("Bad SSL version");
458             break;
459     }
460
461     if (method == NULL)
462         err_sys("unable to get method");
463
464     ctx = CyaSSL_CTX_new(method);
465     if (ctx == NULL)
466         err_sys("unable to get ctx");
467
468     if (cipherList)
469         if (CyaSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
470             err_sys("client can't set cipher list 1");
471
472 #ifdef CYASSL_LEANPSK
473     usePsk = 1;
474 #endif
475
476 #if defined(NO_RSA) && !defined(HAVE_ECC)
477     usePsk = 1;
478 #endif
479
480     if (fewerPackets)
481         CyaSSL_CTX_set_group_messages(ctx);
482
483     if (usePsk) {
484 #ifndef NO_PSK
485         CyaSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
486         if (cipherList == NULL) {
487             const char *defaultCipherList;
488             #ifdef HAVE_NULL_CIPHER
489                 defaultCipherList = "PSK-NULL-SHA256";
490             #else
491                 defaultCipherList = "PSK-AES128-CBC-SHA256";
492             #endif
493             if (CyaSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=SSL_SUCCESS)
494                 err_sys("client can't set cipher list 2");
495         }
496 #endif
497         useClientCert = 0;
498     }
499
500 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
501     CyaSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
502 #endif
503
504 #if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
505     if (cipherList == NULL) {
506         /* don't use EDH, can't sniff tmp keys */
507         if (CyaSSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS) {
508             err_sys("client can't set cipher list 3");
509         }
510     }
511 #endif
512
513 #ifdef HAVE_OCSP
514     if (useOcsp) {
515         if (ocspUrl != NULL) {
516             CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
517             CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE
518                                                     | CYASSL_OCSP_URL_OVERRIDE);
519         }
520         else
521             CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE);
522     }
523 #endif
524
525 #ifdef USER_CA_CB
526     CyaSSL_CTX_SetCACb(ctx, CaCb);
527 #endif
528
529 #ifdef VERIFY_CALLBACK
530     CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
531 #endif
532 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
533     if (useClientCert){
534         if (CyaSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS)
535             err_sys("can't load client cert file, check file and run from"
536                     " CyaSSL home dir");
537
538         if (CyaSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
539                                          != SSL_SUCCESS)
540             err_sys("can't load client private key file, check file and run "
541                     "from CyaSSL home dir");
542     }
543
544     if (!usePsk) {
545         if (CyaSSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
546                 err_sys("can't load ca file, Please run from CyaSSL home dir");
547     }
548 #endif
549 #if !defined(NO_CERTS)
550     if (!usePsk && doPeerCheck == 0)
551         CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
552 #endif
553
554 #ifdef HAVE_CAVIUM
555     CyaSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID);
556 #endif
557
558 #ifdef HAVE_SNI
559     if (sniHostName)
560         if (CyaSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName))
561                                                                  != SSL_SUCCESS)
562             err_sys("UseSNI failed");
563 #endif
564 #ifdef HAVE_MAX_FRAGMENT
565     if (maxFragment)
566         if (CyaSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS)
567             err_sys("UseMaxFragment failed");
568 #endif
569 #ifdef HAVE_TRUNCATED_HMAC
570     if (truncatedHMAC)
571         if (CyaSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
572             err_sys("UseTruncatedHMAC failed");
573 #endif
574
575     if (benchmark) {
576         /* time passed in number of connects give average */
577         int times = benchmark;
578         int i = 0;
579
580         double start = current_time(), avg;
581
582         for (i = 0; i < times; i++) {
583             tcp_connect(&sockfd, host, port, doDTLS);
584
585             ssl = CyaSSL_new(ctx);
586             CyaSSL_set_fd(ssl, sockfd);
587             if (CyaSSL_connect(ssl) != SSL_SUCCESS)
588                 err_sys("SSL_connect failed");
589
590             CyaSSL_shutdown(ssl);
591             CyaSSL_free(ssl);
592             CloseSocket(sockfd);
593         }
594         avg = current_time() - start;
595         avg /= times;
596         avg *= 1000;   /* milliseconds */
597         printf("CyaSSL_connect avg took: %8.3f milliseconds\n", avg);
598
599         CyaSSL_CTX_free(ctx);
600         ((func_args*)args)->return_code = 0;
601
602         exit(EXIT_SUCCESS);
603     }
604     
605     #if defined(CYASSL_MDK_ARM)
606     CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
607     #endif
608     
609     ssl = CyaSSL_new(ctx);
610     if (ssl == NULL)
611         err_sys("unable to get SSL object");
612     if (doDTLS) {
613         SOCKADDR_IN_T addr;
614         build_addr(&addr, host, port, 1);
615         CyaSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
616         tcp_socket(&sockfd, 1);
617     }
618     else {
619         tcp_connect(&sockfd, host, port, 0);
620     }
621     CyaSSL_set_fd(ssl, sockfd);
622 #ifdef HAVE_CRL
623     if (CyaSSL_EnableCRL(ssl, CYASSL_CRL_CHECKALL) != SSL_SUCCESS)
624         err_sys("can't enable crl check");
625     if (CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
626         err_sys("can't load crl, check crlfile and date validity");
627     if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
628         err_sys("can't set crl callback");
629 #endif
630 #ifdef ATOMIC_USER
631     if (atomicUser)
632         SetupAtomicUser(ctx, ssl);
633 #endif
634 #ifdef HAVE_PK_CALLBACKS
635     if (pkCallbacks)
636         SetupPkCallbacks(ctx, ssl);
637 #endif
638     if (matchName && doPeerCheck)
639         CyaSSL_check_domain_name(ssl, domain);
640 #ifndef CYASSL_CALLBACKS
641     if (nonBlocking) {
642         CyaSSL_set_using_nonblock(ssl, 1);
643         tcp_set_nonblocking(&sockfd);
644         NonBlockingSSL_Connect(ssl);
645     }
646     else if (CyaSSL_connect(ssl) != SSL_SUCCESS) {
647         /* see note at top of README */
648         int  err = CyaSSL_get_error(ssl, 0);
649         char buffer[CYASSL_MAX_ERROR_SZ];
650         printf("err = %d, %s\n", err,
651                                 CyaSSL_ERR_error_string(err, buffer));
652         err_sys("SSL_connect failed");
653         /* if you're getting an error here  */
654     }
655 #else
656     timeout.tv_sec  = 2;
657     timeout.tv_usec = 0;
658     NonBlockingSSL_Connect(ssl);  /* will keep retrying on timeout */
659 #endif
660     showPeer(ssl);
661
662     if (sendGET) {
663         printf("SSL connect ok, sending GET...\n");
664         msgSz = 28;
665         strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz);
666         msg[msgSz] = '\0';
667     }
668     if (CyaSSL_write(ssl, msg, msgSz) != msgSz)
669         err_sys("SSL_write failed");
670
671     input = CyaSSL_read(ssl, reply, sizeof(reply)-1);
672     if (input > 0) {
673         reply[input] = 0;
674         printf("Server response: %s\n", reply);
675
676         if (sendGET) {  /* get html */
677             while (1) {
678                 input = CyaSSL_read(ssl, reply, sizeof(reply)-1);
679                 if (input > 0) {
680                     reply[input] = 0;
681                     printf("%s\n", reply);
682                 }
683                 else
684                     break;
685             }
686         }
687     }
688     else if (input < 0) {
689         int readErr = CyaSSL_get_error(ssl, 0);
690         if (readErr != SSL_ERROR_WANT_READ)
691             err_sys("CyaSSL_read failed");
692     }
693
694 #ifndef NO_SESSION_CACHE
695     if (resumeSession) {
696         if (doDTLS) {
697             strncpy(msg, "break", 6);
698             msgSz = (int)strlen(msg);
699             /* try to send session close */
700             CyaSSL_write(ssl, msg, msgSz);
701         }
702         session   = CyaSSL_get_session(ssl);
703         sslResume = CyaSSL_new(ctx);
704     }
705 #endif
706
707     if (doDTLS == 0)            /* don't send alert after "break" command */
708         CyaSSL_shutdown(ssl);  /* echoserver will interpret as new conn */
709 #ifdef ATOMIC_USER
710     if (atomicUser)
711         FreeAtomicUser(ssl);
712 #endif
713     CyaSSL_free(ssl);
714     CloseSocket(sockfd);
715
716 #ifndef NO_SESSION_CACHE
717     if (resumeSession) {
718         if (doDTLS) {
719             SOCKADDR_IN_T addr;
720             #ifdef USE_WINDOWS_API 
721                 Sleep(500);
722             #else
723                 sleep(1);
724             #endif
725             build_addr(&addr, host, port, 1);
726             CyaSSL_dtls_set_peer(sslResume, &addr, sizeof(addr));
727             tcp_socket(&sockfd, 1);
728         }
729         else {
730             tcp_connect(&sockfd, host, port, 0);
731         }
732         CyaSSL_set_fd(sslResume, sockfd);
733         CyaSSL_set_session(sslResume, session);
734        
735         showPeer(sslResume);
736 #ifndef CYASSL_CALLBACKS
737         if (nonBlocking) {
738             CyaSSL_set_using_nonblock(sslResume, 1);
739             tcp_set_nonblocking(&sockfd);
740             NonBlockingSSL_Connect(sslResume);
741         }
742         else if (CyaSSL_connect(sslResume) != SSL_SUCCESS)
743             err_sys("SSL resume failed");
744 #else
745         timeout.tv_sec  = 2;
746         timeout.tv_usec = 0;
747         NonBlockingSSL_Connect(ssl);  /* will keep retrying on timeout */
748 #endif
749
750         if (CyaSSL_session_reused(sslResume))
751             printf("reused session id\n");
752         else
753             printf("didn't reuse session id!!!\n");
754
755         if (CyaSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
756             err_sys("SSL_write failed");
757
758         if (nonBlocking) {
759             /* give server a chance to bounce a message back to client */
760             #ifdef USE_WINDOWS_API
761                 Sleep(500);
762             #else
763                 sleep(1);
764             #endif
765         }
766
767         input = CyaSSL_read(sslResume, reply, sizeof(reply)-1);
768         if (input > 0) {
769             reply[input] = 0;
770             printf("Server resume response: %s\n", reply);
771         }
772
773         /* try to send session break */
774         CyaSSL_write(sslResume, msg, msgSz); 
775
776         CyaSSL_shutdown(sslResume);
777         CyaSSL_free(sslResume);
778         CloseSocket(sockfd);
779     }
780 #endif /* NO_SESSION_CACHE */
781
782     CyaSSL_CTX_free(ctx);
783
784     ((func_args*)args)->return_code = 0;
785
786 #ifdef USE_CYASSL_MEMORY
787     if (trackMemory)
788         ShowMemoryTracker();
789 #endif /* USE_CYASSL_MEMORY */
790
791     return 0;
792 }
793
794
795 /* so overall tests can pull in test function */
796 #ifndef NO_MAIN_DRIVER
797
798     int main(int argc, char** argv)
799     {
800         func_args args;
801
802 #ifdef HAVE_CAVIUM
803         int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID);
804         if (ret != 0)
805             err_sys("Cavium OpenNitroxDevice failed");
806 #endif /* HAVE_CAVIUM */
807
808         StartTCP();
809
810         args.argc = argc;
811         args.argv = argv;
812
813         CyaSSL_Init();
814 #if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL) && !defined(STACK_TRAP)
815         CyaSSL_Debugging_ON();
816 #endif
817         if (CurrentDir("client"))
818             ChangeDirBack(2);
819         else if (CurrentDir("Debug") || CurrentDir("Release"))
820             ChangeDirBack(3);
821   
822 #ifdef HAVE_STACK_SIZE
823         StackSizeCheck(&args, client_test);
824 #else 
825         client_test(&args);
826 #endif
827         CyaSSL_Cleanup();
828
829 #ifdef HAVE_CAVIUM
830         CspShutdown(CAVIUM_DEV_ID);
831 #endif
832         return args.return_code;
833     }
834
835     int myoptind = 0;
836     char* myoptarg = NULL;
837
838 #endif /* NO_MAIN_DRIVER */
839
840
841
842 #ifdef CYASSL_CALLBACKS
843
844     int handShakeCB(HandShakeInfo* info)
845     {
846         (void)info;
847         return 0;
848     }
849
850
851     int timeoutCB(TimeoutInfo* info)
852     {
853         (void)info;
854         return 0;
855     }
856
857 #endif
858