summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c')
-rw-r--r--FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c b/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c
new file mode 100644
index 000000000..451c9d13b
--- /dev/null
+++ b/FreeRTOS-Labs/Source/FreeRTOS-IoT-Libraries/c_sdk/standard/common/src/iot_logging.c
@@ -0,0 +1,451 @@
+/*
+ * IoT Common V1.1.0
+ * Copyright (C) 2018 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 iot_logging.c
+ * @brief Implementation of logging functions from iot_logging.h
+ */
+
+/* The config header is always included first. */
+#include "iot_config.h"
+
+/* Standard includes. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Platform clock include. */
+#include "platform/iot_clock.h"
+
+/* Logging includes. */
+#include "iot_logging.h"
+
+/*-----------------------------------------------------------*/
+
+/* This implementation assumes the following values for the log level constants.
+ * Ensure that the values have not been modified. */
+#if IOT_LOG_NONE != 0
+ #error "IOT_LOG_NONE must be 0."
+#endif
+#if IOT_LOG_ERROR != 1
+ #error "IOT_LOG_ERROR must be 1."
+#endif
+#if IOT_LOG_WARN != 2
+ #error "IOT_LOG_WARN must be 2."
+#endif
+#if IOT_LOG_INFO != 3
+ #error "IOT_LOG_INFO must be 3."
+#endif
+#if IOT_LOG_DEBUG != 4
+ #error "IOT_LOG_DEBUG must be 4."
+#endif
+
+/**
+ * @def IotLogging_Puts( message )
+ * @brief Function the logging library uses to print a line.
+ *
+ * This function can be set by using a define. By default, the standard library
+ * [puts](http://pubs.opengroup.org/onlinepubs/9699919799/functions/puts.html)
+ * function is used.
+ */
+#ifndef IotLogging_Puts
+ #define IotLogging_Puts puts
+#endif
+
+/*
+ * Provide default values for undefined memory allocation functions based on
+ * the usage of dynamic memory allocation.
+ */
+#if IOT_STATIC_MEMORY_ONLY == 1
+ /* Static memory allocation header. */
+ #include "iot_static_memory.h"
+
+/**
+ * @brief Allocate a new logging buffer. This function must have the same
+ * signature as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
+ */
+ #ifndef IotLogging_Malloc
+ #define IotLogging_Malloc Iot_MallocMessageBuffer
+ #endif
+
+/**
+ * @brief Free a logging buffer. This function must have the same signature
+ * as [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
+ */
+ #ifndef IotLogging_Free
+ #define IotLogging_Free Iot_FreeMessageBuffer
+ #endif
+
+/**
+ * @brief Get the size of a logging buffer. Statically-allocated buffers
+ * should all have the same size.
+ */
+ #ifndef IotLogging_StaticBufferSize
+ #define IotLogging_StaticBufferSize Iot_MessageBufferSize
+ #endif
+#else /* if IOT_STATIC_MEMORY_ONLY == 1 */
+ #ifndef IotLogging_Malloc
+ #include <stdlib.h>
+ #define IotLogging_Malloc malloc
+ #endif
+
+ #ifndef IotLogging_Free
+ #include <stdlib.h>
+ #define IotLogging_Free free
+ #endif
+#endif /* if IOT_STATIC_MEMORY_ONLY == 1 */
+
+/**
+ * @brief A guess of the maximum length of a timestring.
+ *
+ * There's no way for this logging library to know the length of a timestring
+ * before it's generated. Therefore, the logging library will assume a maximum
+ * length of any timestring it may get. This value should be generous enough
+ * to accommodate the vast majority of timestrings.
+ *
+ * @see @ref platform_clock_function_gettimestring
+ */
+#define MAX_TIMESTRING_LENGTH ( 64 )
+
+/**
+ * @brief The longest string in #_pLogLevelStrings (below), plus 3 to accommodate
+ * `[]` and a null-terminator.
+ */
+#define MAX_LOG_LEVEL_LENGTH ( 8 )
+
+/**
+ * @brief How many bytes @ref logging_function_genericprintbuffer should output on
+ * each line.
+ */
+#define BYTES_PER_LINE ( 16 )
+
+/*-----------------------------------------------------------*/
+
+/**
+ * @brief Lookup table for log levels.
+ *
+ * Converts one of the @ref logging_constants_levels to a string.
+ */
+static const char * const _pLogLevelStrings[ 5 ] =
+{
+ "", /* IOT_LOG_NONE */
+ "ERROR", /* IOT_LOG_ERROR */
+ "WARN ", /* IOT_LOG_WARN */
+ "INFO ", /* IOT_LOG_INFO */
+ "DEBUG" /* IOT_LOG_DEBUG */
+};
+
+/*-----------------------------------------------------------*/
+
+#if !defined( IOT_STATIC_MEMORY_ONLY ) || ( IOT_STATIC_MEMORY_ONLY == 0 )
+ static bool _reallocLoggingBuffer( void ** pOldBuffer,
+ size_t newSize,
+ size_t oldSize )
+ {
+ bool status = false;
+
+ /* Allocate a new, larger buffer. */
+ void * pNewBuffer = IotLogging_Malloc( newSize );
+
+ /* Ensure that memory allocation succeeded. */
+ if( pNewBuffer != NULL )
+ {
+ /* Copy the data from the old buffer to the new buffer. */
+ ( void ) memcpy( pNewBuffer, *pOldBuffer, oldSize );
+
+ /* Free the old buffer and update the pointer. */
+ IotLogging_Free( *pOldBuffer );
+ *pOldBuffer = pNewBuffer;
+
+ status = true;
+ }
+
+ return status;
+ }
+#endif /* if !defined( IOT_STATIC_MEMORY_ONLY ) || ( IOT_STATIC_MEMORY_ONLY == 0 ) */
+
+/*-----------------------------------------------------------*/
+
+void IotLog_Generic( int libraryLogSetting,
+ const char * const pLibraryName,
+ int messageLevel,
+ const IotLogConfig_t * const pLogConfig,
+ const char * const pFormat,
+ ... )
+{
+ int requiredMessageSize = 0;
+ size_t bufferSize = 0,
+ bufferPosition = 0, timestringLength = 0;
+ char * pLoggingBuffer = NULL;
+ va_list args;
+
+ /* If the library's log level setting is lower than the message level,
+ * return without doing anything. */
+ if( ( messageLevel == 0 ) || ( messageLevel > libraryLogSetting ) )
+ {
+ return;
+ }
+
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideLogLevel == false ) )
+ {
+ /* Add length of log level if requested. */
+ bufferSize += MAX_LOG_LEVEL_LENGTH;
+ }
+
+ /* Estimate the amount of buffer needed for this log message. */
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideLibraryName == false ) )
+ {
+ /* Add size of library name if requested. Add 2 to accommodate "[]". */
+ bufferSize += strlen( pLibraryName ) + 2;
+ }
+
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideTimestring == false ) )
+ {
+ /* Add length of timestring if requested. */
+ bufferSize += MAX_TIMESTRING_LENGTH;
+ }
+
+ /* Add 64 as an initial (arbitrary) guess for the length of the message. */
+ bufferSize += 64;
+
+ /* In static memory mode, check that the log message will fit in the a
+ * static buffer. */
+ #if IOT_STATIC_MEMORY_ONLY == 1
+ if( bufferSize >= IotLogging_StaticBufferSize() )
+ {
+ /* If the static buffers are likely too small to fit the log message,
+ * return. */
+ return;
+ }
+
+ /* Otherwise, update the buffer size to the size of a static buffer. */
+ bufferSize = IotLogging_StaticBufferSize();
+ #endif
+
+ /* Allocate memory for the logging buffer. */
+ pLoggingBuffer = ( char * ) IotLogging_Malloc( bufferSize );
+
+ if( pLoggingBuffer == NULL )
+ {
+ return;
+ }
+
+ /* Print the message log level if requested. */
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideLogLevel == false ) )
+ {
+ /* Ensure that message level is valid. */
+ if( ( messageLevel >= IOT_LOG_NONE ) && ( messageLevel <= IOT_LOG_DEBUG ) )
+ {
+ /* Add the log level string to the logging buffer. */
+ requiredMessageSize = snprintf( pLoggingBuffer + bufferPosition,
+ bufferSize - bufferPosition,
+ "[%s]",
+ _pLogLevelStrings[ messageLevel ] );
+
+ /* Check for encoding errors. */
+ if( requiredMessageSize <= 0 )
+ {
+ IotLogging_Free( pLoggingBuffer );
+
+ return;
+ }
+
+ /* Update the buffer position. */
+ bufferPosition += ( size_t ) requiredMessageSize;
+ }
+ }
+
+ /* Print the library name if requested. */
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideLibraryName == false ) )
+ {
+ /* Add the library name to the logging buffer. */
+ requiredMessageSize = snprintf( pLoggingBuffer + bufferPosition,
+ bufferSize - bufferPosition,
+ "[%s]",
+ pLibraryName );
+
+ /* Check for encoding errors. */
+ if( requiredMessageSize <= 0 )
+ {
+ IotLogging_Free( pLoggingBuffer );
+
+ return;
+ }
+
+ /* Update the buffer position. */
+ bufferPosition += ( size_t ) requiredMessageSize;
+ }
+
+ /* Print the timestring if requested. */
+ if( ( pLogConfig == NULL ) || ( pLogConfig->hideTimestring == false ) )
+ {
+ /* Add the opening '[' enclosing the timestring. */
+ pLoggingBuffer[ bufferPosition ] = '[';
+ bufferPosition++;
+
+ /* Generate the timestring and add it to the buffer. */
+ if( IotClock_GetTimestring( pLoggingBuffer + bufferPosition,
+ bufferSize - bufferPosition,
+ &timestringLength ) == true )
+ {
+ /* If the timestring was successfully generated, add the closing "]". */
+ bufferPosition += timestringLength;
+ pLoggingBuffer[ bufferPosition ] = ']';
+ bufferPosition++;
+ }
+ else
+ {
+ /* Sufficient memory for a timestring should have been allocated. A timestring
+ * probably failed to generate due to a clock read error; remove the opening '['
+ * from the logging buffer. */
+ bufferPosition--;
+ pLoggingBuffer[ bufferPosition ] = '\0';
+ }
+ }
+
+ /* Add a padding space between the last closing ']' and the message, unless
+ * the logging buffer is empty. */
+ if( bufferPosition > 0 )
+ {
+ pLoggingBuffer[ bufferPosition ] = ' ';
+ bufferPosition++;
+ }
+
+ va_start( args, pFormat );
+
+ /* Add the log message to the logging buffer. */
+ requiredMessageSize = vsnprintf( pLoggingBuffer + bufferPosition,
+ bufferSize - bufferPosition,
+ pFormat,
+ args );
+
+ va_end( args );
+
+ /* If the logging buffer was too small to fit the log message, reallocate
+ * a larger logging buffer. */
+ if( ( size_t ) requiredMessageSize >= bufferSize - bufferPosition )
+ {
+ #if IOT_STATIC_MEMORY_ONLY == 1
+
+ /* There's no point trying to allocate a larger static buffer. Return
+ * immediately. */
+ IotLogging_Free( pLoggingBuffer );
+
+ return;
+ #else
+ if( _reallocLoggingBuffer( ( void ** ) &pLoggingBuffer,
+ ( size_t ) requiredMessageSize + bufferPosition + 1,
+ bufferSize ) == false )
+ {
+ /* If buffer reallocation failed, return. */
+ IotLogging_Free( pLoggingBuffer );
+
+ return;
+ }
+
+ /* Reallocation successful, update buffer size. */
+ bufferSize = ( size_t ) requiredMessageSize + bufferPosition + 1;
+
+ /* Add the log message to the buffer. Now that the buffer has been
+ * reallocated, this should succeed. */
+ va_start( args, pFormat );
+ requiredMessageSize = vsnprintf( pLoggingBuffer + bufferPosition,
+ bufferSize - bufferPosition,
+ pFormat,
+ args );
+ va_end( args );
+ #endif /* if IOT_STATIC_MEMORY_ONLY == 1 */
+ }
+
+ /* Check for encoding errors. */
+ if( requiredMessageSize <= 0 )
+ {
+ IotLogging_Free( pLoggingBuffer );
+
+ return;
+ }
+
+ /* Print the logging buffer to stdout. */
+ IotLogging_Puts( pLoggingBuffer );
+
+ /* Free the logging buffer. */
+ IotLogging_Free( pLoggingBuffer );
+}
+
+/*-----------------------------------------------------------*/
+
+void IotLog_GenericPrintBuffer( const char * const pLibraryName,
+ const char * const pHeader,
+ const uint8_t * const pBuffer,
+ size_t bufferSize )
+{
+ size_t i = 0, offset = 0;
+
+ /* Allocate memory to hold each line of the log message. Since each byte
+ * of pBuffer is printed in 4 characters (2 digits, a space, and a null-
+ * terminator), the size of each line is 4 * BYTES_PER_LINE. */
+ char * pMessageBuffer = IotLogging_Malloc( 4 * BYTES_PER_LINE );
+
+ /* Exit if no memory is available. */
+ if( pMessageBuffer == NULL )
+ {
+ return;
+ }
+
+ /* Print pHeader before printing pBuffer. */
+ if( pHeader != NULL )
+ {
+ IotLog_Generic( IOT_LOG_DEBUG,
+ pLibraryName,
+ IOT_LOG_DEBUG,
+ NULL,
+ pHeader );
+ }
+
+ /* Print each byte in pBuffer. */
+ for( i = 0; i < bufferSize; i++ )
+ {
+ /* Print a line if BYTES_PER_LINE is reached. But don't print a line
+ * at the beginning (when i=0). */
+ if( ( i % BYTES_PER_LINE == 0 ) && ( i != 0 ) )
+ {
+ IotLogging_Puts( pMessageBuffer );
+
+ /* Reset offset so that pMessageBuffer is filled from the beginning. */
+ offset = 0;
+ }
+
+ /* Print a single byte into pMessageBuffer. */
+ ( void ) snprintf( pMessageBuffer + offset, 4, "%02x ", pBuffer[ i ] );
+
+ /* Move the offset where the next character is printed. */
+ offset += 3;
+ }
+
+ /* Print the final line of bytes. This line isn't printed by the for-loop above. */
+ IotLogging_Puts( pMessageBuffer );
+
+ /* Free memory used by this function. */
+ IotLogging_Free( pMessageBuffer );
+}
+
+/*-----------------------------------------------------------*/