mqtt_wss_log.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright: SPDX-License-Identifier: GPL-3.0-only
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include "mqtt_wss_log.h"
  7. #include "common_internal.h"
  8. struct mqtt_wss_log_ctx {
  9. mqtt_wss_log_callback_t extern_log_fnc;
  10. char *ctx_prefix;
  11. char *buffer;
  12. char *buffer_w_ptr;
  13. size_t buffer_bytes_avail;
  14. };
  15. #define LOG_BUFFER_SIZE 1024 * 4
  16. #define LOG_CTX_PREFIX_SEV_STR " : "
  17. #define LOG_CTX_PREFIX_LIMIT 15
  18. #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
  19. #if (LOG_CTX_PREFIX_LIMIT * 10) > LOG_BUFFER_SIZE
  20. #error "LOG_BUFFER_SIZE too small"
  21. #endif
  22. mqtt_wss_log_ctx_t mqtt_wss_log_ctx_create(const char *ctx_prefix, mqtt_wss_log_callback_t log_callback)
  23. {
  24. mqtt_wss_log_ctx_t ctx = mw_calloc(1, sizeof(struct mqtt_wss_log_ctx));
  25. if(!ctx)
  26. return NULL;
  27. if(log_callback) {
  28. ctx->extern_log_fnc = log_callback;
  29. ctx->buffer = mw_calloc(1, LOG_BUFFER_SIZE);
  30. if(!ctx->buffer)
  31. goto cleanup;
  32. ctx->buffer_w_ptr = ctx->buffer;
  33. if(ctx_prefix) {
  34. *(ctx->buffer_w_ptr++) = '[';
  35. strncpy(ctx->buffer_w_ptr, ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
  36. ctx->buffer_w_ptr += strnlen(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
  37. *(ctx->buffer_w_ptr++) = ']';
  38. }
  39. strcpy(ctx->buffer_w_ptr, LOG_CTX_PREFIX_SEV_STR);
  40. ctx->buffer_w_ptr += strlen(LOG_CTX_PREFIX_SEV_STR);
  41. // no term '\0' -> calloc is used
  42. ctx->buffer_bytes_avail = LOG_BUFFER_SIZE - strlen(ctx->buffer);
  43. return ctx;
  44. }
  45. if(ctx_prefix) {
  46. ctx->ctx_prefix = strndup(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
  47. if(!ctx->ctx_prefix)
  48. goto cleanup;
  49. }
  50. return ctx;
  51. cleanup:
  52. mw_free(ctx);
  53. return NULL;
  54. }
  55. void mqtt_wss_log_ctx_destroy(mqtt_wss_log_ctx_t ctx)
  56. {
  57. mw_free(ctx->ctx_prefix);
  58. mw_free(ctx->buffer);
  59. mw_free(ctx);
  60. }
  61. static inline char severity_to_c(int severity)
  62. {
  63. switch (severity) {
  64. case MQTT_WSS_LOG_FATAL:
  65. return 'F';
  66. case MQTT_WSS_LOG_ERROR:
  67. return 'E';
  68. case MQTT_WSS_LOG_WARN:
  69. return 'W';
  70. case MQTT_WSS_LOG_INFO:
  71. return 'I';
  72. case MQTT_WSS_LOG_DEBUG:
  73. return 'D';
  74. default:
  75. return '?';
  76. }
  77. }
  78. void mws_log(int severity, mqtt_wss_log_ctx_t ctx, const char *fmt, va_list args)
  79. {
  80. size_t size;
  81. if(ctx->extern_log_fnc) {
  82. size = vsnprintf(ctx->buffer_w_ptr, ctx->buffer_bytes_avail, fmt, args);
  83. *(ctx->buffer_w_ptr - 3) = severity_to_c(severity);
  84. ctx->extern_log_fnc(severity, ctx->buffer);
  85. if(size >= ctx->buffer_bytes_avail)
  86. mws_error(ctx, "Last message of this type was truncated! Consider what you log or increase LOG_BUFFER_SIZE if really needed.");
  87. return;
  88. }
  89. if(ctx->ctx_prefix)
  90. printf("[%s] ", ctx->ctx_prefix);
  91. printf("%c: ", severity_to_c(severity));
  92. vprintf(fmt, args);
  93. putchar('\n');
  94. }
  95. #define DEFINE_MWS_SEV_FNC(severity_fncname, severity) \
  96. void mws_ ## severity_fncname(mqtt_wss_log_ctx_t ctx, const char *fmt, ...) \
  97. { \
  98. va_list args; \
  99. va_start(args, fmt); \
  100. mws_log(severity, ctx, fmt, args); \
  101. va_end(args); \
  102. }
  103. DEFINE_MWS_SEV_FNC(fatal, MQTT_WSS_LOG_FATAL)
  104. DEFINE_MWS_SEV_FNC(error, MQTT_WSS_LOG_ERROR)
  105. DEFINE_MWS_SEV_FNC(warn, MQTT_WSS_LOG_WARN )
  106. DEFINE_MWS_SEV_FNC(info, MQTT_WSS_LOG_INFO )
  107. DEFINE_MWS_SEV_FNC(debug, MQTT_WSS_LOG_DEBUG)