Misc mqtt related code cleanup (#18622)
* Remove pthread locks / use spinlocks * Remove redundant checks as mallocz, callocz can't return NULL * Change logging More code cleanup * Change random number generation Set Origin to empty Use BCryptGenRandom * More cleanup Deduplicate base64_encode/decode * Address review comments
Stelios Fragkakis committed
Sep 29, 2024 at 20:42 UTC
fbeee6b12268b9fea06bdae93463eec5deabc68f
20 files changed
+546
-1016
CMakeLists.txt
+1
-3
@@ -1555,8 +1555,6 @@ endif()
1555
set(MQTT_WEBSOCKETS_FILES
1556
src/aclk/mqtt_websockets/mqtt_wss_client.c
1557
src/aclk/mqtt_websockets/mqtt_wss_client.h
1558
- src/aclk/mqtt_websockets/mqtt_wss_log.c
1559
- src/aclk/mqtt_websockets/mqtt_wss_log.h
1558
src/aclk/mqtt_websockets/ws_client.c
1559
src/aclk/mqtt_websockets/ws_client.h
1560
src/aclk/mqtt_websockets/mqtt_ng.c
@@ -1721,7 +1719,7 @@ target_include_directories(libnetdata BEFORE PUBLIC ${CONFIG_H_DIR} ${CMAKE_SOUR
1719
target_link_libraries(libnetdata PUBLIC
1720
"$<$<NOT:$<BOOL:${HAVE_BUILTIN_ATOMICS}>>:atomic>"
1721
"$<$<OR:$<BOOL:${OS_LINUX}>,$<BOOL:${OS_FREEBSD}>>:pthread;rt>"
1724
- "$<$<BOOL:${OS_WINDOWS}>:kernel32;advapi32;winmm;rpcrt4>"
1722
+ "$<$<BOOL:${OS_WINDOWS}>:kernel32;advapi32;winmm;rpcrt4;bcrypt>"
1723
"$<$<BOOL:${LINK_LIBM}>:m>"
1724
"${SYSTEMD_LDFLAGS}")
1725
src/aclk/aclk.c
+8
-32
@@ -226,30 +226,6 @@ static int wait_till_agent_claim_ready()
226
return 1;
227
}
228
229
-void aclk_mqtt_wss_log_cb(mqtt_wss_log_type_t log_type, const char* str)
230
-{
231
- switch(log_type) {
232
- case MQTT_WSS_LOG_ERROR:
233
- case MQTT_WSS_LOG_FATAL:
234
- nd_log(NDLS_DAEMON, NDLP_ERR, "%s", str);
235
- return;
236
-
237
- case MQTT_WSS_LOG_WARN:
238
- nd_log(NDLS_DAEMON, NDLP_WARNING, "%s", str);
239
- return;
240
-
241
- case MQTT_WSS_LOG_INFO:
242
- nd_log(NDLS_DAEMON, NDLP_INFO, "%s", str);
243
- return;
244
-
245
- case MQTT_WSS_LOG_DEBUG:
246
- return;
247
-
248
- default:
249
- nd_log(NDLS_DAEMON, NDLP_ERR, "Unknown log type from mqtt_wss");
250
- }
251
-}
252
-
229
static void msg_callback(const char *topic, const void *msg, size_t msglen, int qos)
230
{
231
UNUSED(qos);
@@ -362,7 +338,7 @@ static inline void mqtt_connected_actions(mqtt_wss_client client)
338
aclk_rcvd_cloud_msgs = 0;
339
aclk_connection_counter++;
340
365
- aclk_topic_cache_iter_t iter = ACLK_TOPIC_CACHE_ITER_T_INITIALIZER;
341
+ size_t iter = 0;
342
while ((topic = (char*)aclk_topic_cache_iterate(&iter)) != NULL)
343
mqtt_wss_set_topic_alias(client, topic);
344
@@ -768,7 +744,7 @@ static int aclk_attempt_to_connect(mqtt_wss_client client)
744
*/
745
void *aclk_main(void *ptr)
746
{
771
- struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
747
+ struct netdata_static_thread *static_thread = ptr;
748
749
ACLK_PROXY_TYPE proxy_type;
750
aclk_get_proxy(&proxy_type);
@@ -783,7 +759,7 @@ void *aclk_main(void *ptr)
759
if (wait_till_agent_claim_ready())
760
goto exit;
761
786
- if (!(mqttwss_client = mqtt_wss_new("mqtt_wss", aclk_mqtt_wss_log_cb, msg_callback, puback_callback))) {
762
+ if (!((mqttwss_client = mqtt_wss_new(msg_callback, puback_callback)))) {
763
netdata_log_error("Couldn't initialize MQTT_WSS network library");
764
goto exit;
765
}
@@ -1025,22 +1001,22 @@ char *aclk_state(void)
1001
}
1002
1003
buffer_sprintf(wb, "Online: %s\nReconnect count: %d\nBanned By Cloud: %s\n", aclk_online() ? "Yes" : "No", aclk_connection_counter > 0 ? (aclk_connection_counter - 1) : 0, aclk_disable_runtime ? "Yes" : "No");
1028
- if (last_conn_time_mqtt && (tmptr = localtime_r(&last_conn_time_mqtt, &tmbuf)) ) {
1004
+ if (last_conn_time_mqtt && ((tmptr = localtime_r(&last_conn_time_mqtt, &tmbuf))) ) {
1005
char timebuf[26];
1006
strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tmptr);
1007
buffer_sprintf(wb, "Last Connection Time: %s\n", timebuf);
1008
}
1033
- if (last_conn_time_appl && (tmptr = localtime_r(&last_conn_time_appl, &tmbuf)) ) {
1009
+ if (last_conn_time_appl && ((tmptr = localtime_r(&last_conn_time_appl, &tmbuf))) ) {
1010
char timebuf[26];
1011
strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tmptr);
1012
buffer_sprintf(wb, "Last Connection Time + %d PUBACKs received: %s\n", ACLK_PUBACKS_CONN_STABLE, timebuf);
1013
}
1038
- if (last_disconnect_time && (tmptr = localtime_r(&last_disconnect_time, &tmbuf)) ) {
1014
+ if (last_disconnect_time && ((tmptr = localtime_r(&last_disconnect_time, &tmbuf))) ) {
1015
char timebuf[26];
1016
strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tmptr);
1017
buffer_sprintf(wb, "Last Disconnect Time: %s\n", timebuf);
1018
}
1043
- if (!aclk_connected && next_connection_attempt && (tmptr = localtime_r(&next_connection_attempt, &tmbuf)) ) {
1019
+ if (!aclk_connected && next_connection_attempt && ((tmptr = localtime_r(&next_connection_attempt, &tmbuf))) ) {
1020
char timebuf[26];
1021
strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tmptr);
1022
buffer_sprintf(wb, "Next Connection Attempt At: %s\nLast Backoff: %.3f", timebuf, last_backoff_value);
@@ -1107,7 +1083,7 @@ static void fill_alert_status_for_host_json(json_object *obj, RRDHOST *host)
1083
static json_object *timestamp_to_json(const time_t *t)
1084
{
1085
struct tm *tmptr, tmbuf;
1110
- if (*t && (tmptr = gmtime_r(t, &tmbuf)) ) {
1086
+ if (*t && ((tmptr = gmtime_r(t, &tmbuf))) ) {
1087
char timebuf[26];
1088
strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tmptr);
1089
return json_object_new_string(timebuf);
src/aclk/aclk_otp.c
+5
-37
@@ -267,40 +267,8 @@ exit:
267
}
268
#endif
269
270
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
271
-static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
272
-{
273
- EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
274
-
275
- if (ctx != NULL) {
276
- memset(ctx, 0, sizeof(*ctx));
277
- }
278
- return ctx;
279
-}
280
-static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
281
-{
282
- OPENSSL_free(ctx);
283
- return;
284
-}
285
-#endif
286
-
270
#define CHALLENGE_LEN 256
271
#define CHALLENGE_LEN_BASE64 344
289
-inline static int base64_decode_helper(unsigned char *out, int *outl, const unsigned char *in, int in_len)
290
-{
291
- unsigned char remaining_data[CHALLENGE_LEN];
292
- EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
293
- EVP_DecodeInit(ctx);
294
- EVP_DecodeUpdate(ctx, out, outl, in, in_len);
295
- int remainder = 0;
296
- EVP_DecodeFinal(ctx, remaining_data, &remainder);
297
- EVP_ENCODE_CTX_free(ctx);
298
- if (remainder) {
299
- netdata_log_error("Unexpected data at EVP_DecodeFinal");
300
- return 1;
301
- }
302
- return 0;
303
-}
272
273
#define OTP_URL_PREFIX "/api/v1/auth/node/"
274
int aclk_get_otp_challenge(url_t *target, const char *agent_id, unsigned char **challenge, int *challenge_bytes, bool *fallback_ipv4)
@@ -347,7 +315,7 @@ int aclk_get_otp_challenge(url_t *target, const char *agent_id, unsigned char **
315
goto cleanup_json;
316
}
317
const char *challenge_base64;
350
- if (!(challenge_base64 = json_object_get_string(challenge_json))) {
318
+ if (!((challenge_base64 = json_object_get_string(challenge_json)))) {
319
netdata_log_error("Failed to extract challenge from JSON object");
320
goto cleanup_json;
321
}
@@ -356,8 +324,9 @@ int aclk_get_otp_challenge(url_t *target, const char *agent_id, unsigned char **
324
goto cleanup_json;
325
}
326
359
- *challenge = mallocz((CHALLENGE_LEN_BASE64 / 4) * 3);
360
- base64_decode_helper(*challenge, challenge_bytes, (const unsigned char*)challenge_base64, strlen(challenge_base64));
327
+ *challenge = mallocz(CHALLENGE_LEN);
328
+ *challenge_bytes = netdata_base64_decode(*challenge, (const unsigned char *) challenge_base64, CHALLENGE_LEN_BASE64);
329
+
330
if (*challenge_bytes != CHALLENGE_LEN) {
331
netdata_log_error("Unexpected challenge length of %d instead of %d", *challenge_bytes, CHALLENGE_LEN);
332
freez(*challenge);
@@ -375,7 +344,6 @@ cleanup_resp:
344
345
int aclk_send_otp_response(const char *agent_id, const unsigned char *response, int response_bytes, url_t *target, struct auth_data *mqtt_auth, bool *fallback_ipv4)
346
{
378
- int len;
347
int rc = 1;
348
https_req_t req = HTTPS_REQ_T_INITIALIZER;
349
https_req_response_t resp = HTTPS_REQ_RESPONSE_T_INITIALIZER;
@@ -387,7 +355,7 @@ int aclk_send_otp_response(const char *agent_id, const unsigned char *response,
355
unsigned char base64[CHALLENGE_LEN_BASE64 + 1];
356
memset(base64, 0, CHALLENGE_LEN_BASE64 + 1);
357
390
- base64_encode_helper(base64, &len, response, response_bytes);
358
+ (void) netdata_base64_encode(base64, response, response_bytes);
359
360
BUFFER *url = buffer_create(strlen(OTP_URL_PREFIX) + UUID_STR_LEN + 20, &netdata_buffers_statistics.buffers_aclk);
361
BUFFER *resp_json = buffer_create(strlen(OTP_URL_PREFIX) + UUID_STR_LEN + 20, &netdata_buffers_statistics.buffers_aclk);
src/aclk/aclk_tx_msgs.c
+1
-1
@@ -77,7 +77,7 @@ static short aclk_send_message_with_bin_payload(mqtt_wss_client client, json_obj
77
78
int rc = mqtt_wss_publish5(client, (char*)topic, NULL, full_msg, &freez_aclk_publish5b, full_msg_len, MQTT_WSS_PUB_QOS1, &packet_id);
79
80
- if (rc == MQTT_WSS_ERR_TOO_BIG_FOR_SERVER)
80
+ if (rc == MQTT_WSS_ERR_MSG_TOO_BIG)
81
return HTTP_RESP_CONTENT_TOO_LONG;
82
83
return 0;
src/aclk/aclk_util.c
+1
-42
@@ -309,7 +309,7 @@ const char *aclk_get_topic(enum aclk_topics topic)
309
* having to resort to callbacks.
310
*/
311
312
-const char *aclk_topic_cache_iterate(aclk_topic_cache_iter_t *iter)
312
+const char *aclk_topic_cache_iterate(size_t *iter)
313
{
314
if (!aclk_topic_cache) {
315
netdata_log_error("Topic cache not initialized when %s was called.", __FUNCTION__);
@@ -434,44 +434,3 @@ void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd, enum mqtt
434
435
freez(proxy);
436
}
437
-
438
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
439
-static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
440
-{
441
- EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
442
-
443
- if (ctx != NULL) {
444
- memset(ctx, 0, sizeof(*ctx));
445
- }
446
- return ctx;
447
-}
448
-static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
449
-{
450
- OPENSSL_free(ctx);
451
- return;
452
-}
453
-#endif
454
-
455
-int base64_encode_helper(unsigned char *out, int *outl, const unsigned char *in, int in_len)
456
-{
457
- int len;
458
- unsigned char *str = out;
459
- EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
460
- EVP_EncodeInit(ctx);
461
- EVP_EncodeUpdate(ctx, str, outl, in, in_len);
462
- str += *outl;
463
- EVP_EncodeFinal(ctx, str, &len);
464
- *outl += len;
465
-
466
- str = out;
467
- while(*str) {
468
- if (*str != 0x0D && *str != 0x0A)
469
- *out++ = *str++;
470
- else
471
- str++;
472
- }
473
- *out = 0;
474
-
475
- EVP_ENCODE_CTX_free(ctx);
476
- return 0;
477
-}
src/aclk/aclk_util.h
+2
-9
@@ -93,15 +93,10 @@ enum aclk_topics {
93
ACLK_TOPICID_CTXS_UPDATED = 20
94
};
95
96
-typedef size_t aclk_topic_cache_iter_t;
97
-#define ACLK_TOPIC_CACHE_ITER_T_INITIALIZER (0)
98
-
96
const char *aclk_get_topic(enum aclk_topics topic);
100
-int aclk_generate_topic_cache(struct json_object *json);
97
+int aclk_generate_topic_cache(json_object *json);
98
void free_topic_cache(void);
102
-const char *aclk_topic_cache_iterate(aclk_topic_cache_iter_t *iter);
103
-// TODO
104
-// aclk_topics_reload //when claim id changes
99
+const char *aclk_topic_cache_iterate(size_t *iter);
100
101
#ifdef ACLK_LOG_CONVERSATION_DIR
102
extern volatile int aclk_conversation_log_counter;
@@ -113,6 +108,4 @@ unsigned long int aclk_tbeb_delay(int reset, int base, unsigned long int min, un
108
109
void aclk_set_proxy(char **ohost, int *port, char **uname, char **pwd, enum mqtt_wss_proxy_type *type);
110
116
-int base64_encode_helper(unsigned char *out, int *outl, const unsigned char *in, int in_len);
117
-
111
#endif /* ACLK_UTIL_H */
src/aclk/https_client.c
+1
-2
@@ -556,7 +556,7 @@ static int handle_http_request(https_req_ctx_t *ctx) {
556
// we remove those but during encoding we need that space in the buffer
557
creds_base64_len += (1+(creds_base64_len/64)) * strlen("\n");
558
char *creds_base64 = callocz(1, creds_base64_len + 1);
559
- base64_encode_helper((unsigned char*)creds_base64, &creds_base64_len, (unsigned char*)creds_plain, creds_plain_len);
559
+ (void) netdata_base64_encode((unsigned char *)creds_base64, (unsigned char *)creds_plain, creds_plain_len);
560
buffer_sprintf(hdr, "Proxy-Authorization: Basic %s\x0D\x0A", creds_base64);
561
freez(creds_plain);
562
}
@@ -584,7 +584,6 @@ static int handle_http_request(https_req_ctx_t *ctx) {
584
if (ctx->parse_ctx.chunked_response)
585
freez(ctx->parse_ctx.chunked_response);
586
rc = 4;
587
- goto err_exit;
587
}
588
589
err_exit:
src/aclk/mqtt_websockets/mqtt_ng.c
+210
-281
@@ -8,16 +8,8 @@
8
9
#include "common_internal.h"
10
#include "mqtt_constants.h"
11
-#include "mqtt_wss_log.h"
11
#include "mqtt_ng.h"
12
14
-#define UNIT_LOG_PREFIX "mqtt_client: "
15
-#define FATAL(fmt, ...) mws_fatal(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
16
-#define ERROR(fmt, ...) mws_error(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
17
-#define WARN(fmt, ...) mws_warn (client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
18
-#define INFO(fmt, ...) mws_info (client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
19
-#define DEBUG(fmt, ...) mws_debug(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
20
-
13
#define SMALL_STRING_DONT_FRAGMENT_LIMIT 128
14
15
#define LOCK_HDR_BUFFER(buffer) spinlock_lock(&((buffer)->spinlock))
@@ -216,7 +208,7 @@ struct topic_aliases_data {
208
c_rhash stoi_dict;
209
uint32_t idx_max;
210
uint32_t idx_assigned;
219
- pthread_rwlock_t rwlock;
211
+ SPINLOCK spinlock;
212
};
213
214
struct mqtt_ng_client {
@@ -226,8 +218,6 @@ struct mqtt_ng_client {
218
219
mqtt_msg_data connect_msg;
220
229
- mqtt_wss_log_ctx_t log;
230
-
221
mqtt_ng_send_fnc_t send_fnc_ptr;
222
void *user_ctx;
223
@@ -245,7 +235,7 @@ struct mqtt_ng_client {
235
unsigned int ping_pending:1;
236
237
struct mqtt_ng_stats stats;
248
- pthread_mutex_t stats_mutex;
238
+ SPINLOCK stats_spinlock;
239
240
struct topic_aliases_data tx_topic_aliases;
241
c_rhash rx_aliases;
@@ -399,7 +389,7 @@ enum memory_mode {
389
CALLER_RESPONSIBLE
390
};
391
402
-static inline enum memory_mode ptr2memory_mode(void * ptr) {
392
+static enum memory_mode ptr2memory_mode(void * ptr) {
393
if (ptr == NULL)
394
return MEMCPY;
395
if (ptr == CALLER_RESPONSIBILITY)
@@ -484,15 +474,8 @@ static void buffer_rebuild(struct header_buffer *buf)
474
} while(frag);
475
}
476
487
-static void buffer_garbage_collect(struct header_buffer *buf, mqtt_wss_log_ctx_t log_ctx)
477
+static void buffer_garbage_collect(struct header_buffer *buf)
478
{
489
-#if !defined(MQTT_DEBUG_VERBOSE) && !defined(ADDITIONAL_CHECKS)
490
- (void) log_ctx;
491
-#endif
492
-#ifdef MQTT_DEBUG_VERBOSE
493
- mws_debug(log_ctx, "Buffer Garbage Collection!");
494
-#endif
495
-
479
struct buffer_fragment *frag = BUFFER_FIRST_FRAG(buf);
480
while (frag) {
481
if (!frag_is_marked_for_gc(frag))
@@ -503,12 +486,8 @@ static void buffer_garbage_collect(struct header_buffer *buf, mqtt_wss_log_ctx_t
486
frag = frag->next;
487
}
488
506
- if (frag == BUFFER_FIRST_FRAG(buf)) {
507
-#ifdef MQTT_DEBUG_VERBOSE
508
- mws_debug(log_ctx, "Buffer Garbage Collection! No Space Reclaimed!");
509
-#endif
489
+ if (frag == BUFFER_FIRST_FRAG(buf))
490
return;
511
- }
491
492
if (!frag) {
493
buf->tail_frag = NULL;
@@ -527,21 +506,17 @@ static void buffer_garbage_collect(struct header_buffer *buf, mqtt_wss_log_ctx_t
506
buffer_rebuild(buf);
507
}
508
530
-static void transaction_buffer_garbage_collect(struct transaction_buffer *buf, mqtt_wss_log_ctx_t log_ctx)
509
+static void transaction_buffer_garbage_collect(struct transaction_buffer *buf)
510
{
532
-#ifdef MQTT_DEBUG_VERBOSE
533
- mws_debug(log_ctx, "Transaction Buffer Garbage Collection! %s", buf->sending_frag == NULL ? "NULL" : "in flight message");
534
-#endif
535
-
511
// Invalidate the cached sending fragment
512
// as we will move data around
513
if (buf->sending_frag != &ping_frag)
514
buf->sending_frag = NULL;
515
541
- buffer_garbage_collect(&buf->hdr_buffer, log_ctx);
516
+ buffer_garbage_collect(&buf->hdr_buffer);
517
}
518
544
-static int transaction_buffer_grow(struct transaction_buffer *buf, mqtt_wss_log_ctx_t log_ctx, float rate, size_t max)
519
+static int transaction_buffer_grow(struct transaction_buffer *buf, float rate, size_t max)
520
{
521
if (buf->hdr_buffer.size >= max)
522
return 0;
@@ -557,29 +532,25 @@ static int transaction_buffer_grow(struct transaction_buffer *buf, mqtt_wss_log_
532
533
void *ret = reallocz(buf->hdr_buffer.data, buf->hdr_buffer.size);
534
if (ret == NULL) {
560
- mws_warn(log_ctx, "Buffer growth failed (realloc)");
535
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "Buffer growth failed (realloc)");
536
return 1;
537
}
538
564
- mws_debug(log_ctx, "Message metadata buffer was grown");
539
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "Message metadata buffer was grown");
540
541
buf->hdr_buffer.data = ret;
542
buffer_rebuild(&buf->hdr_buffer);
543
return 0;
544
}
545
571
-inline static int transaction_buffer_init(struct transaction_buffer *to_init, size_t size)
546
+inline static void transaction_buffer_init(struct transaction_buffer *to_init, size_t size)
547
{
548
spinlock_init(&to_init->spinlock);
549
550
to_init->hdr_buffer.size = size;
551
to_init->hdr_buffer.data = mallocz(size);
577
- if (to_init->hdr_buffer.data == NULL)
578
- return 1;
579
-
552
to_init->hdr_buffer.tail = to_init->hdr_buffer.data;
553
to_init->hdr_buffer.tail_frag = NULL;
582
- return 0;
554
}
555
556
static void transaction_buffer_destroy(struct transaction_buffer *to_init)
@@ -620,54 +591,30 @@ void transaction_buffer_transaction_rollback(struct transaction_buffer *buf, str
591
struct mqtt_ng_client *mqtt_ng_init(struct mqtt_ng_init *settings)
592
{
593
struct mqtt_ng_client *client = callocz(1, sizeof(struct mqtt_ng_client));
623
- if (client == NULL)
624
- return NULL;
594
626
- if (transaction_buffer_init(&client->main_buffer, HEADER_BUFFER_SIZE))
627
- goto err_free_client;
595
+ transaction_buffer_init(&client->main_buffer, HEADER_BUFFER_SIZE);
596
597
client->rx_aliases = RX_ALIASES_INITIALIZE();
630
- if (client->rx_aliases == NULL)
631
- goto err_free_trx_buf;
598
633
- if (pthread_mutex_init(&client->stats_mutex, NULL))
634
- goto err_free_rx_alias;
599
+ spinlock_init(&client->stats_spinlock);
600
+ spinlock_init(&client->tx_topic_aliases.spinlock);
601
602
client->tx_topic_aliases.stoi_dict = TX_ALIASES_INITIALIZE();
637
- if (client->tx_topic_aliases.stoi_dict == NULL)
638
- goto err_free_stats_mutex;
603
client->tx_topic_aliases.idx_max = UINT16_MAX;
604
641
- if (pthread_rwlock_init(&client->tx_topic_aliases.rwlock, NULL))
642
- goto err_free_tx_alias;
643
-
605
// TODO just embed the struct into mqtt_ng_client
606
client->parser.received_data = settings->data_in;
607
client->send_fnc_ptr = settings->data_out_fnc;
608
client->user_ctx = settings->user_ctx;
609
649
- client->log = settings->log;
650
-
610
client->puback_callback = settings->puback_callback;
611
client->connack_callback = settings->connack_callback;
612
client->msg_callback = settings->msg_callback;
613
614
return client;
656
-
657
-err_free_tx_alias:
658
- c_rhash_destroy(client->tx_topic_aliases.stoi_dict);
659
-err_free_stats_mutex:
660
- pthread_mutex_destroy(&client->stats_mutex);
661
-err_free_rx_alias:
662
- c_rhash_destroy(client->rx_aliases);
663
-err_free_trx_buf:
664
- transaction_buffer_destroy(&client->main_buffer);
665
-err_free_client:
666
- freez(client);
667
- return NULL;
615
}
616
670
-static inline uint8_t get_control_packet_type(uint8_t first_hdr_byte)
617
+static uint8_t get_control_packet_type(uint8_t first_hdr_byte)
618
{
619
return first_hdr_byte >> 4;
620
}
@@ -699,33 +646,27 @@ static void mqtt_ng_destroy_tx_alias_hash(c_rhash hash)
646
void mqtt_ng_destroy(struct mqtt_ng_client *client)
647
{
648
transaction_buffer_destroy(&client->main_buffer);
702
- pthread_mutex_destroy(&client->stats_mutex);
649
650
mqtt_ng_destroy_tx_alias_hash(client->tx_topic_aliases.stoi_dict);
705
- pthread_rwlock_destroy(&client->tx_topic_aliases.rwlock);
651
mqtt_ng_destroy_rx_alias_hash(client->rx_aliases);
652
653
freez(client);
654
}
655
711
-int frag_set_external_data(mqtt_wss_log_ctx_t log, struct buffer_fragment *frag, void *data, size_t data_len, free_fnc_t data_free_fnc)
656
+int frag_set_external_data(struct buffer_fragment *frag, void *data, size_t data_len, free_fnc_t data_free_fnc)
657
{
658
if (frag->len) {
659
// TODO?: This could potentially be done in future if we set rule
660
// external data always follows in buffer data
661
// could help reduce fragmentation in some messages but
662
// currently not worth it considering time is tight
718
- mws_fatal(log, UNIT_LOG_PREFIX "INTERNAL ERROR: Cannot set external data to fragment already containing in buffer data!");
663
+ nd_log(NDLS_DAEMON, NDLP_ERR, "INTERNAL ERROR: Cannot set external data to fragment already containing in buffer data!");
664
return 1;
665
}
666
667
switch (ptr2memory_mode(data_free_fnc)) {
668
case MEMCPY:
669
frag->data = mallocz(data_len);
725
- if (frag->data == NULL) {
726
- mws_error(log, UNIT_LOG_PREFIX "OOM while malloc @_optimized_add");
727
- return 1;
728
- }
670
memcpy(frag->data, data, data_len);
671
break;
672
case EXTERNAL_FREE_AFTER_USE:
@@ -807,18 +748,18 @@ static size_t mqtt_ng_connect_size(struct mqtt_auth_properties *auth,
748
#define PACK_2B_INT(buffer, integer, frag) { *(uint16_t *)WRITE_POS(frag) = htobe16((integer)); \
749
DATA_ADVANCE(buffer, sizeof(uint16_t), frag); }
750
810
-static int _optimized_add(struct header_buffer *buf, mqtt_wss_log_ctx_t log_ctx, void *data, size_t data_len, free_fnc_t data_free_fnc, struct buffer_fragment **frag)
751
+static int _optimized_add(struct header_buffer *buf, void *data, size_t data_len, free_fnc_t data_free_fnc, struct buffer_fragment **frag)
752
{
753
if (data_len > SMALL_STRING_DONT_FRAGMENT_LIMIT) {
754
buffer_frag_flag_t flags = BUFFER_FRAG_DATA_EXTERNAL;
755
if ((*frag)->flags & BUFFER_FRAG_GARBAGE_COLLECT_ON_SEND)
756
flags |= BUFFER_FRAG_GARBAGE_COLLECT_ON_SEND;
757
if( (*frag = buffer_new_frag(buf, flags)) == NULL ) {
817
- mws_error(log_ctx, "Out of buffer space while generating the message");
758
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Out of buffer space while generating the message");
759
return 1;
760
}
820
- if (frag_set_external_data(log_ctx, *frag, data, data_len, data_free_fnc)) {
821
- mws_error(log_ctx, "Error adding external data to newly created fragment");
761
+ if (frag_set_external_data(*frag, data, data_len, data_free_fnc)) {
762
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error adding external data to newly created fragment");
763
return 1;
764
}
765
// we dont want to write to this fragment anymore
@@ -833,31 +774,30 @@ static int _optimized_add(struct header_buffer *buf, mqtt_wss_log_ctx_t log_ctx,
774
return 0;
775
}
776
836
-#define TRY_GENERATE_MESSAGE(generator_function, client, ...) \
837
- int rc = generator_function(&client->main_buffer, client->log, ##__VA_ARGS__); \
777
+#define TRY_GENERATE_MESSAGE(generator_function, ...) \
778
+ int rc = generator_function(&client->main_buffer, ##__VA_ARGS__); \
779
if (rc == MQTT_NG_MSGGEN_BUFFER_OOM) { \
780
LOCK_HDR_BUFFER(&client->main_buffer); \
840
- transaction_buffer_garbage_collect((&client->main_buffer), client->log); \
781
+ transaction_buffer_garbage_collect((&client->main_buffer)); \
782
UNLOCK_HDR_BUFFER(&client->main_buffer); \
842
- rc = generator_function(&client->main_buffer, client->log, ##__VA_ARGS__); \
783
+ rc = generator_function(&client->main_buffer, ##__VA_ARGS__); \
784
if (rc == MQTT_NG_MSGGEN_BUFFER_OOM && client->max_mem_bytes) { \
785
LOCK_HDR_BUFFER(&client->main_buffer); \
845
- transaction_buffer_grow((&client->main_buffer), client->log, GROWTH_FACTOR, client->max_mem_bytes); \
786
+ transaction_buffer_grow((&client->main_buffer),GROWTH_FACTOR, client->max_mem_bytes); \
787
UNLOCK_HDR_BUFFER(&client->main_buffer); \
847
- rc = generator_function(&client->main_buffer, client->log, ##__VA_ARGS__); \
788
+ rc = generator_function(&client->main_buffer, ##__VA_ARGS__); \
789
} \
790
if (rc == MQTT_NG_MSGGEN_BUFFER_OOM) \
850
- mws_error(client->log, "%s failed to generate message due to insufficient buffer space (line %d)", __FUNCTION__, __LINE__); \
791
+ nd_log(NDLS_DAEMON, NDLP_ERR, "%s failed to generate message due to insufficient buffer space (line %d)", __FUNCTION__, __LINE__); \
792
} \
793
if (rc == MQTT_NG_MSGGEN_OK) { \
853
- pthread_mutex_lock(&client->stats_mutex); \
794
+ spinlock_lock(&client->stats_spinlock); \
795
client->stats.tx_messages_queued++; \
855
- pthread_mutex_unlock(&client->stats_mutex); \
796
+ spinlock_unlock(&client->stats_spinlock); \
797
} \
798
return rc;
799
800
mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
860
- mqtt_wss_log_ctx_t log_ctx,
801
struct mqtt_auth_properties *auth,
802
struct mqtt_lwt_properties *lwt,
803
uint8_t clean_start,
@@ -865,7 +805,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
805
{
806
// Sanity Checks First (are given parameters correct and up to MQTT spec)
807
if (!auth->client_id) {
868
- mws_error(log_ctx, "ClientID must be set. [MQTT-3.1.3-3]");
808
+ nd_log(NDLS_DAEMON, NDLP_ERR, "ClientID must be set. [MQTT-3.1.3-3]");
809
return NULL;
810
}
811
@@ -876,29 +816,29 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
816
// however server MUST allow ClientIDs between 1-23 bytes [MQTT-3.1.3-5]
817
// so we will warn client server might not like this and he is using it
818
// at his own risk!
879
- mws_warn(log_ctx, "client_id provided is empty string. This might not be allowed by server [MQTT-3.1.3-6]");
819
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "client_id provided is empty string. This might not be allowed by server [MQTT-3.1.3-6]");
820
}
821
if(len > MQTT_MAX_CLIENT_ID) {
822
// [MQTT-3.1.3-5] server MUST allow client_id length 1-32
823
// server MAY allow longer client_id, if user provides longer client_id
824
// warn them he is doing so at his own risk!
885
- mws_warn(log_ctx, "client_id provided is longer than 23 bytes, server might not allow that [MQTT-3.1.3-5]");
825
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "client_id provided is longer than 23 bytes, server might not allow that [MQTT-3.1.3-5]");
826
}
827
828
if (lwt) {
829
if (lwt->will_message && lwt->will_message_size > 65535) {
890
- mws_error(log_ctx, "Will message cannot be longer than 65535 bytes due to MQTT protocol limitations [MQTT-3.1.3-4] and [MQTT-1.5.6]");
830
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Will message cannot be longer than 65535 bytes due to MQTT protocol limitations [MQTT-3.1.3-4] and [MQTT-1.5.6]");
831
return NULL;
832
}
833
834
if (!lwt->will_topic) { //TODO topic given with strlen==0 ? check specs
895
- mws_error(log_ctx, "If will message is given will topic must also be given [MQTT-3.1.3.3]");
835
+ nd_log(NDLS_DAEMON, NDLP_ERR, "If will message is given will topic must also be given [MQTT-3.1.3.3]");
836
return NULL;
837
}
838
839
if (lwt->will_qos > MQTT_MAX_QOS) {
840
// refer to [MQTT-3-1.2-12]
901
- mws_error(log_ctx, "QOS for LWT message is bigger than max");
841
+ nd_log(NDLS_DAEMON, NDLP_ERR, "QOS for LWT message is bigger than max");
842
return NULL;
843
}
844
}
@@ -932,8 +872,10 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
872
*connect_flags = 0;
873
if (auth->username)
874
*connect_flags |= MQTT_CONNECT_FLAG_USERNAME;
875
+
876
if (auth->password)
877
*connect_flags |= MQTT_CONNECT_FLAG_PASSWORD;
878
+
879
if (lwt) {
880
*connect_flags |= MQTT_CONNECT_FLAG_LWT;
881
*connect_flags |= lwt->will_qos << MQTT_CONNECT_FLAG_QOS_BITSHIFT;
@@ -957,7 +899,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
899
// [MQTT-3.1.3.1] Client identifier
900
CHECK_BYTES_AVAILABLE(&trx_buf->hdr_buffer, 2, goto fail_rollback);
901
PACK_2B_INT(&trx_buf->hdr_buffer, strlen(auth->client_id), frag);
960
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, auth->client_id, strlen(auth->client_id), auth->client_id_free, &frag))
902
+ if (_optimized_add(&trx_buf->hdr_buffer, auth->client_id, strlen(auth->client_id), auth->client_id_free, &frag))
903
goto fail_rollback;
904
905
if (lwt != NULL) {
@@ -971,7 +913,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
913
// Will Topic [MQTT-3.1.3.3]
914
CHECK_BYTES_AVAILABLE(&trx_buf->hdr_buffer, 2, goto fail_rollback);
915
PACK_2B_INT(&trx_buf->hdr_buffer, strlen(lwt->will_topic), frag);
974
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, lwt->will_topic, strlen(lwt->will_topic), lwt->will_topic_free, &frag))
916
+ if (_optimized_add(&trx_buf->hdr_buffer, lwt->will_topic, strlen(lwt->will_topic), lwt->will_topic_free, &frag))
917
goto fail_rollback;
918
919
// Will Payload [MQTT-3.1.3.4]
@@ -979,7 +921,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
921
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
922
CHECK_BYTES_AVAILABLE(&trx_buf->hdr_buffer, 2, goto fail_rollback);
923
PACK_2B_INT(&trx_buf->hdr_buffer, lwt->will_message_size, frag);
982
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, lwt->will_message, lwt->will_message_size, lwt->will_topic_free, &frag))
924
+ if (_optimized_add(&trx_buf->hdr_buffer, lwt->will_message, lwt->will_message_size, lwt->will_topic_free, &frag))
925
goto fail_rollback;
926
}
927
}
@@ -989,7 +931,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
931
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
932
CHECK_BYTES_AVAILABLE(&trx_buf->hdr_buffer, 2, goto fail_rollback);
933
PACK_2B_INT(&trx_buf->hdr_buffer, strlen(auth->username), frag);
992
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, auth->username, strlen(auth->username), auth->username_free, &frag))
934
+ if (_optimized_add(&trx_buf->hdr_buffer, auth->username, strlen(auth->username), auth->username_free, &frag))
935
goto fail_rollback;
936
}
937
@@ -998,7 +940,7 @@ mqtt_msg_data mqtt_ng_generate_connect(struct transaction_buffer *trx_buf,
940
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
941
CHECK_BYTES_AVAILABLE(&trx_buf->hdr_buffer, 2, goto fail_rollback);
942
PACK_2B_INT(&trx_buf->hdr_buffer, strlen(auth->password), frag);
1001
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, auth->password, strlen(auth->password), auth->password_free, &frag))
943
+ if (_optimized_add(&trx_buf->hdr_buffer, auth->password, strlen(auth->password), auth->password_free, &frag))
944
goto fail_rollback;
945
}
946
trx_buf->hdr_buffer.tail_frag->flags |= BUFFER_FRAG_MQTT_PACKET_TAIL;
@@ -1024,28 +966,23 @@ int mqtt_ng_connect(struct mqtt_ng_client *client,
966
buffer_purge(&client->main_buffer.hdr_buffer);
967
UNLOCK_HDR_BUFFER(&client->main_buffer);
968
1027
- pthread_rwlock_wrlock(&client->tx_topic_aliases.rwlock);
969
+ spinlock_lock(&client->tx_topic_aliases.spinlock);
970
// according to MQTT spec topic aliases should not be persisted
971
// even if clean session is true
972
mqtt_ng_destroy_tx_alias_hash(client->tx_topic_aliases.stoi_dict);
973
+
974
client->tx_topic_aliases.stoi_dict = TX_ALIASES_INITIALIZE();
1032
- if (client->tx_topic_aliases.stoi_dict == NULL) {
1033
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
1034
- return 1;
1035
- }
975
client->tx_topic_aliases.idx_assigned = 0;
1037
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
976
+ spinlock_unlock(&client->tx_topic_aliases.spinlock);
977
978
mqtt_ng_destroy_rx_alias_hash(client->rx_aliases);
979
client->rx_aliases = RX_ALIASES_INITIALIZE();
1041
- if (client->rx_aliases == NULL)
1042
- return 1;
980
1044
- client->connect_msg = mqtt_ng_generate_connect(&client->main_buffer, client->log, auth, lwt, clean_start, keep_alive);
981
+ client->connect_msg = mqtt_ng_generate_connect(&client->main_buffer, auth, lwt, clean_start, keep_alive);
982
if (client->connect_msg == NULL)
983
return 1;
984
1048
- pthread_mutex_lock(&client->stats_mutex);
985
+ spinlock_lock(&client->stats_spinlock);
986
if (clean_start)
987
client->stats.tx_messages_queued = 1;
988
else
@@ -1053,7 +990,7 @@ int mqtt_ng_connect(struct mqtt_ng_client *client,
990
991
client->stats.tx_messages_sent = 0;
992
client->stats.rx_messages_rcvd = 0;
1056
- pthread_mutex_unlock(&client->stats_mutex);
993
+ spinlock_unlock(&client->stats_spinlock);
994
995
client->client_state = CONNECT_PENDING;
996
return 0;
@@ -1065,15 +1002,16 @@ uint16_t get_unused_packet_id() {
1002
return packet_id ? packet_id : ++packet_id;
1003
}
1004
1068
-static inline size_t mqtt_ng_publish_size(const char *topic,
1069
- size_t msg_len,
1070
- uint16_t topic_id)
1005
+static size_t mqtt_ng_publish_size(
1006
+ const char *topic,
1007
+ size_t msg_len,
1008
+ uint16_t topic_id)
1009
{
1072
- size_t retval = 2 /* Topic Name Length */
1073
- + (topic == NULL ? 0 : strlen(topic))
1074
- + 2 /* Packet identifier */
1075
- + 1 /* Properties Length TODO for now fixed to 1 property */
1076
- + msg_len;
1010
+ size_t retval = 2
1011
+ + (topic == NULL ? 0 : strlen(topic)) /* Topic Name Length */
1012
+ + 2 /* Packet identifier */
1013
+ + 1 /* Properties Length for now fixed to 1 property */
1014
+ + msg_len;
1015
1016
if (topic_id)
1017
retval += 3;
@@ -1082,7 +1020,6 @@ static inline size_t mqtt_ng_publish_size(const char *topic,
1020
}
1021
1022
int mqtt_ng_generate_publish(struct transaction_buffer *trx_buf,
1085
- mqtt_wss_log_ctx_t log_ctx,
1023
char *topic,
1024
free_fnc_t topic_free,
1025
void *msg,
@@ -1121,7 +1058,7 @@ int mqtt_ng_generate_publish(struct transaction_buffer *trx_buf,
1058
// [MQTT-3.3.2.1]
1059
PACK_2B_INT(&trx_buf->hdr_buffer, topic == NULL ? 0 : strlen(topic), frag);
1060
if (topic != NULL) {
1124
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, topic, strlen(topic), topic_free, &frag))
1061
+ if (_optimized_add(&trx_buf->hdr_buffer, topic, strlen(topic), topic_free, &frag))
1062
goto fail_rollback;
1063
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
1064
}
@@ -1145,7 +1082,7 @@ int mqtt_ng_generate_publish(struct transaction_buffer *trx_buf,
1082
if( (frag = buffer_new_frag(&trx_buf->hdr_buffer, BUFFER_FRAG_DATA_EXTERNAL)) == NULL )
1083
goto fail_rollback;
1084
1148
- if (frag_set_external_data(log_ctx, frag, msg, msg_len, msg_free))
1085
+ if (frag_set_external_data(frag, msg, msg_len, msg_free))
1086
goto fail_rollback;
1087
1088
trx_buf->hdr_buffer.tail_frag->flags |= BUFFER_FRAG_MQTT_PACKET_TAIL;
@@ -1169,9 +1106,9 @@ int mqtt_ng_publish(struct mqtt_ng_client *client,
1106
uint16_t *packet_id)
1107
{
1108
struct topic_alias_data *alias = NULL;
1172
- pthread_rwlock_rdlock(&client->tx_topic_aliases.rwlock);
1109
+ spinlock_lock(&client->tx_topic_aliases.spinlock);
1110
c_rhash_get_ptr_by_str(client->tx_topic_aliases.stoi_dict, topic, (void**)&alias);
1174
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
1111
+ spinlock_unlock(&client->tx_topic_aliases.spinlock);
1112
1113
uint16_t topic_id = 0;
1114
@@ -1185,14 +1122,14 @@ int mqtt_ng_publish(struct mqtt_ng_client *client,
1122
}
1123
1124
if (client->max_msg_size && PUBLISH_SP_SIZE + mqtt_ng_publish_size(topic, msg_len, topic_id) > client->max_msg_size) {
1188
- mws_error(client->log, "Message too big for server: %zu", msg_len);
1125
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Message too big for server: %zu", msg_len);
1126
return MQTT_NG_MSGGEN_MSG_TOO_BIG;
1127
}
1128
1192
- TRY_GENERATE_MESSAGE(mqtt_ng_generate_publish, client, topic, topic_free, msg, msg_free, msg_len, publish_flags, packet_id, topic_id);
1129
+ TRY_GENERATE_MESSAGE(mqtt_ng_generate_publish, topic, topic_free, msg, msg_free, msg_len, publish_flags, packet_id, topic_id);
1130
}
1131
1195
-static inline size_t mqtt_ng_subscribe_size(struct mqtt_sub *subs, size_t sub_count)
1132
+static size_t mqtt_ng_subscribe_size(struct mqtt_sub *subs, size_t sub_count)
1133
{
1134
size_t len = 2 /* Packet Identifier */ + 1 /* Properties Length TODO for now fixed 0 */;
1135
len += sub_count * (2 /* topic filter string length */ + 1 /* [MQTT-3.8.3.1] Subscription Options Byte */);
@@ -1203,7 +1140,7 @@ static inline size_t mqtt_ng_subscribe_size(struct mqtt_sub *subs, size_t sub_co
1140
return len;
1141
}
1142
1206
-int mqtt_ng_generate_subscribe(struct transaction_buffer *trx_buf, mqtt_wss_log_ctx_t log_ctx, struct mqtt_sub *subs, size_t sub_count)
1143
+int mqtt_ng_generate_subscribe(struct transaction_buffer *trx_buf, struct mqtt_sub *subs, size_t sub_count)
1144
{
1145
// >> START THE RODEO <<
1146
transaction_buffer_transaction_start(trx_buf);
@@ -1238,7 +1175,7 @@ int mqtt_ng_generate_subscribe(struct transaction_buffer *trx_buf, mqtt_wss_log_
1175
for (size_t i = 0; i < sub_count; i++) {
1176
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
1177
PACK_2B_INT(&trx_buf->hdr_buffer, strlen(subs[i].topic), frag);
1241
- if (_optimized_add(&trx_buf->hdr_buffer, log_ctx, subs[i].topic, strlen(subs[i].topic), subs[i].topic_free, &frag))
1178
+ if (_optimized_add(&trx_buf->hdr_buffer, subs[i].topic, strlen(subs[i].topic), subs[i].topic_free, &frag))
1179
goto fail_rollback;
1180
BUFFER_TRANSACTION_NEW_FRAG(&trx_buf->hdr_buffer, 0, frag, goto fail_rollback);
1181
*WRITE_POS(frag) = subs[i].options;
@@ -1255,12 +1192,11 @@ fail_rollback:
1192
1193
int mqtt_ng_subscribe(struct mqtt_ng_client *client, struct mqtt_sub *subs, size_t sub_count)
1194
{
1258
- TRY_GENERATE_MESSAGE(mqtt_ng_generate_subscribe, client, subs, sub_count);
1195
+ TRY_GENERATE_MESSAGE(mqtt_ng_generate_subscribe, subs, sub_count);
1196
}
1197
1261
-int mqtt_ng_generate_disconnect(struct transaction_buffer *trx_buf, mqtt_wss_log_ctx_t log_ctx, uint8_t reason_code)
1198
+int mqtt_ng_generate_disconnect(struct transaction_buffer *trx_buf, uint8_t reason_code)
1199
{
1263
- (void) log_ctx;
1200
// >> START THE RODEO <<
1201
transaction_buffer_transaction_start(trx_buf);
1202
@@ -1299,12 +1235,11 @@ fail_rollback:
1235
1236
int mqtt_ng_disconnect(struct mqtt_ng_client *client, uint8_t reason_code)
1237
{
1302
- TRY_GENERATE_MESSAGE(mqtt_ng_generate_disconnect, client, reason_code);
1238
+ TRY_GENERATE_MESSAGE(mqtt_ng_generate_disconnect, reason_code);
1239
}
1240
1305
-static int mqtt_generate_puback(struct transaction_buffer *trx_buf, mqtt_wss_log_ctx_t log_ctx, uint16_t packet_id, uint8_t reason_code)
1241
+static int mqtt_generate_puback(struct transaction_buffer *trx_buf, uint16_t packet_id, uint8_t reason_code)
1242
{
1307
- (void) log_ctx;
1243
// >> START THE RODEO <<
1244
transaction_buffer_transaction_start(trx_buf);
1245
@@ -1344,7 +1279,7 @@ fail_rollback:
1279
1280
static int mqtt_ng_puback(struct mqtt_ng_client *client, uint16_t packet_id, uint8_t reason_code)
1281
{
1347
- TRY_GENERATE_MESSAGE(mqtt_generate_puback, client, packet_id, reason_code);
1282
+ TRY_GENERATE_MESSAGE(mqtt_generate_puback, packet_id, reason_code);
1283
}
1284
1285
int mqtt_ng_ping(struct mqtt_ng_client *client)
@@ -1361,7 +1296,6 @@ int mqtt_ng_ping(struct mqtt_ng_client *client)
1296
#define MQTT_NG_CLIENT_PROTOCOL_ERROR -1
1297
#define MQTT_NG_CLIENT_SERVER_RETURNED_ERROR -2
1298
#define MQTT_NG_CLIENT_NOT_IMPL_YET -3
1364
-#define MQTT_NG_CLIENT_OOM -4
1299
#define MQTT_NG_CLIENT_INTERNAL_ERROR -5
1300
1301
#define BUF_READ_CHECK_AT_LEAST(buf, x) \
@@ -1370,10 +1304,10 @@ int mqtt_ng_ping(struct mqtt_ng_client *client)
1304
1305
#define vbi_parser_reset_ctx(ctx) memset(ctx, 0, sizeof(struct mqtt_vbi_parser_ctx))
1306
1373
-static int vbi_parser_parse(struct mqtt_vbi_parser_ctx *ctx, rbuf_t data, mqtt_wss_log_ctx_t log)
1307
+static int vbi_parser_parse(struct mqtt_vbi_parser_ctx *ctx, rbuf_t data)
1308
{
1309
if (ctx->bytes > MQTT_VBI_MAXBYTES - 1) {
1376
- mws_error(log, "MQTT Variable Byte Integer can't be longer than %d bytes", MQTT_VBI_MAXBYTES);
1310
+ nd_log(NDLS_DAEMON, NDLP_ERR, "MQTT Variable Byte Integer can't be longer than %d bytes", MQTT_VBI_MAXBYTES);
1311
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1312
}
1313
if (!ctx->bytes || ctx->data[ctx->bytes-1] & MQTT_VBI_CONTINUATION_FLAG) {
@@ -1385,7 +1319,7 @@ static int vbi_parser_parse(struct mqtt_vbi_parser_ctx *ctx, rbuf_t data, mqtt_w
1319
}
1320
1321
if (mqtt_vbi_to_uint32(ctx->data, &ctx->result)) {
1388
- mws_error(log, "MQTT Variable Byte Integer failed to be parsed.");
1322
+ nd_log(NDLS_DAEMON, NDLP_ERR, "MQTT Variable Byte Integer failed to be parsed.");
1323
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1324
}
1325
@@ -1471,12 +1405,12 @@ struct mqtt_property *get_property_by_id(struct mqtt_property *props, uint8_t pr
1405
}
1406
1407
// Parses [MQTT-2.2.2]
1474
-static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t data, mqtt_wss_log_ctx_t log)
1408
+static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t data)
1409
{
1410
int rc;
1411
switch (ctx->state) {
1412
case PROPERTIES_LENGTH:
1479
- rc = vbi_parser_parse(&ctx->vbi_parser_ctx, data, log);
1413
+ rc = vbi_parser_parse(&ctx->vbi_parser_ctx, data);
1414
if (rc == MQTT_NG_CLIENT_PARSE_DONE) {
1415
ctx->properties_length = ctx->vbi_parser_ctx.result;
1416
ctx->bytes_consumed += ctx->vbi_parser_ctx.bytes;
@@ -1525,7 +1459,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1459
ctx->state = PROPERTY_TYPE_STR_BIN_LEN;
1460
break;
1461
default:
1528
- mws_error(log, "Unsupported property type %d for property id %d.", (int)ctx->tail->type, (int)ctx->tail->id);
1462
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unsupported property type %d for property id %d.", (int)ctx->tail->type, (int)ctx->tail->id);
1463
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1464
}
1465
break;
@@ -1543,7 +1477,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1477
ctx->state = PROPERTY_TYPE_STR;
1478
break;
1479
default:
1546
- mws_error(log, "Unexpected datatype in PROPERTY_TYPE_STR_BIN_LEN %d", (int)ctx->tail->type);
1480
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unexpected datatype in PROPERTY_TYPE_STR_BIN_LEN %d", (int)ctx->tail->type);
1481
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1482
}
1483
break;
@@ -1568,7 +1502,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1502
ctx->state = PROPERTY_NEXT;
1503
break;
1504
case PROPERTY_TYPE_VBI:
1571
- rc = vbi_parser_parse(&ctx->vbi_parser_ctx, data, log);
1505
+ rc = vbi_parser_parse(&ctx->vbi_parser_ctx, data);
1506
if (rc == MQTT_NG_CLIENT_PARSE_DONE) {
1507
ctx->tail->data.uint32 = ctx->vbi_parser_ctx.result;
1508
ctx->bytes_consumed += ctx->vbi_parser_ctx.bytes;
@@ -1618,9 +1552,9 @@ static int parse_connack_varhdr(struct mqtt_ng_client *client)
1552
mqtt_properties_parser_ctx_reset(&parser->properties_parser);
1553
break;
1554
case MQTT_PARSE_VARHDR_PROPS:
1621
- return parse_properties_array(&parser->properties_parser, parser->received_data, client->log);
1555
+ return parse_properties_array(&parser->properties_parser, parser->received_data);
1556
default:
1623
- ERROR("invalid state for connack varhdr parser");
1557
+ nd_log(NDLS_DAEMON, NDLP_ERR, "invalid state for connack varhdr parser");
1558
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1559
}
1560
return MQTT_NG_CLIENT_OK_CALL_AGAIN;
@@ -1644,9 +1578,9 @@ static int parse_disconnect_varhdr(struct mqtt_ng_client *client)
1578
mqtt_properties_parser_ctx_reset(&parser->properties_parser);
1579
break;
1580
case MQTT_PARSE_VARHDR_PROPS:
1647
- return parse_properties_array(&parser->properties_parser, parser->received_data, client->log);
1581
+ return parse_properties_array(&parser->properties_parser, parser->received_data);
1582
default:
1649
- ERROR("invalid state for connack varhdr parser");
1583
+ nd_log(NDLS_DAEMON, NDLP_ERR, "invalid state for connack varhdr parser");
1584
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1585
}
1586
return MQTT_NG_CLIENT_OK_CALL_AGAIN;
@@ -1682,9 +1616,9 @@ static int parse_puback_varhdr(struct mqtt_ng_client *client)
1616
mqtt_properties_parser_ctx_reset(&parser->properties_parser);
1617
/* FALLTHROUGH */
1618
case MQTT_PARSE_VARHDR_PROPS:
1685
- return parse_properties_array(&parser->properties_parser, parser->received_data, client->log);
1619
+ return parse_properties_array(&parser->properties_parser, parser->received_data);
1620
default:
1687
- ERROR("invalid state for puback varhdr parser");
1621
+ nd_log(NDLS_DAEMON, NDLP_ERR, "invalid state for puback varhdr parser");
1622
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1623
}
1624
return MQTT_NG_CLIENT_OK_CALL_AGAIN;
@@ -1707,7 +1641,7 @@ static int parse_suback_varhdr(struct mqtt_ng_client *client)
1641
mqtt_properties_parser_ctx_reset(&parser->properties_parser);
1642
/* FALLTHROUGH */
1643
case MQTT_PARSE_VARHDR_PROPS:
1710
- rc = parse_properties_array(&parser->properties_parser, parser->received_data, client->log);
1644
+ rc = parse_properties_array(&parser->properties_parser, parser->received_data);
1645
if (rc != MQTT_NG_CLIENT_PARSE_DONE)
1646
return rc;
1647
parser->mqtt_parsed_len += parser->properties_parser.bytes_consumed;
@@ -1728,7 +1662,7 @@ static int parse_suback_varhdr(struct mqtt_ng_client *client)
1662
1663
return MQTT_NG_CLIENT_NEED_MORE_BYTES;
1664
default:
1731
- ERROR("invalid state for suback varhdr parser");
1665
+ nd_log(NDLS_DAEMON, NDLP_ERR, "invalid state for suback varhdr parser");
1666
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1667
}
1668
return MQTT_NG_CLIENT_OK_CALL_AGAIN;
@@ -1752,8 +1686,6 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1686
break;
1687
}
1688
publish->topic = callocz(1, publish->topic_len + 1 /* add 0x00 */);
1755
- if (publish->topic == NULL)
1756
- return MQTT_NG_CLIENT_OOM;
1689
parser->varhdr_state = MQTT_PARSE_VARHDR_TOPICNAME;
1690
/* FALLTHROUGH */
1691
case MQTT_PARSE_VARHDR_TOPICNAME:
@@ -1779,7 +1711,7 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1711
parser->mqtt_parsed_len += 2;
1712
/* FALLTHROUGH */
1713
case MQTT_PARSE_VARHDR_PROPS:
1782
- rc = parse_properties_array(&parser->properties_parser, parser->received_data, client->log);
1714
+ rc = parse_properties_array(&parser->properties_parser, parser->received_data);
1715
if (rc != MQTT_NG_CLIENT_PARSE_DONE)
1716
return rc;
1717
parser->mqtt_parsed_len += parser->properties_parser.bytes_consumed;
@@ -1789,7 +1721,7 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1721
if (parser->mqtt_fixed_hdr_remaining_length < parser->mqtt_parsed_len) {
1722
freez(publish->topic);
1723
publish->topic = NULL;
1792
- ERROR("Error parsing PUBLISH message");
1724
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error parsing PUBLISH message");
1725
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1726
}
1727
publish->data_len = parser->mqtt_fixed_hdr_remaining_length - parser->mqtt_parsed_len;
@@ -1800,18 +1732,12 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1732
BUF_READ_CHECK_AT_LEAST(parser->received_data, publish->data_len);
1733
1734
publish->data = mallocz(publish->data_len);
1803
- if (publish->data == NULL) {
1804
- freez(publish->topic);
1805
- publish->topic = NULL;
1806
- return MQTT_NG_CLIENT_OOM;
1807
- }
1808
-
1735
rbuf_pop(parser->received_data, publish->data, publish->data_len);
1736
parser->mqtt_parsed_len += publish->data_len;
1737
1738
return MQTT_NG_CLIENT_PARSE_DONE;
1739
default:
1814
- ERROR("invalid state for publish varhdr parser");
1740
+ nd_log(NDLS_DAEMON, NDLP_ERR, "invalid state for publish varhdr parser");
1741
return MQTT_NG_CLIENT_INTERNAL_ERROR;
1742
}
1743
return MQTT_NG_CLIENT_OK_CALL_AGAIN;
@@ -1831,7 +1757,7 @@ static int parse_data(struct mqtt_ng_client *client)
1757
parser->state = MQTT_PARSE_FIXED_HEADER_LEN;
1758
break;
1759
case MQTT_PARSE_FIXED_HEADER_LEN:
1834
- rc = vbi_parser_parse(&parser->vbi_parser, parser->received_data, client->log);
1760
+ rc = vbi_parser_parse(&parser->vbi_parser, parser->received_data);
1761
if (rc == MQTT_NG_CLIENT_PARSE_DONE) {
1762
parser->mqtt_fixed_hdr_remaining_length = parser->vbi_parser.result;
1763
parser->state = MQTT_PARSE_VARIABLE_HEADER;
@@ -1874,7 +1800,7 @@ static int parse_data(struct mqtt_ng_client *client)
1800
return rc;
1801
case MQTT_CPT_PINGRESP:
1802
if (parser->mqtt_fixed_hdr_remaining_length) {
1877
- ERROR ("PINGRESP has to be 0 Remaining Length."); // [MQTT-3.13.1]
1803
+ nd_log(NDLS_DAEMON, NDLP_ERR, "PINGRESP has to be 0 Remaining Length."); // [MQTT-3.13.1]
1804
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1805
}
1806
parser->state = MQTT_PARSE_MQTT_PACKET_DONE;
@@ -1887,7 +1813,7 @@ static int parse_data(struct mqtt_ng_client *client)
1813
}
1814
return rc;
1815
default:
1890
- ERROR("Parsing Control Packet Type %" PRIu8 " not implemented yet.", get_control_packet_type(parser->mqtt_control_packet_type));
1816
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Parsing Control Packet Type %" PRIu8 " not implemented yet.", get_control_packet_type(parser->mqtt_control_packet_type));
1817
rbuf_bump_tail(parser->received_data, parser->mqtt_fixed_hdr_remaining_length);
1818
parser->state = MQTT_PARSE_MQTT_PACKET_DONE;
1819
return MQTT_NG_CLIENT_NOT_IMPL_YET;
@@ -1950,7 +1876,7 @@ static int send_fragment(struct mqtt_ng_client *client) {
1876
if (bytes)
1877
processed = client->send_fnc_ptr(client->user_ctx, ptr, bytes);
1878
else
1953
- WARN("This fragment was fully sent already. This should not happen!");
1879
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "This fragment was fully sent already. This should not happen!");
1880
1881
frag->sent += processed;
1882
if (frag->sent != frag->len)
@@ -1958,11 +1884,11 @@ static int send_fragment(struct mqtt_ng_client *client) {
1884
1885
if (frag->flags & BUFFER_FRAG_MQTT_PACKET_TAIL) {
1886
client->time_of_last_send = time(NULL);
1961
- pthread_mutex_lock(&client->stats_mutex);
1887
+ spinlock_lock(&client->stats_spinlock);
1888
if (client->main_buffer.sending_frag != &ping_frag)
1889
client->stats.tx_messages_queued--;
1890
client->stats.tx_messages_sent++;
1965
- pthread_mutex_unlock(&client->stats_mutex);
1891
+ spinlock_unlock(&client->stats_spinlock);
1892
client->main_buffer.sending_frag = NULL;
1893
return 1;
1894
}
@@ -1986,7 +1912,7 @@ static void try_send_all(struct mqtt_ng_client *client) {
1912
} while(send_all_message_fragments(client) >= 0);
1913
}
1914
1989
-static inline void mark_message_for_gc(struct buffer_fragment *frag)
1915
+static void mark_message_for_gc(struct buffer_fragment *frag)
1916
{
1917
while (frag) {
1918
frag->flags |= BUFFER_FRAG_GARBAGE_COLLECT;
@@ -2004,7 +1930,7 @@ static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1930
while (frag) {
1931
if ( (frag->flags & BUFFER_FRAG_MQTT_PACKET_HEAD) && frag->packet_id == packet_id) {
1932
if (!frag->sent) {
2007
- ERROR("Received packet_id (%" PRIu16 ") belongs to MQTT packet which was not yet sent!", packet_id);
1933
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Received packet_id (%" PRIu16 ") belongs to MQTT packet which was not yet sent!", packet_id);
1934
UNLOCK_HDR_BUFFER(&client->main_buffer);
1935
return 1;
1936
}
@@ -2014,7 +1940,7 @@ static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1940
}
1941
frag = frag->next;
1942
}
2017
- ERROR("Received packet_id (%" PRIu16 ") is unknown!", packet_id);
1943
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Received packet_id (%" PRIu16 ") is unknown!", packet_id);
1944
UNLOCK_HDR_BUFFER(&client->main_buffer);
1945
return 1;
1946
}
@@ -2022,110 +1948,113 @@ static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1948
int handle_incoming_traffic(struct mqtt_ng_client *client)
1949
{
1950
int rc;
1951
+ while ((rc = parse_data(client)) == MQTT_NG_CLIENT_OK_CALL_AGAIN) {
1952
+ ;
1953
+ }
1954
+ if (rc != MQTT_NG_CLIENT_MQTT_PACKET_DONE)
1955
+ return rc;
1956
+
1957
struct mqtt_publish *pub;
2026
- while( (rc = parse_data(client)) == MQTT_NG_CLIENT_OK_CALL_AGAIN );
2027
- if ( rc == MQTT_NG_CLIENT_MQTT_PACKET_DONE ) {
2028
- struct mqtt_property *prop;
2029
-#ifdef MQTT_DEBUG_VERBOSE
2030
- DEBUG("MQTT Packet Parsed Successfully!");
2031
-#endif
2032
- pthread_mutex_lock(&client->stats_mutex);
2033
- client->stats.rx_messages_rcvd++;
2034
- pthread_mutex_unlock(&client->stats_mutex);
2035
-
2036
- switch (get_control_packet_type(client->parser.mqtt_control_packet_type)) {
2037
- case MQTT_CPT_CONNACK:
2038
-#ifdef MQTT_DEBUG_VERBOSE
2039
- DEBUG("Received CONNACK");
2040
-#endif
2041
- LOCK_HDR_BUFFER(&client->main_buffer);
2042
- mark_message_for_gc(client->connect_msg);
2043
- UNLOCK_HDR_BUFFER(&client->main_buffer);
2044
- client->connect_msg = NULL;
2045
- if (client->client_state != CONNECTING) {
2046
- ERROR("Received unexpected CONNACK");
2047
- client->client_state = ERROR;
2048
- return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2049
- }
2050
- if ((prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_MAX_PKT_SIZE)) != NULL) {
2051
- INFO("MQTT server limits message size to %" PRIu32, prop->data.uint32);
2052
- client->max_msg_size = prop->data.uint32;
2053
- }
2054
- if (client->connack_callback)
2055
- client->connack_callback(client->user_ctx, client->parser.mqtt_packet.connack.reason_code);
2056
- if (!client->parser.mqtt_packet.connack.reason_code) {
2057
- INFO("MQTT Connection Accepted By Server");
2058
- client->client_state = CONNECTED;
2059
- break;
2060
- }
1958
+ struct mqtt_property *prop;
1959
+ spinlock_lock(&client->stats_spinlock);
1960
+ client->stats.rx_messages_rcvd++;
1961
+ spinlock_unlock(&client->stats_spinlock);
1962
+
1963
+ uint8_t ctrl_packet_type = get_control_packet_type(client->parser.mqtt_control_packet_type);
1964
+ switch (ctrl_packet_type) {
1965
+ case MQTT_CPT_CONNACK:
1966
+ LOCK_HDR_BUFFER(&client->main_buffer);
1967
+ mark_message_for_gc(client->connect_msg);
1968
+ UNLOCK_HDR_BUFFER(&client->main_buffer);
1969
+
1970
+ client->connect_msg = NULL;
1971
+
1972
+ if (client->client_state != CONNECTING) {
1973
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Received unexpected CONNACK");
1974
client->client_state = ERROR;
2062
- return MQTT_NG_CLIENT_SERVER_RETURNED_ERROR;
2063
- case MQTT_CPT_PUBACK:
2064
-#ifdef MQTT_DEBUG_VERBOSE
2065
- DEBUG("Received PUBACK %" PRIu16, client->parser.mqtt_packet.puback.packet_id);
2066
-#endif
2067
- if (mark_packet_acked(client, client->parser.mqtt_packet.puback.packet_id))
2068
- return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2069
- if (client->puback_callback)
2070
- client->puback_callback(client->parser.mqtt_packet.puback.packet_id);
2071
- break;
2072
- case MQTT_CPT_PINGRESP:
2073
-#ifdef MQTT_DEBUG_VERBOSE
2074
- DEBUG("Received PINGRESP");
2075
-#endif
2076
- break;
2077
- case MQTT_CPT_SUBACK:
2078
-#ifdef MQTT_DEBUG_VERBOSE
2079
- DEBUG("Received SUBACK %" PRIu16, client->parser.mqtt_packet.suback.packet_id);
2080
-#endif
2081
- if (mark_packet_acked(client, client->parser.mqtt_packet.suback.packet_id))
2082
- return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1975
+ return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1976
+ }
1977
+
1978
+ if ((prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_MAX_PKT_SIZE)) != NULL) {
1979
+ nd_log(NDLS_DAEMON, NDLP_INFO, "MQTT server limits message size to %" PRIu32, prop->data.uint32);
1980
+ client->max_msg_size = prop->data.uint32;
1981
+ }
1982
+
1983
+ if (client->connack_callback)
1984
+ client->connack_callback(client->user_ctx, client->parser.mqtt_packet.connack.reason_code);
1985
+ if (!client->parser.mqtt_packet.connack.reason_code) {
1986
+ nd_log(NDLS_DAEMON, NDLP_INFO, "MQTT Connection Accepted By Server");
1987
+ client->client_state = CONNECTED;
1988
break;
2084
- case MQTT_CPT_PUBLISH:
2085
-#ifdef MQTT_DEBUG_VERBOSE
2086
- DEBUG("Recevied PUBLISH");
2087
-#endif
2088
- pub = &client->parser.mqtt_packet.publish;
2089
- if (pub->qos > 1) {
2090
- freez(pub->topic);
2091
- freez(pub->data);
2092
- return MQTT_NG_CLIENT_NOT_IMPL_YET;
2093
- }
2094
- if ( pub->qos == 1 && (rc = mqtt_ng_puback(client, pub->packet_id, 0)) ) {
2095
- client->client_state = ERROR;
2096
- ERROR("Error generating PUBACK reply for PUBLISH");
2097
- return rc;
2098
- }
2099
- if ( (prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_TOPIC_ALIAS)) != NULL ) {
2100
- // Topic Alias property was sent from server
2101
- void *topic_ptr;
2102
- if (!c_rhash_get_ptr_by_uint64(client->rx_aliases, prop->data.uint8, &topic_ptr)) {
2103
- if (pub->topic != NULL) {
2104
- ERROR("We do not yet support topic alias reassignment");
2105
- return MQTT_NG_CLIENT_NOT_IMPL_YET;
2106
- }
2107
- pub->topic = topic_ptr;
2108
- } else {
2109
- if (pub->topic == NULL) {
2110
- ERROR("Topic alias with id %d unknown and topic not set by server!", prop->data.uint8);
2111
- return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2112
- }
2113
- c_rhash_insert_uint64_ptr(client->rx_aliases, prop->data.uint8, pub->topic);
1989
+ }
1990
+ client->client_state = ERROR;
1991
+ return MQTT_NG_CLIENT_SERVER_RETURNED_ERROR;
1992
+
1993
+ case MQTT_CPT_PUBACK:
1994
+ if (mark_packet_acked(client, client->parser.mqtt_packet.puback.packet_id))
1995
+ return MQTT_NG_CLIENT_PROTOCOL_ERROR;
1996
+ if (client->puback_callback)
1997
+ client->puback_callback(client->parser.mqtt_packet.puback.packet_id);
1998
+ break;
1999
+
2000
+ case MQTT_CPT_PINGRESP:
2001
+ break;
2002
+
2003
+ case MQTT_CPT_SUBACK:
2004
+ if (mark_packet_acked(client, client->parser.mqtt_packet.suback.packet_id))
2005
+ return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2006
+ break;
2007
+
2008
+ case MQTT_CPT_PUBLISH:
2009
+ pub = &client->parser.mqtt_packet.publish;
2010
+
2011
+ if (pub->qos > 1) {
2012
+ freez(pub->topic);
2013
+ freez(pub->data);
2014
+ return MQTT_NG_CLIENT_NOT_IMPL_YET;
2015
+ }
2016
+
2017
+ if ( pub->qos == 1 && ((rc = mqtt_ng_puback(client, pub->packet_id, 0))) ) {
2018
+ client->client_state = ERROR;
2019
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error generating PUBACK reply for PUBLISH");
2020
+ return rc;
2021
+ }
2022
+
2023
+ if ( (prop = get_property_by_id(client->parser.properties_parser.head, MQTT_PROP_TOPIC_ALIAS)) != NULL ) {
2024
+ // Topic Alias property was sent from server
2025
+ void *topic_ptr;
2026
+ if (!c_rhash_get_ptr_by_uint64(client->rx_aliases, prop->data.uint8, &topic_ptr)) {
2027
+ if (pub->topic != NULL) {
2028
+ nd_log(NDLS_DAEMON, NDLP_ERR, "We do not yet support topic alias reassignment");
2029
+ return MQTT_NG_CLIENT_NOT_IMPL_YET;
2030
}
2031
+ pub->topic = topic_ptr;
2032
+ } else {
2033
+ if (pub->topic == NULL) {
2034
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Topic alias with id %d unknown and topic not set by server!", prop->data.uint8);
2035
+ return MQTT_NG_CLIENT_PROTOCOL_ERROR;
2036
+ }
2037
+ c_rhash_insert_uint64_ptr(client->rx_aliases, prop->data.uint8, pub->topic);
2038
}
2116
- if (client->msg_callback)
2117
- client->msg_callback(pub->topic, pub->data, pub->data_len, pub->qos);
2118
- // in case we have property topic alias and we have topic we take over the string
2119
- // and add pointer to it into topic alias list
2120
- if (prop == NULL)
2121
- freez(pub->topic);
2122
- freez(pub->data);
2123
- return MQTT_NG_CLIENT_WANT_WRITE;
2124
- case MQTT_CPT_DISCONNECT:
2125
- INFO ("Got MQTT DISCONNECT control packet from server. Reason code: %d", (int)client->parser.mqtt_packet.disconnect.reason_code);
2126
- client->client_state = DISCONNECTED;
2127
- break;
2128
- }
2039
+ }
2040
+
2041
+ if (client->msg_callback)
2042
+ client->msg_callback(pub->topic, pub->data, pub->data_len, pub->qos);
2043
+ // in case we have property topic alias and we have topic we take over the string
2044
+ // and add pointer to it into topic alias list
2045
+ if (prop == NULL)
2046
+ freez(pub->topic);
2047
+ freez(pub->data);
2048
+ return MQTT_NG_CLIENT_WANT_WRITE;
2049
+
2050
+ case MQTT_CPT_DISCONNECT:
2051
+ nd_log(NDLS_DAEMON, NDLP_INFO, "Got MQTT DISCONNECT control packet from server. Reason code: %d", (int)client->parser.mqtt_packet.disconnect.reason_code);
2052
+ client->client_state = DISCONNECTED;
2053
+ break;
2054
+
2055
+ default:
2056
+ nd_log(NDLS_DAEMON, NDLP_INFO, "Got unknown control packet %u from server", ctrl_packet_type);
2057
+ break;
2058
}
2059
2060
return rc;
@@ -2173,9 +2102,9 @@ void mqtt_ng_set_max_mem(struct mqtt_ng_client *client, size_t bytes)
2102
2103
void mqtt_ng_get_stats(struct mqtt_ng_client *client, struct mqtt_ng_stats *stats)
2104
{
2176
- pthread_mutex_lock(&client->stats_mutex);
2105
+ spinlock_lock(&client->stats_spinlock);
2106
memcpy(stats, &client->stats, sizeof(struct mqtt_ng_stats));
2178
- pthread_mutex_unlock(&client->stats_mutex);
2107
+ spinlock_unlock(&client->stats_spinlock);
2108
2109
stats->tx_bytes_queued = 0;
2110
stats->tx_buffer_reclaimable = 0;
@@ -2198,11 +2127,11 @@ void mqtt_ng_get_stats(struct mqtt_ng_client *client, struct mqtt_ng_stats *stat
2127
int mqtt_ng_set_topic_alias(struct mqtt_ng_client *client, const char *topic)
2128
{
2129
uint16_t idx;
2201
- pthread_rwlock_wrlock(&client->tx_topic_aliases.rwlock);
2130
+ spinlock_lock(&client->tx_topic_aliases.spinlock);
2131
2132
if (client->tx_topic_aliases.idx_assigned >= client->tx_topic_aliases.idx_max) {
2204
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
2205
- mws_error(client->log, "Tx topic alias indexes were exhausted (current version of the library doesn't support reassigning yet. Feel free to contribute.");
2133
+ spinlock_unlock(&client->tx_topic_aliases.spinlock);
2134
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Tx topic alias indexes were exhausted (current version of the library doesn't support reassigning yet. Feel free to contribute.");
2135
return 0; //0 is not a valid topic alias
2136
}
2137
@@ -2211,8 +2140,8 @@ int mqtt_ng_set_topic_alias(struct mqtt_ng_client *client, const char *topic)
2140
// this is not a problem for library but might be helpful to warn user
2141
// as it might indicate bug in their program (but also might be expected)
2142
idx = alias->idx;
2214
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
2215
- mws_debug(client->log, "%s topic \"%s\" already has alias set. Ignoring.", __FUNCTION__, topic);
2143
+ spinlock_unlock(&client->tx_topic_aliases.spinlock);
2144
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "%s topic \"%s\" already has alias set. Ignoring.", __FUNCTION__, topic);
2145
return idx;
2146
}
2147
@@ -2223,6 +2152,6 @@ int mqtt_ng_set_topic_alias(struct mqtt_ng_client *client, const char *topic)
2152
2153
c_rhash_insert_str_ptr(client->tx_topic_aliases.stoi_dict, topic, (void*)alias);
2154
2226
- pthread_rwlock_unlock(&client->tx_topic_aliases.rwlock);
2155
+ spinlock_unlock(&client->tx_topic_aliases.spinlock);
2156
return idx;
2157
}
src/aclk/mqtt_websockets/mqtt_ng.h
-1
@@ -67,7 +67,6 @@ int mqtt_ng_ping(struct mqtt_ng_client *client);
67
typedef ssize_t (*mqtt_ng_send_fnc_t)(void *user_ctx, const void* buf, size_t len);
68
69
struct mqtt_ng_init {
70
- mqtt_wss_log_ctx_t log;
70
rbuf_t data_in;
71
mqtt_ng_send_fnc_t data_out_fnc;
72
void *user_ctx;
src/aclk/mqtt_websockets/mqtt_wss_client.c
+97
-219
@@ -57,6 +57,8 @@ char *util_openssl_ret_err(int err)
57
return "SSL_ERROR_SYSCALL";
58
case SSL_ERROR_SSL:
59
return "SSL_ERROR_SSL";
60
+ default:
61
+ break;
62
}
63
return "UNKNOWN";
64
}
@@ -64,8 +66,6 @@ char *util_openssl_ret_err(int err)
66
struct mqtt_wss_client_struct {
67
ws_client *ws_client;
68
67
- mqtt_wss_log_ctx_t log;
68
-
69
// immediate connection (e.g. proxy server)
70
char *host;
71
int port;
@@ -117,69 +117,49 @@ static void mws_connack_callback_ng(void *user_ctx, int code)
117
switch(code) {
118
case 0:
119
client->mqtt_connected = 1;
120
- return;
120
+ break;
121
//TODO manual labor: all the CONNACK error codes with some nice error message
122
default:
123
- mws_error(client->log, "MQTT CONNACK returned error %d", code);
124
- return;
123
+ nd_log(NDLS_DAEMON, NDLP_ERR, "MQTT CONNACK returned error %d", code);
124
+ break;
125
}
126
}
127
128
static ssize_t mqtt_send_cb(void *user_ctx, const void* buf, size_t len)
129
{
130
mqtt_wss_client client = user_ctx;
131
-#ifdef DEBUG_ULTRA_VERBOSE
132
- mws_debug(client->log, "mqtt_pal_sendall(len=%d)", len);
133
-#endif
131
int ret = ws_client_send(client->ws_client, WS_OP_BINARY_FRAME, buf, len);
135
- if (ret >= 0 && (size_t)ret != len) {
136
-#ifdef DEBUG_ULTRA_VERBOSE
137
- mws_debug(client->log, "Not complete message sent (Msg=%d,Sent=%d). Need to arm POLLOUT!", len, ret);
138
-#endif
132
+ if (ret >= 0 && (size_t)ret != len)
133
client->mqtt_didnt_finish_write = 1;
140
- }
134
return ret;
135
}
136
144
-mqtt_wss_client mqtt_wss_new(const char *log_prefix,
145
- mqtt_wss_log_callback_t log_callback,
146
- msg_callback_fnc_t msg_callback,
147
- void (*puback_callback)(uint16_t packet_id))
137
+mqtt_wss_client mqtt_wss_new(
138
+ msg_callback_fnc_t msg_callback,
139
+ void (*puback_callback)(uint16_t packet_id))
140
{
149
- mqtt_wss_log_ctx_t log;
150
-
151
- log = mqtt_wss_log_ctx_create(log_prefix, log_callback);
152
- if(!log)
153
- return NULL;
154
-
141
SSL_library_init();
142
SSL_load_error_strings();
143
144
mqtt_wss_client client = callocz(1, sizeof(struct mqtt_wss_client_struct));
159
- if (!client) {
160
- mws_error(log, "OOM alocating mqtt_wss_client");
161
- goto fail;
162
- }
145
146
spinlock_init(&client->stat_lock);
147
148
client->msg_callback = msg_callback;
149
client->puback_callback = puback_callback;
150
169
- client->ws_client = ws_client_new(0, &client->target_host, log);
151
+ client->ws_client = ws_client_new(0, &client->target_host);
152
if (!client->ws_client) {
171
- mws_error(log, "Error creating ws_client");
153
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error creating ws_client");
154
goto fail_1;
155
}
156
175
- client->log = log;
176
-
157
#ifdef __APPLE__
158
if (pipe(client->write_notif_pipe)) {
159
#else
160
if (pipe2(client->write_notif_pipe, O_CLOEXEC /*| O_DIRECT*/)) {
161
#endif
182
- mws_error(log, "Couldn't create pipe");
162
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Couldn't create pipe");
163
goto fail_2;
164
}
165
@@ -189,7 +169,6 @@ mqtt_wss_client mqtt_wss_new(const char *log_prefix,
169
client->poll_fds[POLLFD_SOCKET].events = POLLIN;
170
171
struct mqtt_ng_init settings = {
192
- .log = log,
172
.data_in = client->ws_client->buf_to_mqtt,
173
.data_out_fnc = &mqtt_send_cb,
174
.user_ctx = client,
@@ -197,22 +176,14 @@ mqtt_wss_client mqtt_wss_new(const char *log_prefix,
176
.puback_callback = puback_callback,
177
.msg_callback = msg_callback
178
};
200
- if ( (client->mqtt = mqtt_ng_init(&settings)) == NULL ) {
201
- mws_error(log, "Error initializing internal MQTT client");
202
- goto fail_3;
203
- }
179
+ client->mqtt = mqtt_ng_init(&settings);
180
181
return client;
182
207
-fail_3:
208
- close(client->write_notif_pipe[PIPE_WRITE_END]);
209
- close(client->write_notif_pipe[PIPE_READ_END]);
183
fail_2:
184
ws_client_destroy(client->ws_client);
185
fail_1:
186
freez(client);
214
-fail:
215
- mqtt_wss_log_ctx_destroy(log);
187
return NULL;
188
}
189
@@ -253,30 +224,25 @@ void mqtt_wss_destroy(mqtt_wss_client client)
224
if (client->sockfd > 0)
225
close(client->sockfd);
226
256
- mqtt_wss_log_ctx_destroy(client->log);
227
freez(client);
228
}
229
230
static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
231
{
262
- SSL *ssl;
263
- X509 *err_cert;
264
- mqtt_wss_client client;
265
- int err = 0, depth;
266
- char *err_str;
232
+ int err = 0;
233
268
- ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
269
- client = SSL_get_ex_data(ssl, 0);
234
+ SSL* ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
235
+ mqtt_wss_client client = SSL_get_ex_data(ssl, 0);
236
237
// TODO handle depth as per https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
238
239
if (!preverify_ok) {
240
err = X509_STORE_CTX_get_error(ctx);
275
- depth = X509_STORE_CTX_get_error_depth(ctx);
276
- err_cert = X509_STORE_CTX_get_current_cert(ctx);
277
- err_str = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
241
+ int depth = X509_STORE_CTX_get_error_depth(ctx);
242
+ X509* err_cert = X509_STORE_CTX_get_current_cert(ctx);
243
+ char* err_str = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
244
279
- mws_error(client->log, "verify error:num=%d:%s:depth=%d:%s", err,
245
+ nd_log(NDLS_DAEMON, NDLP_ERR, "verify error:num=%d:%s:depth=%d:%s", err,
246
X509_verify_cert_error_string(err), depth, err_str);
247
248
freez(err_str);
@@ -286,7 +252,7 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
252
client->ssl_flags & MQTT_WSS_SSL_ALLOW_SELF_SIGNED)
253
{
254
preverify_ok = 1;
289
- mws_error(client->log, "Self Signed Certificate Accepted as the connection was "
255
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Self Signed Certificate Accepted as the connection was "
256
"requested with MQTT_WSS_SSL_ALLOW_SELF_SIGNED");
257
}
258
@@ -300,16 +266,14 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
266
#define HTTP_HDR_TERMINATOR "\x0D\x0A\x0D\x0A"
267
#define HTTP_CODE_LEN 4
268
#define HTTP_REASON_MAX_LEN 512
303
-static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
269
+static int http_parse_reply(rbuf_t buf)
270
{
305
- char *ptr;
271
char http_code_s[4];
307
- int http_code;
272
int idx;
273
274
if (rbuf_memcmp_n(buf, PROXY_HTTP, strlen(PROXY_HTTP))) {
275
if (rbuf_memcmp_n(buf, PROXY_HTTP10, strlen(PROXY_HTTP10))) {
312
- mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
276
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy expected reply with \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
277
return 1;
278
}
279
}
@@ -317,39 +281,37 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
281
rbuf_bump_tail(buf, strlen(PROXY_HTTP));
282
283
if (!rbuf_pop(buf, http_code_s, 1) || http_code_s[0] != 0x20) {
320
- mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
284
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy missing space after \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
285
return 2;
286
}
287
288
if (!rbuf_pop(buf, http_code_s, HTTP_CODE_LEN)) {
325
- mws_error(client->log, "http_proxy missing HTTP code");
289
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy missing HTTP code");
290
return 3;
291
}
292
293
for (int i = 0; i < HTTP_CODE_LEN - 1; i++)
294
if (http_code_s[i] > 0x39 || http_code_s[i] < 0x30) {
331
- mws_error(client->log, "http_proxy HTTP code non numeric");
295
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy HTTP code non numeric");
296
return 4;
297
}
298
299
http_code_s[HTTP_CODE_LEN - 1] = 0;
336
- http_code = atoi(http_code_s);
300
+ int http_code = str2i(http_code_s);
301
302
// TODO check if we ever have more headers here
303
rbuf_find_bytes(buf, HTTP_ENDLINE, strlen(HTTP_ENDLINE), &idx);
304
if (idx >= HTTP_REASON_MAX_LEN) {
341
- mws_error(client->log, "http_proxy returned reason that is too long");
305
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy returned reason that is too long");
306
return 5;
307
}
308
309
if (http_code != 200) {
346
- ptr = mallocz(idx + 1);
347
- if (!ptr)
348
- return 6;
310
+ char *ptr = mallocz(idx + 1);
311
rbuf_pop(buf, ptr, idx);
312
ptr[idx] = 0;
313
352
- mws_error(client->log, "http_proxy returned error code %d \"%s\"", http_code, ptr);
314
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy returned error code %d \"%s\"", http_code, ptr);
315
freez(ptr);
316
return 7;
317
}/* else
@@ -362,52 +324,11 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
324
rbuf_bump_tail(buf, strlen(HTTP_HDR_TERMINATOR));
325
326
if (rbuf_bytes_available(buf)) {
365
- mws_error(client->log, "http_proxy unexpected trailing bytes after end of HTTP hdr");
327
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy unexpected trailing bytes after end of HTTP hdr");
328
return 8;
329
}
330
369
- mws_debug(client->log, "http_proxy CONNECT succeeded");
370
- return 0;
371
-}
372
-
373
-#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
374
-static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
375
-{
376
- EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
377
-
378
- if (ctx != NULL) {
379
- memset(ctx, 0, sizeof(*ctx));
380
- }
381
- return ctx;
382
-}
383
-static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
384
-{
385
- OPENSSL_free(ctx);
386
- return;
387
-}
388
-#endif
389
-
390
-inline static int base64_encode_helper(unsigned char *out, int *outl, const unsigned char *in, int in_len)
391
-{
392
- int len;
393
- unsigned char *str = out;
394
- EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
395
- EVP_EncodeInit(ctx);
396
- EVP_EncodeUpdate(ctx, str, outl, in, in_len);
397
- str += *outl;
398
- EVP_EncodeFinal(ctx, str, &len);
399
- *outl += len;
400
-
401
- str = out;
402
- while(*str) {
403
- if (*str != 0x0D && *str != 0x0A)
404
- *out++ = *str++;
405
- else
406
- str++;
407
- }
408
- *out = 0;
409
-
410
- EVP_ENCODE_CTX_free(ctx);
331
+ nd_log(NDLS_DAEMON, NDLP_DEBUG, "http_proxy CONNECT succeeded");
332
return 0;
333
}
334
@@ -418,13 +339,12 @@ static int http_proxy_connect(mqtt_wss_client client)
339
rbuf_t r_buf = rbuf_create(4096);
340
if (!r_buf)
341
return 1;
421
- char *r_buf_ptr;
342
size_t r_buf_linear_insert_capacity;
343
344
poll_fd.fd = client->sockfd;
345
poll_fd.events = POLLIN;
346
427
- r_buf_ptr = rbuf_get_linear_insert_range(r_buf, &r_buf_linear_insert_capacity);
347
+ char *r_buf_ptr = rbuf_get_linear_insert_range(r_buf, &r_buf_linear_insert_capacity);
348
snprintf(r_buf_ptr, r_buf_linear_insert_capacity,"%s %s:%d %s" HTTP_ENDLINE "Host: %s" HTTP_ENDLINE, PROXY_CONNECT,
349
client->target_host, client->target_port, PROXY_HTTP, client->target_host);
350
write(client->sockfd, r_buf_ptr, strlen(r_buf_ptr));
@@ -433,7 +353,7 @@ static int http_proxy_connect(mqtt_wss_client client)
353
size_t creds_plain_len = strlen(client->proxy_uname) + strlen(client->proxy_passwd) + 2;
354
char *creds_plain = mallocz(creds_plain_len);
355
if (!creds_plain) {
436
- mws_error(client->log, "OOM creds_plain");
356
+ nd_log(NDLS_DAEMON, NDLP_ERR, "OOM creds_plain");
357
rc = 6;
358
goto cleanup;
359
}
@@ -444,7 +364,7 @@ static int http_proxy_connect(mqtt_wss_client client)
364
char *creds_base64 = mallocz(creds_base64_len + 1);
365
if (!creds_base64) {
366
freez(creds_plain);
447
- mws_error(client->log, "OOM creds_base64");
367
+ nd_log(NDLS_DAEMON, NDLP_ERR, "OOM creds_base64");
368
rc = 6;
369
goto cleanup;
370
}
@@ -454,8 +374,7 @@ static int http_proxy_connect(mqtt_wss_client client)
374
*ptr++ = ':';
375
strcpy(ptr, client->proxy_passwd);
376
457
- int b64_len;
458
- base64_encode_helper((unsigned char*)creds_base64, &b64_len, (unsigned char*)creds_plain, strlen(creds_plain));
377
+ (void) netdata_base64_encode((unsigned char*)creds_base64, (unsigned char*)creds_plain, strlen(creds_plain));
378
freez(creds_plain);
379
380
r_buf_ptr = rbuf_get_linear_insert_range(r_buf, &r_buf_linear_insert_capacity);
@@ -470,13 +389,13 @@ static int http_proxy_connect(mqtt_wss_client client)
389
// or timeout
390
while ((rc = poll(&poll_fd, 1, 1000)) >= 0) {
391
if (!rc) {
473
- mws_error(client->log, "http_proxy timeout waiting reply from proxy server");
392
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy timeout waiting reply from proxy server");
393
rc = 2;
394
goto cleanup;
395
}
396
r_buf_ptr = rbuf_get_linear_insert_range(r_buf, &r_buf_linear_insert_capacity);
397
if (!r_buf_ptr) {
479
- mws_error(client->log, "http_proxy read ring buffer full");
398
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy read ring buffer full");
399
rc = 3;
400
goto cleanup;
401
}
@@ -484,20 +403,20 @@ static int http_proxy_connect(mqtt_wss_client client)
403
if (errno == EWOULDBLOCK || errno == EAGAIN) {
404
continue;
405
}
487
- mws_error(client->log, "http_proxy error reading from socket \"%s\"", strerror(errno));
406
+ nd_log(NDLS_DAEMON, NDLP_ERR, "http_proxy error reading from socket \"%s\"", strerror(errno));
407
rc = 4;
408
goto cleanup;
409
}
410
rbuf_bump_head(r_buf, rc);
411
if (rbuf_find_bytes(r_buf, HTTP_HDR_TERMINATOR, strlen(HTTP_HDR_TERMINATOR), &rc)) {
412
rc = 0;
494
- if (http_parse_reply(client, r_buf))
413
+ if (http_parse_reply(r_buf))
414
rc = 5;
415
416
goto cleanup;
417
}
418
}
500
- mws_error(client->log, "proxy negotiation poll error \"%s\"", strerror(errno));
419
+ nd_log(NDLS_DAEMON, NDLP_ERR, "proxy negotiation poll error \"%s\"", strerror(errno));
420
rc = 5;
421
cleanup:
422
rbuf_free(r_buf);
@@ -510,11 +429,11 @@ int mqtt_wss_connect(
429
int port,
430
struct mqtt_connect_params *mqtt_params,
431
int ssl_flags,
513
- struct mqtt_wss_proxy *proxy,
432
+ const struct mqtt_wss_proxy *proxy,
433
bool *fallback_ipv4)
434
{
435
if (!mqtt_params) {
517
- mws_error(client->log, "mqtt_params can't be null!");
436
+ nd_log(NDLS_DAEMON, NDLP_ERR, "mqtt_params can't be null!");
437
return -1;
438
}
439
@@ -571,7 +490,7 @@ int mqtt_wss_connect(
490
struct timeval timeout = { .tv_sec = 10, .tv_usec = 0 };
491
int fd = connect_to_this_ip46(IPPROTO_TCP, SOCK_STREAM, client->host, 0, port_str, &timeout, fallback_ipv4);
492
if (fd < 0) {
574
- mws_error(client->log, "Could not connect to remote endpoint \"%s\", port %d.\n", client->host, port);
493
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Could not connect to remote endpoint \"%s\", port %d.\n", client->host, port);
494
return -3;
495
}
496
@@ -586,12 +505,12 @@ int mqtt_wss_connect(
505
int flag = 1;
506
int result = setsockopt(client->sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
507
if (result < 0)
589
- mws_error(client->log, "Could not dissable NAGLE");
508
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Could not dissable NAGLE");
509
510
client->poll_fds[POLLFD_SOCKET].fd = client->sockfd;
511
512
if (fcntl(client->sockfd, F_SETFL, fcntl(client->sockfd, F_GETFL, 0) | O_NONBLOCK) == -1) {
594
- mws_error(client->log, "Error setting O_NONBLOCK to TCP socket. \"%s\"", strerror(errno));
513
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error setting O_NONBLOCK to TCP socket. \"%s\"", strerror(errno));
514
return -8;
515
}
516
@@ -607,7 +526,7 @@ int mqtt_wss_connect(
526
SSL_library_init();
527
#else
528
if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) != 1) {
610
- mws_error(client->log, "Failed to initialize SSL");
529
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to initialize SSL");
530
return -1;
531
};
532
#endif
@@ -624,7 +543,7 @@ int mqtt_wss_connect(
543
SSL_CTX_set_default_verify_paths(client->ssl_ctx);
544
SSL_CTX_set_verify(client->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, cert_verify_callback);
545
} else
627
- mws_error(client->log, "SSL Certificate checking completely disabled!!!");
546
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL Certificate checking completely disabled!!!");
547
548
#ifdef MQTT_WSS_DEBUG
549
if(client->ssl_ctx_keylog_cb)
@@ -634,7 +553,7 @@ int mqtt_wss_connect(
553
client->ssl = SSL_new(client->ssl_ctx);
554
if (!(client->ssl_flags & MQTT_WSS_SSL_DONT_CHECK_CERTS)) {
555
if (!SSL_set_ex_data(client->ssl, 0, client)) {
637
- mws_error(client->log, "Could not SSL_set_ex_data");
556
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Could not SSL_set_ex_data");
557
return -4;
558
}
559
}
@@ -642,27 +561,27 @@ int mqtt_wss_connect(
561
SSL_set_connect_state(client->ssl);
562
563
if (!SSL_set_tlsext_host_name(client->ssl, client->target_host)) {
645
- mws_error(client->log, "Error setting TLS SNI host");
564
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error setting TLS SNI host");
565
return -7;
566
}
567
568
result = SSL_connect(client->ssl);
569
if (result != -1 && result != 1) {
651
- mws_error(client->log, "SSL could not connect");
570
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL could not connect");
571
return -5;
572
}
573
574
if (result == -1) {
575
int ec = SSL_get_error(client->ssl, result);
576
if (ec != SSL_ERROR_WANT_READ && ec != SSL_ERROR_WANT_WRITE) {
658
- mws_error(client->log, "Failed to start SSL connection");
577
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to start SSL connection");
578
return -6;
579
}
580
}
581
582
client->mqtt_keepalive = (mqtt_params->keep_alive ? mqtt_params->keep_alive : 400);
583
665
- mws_info(client->log, "Going to connect using internal MQTT 5 implementation");
584
+ nd_log(NDLS_DAEMON, NDLP_INFO, "Going to connect using internal MQTT 5 implementation");
585
struct mqtt_auth_properties auth;
586
auth.client_id = (char*)mqtt_params->clientid;
587
auth.client_id_free = NULL;
@@ -682,7 +601,7 @@ int mqtt_wss_connect(
601
602
int ret = mqtt_ng_connect(client->mqtt, &auth, mqtt_params->will_msg ? &lwt : NULL, 1, client->mqtt_keepalive);
603
if (ret) {
685
- mws_error(client->log, "Error generating MQTT connect");
604
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error generating MQTT connect");
605
return 1;
606
}
607
@@ -691,7 +610,7 @@ int mqtt_wss_connect(
610
// wait till MQTT connection is established
611
while (!client->mqtt_connected) {
612
if(mqtt_wss_service(client, -1)) {
694
- mws_error(client->log, "Error connecting to MQTT WSS server \"%s\", port %d.", host, port);
613
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Error connecting to MQTT WSS server \"%s\", port %d.", host, port);
614
return 2;
615
}
616
}
@@ -704,14 +623,14 @@ int mqtt_wss_connect(
623
#define NSEC_PER_MSEC 1000000ULL
624
#define NSEC_PER_SEC 1000000000ULL
625
707
-static inline uint64_t boottime_usec(mqtt_wss_client client) {
626
+static uint64_t boottime_usec(void) {
627
struct timespec ts;
628
#if defined(__APPLE__) || defined(__FreeBSD__)
629
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
630
#else
631
if (clock_gettime(CLOCK_BOOTTIME, &ts) == -1) {
632
#endif
714
- mws_error(client->log, "clock_gettimte failed");
633
+ nd_log(NDLS_DAEMON, NDLP_ERR, "clock_gettimte failed");
634
return 0;
635
}
636
return (uint64_t)ts.tv_sec * USEC_PER_SEC + (ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC;
@@ -720,7 +639,7 @@ static inline uint64_t boottime_usec(mqtt_wss_client client) {
639
#define MWS_TIMED_OUT 1
640
#define MWS_ERROR 2
641
#define MWS_OK 0
723
-static inline const char *mqtt_wss_error_tos(int ec)
642
+static const char *mqtt_wss_error_tos(int ec)
643
{
644
switch(ec) {
645
case MWS_TIMED_OUT:
@@ -733,13 +652,12 @@ static inline const char *mqtt_wss_error_tos(int ec)
652
653
}
654
736
-static inline int mqtt_wss_service_all(mqtt_wss_client client, int timeout_ms)
655
+static int mqtt_wss_service_all(mqtt_wss_client client, int timeout_ms)
656
{
738
- uint64_t exit_by = boottime_usec(client) + (timeout_ms * NSEC_PER_MSEC);
739
- uint64_t now;
657
+ uint64_t exit_by = boottime_usec() + (timeout_ms * NSEC_PER_MSEC);
658
client->poll_fds[POLLFD_SOCKET].events |= POLLOUT; // TODO when entering mwtt_wss_service use out buffer size to arm POLLOUT
659
while (rbuf_bytes_available(client->ws_client->buf_write)) {
742
- now = boottime_usec(client);
660
+ const uint64_t now = boottime_usec();
661
if (now >= exit_by)
662
return MWS_TIMED_OUT;
663
if (mqtt_wss_service(client, exit_by - now))
@@ -750,15 +668,13 @@ static inline int mqtt_wss_service_all(mqtt_wss_client client, int timeout_ms)
668
669
void mqtt_wss_disconnect(mqtt_wss_client client, int timeout_ms)
670
{
753
- int ret;
754
-
671
// block application from sending more MQTT messages
672
client->mqtt_disconnecting = 1;
673
674
// send whatever was left at the time of calling this function
759
- ret = mqtt_wss_service_all(client, timeout_ms / 4);
675
+ int ret = mqtt_wss_service_all(client, timeout_ms / 4);
676
if(ret)
761
- mws_error(client->log,
677
+ nd_log(NDLS_DAEMON, NDLP_ERR,
678
"Error while trying to send all remaining data in an attempt "
679
"to gracefully disconnect! EC=%d Desc:\"%s\"",
680
ret,
@@ -770,7 +686,7 @@ void mqtt_wss_disconnect(mqtt_wss_client client, int timeout_ms)
686
687
ret = mqtt_wss_service_all(client, timeout_ms / 4);
688
if(ret)
773
- mws_error(client->log,
689
+ nd_log(NDLS_DAEMON, NDLP_ERR,
690
"Error while trying to send MQTT disconnect message in an attempt "
691
"to gracefully disconnect! EC=%d Desc:\"%s\"",
692
ret,
@@ -783,7 +699,7 @@ void mqtt_wss_disconnect(mqtt_wss_client client, int timeout_ms)
699
if(ret) {
700
// Some MQTT/WSS servers will close socket on receipt of MQTT disconnect and
701
// do not wait for WebSocket to be closed properly
786
- mws_warn(client->log,
702
+ nd_log(NDLS_DAEMON, NDLP_WARNING,
703
"Error while trying to send WebSocket disconnect message in an attempt "
704
"to gracefully disconnect! EC=%d Desc:\"%s\".",
705
ret,
@@ -798,22 +714,19 @@ void mqtt_wss_disconnect(mqtt_wss_client client, int timeout_ms)
714
client->sockfd = -1;
715
}
716
801
-static inline void mqtt_wss_wakeup(mqtt_wss_client client)
717
+static void mqtt_wss_wakeup(mqtt_wss_client client)
718
{
803
-#ifdef DEBUG_ULTRA_VERBOSE
804
- mws_debug(client->log, "mqtt_wss_wakup - forcing wake up of main loop");
805
-#endif
719
write(client->write_notif_pipe[PIPE_WRITE_END], " ", 1);
720
}
721
722
#define THROWAWAY_BUF_SIZE 32
723
char throwaway[THROWAWAY_BUF_SIZE];
811
-static inline void util_clear_pipe(int fd)
724
+static void util_clear_pipe(int fd)
725
{
726
(void)read(fd, throwaway, THROWAWAY_BUF_SIZE);
727
}
728
816
-static inline void set_socket_pollfds(mqtt_wss_client client, int ssl_ret) {
729
+static void set_socket_pollfds(mqtt_wss_client client, int ssl_ret) {
730
if (ssl_ret == SSL_ERROR_WANT_WRITE)
731
client->poll_fds[POLLFD_SOCKET].events |= POLLOUT;
732
if (ssl_ret == SSL_ERROR_WANT_READ)
@@ -824,7 +737,7 @@ static int handle_mqtt_internal(mqtt_wss_client client)
737
{
738
int rc = mqtt_ng_sync(client->mqtt);
739
if (rc) {
827
- mws_error(client->log, "mqtt_ng_sync returned %d != 0", rc);
740
+ nd_log(NDLS_DAEMON, NDLP_ERR, "mqtt_ng_sync returned %d != 0", rc);
741
client->mqtt_connected = 0;
742
return 1;
743
}
@@ -832,7 +745,7 @@ static int handle_mqtt_internal(mqtt_wss_client client)
745
}
746
747
#define SEC_TO_MSEC 1000
835
-static inline long long int t_till_next_keepalive_ms(mqtt_wss_client client)
748
+static long long int t_till_next_keepalive_ms(mqtt_wss_client client)
749
{
750
time_t last_send = mqtt_ng_last_send_time(client->mqtt);
751
long long int next_mqtt_keep_alive = (last_send * SEC_TO_MSEC)
@@ -841,10 +754,10 @@ static inline long long int t_till_next_keepalive_ms(mqtt_wss_client client)
754
}
755
756
#ifdef MQTT_WSS_CPUSTATS
844
-static inline uint64_t mqtt_wss_now_usec(mqtt_wss_client client) {
757
+static uint64_t mqtt_wss_now_usec(void) {
758
struct timespec ts;
759
if(clock_gettime(CLOCK_MONOTONIC, &ts) == -1) {
847
- mws_error(client->log, "clock_gettime(CLOCK_MONOTONIC, ×pec) failed.");
760
+ nd_log(NDLS_DAEMON, NDLP_ERR, "clock_gettime(CLOCK_MONOTONIC, ×pec) failed.");
761
return 0;
762
}
763
return (uint64_t)ts.tv_sec * USEC_PER_SEC + (ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC;
@@ -859,61 +772,39 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
772
int send_keepalive = 0;
773
774
#ifdef MQTT_WSS_CPUSTATS
862
- uint64_t t1,t2;
863
- t1 = mqtt_wss_now_usec(client);
864
-#endif
865
-
866
-#ifdef DEBUG_ULTRA_VERBOSE
867
- mws_debug(client->log, ">>>>> mqtt_wss_service <<<<<");
868
- mws_debug(client->log, "Waiting for events: %s%s%s",
869
- (client->poll_fds[POLLFD_SOCKET].events & POLLIN) ? "SOCKET_POLLIN " : "",
870
- (client->poll_fds[POLLFD_SOCKET].events & POLLOUT) ? "SOCKET_POLLOUT " : "",
871
- (client->poll_fds[POLLFD_PIPE].events & POLLIN) ? "PIPE_POLLIN" : "" );
775
+ uint64_t t2;
776
+ uint64_t t1 = mqtt_wss_now_usec();
777
#endif
778
779
// Check user requested TO doesn't interfere with MQTT keep alives
780
long long int till_next_keep_alive = t_till_next_keepalive_ms(client);
781
if (client->mqtt_connected && (timeout_ms < 0 || timeout_ms >= till_next_keep_alive)) {
877
- #ifdef DEBUG_ULTRA_VERBOSE
878
- mws_debug(client->log, "Shortening Timeout requested %d to %lld to ensure keep-alive can be sent", timeout_ms, till_next_keep_alive);
879
- #endif
782
timeout_ms = till_next_keep_alive;
783
send_keepalive = 1;
784
}
785
786
#ifdef MQTT_WSS_CPUSTATS
885
- t2 = mqtt_wss_now_usec(client);
787
+ t2 = mqtt_wss_now_usec();
788
client->stats.time_keepalive += t2 - t1;
789
#endif
790
791
if ((ret = poll(client->poll_fds, 2, timeout_ms >= 0 ? timeout_ms : -1)) < 0) {
792
if (errno == EINTR) {
891
- mws_warn(client->log, "poll interrupted by EINTR");
793
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "poll interrupted by EINTR");
794
return 0;
795
}
894
- mws_error(client->log, "poll error \"%s\"", strerror(errno));
796
+ nd_log(NDLS_DAEMON, NDLP_ERR, "poll error \"%s\"", strerror(errno));
797
return -2;
798
}
799
898
-#ifdef DEBUG_ULTRA_VERBOSE
899
- mws_debug(client->log, "Poll events happened: %s%s%s%s",
900
- (client->poll_fds[POLLFD_SOCKET].revents & POLLIN) ? "SOCKET_POLLIN " : "",
901
- (client->poll_fds[POLLFD_SOCKET].revents & POLLOUT) ? "SOCKET_POLLOUT " : "",
902
- (client->poll_fds[POLLFD_PIPE].revents & POLLIN) ? "PIPE_POLLIN " : "",
903
- (!ret) ? "POLL_TIMEOUT" : "");
904
-#endif
905
-
800
#ifdef MQTT_WSS_CPUSTATS
907
- t1 = mqtt_wss_now_usec(client);
801
+ t1 = mqtt_wss_now_usec();
802
#endif
803
804
if (ret == 0) {
805
if (send_keepalive) {
806
// otherwise we shortened the timeout ourselves to take care of
807
// MQTT keep alives
914
-#ifdef DEBUG_ULTRA_VERBOSE
915
- mws_debug(client->log, "Forcing MQTT Ping/keep-alive");
916
-#endif
808
mqtt_ng_ping(client->mqtt);
809
} else {
810
// if poll timed out and user requested timeout was being used
@@ -923,7 +814,7 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
814
}
815
816
#ifdef MQTT_WSS_CPUSTATS
926
- t2 = mqtt_wss_now_usec(client);
817
+ t2 = mqtt_wss_now_usec();
818
client->stats.time_keepalive += t2 - t1;
819
#endif
820
@@ -931,9 +822,6 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
822
823
if ((ptr = rbuf_get_linear_insert_range(client->ws_client->buf_read, &size))) {
824
if((ret = SSL_read(client->ssl, ptr, size)) > 0) {
934
-#ifdef DEBUG_ULTRA_VERBOSE
935
- mws_debug(client->log, "SSL_Read: Read %d.", ret);
936
-#endif
825
spinlock_lock(&client->stat_lock);
826
client->stats.bytes_rx += ret;
827
spinlock_unlock(&client->stat_lock);
@@ -941,22 +829,19 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
829
} else {
830
int errnobkp = errno;
831
ret = SSL_get_error(client->ssl, ret);
944
-#ifdef DEBUG_ULTRA_VERBOSE
945
- mws_debug(client->log, "Read Err: %s", util_openssl_ret_err(ret));
946
-#endif
832
set_socket_pollfds(client, ret);
833
if (ret != SSL_ERROR_WANT_READ &&
834
ret != SSL_ERROR_WANT_WRITE) {
950
- mws_error(client->log, "SSL_read error: %d %s", ret, util_openssl_ret_err(ret));
835
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL_read error: %d %s", ret, util_openssl_ret_err(ret));
836
if (ret == SSL_ERROR_SYSCALL)
952
- mws_error(client->log, "SSL_read SYSCALL errno: %d %s", errnobkp, strerror(errnobkp));
837
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL_read SYSCALL errno: %d %s", errnobkp, strerror(errnobkp));
838
return MQTT_WSS_ERR_CONN_DROP;
839
}
840
}
841
}
842
843
#ifdef MQTT_WSS_CPUSTATS
959
- t1 = mqtt_wss_now_usec(client);
844
+ t1 = mqtt_wss_now_usec();
845
client->stats.time_read_socket += t1 - t2;
846
#endif
847
@@ -964,18 +849,20 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
849
switch(ret) {
850
case WS_CLIENT_PROTOCOL_ERROR:
851
return MQTT_WSS_ERR_PROTO_WS;
852
+
853
case WS_CLIENT_NEED_MORE_BYTES:
968
-#ifdef DEBUG_ULTRA_VERBOSE
969
- mws_debug(client->log, "WSCLIENT WANT READ");
970
-#endif
854
client->poll_fds[POLLFD_SOCKET].events |= POLLIN;
855
break;
856
+
857
case WS_CLIENT_CONNECTION_CLOSED:
858
return MQTT_WSS_ERR_CONN_DROP;
859
+
860
+ default:
861
+ return MQTT_WSS_ERR_PROTO_WS;
862
}
863
864
#ifdef MQTT_WSS_CPUSTATS
978
- t2 = mqtt_wss_now_usec(client);
865
+ t2 = mqtt_wss_now_usec();
866
client->stats.time_process_websocket += t2 - t1;
867
#endif
868
@@ -990,18 +877,12 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
877
}
878
879
#ifdef MQTT_WSS_CPUSTATS
993
- t1 = mqtt_wss_now_usec(client);
880
+ t1 = mqtt_wss_now_usec();
881
client->stats.time_process_mqtt += t1 - t2;
882
#endif
883
884
if ((ptr = rbuf_get_linear_read_range(client->ws_client->buf_write, &size))) {
998
-#ifdef DEBUG_ULTRA_VERBOSE
999
- mws_debug(client->log, "Have data to write to SSL");
1000
-#endif
885
if ((ret = SSL_write(client->ssl, ptr, size)) > 0) {
1002
-#ifdef DEBUG_ULTRA_VERBOSE
1003
- mws_debug(client->log, "SSL_Write: Written %d of avail %d.", ret, size);
1004
-#endif
886
spinlock_lock(&client->stat_lock);
887
client->stats.bytes_tx += ret;
888
spinlock_unlock(&client->stat_lock);
@@ -1009,15 +890,12 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
890
} else {
891
int errnobkp = errno;
892
ret = SSL_get_error(client->ssl, ret);
1012
-#ifdef DEBUG_ULTRA_VERBOSE
1013
- mws_debug(client->log, "Write Err: %s", util_openssl_ret_err(ret));
1014
-#endif
893
set_socket_pollfds(client, ret);
894
if (ret != SSL_ERROR_WANT_READ &&
895
ret != SSL_ERROR_WANT_WRITE) {
1018
- mws_error(client->log, "SSL_write error: %d %s", ret, util_openssl_ret_err(ret));
896
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL_write error: %d %s", ret, util_openssl_ret_err(ret));
897
if (ret == SSL_ERROR_SYSCALL)
1020
- mws_error(client->log, "SSL_write SYSCALL errno: %d %s", errnobkp, strerror(errnobkp));
898
+ nd_log(NDLS_DAEMON, NDLP_ERR, "SSL_write SYSCALL errno: %d %s", errnobkp, strerror(errnobkp));
899
return MQTT_WSS_ERR_CONN_DROP;
900
}
901
}
@@ -1027,7 +905,7 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
905
util_clear_pipe(client->write_notif_pipe[PIPE_READ_END]);
906
907
#ifdef MQTT_WSS_CPUSTATS
1030
- t2 = mqtt_wss_now_usec(client);
908
+ t2 = mqtt_wss_now_usec();
909
client->stats.time_write_socket += t2 - t1;
910
#endif
911
@@ -1044,12 +922,12 @@ int mqtt_wss_publish5(mqtt_wss_client client,
922
uint16_t *packet_id)
923
{
924
if (client->mqtt_disconnecting) {
1047
- mws_error(client->log, "mqtt_wss is disconnecting can't publish");
925
+ nd_log(NDLS_DAEMON, NDLP_ERR, "mqtt_wss is disconnecting can't publish");
926
return 1;
927
}
928
929
if (!client->mqtt_connected) {
1052
- mws_error(client->log, "MQTT is offline. Can't send message.");
930
+ nd_log(NDLS_DAEMON, NDLP_ERR, "MQTT is offline. Can't send message.");
931
return 1;
932
}
933
uint8_t mqtt_flags = 0;
@@ -1060,7 +938,7 @@ int mqtt_wss_publish5(mqtt_wss_client client,
938
939
int rc = mqtt_ng_publish(client->mqtt, topic, topic_free, msg, msg_free, msg_len, mqtt_flags, packet_id);
940
if (rc == MQTT_NG_MSGGEN_MSG_TOO_BIG)
1063
- return MQTT_WSS_ERR_TOO_BIG_FOR_SERVER;
941
+ return MQTT_WSS_ERR_MSG_TOO_BIG;
942
943
mqtt_wss_wakeup(client);
944
@@ -1071,12 +949,12 @@ int mqtt_wss_subscribe(mqtt_wss_client client, char *topic, int max_qos_level)
949
{
950
(void)max_qos_level; //TODO now hardcoded
951
if (!client->mqtt_connected) {
1074
- mws_error(client->log, "MQTT is offline. Can't subscribe.");
952
+ nd_log(NDLS_DAEMON, NDLP_ERR, "MQTT is offline. Can't subscribe.");
953
return 1;
954
}
955
956
if (client->mqtt_disconnecting) {
1079
- mws_error(client->log, "mqtt_wss is disconnecting can't subscribe");
957
+ nd_log(NDLS_DAEMON, NDLP_ERR, "mqtt_wss is disconnecting can't subscribe");
958
return 1;
959
}
960
src/aclk/mqtt_websockets/mqtt_wss_client.h
+16
-31
@@ -3,49 +3,34 @@
3
#ifndef MQTT_WSS_CLIENT_H
4
#define MQTT_WSS_CLIENT_H
5
6
-#include "mqtt_wss_log.h"
6
#include "common_public.h"
7
9
-// All OK call me at your earliest convinience
10
-#define MQTT_WSS_OK 0
11
-/* All OK, poll timeout you requested when calling mqtt_wss_service expired - you might want to know if timeout
12
- * happened or we got some data or handle same as MQTT_WSS_OK
13
- */
14
-#define MQTT_WSS_OK_TO 1
15
-// Connection was closed by remote
16
-#define MQTT_WSS_ERR_CONN_DROP -1
17
-// Error in MQTT protocol (e.g. malformed packet)
18
-#define MQTT_WSS_ERR_PROTO_MQTT -2
19
-// Error in WebSocket protocol (e.g. malformed packet)
20
-#define MQTT_WSS_ERR_PROTO_WS -3
21
-
22
-#define MQTT_WSS_ERR_TX_BUF_TOO_SMALL -4
23
-#define MQTT_WSS_ERR_RX_BUF_TOO_SMALL -5
24
-
25
-#define MQTT_WSS_ERR_TOO_BIG_FOR_SERVER -6
26
-// if client was initialized with MQTT 3 but MQTT 5 feature
27
-// was requested by user of library
28
-#define MQTT_WSS_ERR_CANT_DO -8
8
+
9
+#define MQTT_WSS_OK 0 // All OK call me at your earliest convinience
10
+#define MQTT_WSS_OK_TO 1 // All OK, poll timeout you requested when calling mqtt_wss_service expired
11
+ //you might want to know if timeout
12
+ //happened or we got some data or handle same as MQTT_WSS_OK
13
+#define MQTT_WSS_ERR_CONN_DROP -1 // Connection was closed by remote
14
+#define MQTT_WSS_ERR_PROTO_MQTT -2 // Error in MQTT protocol (e.g. malformed packet)
15
+#define MQTT_WSS_ERR_PROTO_WS -3 // Error in WebSocket protocol (e.g. malformed packet)
16
+#define MQTT_WSS_ERR_MSG_TOO_BIG -6 // Message size too big for server
17
+#define MQTT_WSS_ERR_CANT_DO -8 // if client was initialized with MQTT 3 but MQTT 5 feature
18
+ // was requested by user of library
19
20
typedef struct mqtt_wss_client_struct *mqtt_wss_client;
21
22
typedef void (*msg_callback_fnc_t)(const char *topic, const void *msg, size_t msglen, int qos);
23
+
24
/* Creates new instance of MQTT over WSS. Doesn't start connection.
34
- * @param log_prefix this is prefix to be used when logging to discern between multiple
35
- * mqtt_wss instances. Can be NULL.
36
- * @param log_callback is function pointer to fnc to be called when mqtt_wss wants
37
- * to log. This allows plugging this library into your own logging system/solution.
38
- * If NULL STDOUT/STDERR will be used.
25
* @param msg_callback is function pointer to function which will be called
26
* when application level message arrives from broker (for subscribed topics).
27
* Can be NULL if you are not interested about incoming messages.
28
* @param puback_callback is function pointer to function to be called when QOS1 Publish
29
* is acknowledged by server
30
*/
45
-mqtt_wss_client mqtt_wss_new(const char *log_prefix,
46
- mqtt_wss_log_callback_t log_callback,
47
- msg_callback_fnc_t msg_callback,
48
- void (*puback_callback)(uint16_t packet_id));
31
+mqtt_wss_client mqtt_wss_new(
32
+ msg_callback_fnc_t msg_callback,
33
+ void (*puback_callback)(uint16_t packet_id));
34
35
void mqtt_wss_set_max_buf_size(mqtt_wss_client client, size_t size);
36
@@ -71,7 +56,7 @@ int mqtt_wss_connect(
56
int port,
57
struct mqtt_connect_params *mqtt_params,
58
int ssl_flags,
74
- struct mqtt_wss_proxy *proxy,
59
+ const struct mqtt_wss_proxy *proxy,
60
bool *fallback_ipv4);
61
int mqtt_wss_service(mqtt_wss_client client, int timeout_ms);
62
void mqtt_wss_disconnect(mqtt_wss_client client, int timeout_ms);
src/aclk/mqtt_websockets/mqtt_wss_log.c
deleted
-126
@@ -1,126 +0,0 @@
1
-// SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-#include "libnetdata/libnetdata.h"
4
-
5
-#include "mqtt_wss_log.h"
6
-
7
-struct mqtt_wss_log_ctx {
8
- mqtt_wss_log_callback_t extern_log_fnc;
9
- char *ctx_prefix;
10
- char *buffer;
11
- char *buffer_w_ptr;
12
- size_t buffer_bytes_avail;
13
-};
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 = callocz(1, sizeof(struct mqtt_wss_log_ctx));
25
- if(!ctx)
26
- return NULL;
27
-
28
- if(log_callback) {
29
- ctx->extern_log_fnc = log_callback;
30
- ctx->buffer = callocz(1, LOG_BUFFER_SIZE);
31
- if(!ctx->buffer)
32
- goto cleanup;
33
-
34
- ctx->buffer_w_ptr = ctx->buffer;
35
- if(ctx_prefix) {
36
- *(ctx->buffer_w_ptr++) = '[';
37
- strncpy(ctx->buffer_w_ptr, ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
38
- ctx->buffer_w_ptr += strnlen(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
39
- *(ctx->buffer_w_ptr++) = ']';
40
- }
41
- strcpy(ctx->buffer_w_ptr, LOG_CTX_PREFIX_SEV_STR);
42
- ctx->buffer_w_ptr += strlen(LOG_CTX_PREFIX_SEV_STR);
43
- // no term '\0' -> calloc is used
44
-
45
- ctx->buffer_bytes_avail = LOG_BUFFER_SIZE - strlen(ctx->buffer);
46
-
47
- return ctx;
48
- }
49
-
50
- if(ctx_prefix) {
51
- ctx->ctx_prefix = strndup(ctx_prefix, LOG_CTX_PREFIX_LIMIT_STR);
52
- if(!ctx->ctx_prefix)
53
- goto cleanup;
54
- }
55
-
56
- return ctx;
57
-
58
-cleanup:
59
- freez(ctx);
60
- return NULL;
61
-}
62
-
63
-void mqtt_wss_log_ctx_destroy(mqtt_wss_log_ctx_t ctx)
64
-{
65
- freez(ctx->ctx_prefix);
66
- freez(ctx->buffer);
67
- freez(ctx);
68
-}
69
-
70
-static inline char severity_to_c(int severity)
71
-{
72
- switch (severity) {
73
- case MQTT_WSS_LOG_FATAL:
74
- return 'F';
75
- case MQTT_WSS_LOG_ERROR:
76
- return 'E';
77
- case MQTT_WSS_LOG_WARN:
78
- return 'W';
79
- case MQTT_WSS_LOG_INFO:
80
- return 'I';
81
- case MQTT_WSS_LOG_DEBUG:
82
- return 'D';
83
- default:
84
- return '?';
85
- }
86
-}
87
-
88
-void mws_log(int severity, mqtt_wss_log_ctx_t ctx, const char *fmt, va_list args)
89
-{
90
- size_t size;
91
-
92
- if(ctx->extern_log_fnc) {
93
- size = vsnprintf(ctx->buffer_w_ptr, ctx->buffer_bytes_avail, fmt, args);
94
- *(ctx->buffer_w_ptr - 3) = severity_to_c(severity);
95
-
96
- ctx->extern_log_fnc(severity, ctx->buffer);
97
-
98
- if(size >= ctx->buffer_bytes_avail)
99
- mws_error(ctx, "Last message of this type was truncated! Consider what you log or increase LOG_BUFFER_SIZE if really needed.");
100
-
101
- return;
102
- }
103
-
104
- if(ctx->ctx_prefix)
105
- printf("[%s] ", ctx->ctx_prefix);
106
-
107
- printf("%c: ", severity_to_c(severity));
108
-
109
- vprintf(fmt, args);
110
- putchar('\n');
111
-}
112
-
113
-#define DEFINE_MWS_SEV_FNC(severity_fncname, severity) \
114
-void mws_ ## severity_fncname(mqtt_wss_log_ctx_t ctx, const char *fmt, ...) \
115
-{ \
116
- va_list args; \
117
- va_start(args, fmt); \
118
- mws_log(severity, ctx, fmt, args); \
119
- va_end(args); \
120
-}
121
-
122
-DEFINE_MWS_SEV_FNC(fatal, MQTT_WSS_LOG_FATAL)
123
-DEFINE_MWS_SEV_FNC(error, MQTT_WSS_LOG_ERROR)
124
-DEFINE_MWS_SEV_FNC(warn, MQTT_WSS_LOG_WARN )
125
-DEFINE_MWS_SEV_FNC(info, MQTT_WSS_LOG_INFO )
126
-DEFINE_MWS_SEV_FNC(debug, MQTT_WSS_LOG_DEBUG)
src/aclk/mqtt_websockets/mqtt_wss_log.h
deleted
-39
@@ -1,39 +0,0 @@
1
-// Copyright: SPDX-License-Identifier: GPL-3.0-only
2
-
3
-#ifndef MQTT_WSS_LOG_H
4
-#define MQTT_WSS_LOG_H
5
-
6
-typedef enum mqtt_wss_log_type {
7
- MQTT_WSS_LOG_DEBUG = 0x01,
8
- MQTT_WSS_LOG_INFO = 0x02,
9
- MQTT_WSS_LOG_WARN = 0x03,
10
- MQTT_WSS_LOG_ERROR = 0x81,
11
- MQTT_WSS_LOG_FATAL = 0x88
12
-} mqtt_wss_log_type_t;
13
-
14
-typedef void (*mqtt_wss_log_callback_t)(mqtt_wss_log_type_t, const char*);
15
-
16
-typedef struct mqtt_wss_log_ctx *mqtt_wss_log_ctx_t;
17
-
18
-/** Creates logging context with optional prefix and optional callback
19
- * @param ctx_prefix String to be prefixed to every log message.
20
- * This is useful if multiple clients are instantiated to be able to
21
- * know which one this message belongs to. Can be `NULL` for no prefix.
22
- * @param log_callback Callback to be called instead of logging to
23
- * `STDOUT` or `STDERR` (if debug enabled otherwise silent). Callback has to be
24
- * pointer to function of `void function(mqtt_wss_log_type_t, const char*)` type.
25
- * If `NULL` default will be used (silent or STDERR/STDOUT).
26
- * @return mqtt_wss_log_ctx_t or `NULL` on error */
27
-mqtt_wss_log_ctx_t mqtt_wss_log_ctx_create(const char *ctx_prefix, mqtt_wss_log_callback_t log_callback);
28
-
29
-/** Destroys logging context and cleans up the memory
30
- * @param ctx Context to destroy */
31
-void mqtt_wss_log_ctx_destroy(mqtt_wss_log_ctx_t ctx);
32
-
33
-void mws_fatal(mqtt_wss_log_ctx_t ctx, const char *fmt, ...);
34
-void mws_error(mqtt_wss_log_ctx_t ctx, const char *fmt, ...);
35
-void mws_warn (mqtt_wss_log_ctx_t ctx, const char *fmt, ...);
36
-void mws_info (mqtt_wss_log_ctx_t ctx, const char *fmt, ...);
37
-void mws_debug(mqtt_wss_log_ctx_t ctx, const char *fmt, ...);
38
-
39
-#endif /* MQTT_WSS_LOG_H */
src/aclk/mqtt_websockets/ws_client.c
+113
-134
@@ -5,78 +5,54 @@
5
#include "ws_client.h"
6
#include "common_internal.h"
7
8
-#define UNIT_LOG_PREFIX "ws_client: "
9
-#define FATAL(fmt, ...) mws_fatal(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
10
-#define ERROR(fmt, ...) mws_error(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
11
-#define WARN(fmt, ...) mws_warn (client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
12
-#define INFO(fmt, ...) mws_info (client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
13
-#define DEBUG(fmt, ...) mws_debug(client->log, UNIT_LOG_PREFIX fmt, ##__VA_ARGS__)
8
+#ifdef OS_WINDOWS
9
+#include <windows.h>
10
+#include <bcrypt.h> // For BCryptGenRandom
11
+#endif
12
+
13
+static uint32_t generate_random_32bit(void) {
14
+ uint32_t random_number = 0;
15
+
16
+ if (RAND_bytes((unsigned char *)&random_number, sizeof(random_number)) != 1) {
17
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to generate a random uint32 mask");
18
+ }
19
+
20
+ return random_number;
21
+}
22
23
const char *websocket_upgrage_hdr = "GET /mqtt HTTP/1.1\x0D\x0A"
24
"Host: %s\x0D\x0A"
25
"Upgrade: websocket\x0D\x0A"
26
"Connection: Upgrade\x0D\x0A"
27
"Sec-WebSocket-Key: %s\x0D\x0A"
20
- "Origin: http://example.com\x0D\x0A"
28
+ "Origin: \x0D\x0A"
29
"Sec-WebSocket-Protocol: mqtt\x0D\x0A"
30
"Sec-WebSocket-Version: 13\x0D\x0A\x0D\x0A";
31
32
const char *mqtt_protoid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
33
34
#define DEFAULT_RINGBUFFER_SIZE (1024*128)
27
-#define ENTROPY_SOURCE "/dev/urandom"
28
-ws_client *ws_client_new(size_t buf_size, char **host, mqtt_wss_log_ctx_t log)
29
-{
30
- ws_client *client;
35
36
+ws_client *ws_client_new(size_t buf_size, char **host)
37
+{
38
if(!host)
39
return NULL;
40
35
- client = callocz(1, sizeof(ws_client));
36
- if (!client)
37
- return NULL;
38
-
41
+ ws_client *client = callocz(1, sizeof(ws_client));
42
client->host = host;
40
- client->log = log;
41
-
43
client->buf_read = rbuf_create(buf_size ? buf_size : DEFAULT_RINGBUFFER_SIZE);
43
- if (!client->buf_read)
44
- goto cleanup;
45
-
44
client->buf_write = rbuf_create(buf_size ? buf_size : DEFAULT_RINGBUFFER_SIZE);
47
- if (!client->buf_write)
48
- goto cleanup_1;
49
-
45
client->buf_to_mqtt = rbuf_create(buf_size ? buf_size : DEFAULT_RINGBUFFER_SIZE);
51
- if (!client->buf_to_mqtt)
52
- goto cleanup_2;
53
-
54
- client->entropy_fd = open(ENTROPY_SOURCE, O_RDONLY | O_CLOEXEC);
55
- if (client->entropy_fd < 1) {
56
- ERROR("Error opening entropy source \"" ENTROPY_SOURCE "\". Reason: \"%s\"", strerror(errno));
57
- goto cleanup_3;
58
- }
46
47
return client;
61
-
62
-cleanup_3:
63
- rbuf_free(client->buf_to_mqtt);
64
-cleanup_2:
65
- rbuf_free(client->buf_write);
66
-cleanup_1:
67
- rbuf_free(client->buf_read);
68
-cleanup:
69
- freez(client);
70
- return NULL;
48
}
49
50
void ws_client_free_headers(ws_client *client)
51
{
52
struct http_header *ptr = client->hs.headers;
76
- struct http_header *tmp;
53
54
while (ptr) {
79
- tmp = ptr;
55
+ struct http_header *tmp = ptr;
56
ptr = ptr->next;
57
freez(tmp);
58
}
@@ -91,7 +67,6 @@ void ws_client_destroy(ws_client *client)
67
ws_client_free_headers(client);
68
freez(client->hs.nonce_reply);
69
freez(client->hs.http_reply_msg);
94
- close(client->entropy_fd);
70
rbuf_free(client->buf_read);
71
rbuf_free(client->buf_write);
72
rbuf_free(client->buf_to_mqtt);
@@ -120,7 +95,7 @@ void ws_client_reset(ws_client *client)
95
int ws_client_add_http_header(ws_client *client, struct http_header *hdr)
96
{
97
if (client->hs.hdr_count > MAX_HTTP_HDR_COUNT) {
123
- ERROR("Too many HTTP response header fields");
98
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Too many HTTP response header fields");
99
return -1;
100
}
101
@@ -135,7 +110,7 @@ int ws_client_add_http_header(ws_client *client, struct http_header *hdr)
110
return 0;
111
}
112
138
-int ws_client_want_write(ws_client *client)
113
+int ws_client_want_write(const ws_client *client)
114
{
115
return rbuf_bytes_available(client->buf_write);
116
}
@@ -144,78 +119,92 @@ int ws_client_want_write(ws_client *client)
119
#define TEMP_BUF_SIZE 4096
120
int ws_client_start_handshake(ws_client *client)
121
{
147
- nd_uuid_t nonce;
122
+ unsigned char nonce[WEBSOCKET_NONCE_SIZE];
123
char nonce_b64[256];
124
char second[TEMP_BUF_SIZE];
125
unsigned int md_len;
151
- unsigned char *digest;
126
+ unsigned char digest[EVP_MAX_MD_SIZE]; // EVP_MAX_MD_SIZE ensures enough space
127
EVP_MD_CTX *md_ctx;
128
const EVP_MD *md;
129
+ int rc = 1;
130
131
if(!client->host || !*client->host) {
156
- ERROR("Hostname has not been set. We should not be able to come here!");
132
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Hostname has not been set. We should not be able to come here!");
133
return 1;
134
}
135
160
- uuid_generate_random(nonce);
161
- EVP_EncodeBlock((unsigned char *)nonce_b64, (const unsigned char *)nonce, WEBSOCKET_NONCE_SIZE);
162
- snprintf(second, TEMP_BUF_SIZE, websocket_upgrage_hdr, *client->host, nonce_b64);
163
-
164
- if(rbuf_bytes_free(client->buf_write) < strlen(second)) {
165
- ERROR("Write buffer capacity too low.");
136
+ // Generate a random 16-byte nonce
137
+ if (!RAND_bytes(nonce, WEBSOCKET_NONCE_SIZE)) {
138
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to generate nonce");
139
return 1;
140
}
141
169
- rbuf_push(client->buf_write, second, strlen(second));
170
- client->state = WS_HANDSHAKE;
171
-
172
- //Calculating expected Sec-WebSocket-Accept reply
173
- snprintf(second, TEMP_BUF_SIZE, "%s%s", nonce_b64, mqtt_protoid);
174
-
142
+ // Initialize the digest context
143
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
144
md_ctx = EVP_MD_CTX_create();
145
#else
146
md_ctx = EVP_MD_CTX_new();
147
#endif
148
if (md_ctx == NULL) {
181
- ERROR("Cant create EVP_MD Context");
149
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Can't create EVP_MD context");
150
return 1;
151
}
152
185
- md = EVP_get_digestbyname("sha1");
153
+ md = EVP_sha1(); // Use SHA-1 for WebSocket handshake
154
if (!md) {
187
- ERROR("Unknown message digest");
188
- return 1;
155
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unknown message digest SHA-1");
156
+ goto exit_with_error;
157
}
158
191
- if ((digest = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha256()))) == NULL) {
192
- ERROR("Cant alloc digest");
193
- return 1;
159
+ (void) netdata_base64_encode((unsigned char *) nonce_b64, nonce, WEBSOCKET_NONCE_SIZE);
160
+
161
+ // Format and push the upgrade header to the write buffer
162
+ size_t bytes = snprintf(second, TEMP_BUF_SIZE, websocket_upgrage_hdr, *client->host, nonce_b64);
163
+ if(rbuf_bytes_free(client->buf_write) < bytes) {
164
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Write buffer capacity too low.");
165
+ goto exit_with_error;
166
+ }
167
+ rbuf_push(client->buf_write, second, bytes);
168
+
169
+ client->state = WS_HANDSHAKE;
170
+
171
+ // Create the expected Sec-WebSocket-Accept value
172
+ bytes = snprintf(second, TEMP_BUF_SIZE, "%s%s", nonce_b64, mqtt_protoid);
173
+
174
+ if (!EVP_DigestInit_ex(md_ctx, md, NULL)) {
175
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to initialize digest context");
176
+ goto exit_with_error;
177
+ }
178
+
179
+ if (!EVP_DigestUpdate(md_ctx, second, bytes)) {
180
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to update digest");
181
+ goto exit_with_error;
182
}
183
196
- EVP_DigestInit_ex(md_ctx, md, NULL);
197
- EVP_DigestUpdate(md_ctx, second, strlen(second));
198
- EVP_DigestFinal_ex(md_ctx, digest, &md_len);
184
+ if (!EVP_DigestFinal_ex(md_ctx, digest, &md_len)) {
185
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to finalize digest");
186
+ goto exit_with_error;
187
+ }
188
200
- EVP_EncodeBlock((unsigned char *)nonce_b64, digest, (int) md_len);
189
+ (void) netdata_base64_encode((unsigned char *) nonce_b64, digest, md_len);
190
191
freez(client->hs.nonce_reply);
192
client->hs.nonce_reply = strdupz(nonce_b64);
193
+ rc = 0;
194
205
- OPENSSL_free(digest);
206
-
195
+exit_with_error:
196
#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110)
197
EVP_MD_CTX_destroy(md_ctx);
198
#else
199
EVP_MD_CTX_free(md_ctx);
200
#endif
201
213
- return 0;
202
+ return rc;
203
}
204
205
#define BUF_READ_MEMCMP_CONST(const, err) \
206
if (rbuf_memcmp_n(client->buf_read, const, strlen(const))) { \
218
- ERROR(err); \
207
+ nd_log(NDLS_DAEMON, NDLP_ERR, err); \
208
rbuf_flush(client->buf_read); \
209
return WS_CLIENT_PROTOCOL_ERROR; \
210
}
@@ -241,7 +230,7 @@ int ws_client_start_handshake(ws_client *client)
230
231
#define HTTP_HDR_LINE_CHECK_LIMIT(x) \
232
if ((x) >= MAX_HTTP_LINE_LENGTH) { \
244
- ERROR("HTTP line received is too long. Maximum is %d", MAX_HTTP_LINE_LENGTH); \
233
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP line received is too long. Maximum is %d", MAX_HTTP_LINE_LENGTH); \
234
return WS_CLIENT_PROTOCOL_ERROR; \
235
}
236
@@ -264,13 +253,13 @@ int ws_client_parse_handshake_resp(ws_client *client)
253
BUF_READ_CHECK_AT_LEAST(HTTP_SC_LENGTH); // "XXX " http return code
254
rbuf_pop(client->buf_read, buf, HTTP_SC_LENGTH);
255
if (buf[HTTP_SC_LENGTH - 1] != 0x20) {
267
- ERROR("HTTP status code received is not terminated by space (0x20)");
256
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP status code received is not terminated by space (0x20)");
257
return WS_CLIENT_PROTOCOL_ERROR;
258
}
259
buf[HTTP_SC_LENGTH - 1] = 0;
260
client->hs.http_code = atoi(buf);
261
if (client->hs.http_code < 100 || client->hs.http_code >= 600) {
273
- ERROR("HTTP status code received not in valid range 100-600");
262
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP status code received not in valid range 100-600");
263
return WS_CLIENT_PROTOCOL_ERROR;
264
}
265
client->hs.hdr_state = WS_HDR_ENDLINE;
@@ -309,16 +298,16 @@ int ws_client_parse_handshake_resp(ws_client *client)
298
299
ptr = rbuf_find_bytes(client->buf_read, HTTP_HDR_SEPARATOR, strlen(HTTP_HDR_SEPARATOR), &idx_sep);
300
if (!ptr || idx_sep > idx_crlf) {
312
- ERROR("Expected HTTP hdr field key/value separator \": \" before endline in non empty HTTP header line");
301
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Expected HTTP hdr field key/value separator \": \" before endline in non empty HTTP header line");
302
return WS_CLIENT_PROTOCOL_ERROR;
303
}
304
if (idx_crlf == idx_sep + (int)strlen(HTTP_HDR_SEPARATOR)) {
316
- ERROR("HTTP Header value cannot be empty");
305
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP Header value cannot be empty");
306
return WS_CLIENT_PROTOCOL_ERROR;
307
}
308
309
if (idx_sep > HTTP_HEADER_NAME_MAX_LEN) {
321
- ERROR("HTTP header too long (%d)", idx_sep);
310
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP header too long (%d)", idx_sep);
311
return WS_CLIENT_PROTOCOL_ERROR;
312
}
313
@@ -326,23 +315,21 @@ int ws_client_parse_handshake_resp(ws_client *client)
315
hdr->key = ((char*)hdr) + sizeof(struct http_header);
316
hdr->value = hdr->key + idx_sep + 1;
317
329
- bytes = rbuf_pop(client->buf_read, hdr->key, idx_sep);
318
+ rbuf_pop(client->buf_read, hdr->key, idx_sep);
319
rbuf_bump_tail(client->buf_read, strlen(HTTP_HDR_SEPARATOR));
320
332
- bytes = rbuf_pop(client->buf_read, hdr->value, idx_crlf - idx_sep - strlen(HTTP_HDR_SEPARATOR));
321
+ rbuf_pop(client->buf_read, hdr->value, idx_crlf - idx_sep - strlen(HTTP_HDR_SEPARATOR));
322
rbuf_bump_tail(client->buf_read, strlen(WS_HTTP_NEWLINE));
323
324
for (int i = 0; hdr->key[i]; i++)
325
hdr->key[i] = tolower(hdr->key[i]);
326
338
-// DEBUG("HTTP header \"%s\" received. Value \"%s\"", hdr->key, hdr->value);
339
-
327
if (ws_client_add_http_header(client, hdr))
328
return WS_CLIENT_PROTOCOL_ERROR;
329
330
if (!strcmp(hdr->key, WS_CONN_ACCEPT)) {
331
if (strcmp(client->hs.nonce_reply, hdr->value)) {
345
- ERROR("Received NONCE \"%s\" does not match expected nonce of \"%s\"", hdr->value, client->hs.nonce_reply);
332
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Received NONCE \"%s\" does not match expected nonce of \"%s\"", hdr->value, client->hs.nonce_reply);
333
return WS_CLIENT_PROTOCOL_ERROR;
334
}
335
client->hs.nonce_matched = 1;
@@ -352,21 +339,21 @@ int ws_client_parse_handshake_resp(ws_client *client)
339
340
case WS_HDR_PARSE_DONE:
341
if (!client->hs.nonce_matched) {
355
- ERROR("Missing " WS_CONN_ACCEPT " header");
342
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Missing " WS_CONN_ACCEPT " header");
343
return WS_CLIENT_PROTOCOL_ERROR;
344
}
345
if (client->hs.http_code != 101) {
359
- ERROR("HTTP return code not 101. Received %d with msg \"%s\".", client->hs.http_code, client->hs.http_reply_msg);
346
+ nd_log(NDLS_DAEMON, NDLP_ERR, "HTTP return code not 101. Received %d with msg \"%s\".", client->hs.http_code, client->hs.http_reply_msg);
347
return WS_CLIENT_PROTOCOL_ERROR;
348
}
349
350
client->state = WS_ESTABLISHED;
351
client->hs.hdr_state = WS_HDR_ALL_DONE;
365
- INFO("Websocket Connection Accepted By Server");
352
+ nd_log(NDLS_DAEMON, NDLP_INFO, "Websocket Connection Accepted By Server");
353
return WS_CLIENT_PARSING_DONE;
354
355
case WS_HDR_ALL_DONE:
369
- FATAL("This is error we should never come here!");
356
+ nd_log(NDLS_DAEMON, NDLP_CRIT, "This is error we should never come here!");
357
return WS_CLIENT_PROTOCOL_ERROR;
358
}
359
return 0;
@@ -376,7 +363,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
363
#define WS_FINAL_FRAG BYTE_MSB
364
#define WS_PAYLOAD_MASKED BYTE_MSB
365
379
-static inline size_t get_ws_hdr_size(size_t payload_size)
366
+static size_t get_ws_hdr_size(size_t payload_size)
367
{
368
size_t hdr_len = 2 + 4 /*mask*/;
369
if(payload_size > 125)
@@ -387,7 +374,7 @@ static inline size_t get_ws_hdr_size(size_t payload_size)
374
}
375
376
#define MAX_POSSIBLE_HDR_LEN 14
390
-int ws_client_send(ws_client *client, enum websocket_opcode frame_type, const char *data, size_t size)
377
+int ws_client_send(const ws_client *client, enum websocket_opcode frame_type, const char *data, size_t size)
378
{
379
// TODO maybe? implement fragmenting, it is not necessary though
380
// as both tested MQTT brokers have no reuirement of one MQTT envelope
@@ -395,24 +382,16 @@ int ws_client_send(ws_client *client, enum websocket_opcode frame_type, const ch
382
// one big MQTT message as single fragmented WebSocket envelope
383
char hdr[MAX_POSSIBLE_HDR_LEN];
384
char *ptr = hdr;
398
- char *mask;
385
int size_written = 0;
386
size_t j = 0;
387
388
size_t w_buff_free = rbuf_bytes_free(client->buf_write);
389
size_t hdr_len = get_ws_hdr_size(size);
390
405
- if (w_buff_free < hdr_len * 2) {
406
-#ifdef DEBUG_ULTRA_VERBOSE
407
- DEBUG("Write buffer full. Can't write requested %d size.", size);
408
-#endif
391
+ if (w_buff_free < hdr_len * 2)
392
return 0;
410
- }
393
394
if (w_buff_free < (hdr_len + size)) {
413
-#ifdef DEBUG_ULTRA_VERBOSE
414
- DEBUG("Can't write whole MQTT packet of %d bytes into the buffer. Will do partial send of %d.", size, w_buff_free - hdr_len);
415
-#endif
395
size = w_buff_free - hdr_len;
396
hdr_len = get_ws_hdr_size(size);
397
// the actual needed header size might decrease if we cut number of bytes
@@ -438,12 +417,14 @@ int ws_client_send(ws_client *client, enum websocket_opcode frame_type, const ch
417
ptr += sizeof(be);
418
} else
419
*ptr++ |= size;
441
-
442
- mask = ptr;
443
- if (read(client->entropy_fd, mask, sizeof(uint32_t)) < (ssize_t)sizeof(uint32_t)) {
444
- ERROR("Unable to get mask from \"" ENTROPY_SOURCE "\"");
420
+
421
+ char *mask = ptr;
422
+ uint32_t mask32 = generate_random_32bit();
423
+ if (!mask32) {
424
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unable to get mask to XOR websocket payload");
425
return -2;
426
}
427
+ memcpy(mask, &mask32, sizeof(mask32));
428
429
rbuf_push(client->buf_write, hdr, hdr_len);
430
@@ -469,7 +450,7 @@ int ws_client_send(ws_client *client, enum websocket_opcode frame_type, const ch
450
return size_written;
451
}
452
472
-static int check_opcode(ws_client *client,enum websocket_opcode oc)
453
+static int check_opcode(enum websocket_opcode oc)
454
{
455
switch(oc) {
456
case WS_OP_BINARY_FRAME:
@@ -477,34 +458,34 @@ static int check_opcode(ws_client *client,enum websocket_opcode oc)
458
case WS_OP_PING:
459
return 0;
460
case WS_OP_CONTINUATION_FRAME:
480
- FATAL("WS_OP_CONTINUATION_FRAME NOT IMPLEMENTED YET!!!!");
461
+ nd_log(NDLS_DAEMON, NDLP_ERR, "WS_OP_CONTINUATION_FRAME NOT IMPLEMENTED YET!!!!");
462
return 0;
463
case WS_OP_TEXT_FRAME:
483
- FATAL("WS_OP_TEXT_FRAME NOT IMPLEMENTED YET!!!!");
464
+ nd_log(NDLS_DAEMON, NDLP_ERR, "WS_OP_TEXT_FRAME NOT IMPLEMENTED YET!!!!");
465
return 0;
466
case WS_OP_PONG:
486
- FATAL("WS_OP_PONG NOT IMPLEMENTED YET!!!!");
467
+ nd_log(NDLS_DAEMON, NDLP_ERR, "WS_OP_PONG NOT IMPLEMENTED YET!!!!");
468
return 0;
469
default:
470
return WS_CLIENT_PROTOCOL_ERROR;
471
}
472
}
473
493
-static inline void ws_client_rx_post_hdr_state(ws_client *client)
474
+static void ws_client_rx_post_hdr_state(ws_client *client)
475
{
476
switch(client->rx.opcode) {
477
case WS_OP_BINARY_FRAME:
478
client->rx.parse_state = WS_PAYLOAD_DATA;
498
- return;
479
+ break;
480
case WS_OP_CONNECTION_CLOSE:
481
client->rx.parse_state = WS_PAYLOAD_CONNECTION_CLOSE;
501
- return;
482
+ break;
483
case WS_OP_PING:
484
client->rx.parse_state = WS_PAYLOAD_PING_REQ_PAYLOAD;
504
- return;
485
+ break;
486
default:
487
client->rx.parse_state = WS_PAYLOAD_SKIP_UNKNOWN_PAYLOAD;
507
- return;
488
+ break;
489
}
490
}
491
@@ -520,15 +501,15 @@ int ws_client_process_rx_ws(ws_client *client)
501
client->rx.opcode = buf[0] & (char)~BYTE_MSB;
502
503
if (!(buf[0] & (char)~WS_FINAL_FRAG)) {
523
- ERROR("Not supporting fragmented messages yet!");
504
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Not supporting fragmented messages yet!");
505
return WS_CLIENT_PROTOCOL_ERROR;
506
}
507
527
- if (check_opcode(client, client->rx.opcode) == WS_CLIENT_PROTOCOL_ERROR)
508
+ if (check_opcode(client->rx.opcode) == WS_CLIENT_PROTOCOL_ERROR)
509
return WS_CLIENT_PROTOCOL_ERROR;
510
511
if (buf[1] & (char)WS_PAYLOAD_MASKED) {
531
- ERROR("Mask is not allowed in Server->Client Websocket direction.");
512
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Mask is not allowed in Server->Client Websocket direction.");
513
return WS_CLIENT_PROTOCOL_ERROR;
514
}
515
@@ -563,12 +544,8 @@ int ws_client_process_rx_ws(ws_client *client)
544
if (!rbuf_bytes_available(client->buf_read))
545
return WS_CLIENT_NEED_MORE_BYTES;
546
char *insert = rbuf_get_linear_insert_range(client->buf_to_mqtt, &size);
566
- if (!insert) {
567
-#ifdef DEBUG_ULTRA_VERBOSE
568
- DEBUG("BUFFER TOO FULL. Avail %d req %d", (int)size, (int)remaining);
569
-#endif
547
+ if (!insert)
548
return WS_CLIENT_BUFFER_FULL;
571
- }
549
size = (size > remaining) ? remaining : size;
550
size = rbuf_pop(client->buf_read, insert, size);
551
rbuf_bump_head(client->buf_to_mqtt, size);
@@ -582,11 +559,11 @@ int ws_client_process_rx_ws(ws_client *client)
559
// b) 2byte reason code
560
// c) 2byte reason code followed by message
561
if (client->rx.payload_length == 1) {
585
- ERROR("WebScoket CONNECTION_CLOSE can't have payload of size 1");
562
+ nd_log(NDLS_DAEMON, NDLP_ERR, "WebScoket CONNECTION_CLOSE can't have payload of size 1");
563
return WS_CLIENT_PROTOCOL_ERROR;
564
}
565
if (!client->rx.payload_length) {
589
- INFO("WebSocket server closed the connection without giving reason.");
566
+ nd_log(NDLS_DAEMON, NDLP_INFO, "WebSocket server closed the connection without giving reason.");
567
client->rx.parse_state = WS_PACKET_DONE;
568
break;
569
}
@@ -600,7 +577,7 @@ int ws_client_process_rx_ws(ws_client *client)
577
client->rx.payload_processed += sizeof(uint16_t);
578
579
if(client->rx.payload_processed == client->rx.payload_length) {
603
- INFO("WebSocket server closed the connection with EC=%d. Without message.",
580
+ nd_log(NDLS_DAEMON, NDLP_INFO, "WebSocket server closed the connection with EC=%d. Without message.",
581
client->rx.specific_data.op_close.ec);
582
client->rx.parse_state = WS_PACKET_DONE;
583
break;
@@ -619,7 +596,7 @@ int ws_client_process_rx_ws(ws_client *client)
596
client->rx.payload_length - client->rx.payload_processed);
597
}
598
client->rx.specific_data.op_close.reason[client->rx.payload_length] = 0;
622
- INFO("WebSocket server closed the connection with EC=%d and reason \"%s\"",
599
+ nd_log(NDLS_DAEMON, NDLP_INFO, "WebSocket server closed the connection with EC=%d and reason \"%s\"",
600
client->rx.specific_data.op_close.ec,
601
client->rx.specific_data.op_close.reason);
602
freez(client->rx.specific_data.op_close.reason);
@@ -628,14 +605,14 @@ int ws_client_process_rx_ws(ws_client *client)
605
break;
606
case WS_PAYLOAD_SKIP_UNKNOWN_PAYLOAD:
607
BUF_READ_CHECK_AT_LEAST(client->rx.payload_length);
631
- WARN("Skipping Websocket Packet of unsupported/unknown type");
608
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "Skipping Websocket Packet of unsupported/unknown type");
609
if (client->rx.payload_length)
610
rbuf_bump_tail(client->buf_read, client->rx.payload_length);
611
client->rx.parse_state = WS_PACKET_DONE;
612
return WS_CLIENT_PARSING_DONE;
613
case WS_PAYLOAD_PING_REQ_PAYLOAD:
614
if (client->rx.payload_length > rbuf_get_capacity(client->buf_read) / 2) {
638
- ERROR("Ping arrived with payload which is too big!");
615
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Ping arrived with payload which is too big!");
616
return WS_CLIENT_INTERNAL_ERROR;
617
}
618
BUF_READ_CHECK_AT_LEAST(client->rx.payload_length);
@@ -645,7 +622,7 @@ int ws_client_process_rx_ws(ws_client *client)
622
// then attempt to send as soon as buffer space clears up
623
size = ws_client_send(client, WS_OP_PONG, client->rx.specific_data.ping_msg, client->rx.payload_length);
624
if (size != client->rx.payload_length) {
648
- ERROR("Unable to send the PONG as one packet back. Closing connection.");
625
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unable to send the PONG as one packet back. Closing connection.");
626
return WS_CLIENT_PROTOCOL_ERROR;
627
}
628
client->rx.parse_state = WS_PACKET_DONE;
@@ -657,7 +634,7 @@ int ws_client_process_rx_ws(ws_client *client)
634
return WS_CLIENT_CONNECTION_CLOSED;
635
return WS_CLIENT_PARSING_DONE;
636
default:
660
- FATAL("Unknown parse state");
637
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Unknown parse state");
638
return WS_CLIENT_INTERNAL_ERROR;
639
}
640
return 0;
@@ -690,6 +667,8 @@ int ws_client_process(ws_client *client)
667
case WS_CLIENT_CONNECTION_CLOSED:
668
client->state = WS_CONN_CLOSED_GRACEFUL;
669
break;
670
+ default:
671
+ break;
672
}
673
// if ret == 0 we can continue parsing
674
// if ret == WS_CLIENT_PARSING_DONE we processed
@@ -698,13 +677,13 @@ int ws_client_process(ws_client *client)
677
} while (!ret || ret == WS_CLIENT_PARSING_DONE);
678
break;
679
case WS_ERROR:
701
- ERROR("ws_client is in error state. Restart the connection!");
680
+ nd_log(NDLS_DAEMON, NDLP_ERR, "ws_client is in error state. Restart the connection!");
681
return WS_CLIENT_PROTOCOL_ERROR;
682
case WS_CONN_CLOSED_GRACEFUL:
704
- ERROR("Connection has been gracefully closed. Calling this is useless (and probably bug) until you reconnect again.");
683
+ nd_log(NDLS_DAEMON, NDLP_ERR, "Connection has been gracefully closed. Calling this is useless (and probably bug) until you reconnect again.");
684
return WS_CLIENT_CONNECTION_CLOSED;
685
default:
707
- FATAL("Unknown connection state! Probably memory corruption.");
686
+ nd_log(NDLS_DAEMON, NDLP_CRIT, "Unknown connection state! Probably memory corruption.");
687
return WS_CLIENT_INTERNAL_ERROR;
688
}
689
return ret;
src/aclk/mqtt_websockets/ws_client.h
+3
-8
@@ -3,8 +3,6 @@
3
#ifndef WS_CLIENT_H
4
#define WS_CLIENT_H
5
6
-#include "mqtt_wss_log.h"
7
-
6
#define WS_CLIENT_NEED_MORE_BYTES 0x10
7
#define WS_CLIENT_PARSING_DONE 0x11
8
#define WS_CLIENT_CONNECTION_CLOSED 0x12
@@ -94,23 +92,20 @@ typedef struct websocket_client {
92
// memory usage and remove one more memcpy buf_read->buf_to_mqtt
93
rbuf_t buf_to_mqtt; // RAW data for MQTT lib
94
97
- int entropy_fd;
98
-
95
// careful host is borrowed, don't free
96
char **host;
101
- mqtt_wss_log_ctx_t log;
97
} ws_client;
98
104
-ws_client *ws_client_new(size_t buf_size, char **host, mqtt_wss_log_ctx_t log);
99
+ws_client *ws_client_new(size_t buf_size, char **host);
100
void ws_client_destroy(ws_client *client);
101
void ws_client_reset(ws_client *client);
102
103
int ws_client_start_handshake(ws_client *client);
104
110
-int ws_client_want_write(ws_client *client);
105
+int ws_client_want_write(const ws_client *client);
106
107
int ws_client_process(ws_client *client);
108
114
-int ws_client_send(ws_client *client, enum websocket_opcode frame_type, const char *data, size_t size);
109
+int ws_client_send(const ws_client *client, enum websocket_opcode frame_type, const char *data, size_t size);
110
111
#endif /* WS_CLIENT_H */
src/libnetdata/c_rhash/c_rhash.c
-3
@@ -8,9 +8,6 @@ c_rhash c_rhash_new(size_t bin_count) {
8
bin_count = 1000;
9
10
c_rhash hash = callocz(1, sizeof(struct c_rhash_s) + (bin_count * sizeof(struct bin_ll*)) );
11
- if (hash == NULL)
12
- return NULL;
13
-
11
hash->bin_count = bin_count;
12
hash->bins = (c_rhash_bin *)((char*)hash + sizeof(struct c_rhash_s));
13
src/libnetdata/libnetdata.c
+85
-44
@@ -1570,52 +1570,93 @@ bool rrdr_relative_window_to_absolute_query(time_t *after, time_t *before, time_
1570
return (absolute_period_requested != 1);
1571
}
1572
1573
-int netdata_base64_decode(const char *encoded, char *decoded, size_t decoded_size) {
1574
- static const unsigned char base64_table[256] = {
1575
- ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
1576
- ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
1577
- ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
1578
- ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31,
1579
- ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
1580
- ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
1581
- ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55,
1582
- ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63,
1583
- [0 ... '+' - 1] = 255,
1584
- ['+' + 1 ... '/' - 1] = 255,
1585
- ['9' + 1 ... 'A' - 1] = 255,
1586
- ['Z' + 1 ... 'a' - 1] = 255,
1587
- ['z' + 1 ... 255] = 255
1588
- };
1573
1590
- size_t count = 0;
1591
- unsigned int tmp = 0;
1592
- int i, bit;
1593
-
1594
- if (decoded_size < 1)
1595
- return 0; // Buffer size must be at least 1 for null termination
1596
-
1597
- for (i = 0, bit = 0; encoded[i]; i++) {
1598
- unsigned char value = base64_table[(unsigned char)encoded[i]];
1599
- if (value > 63)
1600
- return -1; // Invalid character in input
1601
-
1602
- tmp = tmp << 6 | value;
1603
- if (++bit == 4) {
1604
- if (count + 3 >= decoded_size) break; // Stop decoding if buffer is full
1605
- decoded[count++] = (tmp >> 16) & 0xFF;
1606
- decoded[count++] = (tmp >> 8) & 0xFF;
1607
- decoded[count++] = tmp & 0xFF;
1608
- tmp = 0;
1609
- bit = 0;
1610
- }
1611
- }
1574
+#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
1575
+static inline EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
1576
+{
1577
+ EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
1578
1613
- if (bit > 0 && count + 1 < decoded_size) {
1614
- tmp <<= 6 * (4 - bit);
1615
- if (bit > 2 && count + 1 < decoded_size) decoded[count++] = (tmp >> 16) & 0xFF;
1616
- if (bit > 3 && count + 1 < decoded_size) decoded[count++] = (tmp >> 8) & 0xFF;
1579
+ if (ctx != NULL) {
1580
+ memset(ctx, 0, sizeof(*ctx));
1581
}
1582
+ return ctx;
1583
+}
1584
+
1585
+static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
1586
+{
1587
+ OPENSSL_free(ctx);
1588
+}
1589
+#endif
1590
1619
- decoded[count] = '\0'; // Null terminate the output string
1620
- return count;
1591
+int netdata_base64_decode(unsigned char *out, const unsigned char *in, const int in_len)
1592
+{
1593
+ int outl;
1594
+ unsigned char remaining_data[256];
1595
+
1596
+ EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
1597
+ EVP_DecodeInit(ctx);
1598
+ EVP_DecodeUpdate(ctx, out, &outl, in, in_len);
1599
+ int remainder = 0;
1600
+ EVP_DecodeFinal(ctx, remaining_data, &remainder);
1601
+ EVP_ENCODE_CTX_free(ctx);
1602
+ if (remainder)
1603
+ return -1;
1604
+
1605
+ return outl;
1606
}
1607
+
1608
+int netdata_base64_encode(unsigned char *encoded, const unsigned char *input, size_t input_size)
1609
+{
1610
+ return EVP_EncodeBlock(encoded, input, input_size);
1611
+}
1612
+
1613
+// Keep internal implementation
1614
+// int netdata_base64_decode_internal(const char *encoded, char *decoded, size_t decoded_size) {
1615
+// static const unsigned char base64_table[256] = {
1616
+// ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
1617
+// ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
1618
+// ['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
1619
+// ['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31,
1620
+// ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
1621
+// ['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
1622
+// ['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55,
1623
+// ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63,
1624
+// [0 ... '+' - 1] = 255,
1625
+// ['+' + 1 ... '/' - 1] = 255,
1626
+// ['9' + 1 ... 'A' - 1] = 255,
1627
+// ['Z' + 1 ... 'a' - 1] = 255,
1628
+// ['z' + 1 ... 255] = 255
1629
+// };
1630
+//
1631
+// size_t count = 0;
1632
+// unsigned int tmp = 0;
1633
+// int i, bit;
1634
+//
1635
+// if (decoded_size < 1)
1636
+// return 0; // Buffer size must be at least 1 for null termination
1637
+//
1638
+// for (i = 0, bit = 0; encoded[i]; i++) {
1639
+// unsigned char value = base64_table[(unsigned char)encoded[i]];
1640
+// if (value > 63)
1641
+// return -1; // Invalid character in input
1642
+//
1643
+// tmp = tmp << 6 | value;
1644
+// if (++bit == 4) {
1645
+// if (count + 3 >= decoded_size) break; // Stop decoding if buffer is full
1646
+// decoded[count++] = (tmp >> 16) & 0xFF;
1647
+// decoded[count++] = (tmp >> 8) & 0xFF;
1648
+// decoded[count++] = tmp & 0xFF;
1649
+// tmp = 0;
1650
+// bit = 0;
1651
+// }
1652
+// }
1653
+//
1654
+// if (bit > 0 && count + 1 < decoded_size) {
1655
+// tmp <<= 6 * (4 - bit);
1656
+// if (bit > 2 && count + 1 < decoded_size) decoded[count++] = (tmp >> 16) & 0xFF;
1657
+// if (bit > 3 && count + 1 < decoded_size) decoded[count++] = (tmp >> 8) & 0xFF;
1658
+// }
1659
+//
1660
+// decoded[count] = '\0'; // Null terminate the output string
1661
+// return count;
1662
+// }
src/libnetdata/libnetdata.h
+2
-1
@@ -642,7 +642,8 @@ extern bool unittest_running;
642
bool rrdr_relative_window_to_absolute(time_t *after, time_t *before, time_t now);
643
bool rrdr_relative_window_to_absolute_query(time_t *after, time_t *before, time_t *now_ptr, bool unittest);
644
645
-int netdata_base64_decode(const char *encoded, char *decoded, size_t decoded_size);
645
+int netdata_base64_decode(unsigned char *out, const unsigned char *in, int in_len);
646
+int netdata_base64_encode(unsigned char *encoded, const unsigned char *input, size_t input_size);
647
648
static inline void freez_charp(char **p) {
649
freez(*p);
src/libnetdata/ringbuffer/ringbuffer.c
-3
@@ -6,9 +6,6 @@
6
rbuf_t rbuf_create(size_t size)
7
{
8
rbuf_t buffer = mallocz(sizeof(struct rbuf) + size);
9
- if (!buffer)
10
- return NULL;
11
-
9
memset(buffer, 0, sizeof(struct rbuf));
10
11
buffer->data = ((char*)buffer) + sizeof(struct rbuf);
src/libnetdata/socket/security.h
+1
@@ -19,6 +19,7 @@ typedef enum __attribute__((packed)) {
19
#define OPENSSL_VERSION_300 0x30000000L
20
21
# include <openssl/ssl.h>
22
+# include <openssl/rand.h>
23
# include <openssl/err.h>
24
# include <openssl/evp.h>
25
# include <openssl/pem.h>