diff options
Diffstat (limited to 'mqtt_websockets/src/mqtt_wss_log.c')
-rw-r--r-- | mqtt_websockets/src/mqtt_wss_log.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/mqtt_websockets/src/mqtt_wss_log.c b/mqtt_websockets/src/mqtt_wss_log.c new file mode 100644 index 00000000..2c8cf32e --- /dev/null +++ b/mqtt_websockets/src/mqtt_wss_log.c @@ -0,0 +1,127 @@ +#include "mqtt_wss_log.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <stdio.h> +#include "common_internal.h" + +struct mqtt_wss_log_ctx { + mqtt_wss_log_callback_t extern_log_fnc; + char *ctx_prefix; + char *buffer; + char *buffer_w_ptr; + size_t buffer_bytes_avail; +}; + +#define LOG_BUFFER_SIZE 1024 * 4 +#define LOG_CTX_PREFIX_SEV_STR " : " +#define LOG_CTX_PREFIX_LIMIT 15 +#define LOG_CTX_PREFIX_LIMIT_STR (LOG_CTX_PREFIX_LIMIT - (2 + strlen(LOG_CTX_PREFIX_SEV_STR))) // with [] characters and affixed ' ' it is total 15 chars +#if (LOG_CTX_PREFIX_LIMIT * 10) > LOG_BUFFER_SIZE +#error "LOG_BUFFER_SIZE too small" +#endif +mqtt_wss_log_ctx_t mqtt_wss_log_ctx_create(const char *ctx_prefix, mqtt_wss_log_callback_t log_callback) +{ + mqtt_wss_log_ctx_t ctx = mw_calloc(1, sizeof(struct mqtt_wss_log_ctx)); + if(!ctx) + return NULL; + + if(log_callback) { + ctx->extern_log_fnc = log_callback; + ctx->buffer = mw_calloc(1, LOG_BUFFER_SIZE); + if(!ctx->buffer) + goto cleanup; + + ctx->buffer_w_ptr = ctx->buffer; + if(ctx_prefix) { + *(ctx->buffer_w_ptr++) = '['; + strncpy(ctx->buffer_w_ptr, ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR); + ctx->buffer_w_ptr += strnlen(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR); + *(ctx->buffer_w_ptr++) = ']'; + } + strcpy(ctx->buffer_w_ptr, LOG_CTX_PREFIX_SEV_STR); + ctx->buffer_w_ptr += strlen(LOG_CTX_PREFIX_SEV_STR); + // no term '\0' -> calloc is used + + ctx->buffer_bytes_avail = LOG_BUFFER_SIZE - strlen(ctx->buffer); + + return ctx; + } + + if(ctx_prefix) { + ctx->ctx_prefix = strndup(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR); + if(!ctx->ctx_prefix) + goto cleanup; + } + + return ctx; + +cleanup: + mw_free(ctx); + return NULL; +} + +void mqtt_wss_log_ctx_destroy(mqtt_wss_log_ctx_t ctx) +{ + mw_free(ctx->ctx_prefix); + mw_free(ctx->buffer); + mw_free(ctx); +} + +static inline char severity_to_c(int severity) +{ + switch (severity) { + case MQTT_WSS_LOG_FATAL: + return 'F'; + case MQTT_WSS_LOG_ERROR: + return 'E'; + case MQTT_WSS_LOG_WARN: + return 'W'; + case MQTT_WSS_LOG_INFO: + return 'I'; + case MQTT_WSS_LOG_DEBUG: + return 'D'; + default: + return '?'; + } +} + +void mws_log(int severity, mqtt_wss_log_ctx_t ctx, const char *fmt, va_list args) +{ + size_t size; + + if(ctx->extern_log_fnc) { + size = vsnprintf(ctx->buffer_w_ptr, ctx->buffer_bytes_avail, fmt, args); + *(ctx->buffer_w_ptr - 3) = severity_to_c(severity); + + ctx->extern_log_fnc(severity, ctx->buffer); + + if(size >= ctx->buffer_bytes_avail) + mws_error(ctx, "Last message of this type was truncated! Consider what you log or increase LOG_BUFFER_SIZE if really needed."); + + return; + } + + if(ctx->ctx_prefix) + printf("[%s] ", ctx->ctx_prefix); + + printf("%c: ", severity_to_c(severity)); + + vprintf(fmt, args); + putchar('\n'); +} + +#define DEFINE_MWS_SEV_FNC(severity_fncname, severity) \ +void mws_ ## severity_fncname(mqtt_wss_log_ctx_t ctx, const char *fmt, ...) \ +{ \ + va_list args; \ + va_start(args, fmt); \ + mws_log(severity, ctx, fmt, args); \ + va_end(args); \ +} + +DEFINE_MWS_SEV_FNC(fatal, MQTT_WSS_LOG_FATAL) +DEFINE_MWS_SEV_FNC(error, MQTT_WSS_LOG_ERROR) +DEFINE_MWS_SEV_FNC(warn, MQTT_WSS_LOG_WARN ) +DEFINE_MWS_SEV_FNC(info, MQTT_WSS_LOG_INFO ) +DEFINE_MWS_SEV_FNC(debug, MQTT_WSS_LOG_DEBUG) |