MbedTLS transport implementation (#175)

This commit is contained in:
leegeth
2020-08-05 09:38:32 -07:00
committed by GitHub
parent a007d6fc90
commit 80bd2bab3c
6 changed files with 1420 additions and 0 deletions
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file threading_alt.h
* @brief mbed TLS threading functions implemented for FreeRTOS.
*/
#ifndef MBEDTLS_THREADING_ALT_H_
#define MBEDTLS_THREADING_ALT_H_
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "semphr.h"
/**
* @brief mbed TLS mutex type.
*
* mbed TLS requires platform specific definition for the mutext type. Defining the type for
* FreeRTOS with FreeRTOS semaphore
* handle and semaphore storage as members.
*/
typedef struct mbedtls_threading_mutex
{
SemaphoreHandle_t mutexHandle;
StaticSemaphore_t mutexStorage;
} mbedtls_threading_mutex_t;
/* mbed TLS mutex functions. */
void mbedtls_platform_mutex_init( mbedtls_threading_mutex_t * pMutex );
void mbedtls_platform_mutex_free( mbedtls_threading_mutex_t * pMutex );
int mbedtls_platform_mutex_lock( mbedtls_threading_mutex_t * pMutex );
int mbedtls_platform_mutex_unlock( mbedtls_threading_mutex_t * pMutex );
#endif /* ifndef MBEDTLS_THREADING_ALT_H_ */
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file freertos_sockets_wrapper.h
* @brief FreeRTOS Sockets connect and disconnect function wrapper.
*/
#ifndef FREERTOS_SOCKETS_WRAPPER_H_
#define FREERTOS_SOCKETS_WRAPPER_H_
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
/**************************************************/
/******* DO NOT CHANGE the following order ********/
/**************************************************/
/* Logging related header files are required to be included in the following order:
* 1. Include the header file "logging_levels.h".
* 2. Define LIBRARY_LOG_NAME and LIBRARY_LOG_LEVEL.
* 3. Include the header file "logging_stack.h".
*/
/* Include header that defines log levels. */
#include "logging_levels.h"
/* Logging configuration for the Sockets. */
#ifndef LIBRARY_LOG_NAME
#define LIBRARY_LOG_NAME "Sockets"
#endif
#ifndef LIBRARY_LOG_LEVEL
#define LIBRARY_LOG_LEVEL LOG_ERROR
#endif
#include "logging_stack.h"
/************ End of logging configuration ****************/
/**
* @brief Establish a connection to server.
*
* @param[out] pTcpSocket The output parameter to return the created socket descriptor.
* @param[in] pHostName Server hostname to connect to.
* @param[in] pServerInfo Server port to connect to.
* @param[in] receiveTimeoutMs Timeout (in milliseconds) for transport receive.
* @param[in] sendTimeoutMs Timeout (in milliseconds) for transport send.
*
* @note A timeout of 0 means infinite timeout.
*
* @return Non-zero value on error, 0 on success.
*/
BaseType_t Sockets_Connect( Socket_t * pTcpSocket,
const char * pHostName,
uint16_t port,
uint32_t receiveTimeoutMs,
uint32_t sendTimeoutMs );
/**
* @brief End connection to server.
*
* @param[in] tcpSocket The socket descriptor.
*/
void Sockets_Disconnect( Socket_t tcpSocket );
#endif /* ifndef FREERTOS_SOCKETS_WRAPPER_H_ */
@@ -0,0 +1,168 @@
/*
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file freertos_sockets_wrapper.c
* @brief FreeRTOS Sockets connect and disconnect wrapper implementation.
*/
/* Standard includes. */
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "freertos_sockets_wrapper.h"
/*-----------------------------------------------------------*/
/* Maximum number of times to call FreeRTOS_recv when initiating a graceful shutdown. */
#ifndef FREERTOS_SOCKETS_WRAPPER_SHUTDOWN_LOOPS
#define FREERTOS_SOCKETS_WRAPPER_SHUTDOWN_LOOPS ( 3 )
#endif
/* A negative error code indicating a network failure. */
#define FREERTOS_SOCKETS_WRAPPER_NETWORK_ERROR ( -1 )
/*-----------------------------------------------------------*/
BaseType_t Sockets_Connect( Socket_t * pTcpSocket,
const char * pHostName,
uint16_t port,
uint32_t receiveTimeoutMs,
uint32_t sendTimeoutMs )
{
Socket_t tcpSocket = FREERTOS_INVALID_SOCKET;
BaseType_t socketStatus = 0;
struct freertos_sockaddr serverAddress = { 0 };
TickType_t transportTimeout = 0;
/* Create a new TCP socket. */
tcpSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
if( tcpSocket == FREERTOS_INVALID_SOCKET )
{
LogError( ( "Failed to create new socket." ) );
socketStatus = FREERTOS_SOCKETS_WRAPPER_NETWORK_ERROR;
}
else
{
LogDebug( ( "Created new TCP socket." ) );
/* Connection parameters. */
serverAddress.sin_family = FREERTOS_AF_INET;
serverAddress.sin_port = FreeRTOS_htons( port );
serverAddress.sin_addr = FreeRTOS_gethostbyname( pHostName );
serverAddress.sin_len = ( uint8_t ) sizeof( serverAddress );
/* Check for errors from DNS lookup. */
if( serverAddress.sin_addr == 0 )
{
LogError( ( "Failed to connect to server: DNS resolution failed: Hostname=%s.",
pHostName ) );
socketStatus = FREERTOS_SOCKETS_WRAPPER_NETWORK_ERROR;
}
}
if( socketStatus == 0 )
{
/* Establish connection. */
LogDebug( ( "Creating TCP Connection to %s.", pHostName ) );
socketStatus = FreeRTOS_connect( tcpSocket, &serverAddress, sizeof( serverAddress ) );
if( socketStatus != 0 )
{
LogError( ( "Failed to connect to server: FreeRTOS_Connect failed: ReturnCode=%d,"
" Hostname=%s, Port=%u.",
socketStatus,
pHostName,
port ) );
}
}
if( socketStatus == 0 )
{
/* Set socket receive timeout. */
transportTimeout = pdMS_TO_TICKS( receiveTimeoutMs );
/* Setting the receive block time cannot fail. */
( void ) FreeRTOS_setsockopt( tcpSocket,
0,
FREERTOS_SO_RCVTIMEO,
&transportTimeout,
sizeof( TickType_t ) );
/* Set socket send timeout. */
transportTimeout = pdMS_TO_TICKS( sendTimeoutMs );
/* Setting the send block time cannot fail. */
( void ) FreeRTOS_setsockopt( tcpSocket,
0,
FREERTOS_SO_SNDTIMEO,
&transportTimeout,
sizeof( TickType_t ) );
}
/* Clean up on failure. */
if( socketStatus != 0 )
{
if( tcpSocket != FREERTOS_INVALID_SOCKET )
{
FreeRTOS_closesocket( tcpSocket );
}
}
else
{
/* Set the socket. */
*pTcpSocket = tcpSocket;
LogInfo( ( "Established TCP connection with %s.", pHostName ) );
}
return socketStatus;
}
/*-----------------------------------------------------------*/
void Sockets_Disconnect( Socket_t tcpSocket )
{
BaseType_t waitForShutdownLoopCount = 0;
uint8_t pDummyBuffer[ 2 ];
if( tcpSocket != FREERTOS_INVALID_SOCKET )
{
/* Initiate graceful shutdown. */
( void ) FreeRTOS_shutdown( tcpSocket, FREERTOS_SHUT_RDWR );
/* Wait for the socket to disconnect gracefully (indicated by FreeRTOS_recv()
* returning a FREERTOS_EINVAL error) before closing the socket. */
while( FreeRTOS_recv( tcpSocket, pDummyBuffer, sizeof( pDummyBuffer ), 0 ) >= 0 )
{
/* We don't need to delay since FreeRTOS_recv should already have a timeout. */
if( ++waitForShutdownLoopCount >= FREERTOS_SOCKETS_WRAPPER_SHUTDOWN_LOOPS )
{
break;
}
}
( void ) FreeRTOS_closesocket( tcpSocket );
}
}
/*-----------------------------------------------------------*/