DTLS-SCTP example client and server

1. Update the example client and server to test DTLS-SCTP.
2. Modify the test.h functions for setting up connections to allow
for a SCTP option.
3. Update other examples to use the new test.h functions.
4. Removed some prototypes in the client header file were some functions
that should have been static to the client.c file and made them static.
This commit is contained in:
John Safranek 2016-08-25 22:20:35 -07:00
parent 6d5df3928f
commit 46e92e0211
7 changed files with 107 additions and 62 deletions

View File

@ -156,8 +156,10 @@ static void ShowVersions(void)
printf("3\n");
}
int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
int doDTLS, int benchmark, int resumeSession)
/* Measures average time to create, connect and disconnect a connection (TPS).
Benchmark = number of connections. */
static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession)
{
/* time passed in number of connects give average */
int times = benchmark;
@ -180,7 +182,7 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
if (ssl == NULL)
err_sys("unable to get SSL object");
tcp_connect(&sockfd, host, port, doDTLS, ssl);
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
#ifndef NO_SESSION_CACHE
if (benchResume)
@ -215,8 +217,9 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
return EXIT_SUCCESS;
}
int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
int doDTLS, int throughput)
/* Measures throughput in kbps. Throughput = number of bytes */
static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
int dtlsUDP, int dtlsSCTP, int throughput)
{
double start, conn_time = 0, tx_time = 0, rx_time = 0;
SOCKET_T sockfd;
@ -227,7 +230,7 @@ int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
ssl = wolfSSL_new(ctx);
if (ssl == NULL)
err_sys("unable to get SSL object");
tcp_connect(&sockfd, host, port, doDTLS, ssl);
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) {
err_sys("error in setting fd");
}
@ -343,7 +346,8 @@ const char* starttlsCmd[6] = {
"QUIT\r\n",
};
int StartTLS_Init(SOCKET_T* sockfd)
/* Initiates the STARTTLS command sequence over TCP */
static int StartTLS_Init(SOCKET_T* sockfd)
{
char tmpBuf[256];
@ -399,7 +403,8 @@ int StartTLS_Init(SOCKET_T* sockfd)
return SSL_SUCCESS;
}
int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown)
/* Closes down the SMTP connection */
static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown)
{
int ret;
char tmpBuf[256];
@ -461,6 +466,10 @@ static void Usage(void)
printf("-g Send server HTTP GET\n");
printf("-u Use UDP DTLS,"
" add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n");
#ifdef WOLFSSL_SCTP
printf("-G Use SCTP DTLS,"
" add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n");
#endif
printf("-m Match domain name in cert\n");
printf("-N Use Non-blocking sockets\n");
printf("-r Resume session\n");
@ -551,6 +560,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
int benchmark = 0;
int throughput = 0;
int doDTLS = 0;
int dtlsUDP = 0;
int dtlsSCTP = 0;
int matchName = 0;
int doPeerCheck = 1;
int nonBlocking = 0;
@ -640,7 +651,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifndef WOLFSSL_VXWORKS
while ((ch = mygetopt(argc, argv,
"?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:"))
"?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:"))
!= -1) {
switch (ch) {
case '?' :
@ -670,7 +681,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
break;
case 'u' :
doDTLS = 1;
doDTLS = 1;
dtlsUDP = 1;
break;
case 'G' :
#ifdef WOLFSSL_SCTP
doDTLS = 1;
dtlsSCTP = 1;
#endif
break;
case 's' :
@ -1212,14 +1231,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (benchmark) {
((func_args*)args)->return_code =
ClientBenchmarkConnections(ctx, host, port, doDTLS, benchmark, resumeSession);
ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP,
benchmark, resumeSession);
wolfSSL_CTX_free(ctx);
exit(EXIT_SUCCESS);
}
if(throughput) {
((func_args*)args)->return_code =
ClientBenchmarkThroughput(ctx, host, port, doDTLS, throughput);
ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP,
throughput);
wolfSSL_CTX_free(ctx);
exit(EXIT_SUCCESS);
}
@ -1305,7 +1326,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
#endif
tcp_connect(&sockfd, host, port, doDTLS, ssl);
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl);
if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) {
err_sys("error in setting fd");
}
@ -1484,7 +1505,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
}
#endif
if (doDTLS == 0) { /* don't send alert after "break" command */
if (dtlsUDP == 0) { /* don't send alert after "break" command */
ret = wolfSSL_shutdown(ssl);
if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
wolfSSL_shutdown(ssl); /* bidirectional shutdown */
@ -1498,7 +1519,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifndef NO_SESSION_CACHE
if (resumeSession) {
if (doDTLS) {
if (dtlsUDP) {
#ifdef USE_WINDOWS_API
Sleep(500);
#elif defined(WOLFSSL_TIRTOS)
@ -1507,7 +1528,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
sleep(1);
#endif
}
tcp_connect(&sockfd, host, port, doDTLS, sslResume);
tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume);
if (wolfSSL_set_fd(sslResume, sockfd) != SSL_SUCCESS) {
err_sys("error in setting fd");
}

View File

@ -26,21 +26,6 @@
THREAD_RETURN WOLFSSL_THREAD client_test(void* args);
/* Measures average time to create, connect and disconnect a connection (TPS).
Benchmark = number of connections. */
int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
int doDTLS, int benchmark, int resumeSession);
/* Measures throughput in kbps. Throughput = number of bytes */
int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
int doDTLS, int throughput);
/* Initiates the STARTTLS command sequence over TCP */
int StartTLS_Init(SOCKET_T* sockfd);
/* Closes down the SMTP connection */
int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown);
#endif /* WOLFSSL_CLIENT_H */

