wolfSSL 3.11.1 for TLS1.3 beta
Fork of wolfSSL by
Diff: wolfcrypt/src/wolfevent.c
- Revision:
- 11:cee25a834751
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfcrypt/src/wolfevent.c Tue May 30 01:44:10 2017 +0000 @@ -0,0 +1,286 @@ +/* wolfevent.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * 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-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <wolfssl/wolfcrypt/settings.h> + + +#ifdef HAVE_WOLF_EVENT + +#include <wolfssl/internal.h> +#include <wolfssl/error-ssl.h> +#include <wolfssl/wolfcrypt/error-crypt.h> + +#include <wolfssl/wolfcrypt/wolfevent.h> + + +int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) +{ + if (event == NULL) { + return BAD_FUNC_ARG; + } + + if (event->pending) { + WOLFSSL_MSG("event already pending!"); + return BAD_COND_E; + } + + XMEMSET(event, 0, sizeof(WOLF_EVENT)); + event->type = type; + event->context = context; + + return 0; +} + +int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags) +{ + int ret = BAD_COND_E; + + /* Check hardware */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST && + event->type <= WOLF_EVENT_TYPE_ASYNC_LAST) + { + ret = wolfAsync_EventPoll(event, flags); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue) +{ + int ret = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(queue, 0, sizeof(WOLF_EVENT_QUEUE)); +#ifndef SINGLE_THREADED + ret = wc_InitMutex(&queue->lock); +#endif + return ret; +} + + +int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Setup event */ + event->next = NULL; + event->pending = 1; + + ret = wolfEventQueue_Add(queue, event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Pop first item off queue */ + *event = queue->head; + ret = wolfEventQueue_Remove(queue, *event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +/* assumes queue is locked by caller */ +int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + if (queue->tail == NULL) { + queue->head = event; + } + else { + queue->tail->next = event; + event->prev = queue->tail; + } + queue->tail = event; /* add to the end either way */ + queue->count++; + + return 0; +} + +/* assumes queue is locked by caller */ +int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + if (event == queue->head && event == queue->tail) { + queue->head = NULL; + queue->tail = NULL; + } + else if (event == queue->head) { + queue->head = event->next; + queue->head->prev = NULL; + } + else if (event == queue->tail) { + queue->tail = event->prev; + queue->tail->next = NULL; + } + else { + WOLF_EVENT* next = event->next; + WOLF_EVENT* prev = event->prev; + next->prev = prev; + prev->next = next; + } + queue->count--; + + return ret; +} + +int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount) +{ + WOLF_EVENT* event; + int ret = 0, count = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* itterate event queue */ + for (event = queue->head; event != NULL; event = event->next) + { + /* optional filter based on context */ + if (context_filter == NULL || event->context == context_filter) { + + /* poll event */ + ret = wolfEvent_Poll(event, flags); + if (ret < 0) break; /* exit for */ + + /* If event is done then process */ + if (event->done) { + /* remove from queue */ + ret = wolfEventQueue_Remove(queue, event); + if (ret < 0) break; /* exit for */ + + /* return pointer in 'events' arg */ + if (events) { + events[count] = event; /* return pointer */ + } + count++; + + /* check to make sure our event list isn't full */ + if (events && count >= maxEvents) { + break; /* exit for */ + } + } + } + } + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + /* return number of properly populated events */ + if (eventCount) { + *eventCount = count; + } + + return ret; +} + +int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue) +{ + int ret; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = queue->count; + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue) +{ + if (queue) { + #ifndef SINGLE_THREADED + wc_FreeMutex(&queue->lock); + #endif + } +} + +#endif /* HAVE_WOLF_EVENT */ +