From efe10c74b1e22cce42a4d0d15572725f436a7407 Mon Sep 17 00:00:00 2001 From: toddouska Date: Tue, 21 Mar 2017 15:07:14 -0700 Subject: [PATCH] add dtls shared example with multiple writers on same WOLFSSL, with a reader at the same time --- .gitignore | 1 + dtls/Makefile | 7 +- dtls/client-dtls-shared.c | 268 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 dtls/client-dtls-shared.c diff --git a/.gitignore b/.gitignore index 52da51c2..c2ede6a7 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ android/wolfssljni-ndk-sample/proguard-project.txt # Example executables /dtls/client-dtls-nonblocking /dtls/client-dtls-resume +/dtls/client-dtls-shared /dtls/client-dtls /dtls/client-udp /dtls/server-dtls-nonblocking diff --git a/dtls/Makefile b/dtls/Makefile index 80f3aa49..003b5544 100644 --- a/dtls/Makefile +++ b/dtls/Makefile @@ -2,7 +2,7 @@ CC=gcc CFLAGS=-Wall -DWOLFSSL_DTLS LIBS=-lwolfssl -lpthread -all: client-udp client-dtls client-dtls-nonblocking client-dtls-resume server-udp server-dtls server-dtls-nonblocking server-dtls-threaded +all: client-udp client-dtls client-dtls-nonblocking client-dtls-resume client-dtls-shared server-udp server-dtls server-dtls-nonblocking server-dtls-threaded client-udp: client-udp.o $(CC) -o $@ $^ $(CFLAGS) @@ -16,6 +16,9 @@ client-dtls-nonblocking: client-dtls-nonblocking.o client-dtls-resume: client-dtls-resume.o $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +client-dtls-shared: client-dtls-shared.o + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + server-udp: server-udp.o $(CC) -o $@ $^ $(CFLAGS) @@ -32,4 +35,4 @@ server-dtls-threaded: server-dtls-threaded.o .PHONY: clean all clean: - rm -f *.o client-udp client-dtls client-dtls-nonblocking client-dtls-resume server-udp server-dtls server-dtls-nonblocking server-dtls-threaded + rm -f *.o client-udp client-dtls client-dtls-nonblocking client-dtls-resume client-dtls-shared server-udp server-dtls server-dtls-nonblocking server-dtls-threaded diff --git a/dtls/client-dtls-shared.c b/dtls/client-dtls-shared.c new file mode 100644 index 00000000..9636329f --- /dev/null +++ b/dtls/client-dtls-shared.c @@ -0,0 +1,268 @@ +/* + * client-dtls-shared.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + *============================================================================= + * + * DTLS client example using multi-thread shared wrapper for + * instructional/learning purposes. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXBUF 1024 +#define MAXMSGS 100 +/* number of writer threads */ +#define THREADS 3 +#define SERV_PORT 11111 + + +typedef struct SharedDtls { + wolfSSL_Mutex shared_mutex; /* mutex for using */ + WOLFSSL* ssl; /* WOLFSSL object being shared */ + int sd; /* socket fd */ + struct sockaddr_in servAddr; /* server sockaddr */ + socklen_t servSz; /* length of servAddr */ + char* recvBuf; /* I/O recv cb buffer */ + int recvSz; /* bytes in recvBuf */ + int handShakeDone; /* is the handshake done? */ +} SharedDtls; + + +int dtls_sendto_cb(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + SharedDtls* shared = (SharedDtls*)ctx; + + return sendto(shared->sd, buf, sz, 0, + (const struct sockaddr*)&shared->servAddr, shared->servSz); +} + + +static int min(int a, int b) +{ + return a > b ? b : a; +} + + +int dtls_recvfrom_cb(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + SharedDtls* shared = (SharedDtls*)ctx; + + if (!shared->handShakeDone) { + /* get directly from socket */ + return recvfrom(shared->sd, buf, sz, 0, NULL, NULL); + } else { + /* get the "pushed" datagram from our cb buffer instead */ + int copied = min(sz, shared->recvSz); + + memcpy(buf, shared->recvBuf, copied); + shared->recvSz -= copied; + + return copied; + } +} + + +/* each thread should have a simple id at startup */ +char get_id(SharedDtls* shared) +{ + char ids[] = "abcdefgh"; + char ret; + static int index = 0; + + wc_LockMutex(&shared->shared_mutex); + + ret = ids[index++]; + + wc_UnLockMutex(&shared->shared_mutex); + + return ret; +} + + +/* DTLS Send function in its own thread */ +void* DatagramSend(void* arg) +{ + int i; + int sendSz; + char sendBuf[MAXBUF]; + SharedDtls* shared = (SharedDtls*)arg; + char id = get_id(shared); + WOLFSSL* ssl = shared->ssl; + + + for (i= 0; i < MAXMSGS; i++) { + + snprintf(sendBuf, MAXBUF, "thread %c sending msg %d\n", id, i); + sendSz = strlen(sendBuf) + 1; + + wc_LockMutex(&shared->shared_mutex); + + if ( (wolfSSL_write(ssl, sendBuf, sendSz)) != sendSz) { + printf("wolfSSL_write failed"); + } + + wc_UnLockMutex(&shared->shared_mutex); + + } + + return NULL; +} + + +/* DTLS Recv function */ +void DatagramRecv(WOLFSSL* ssl, SharedDtls* shared) +{ + int i; + int sz = 0; + char recvBuf[MAXBUF]; + char plainBuf[MAXBUF]; + + for (i = 0; i < THREADS*MAXMSGS; i++) { + /* first get datagram, works in blocking mode too */ + sz = recvfrom(shared->sd, recvBuf, MAXBUF, 0, NULL, NULL); + + wc_LockMutex(&shared->shared_mutex); + + /* push datagram to our cb, no copy needed! */ + shared->recvBuf = recvBuf; + shared->recvSz = sz; + + /* get plaintext */ + if ( (sz = (wolfSSL_read(ssl, plainBuf, MAXBUF-1))) < 0) { + printf("wolfSSL_write failed"); + } + + wc_UnLockMutex(&shared->shared_mutex); + + plainBuf[MAXBUF-1] = '\0'; + printf("got msg %s\n", plainBuf); + } +} + + +int main (int argc, char** argv) +{ + int sockfd = 0, i; + WOLFSSL* ssl = 0; + WOLFSSL_CTX* ctx = 0; + char* ca = "../certs/ca-cert.pem"; + char* ecc_ca = "../certs/server-ecc.pem"; + SharedDtls shared; + + if (argc != 2) { + printf("usage: udpcli \n"); + return 1; + } + + wolfSSL_Init(); + + if ( (ctx = wolfSSL_CTX_new(wolfDTLSv1_2_client_method())) == NULL) { + fprintf(stderr, "wolfSSL_CTX_new error.\n"); + return 1; + } + + if (wolfSSL_CTX_load_verify_locations(ctx, ca, 0) != SSL_SUCCESS) { + fprintf(stderr, "Error loading %s, please check the file.\n", ca); + return 1; + } + if (wolfSSL_CTX_load_verify_locations(ctx, ecc_ca, 0) != SSL_SUCCESS) { + fprintf(stderr, "Error loading %s, please check the file.\n", ecc_ca); + return 1; + } + + wolfSSL_SetIOSend(ctx, dtls_sendto_cb); + wolfSSL_SetIORecv(ctx, dtls_recvfrom_cb); + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + printf("unable to get ssl object"); + return 1; + } + + memset(&shared.servAddr, 0, sizeof(shared.servAddr)); + shared.servAddr.sin_family = AF_INET; + shared.servAddr.sin_port = htons(SERV_PORT); + if (inet_pton(AF_INET, argv[1], &shared.servAddr.sin_addr) < 1) { + printf("Error and/or invalid IP address"); + return 1; + } + + if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("cannot create a socket."); + return 1; + } + + shared.sd = sockfd; + shared.servSz = sizeof(shared.servAddr); + shared.ssl = ssl; + shared.handShakeDone = 0; + + if (wc_InitMutex(&shared.shared_mutex) != 0) { + printf("wc_InitMutex failed"); + return 1; + } + + wolfSSL_SetIOWriteCtx(ssl, &shared); + wolfSSL_SetIOReadCtx(ssl, &shared); + + if (wolfSSL_connect(ssl) != SSL_SUCCESS) { + int err1 = wolfSSL_get_error(ssl, 0); + printf("err = %d, %s\n", err1, wolfSSL_ERR_reason_error_string(err1)); + printf("SSL_connect failed"); + return 1; + } + + shared.handShakeDone = 1; + + pthread_t tid[THREADS]; + for (i = 0; i < THREADS; i++) { + pthread_create(&tid[i], NULL, DatagramSend, &shared); + } + + DatagramRecv(ssl, &shared); + + for (i = 0; i < THREADS; i++) { + pthread_join(tid[i], NULL); + } + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + close(sockfd); + wolfSSL_CTX_free(ctx); + wc_FreeMutex(&shared.shared_mutex); + wolfSSL_Cleanup(); + + return 0; +} +