View File

@ -180,7 +180,7 @@ void echoclient_test(void* args)
#endif /* WOLFSSL_ASYNC_CRYPT */
ssl = SSL_new(ctx);
tcp_connect(&sockfd, yasslIP, port, doDTLS, ssl);
tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl);
SSL_set_fd(ssl, sockfd);
#if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER)

View File

@ -136,7 +136,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
fdOpenSession(Task_self());
#endif
tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0);
#if defined(CYASSL_DTLS)
method = CyaDTLSv1_2_server_method();
@ -373,7 +373,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
CyaSSL_free(ssl);
CloseSocket(clientfd);
#ifdef CYASSL_DTLS
tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0);
SignalReady(args, port);
#endif
}

View File

@ -219,6 +219,10 @@ static void Usage(void)
printf("-t Track wolfSSL memory use\n");
printf("-u Use UDP DTLS,"
" add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n");
#ifdef WOLFSSL_SCTP
printf("-G Use SCTP DTLS,"
" add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n");
#endif
printf("-f Fewer packets/group messages\n");
printf("-r Allow one client Resumption\n");
printf("-N Use Non-blocking sockets\n");
@ -275,6 +279,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
int usePskPlus = 0;
int useAnon = 0;
int doDTLS = 0;
int dtlsUDP = 0;
int dtlsSCTP = 0;
int needDH = 0;
int useNtruKey = 0;
int nonBlocking = 0;
@ -370,7 +376,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
useAnyAddr = 1;
#else
while ((ch = mygetopt(argc, argv,
"?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) {
"?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -404,6 +410,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
case 'u' :
doDTLS = 1;
dtlsUDP = 1;
break;
case 'G' :
#ifdef WOLFSSL_SCTP
doDTLS = 1;
dtlsSCTP = 1;
#endif
break;
case 'f' :
@ -563,6 +577,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
myoptind = 0; /* reset for test cases */
#endif /* !WOLFSSL_VXWORKS */
/* Can only use DTLS over UDP or SCTP, can't do both. */
if (dtlsUDP && dtlsSCTP) {
err_sys("Cannot use DTLS with both UDP and SCTP.");
}
/* sort out DTLS versus TLS versions */
if (version == CLIENT_INVALID_VERSION) {
if (doDTLS)
@ -689,6 +708,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
if (fewerPackets)
CyaSSL_CTX_set_group_messages(ctx);
#ifdef WOLFSSL_SCTP
if (dtlsSCTP)
wolfSSL_CTX_dtls_set_sctp(ctx);
#endif
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif
@ -821,13 +845,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
while (1) {
/* allow resume option */
if(resumeCount > 1) {
if (doDTLS == 0) {
if (dtlsUDP == 0) {
SOCKADDR_IN_T client;
socklen_t client_len = sizeof(client);
clientfd = accept(sockfd, (struct sockaddr*)&client,
(ACCEPT_THIRD_T)&client_len);
} else {
tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP);
clientfd = sockfd;
}
if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) {
@ -908,7 +932,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
readySignal->srfName = serverReadyFile;
}
tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr,
doDTLS, serverReadyFile ? 1 : 0, doListen);
dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen);
doListen = 0; /* Don't listen next time */
if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) {
@ -923,7 +947,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
#endif
#ifdef WOLFSSL_DTLS
if (doDTLS) {
if (doDTLS && dtlsUDP) {
SOCKADDR_IN_T cliaddr;
byte b[1500];
int n;
@ -1039,7 +1063,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
Task_yield();
#endif
if (doDTLS == 0) {
if (dtlsUDP == 0) {
ret = SSL_shutdown(ssl);
if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
SSL_shutdown(ssl); /* bidirectional shutdown */

View File

@ -672,7 +672,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
}
ssl = wolfSSL_new(ctx);
tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 1);
tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1);
CloseSocket(sockfd);
if (wolfSSL_set_fd(ssl, clientfd) != SSL_SUCCESS) {
@ -800,7 +800,8 @@ static void test_client_nofail(void* args)
}
ssl = wolfSSL_new(ctx);
tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl);
tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port,
0, 0, ssl);
if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) {
/*err_sys("SSL_set_fd failed");*/
goto done2;
@ -919,14 +920,14 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
socklen_t cliLen;
cliLen = sizeof(cliAddr);
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0);
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0);
idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK,
(struct sockaddr*)&cliAddr, &cliLen);
AssertIntGT(idx, 0);
wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen);
}
else {
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1);
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1);
CloseSocket(sfd);
}
@ -1051,10 +1052,12 @@ static void run_wolfssl_client(void* args)
ssl = wolfSSL_new(ctx);
if (wolfSSL_dtls(ssl)) {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, ssl);
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port,
1, 0, ssl);
}
else {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl);
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port,
0, 0, ssl);
}
AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd));

View File

@ -564,11 +564,12 @@ static INLINE void showPeer(WOLFSSL* ssl)
static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
word16 port, int udp)
word16 port, int udp, int sctp)
{
int useLookup = 0;
(void)useLookup;
(void)udp;
(void)sctp;
if (addr == NULL)
err_sys("invalid argument to build_addr, addr is NULL");
@ -628,8 +629,17 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET_V;
hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
if (udp) {
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
} else if (sctp) {
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_SCTP;
}
else {
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
}
SNPRINTF(strPort, sizeof(strPort), "%d", port);
strPort[79] = '\0';
@ -649,10 +659,12 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
}
static INLINE void tcp_socket(SOCKET_T* sockfd, int udp)
static INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp)
{
if (udp)
*sockfd = socket(AF_INET_V, SOCK_DGRAM, 0);
else if (sctp)
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
else
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
@ -677,7 +689,7 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp)
#endif /* S_NOSIGPIPE */
#if defined(TCP_NODELAY)
if (!udp)
if (!udp && !sctp)
{
int on = 1;
socklen_t len = sizeof(on);
@ -690,14 +702,14 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp)
}
static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port,
int udp, WOLFSSL* ssl)
int udp, int sctp, WOLFSSL* ssl)
{
SOCKADDR_IN_T addr;
build_addr(&addr, ip, port, udp);
if(udp) {
build_addr(&addr, ip, port, udp, sctp);
if (udp) {
wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
}
tcp_socket(sockfd, udp);
tcp_socket(sockfd, udp, sctp);
if (!udp) {
if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
@ -757,14 +769,14 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr,
int udp)
int udp, int sctp)
{
SOCKADDR_IN_T addr;
/* don't use INADDR_ANY by default, firewall may block, make user switch
on */
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp);
tcp_socket(sockfd, udp);
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp);
tcp_socket(sockfd, udp, sctp);
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
&& !defined(WOLFSSL_KEIL_TCP_NET)
@ -826,8 +838,8 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
SOCKADDR_IN_T addr;
(void)args;
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1);
tcp_socket(sockfd, 1);
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0);
tcp_socket(sockfd, 1, 0);
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \
@ -879,7 +891,7 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
func_args* args, word16 port, int useAnyAddr,
int udp, int ready_file, int do_listen)
int udp, int sctp, int ready_file, int do_listen)
{
SOCKADDR_IN_T client;
socklen_t client_len = sizeof(client);
@ -893,7 +905,7 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
}
if(do_listen) {
tcp_listen(sockfd, &port, useAnyAddr, udp);
tcp_listen(sockfd, &port, useAnyAddr, udp, sctp);
#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
/* signal ready to tcp_accept */