Support IPV6 when establishing MQTT connection to the cloud (#18217)
* Remove ws_client_get_nonce, use uuid instead Use connect_to_this_ip46 function Replace mw_malloc, mw_calloc, mw_free, mw_strdup, mw_realloc Cleanup * Remove unused pub_lock Switch stat lock to spinlock * Set correct host
Stelios Fragkakis committed
Jul 30, 2024 at 12:47 UTC
3994ea0adaa20152e0f94fa39bc8d4a39f5fc732
6 files changed
+139
-169
src/aclk/helpers/mqtt_wss_pal.h
-6
@@ -10,10 +10,4 @@
10
#undef OPENSSL_VERSION_110
11
#undef OPENSSL_VERSION_111
12
13
-#define mw_malloc(...) mallocz(__VA_ARGS__)
14
-#define mw_calloc(...) callocz(__VA_ARGS__)
15
-#define mw_free(...) freez(__VA_ARGS__)
16
-#define mw_strdup(...) strdupz(__VA_ARGS__)
17
-#define mw_realloc(...) reallocz(__VA_ARGS__)
18
-
13
#endif /* MQTT_WSS_PAL_H */
src/aclk/https_client.c
+1
-1
@@ -696,7 +696,7 @@ int https_request(https_req_t *request, https_req_response_t *response) {
696
goto exit_CTX;
697
}
698
699
- if (!SSL_set_tlsext_host_name(ctx->ssl, connect_host)) {
699
+ if (!SSL_set_tlsext_host_name(ctx->ssl, request->host)) {
700
netdata_log_error("Error setting TLS SNI host");
701
goto exit_CTX;
702
}
src/aclk/mqtt_websockets/mqtt_ng.c
+28
-28
@@ -423,7 +423,7 @@ static void buffer_frag_free_data(struct buffer_fragment *frag)
423
if ( frag->flags & BUFFER_FRAG_DATA_EXTERNAL && frag->data != NULL) {
424
switch (ptr2memory_mode(frag->free_fnc)) {
425
case MEMCPY:
426
- mw_free(frag->data);
426
+ freez(frag->data);
427
break;
428
case EXTERNAL_FREE_AFTER_USE:
429
frag->free_fnc(frag->data);
@@ -563,7 +563,7 @@ static int transaction_buffer_grow(struct transaction_buffer *buf, mqtt_wss_log_
563
if (buf->hdr_buffer.size > max)
564
buf->hdr_buffer.size = max;
565
566
- void *ret = mw_realloc(buf->hdr_buffer.data, buf->hdr_buffer.size);
566
+ void *ret = reallocz(buf->hdr_buffer.data, buf->hdr_buffer.size);
567
if (ret == NULL) {
568
mws_warn(log_ctx, "Buffer growth failed (realloc)");
569
return 1;
@@ -581,7 +581,7 @@ inline static int transaction_buffer_init(struct transaction_buffer *to_init, si
581
pthread_mutex_init(&to_init->mutex, NULL);
582
583
to_init->hdr_buffer.size = size;
584
- to_init->hdr_buffer.data = mw_malloc(size);
584
+ to_init->hdr_buffer.data = mallocz(size);
585
if (to_init->hdr_buffer.data == NULL)
586
return 1;
587
@@ -594,7 +594,7 @@ static void transaction_buffer_destroy(struct transaction_buffer *to_init)
594
{
595
buffer_purge(&to_init->hdr_buffer);
596
pthread_mutex_destroy(&to_init->mutex);
597
- mw_free(to_init->hdr_buffer.data);
597
+ freez(to_init->hdr_buffer.data);
598
}
599
600
// Creates transaction
@@ -628,7 +628,7 @@ void transaction_buffer_transaction_rollback(struct transaction_buffer *buf, str
628
#define RX_ALIASES_INITIALIZE() c_rhash_new(UINT16_MAX >> 8)
629
struct mqtt_ng_client *mqtt_ng_init(struct mqtt_ng_init *settings)
630
{
631
- struct mqtt_ng_client *client = mw_calloc(1, sizeof(struct mqtt_ng_client));
631
+ struct mqtt_ng_client *client = callocz(1, sizeof(struct mqtt_ng_client));
632
if (client == NULL)
633
return NULL;
634
@@ -672,7 +672,7 @@ err_free_rx_alias:
672
err_free_trx_buf:
673
transaction_buffer_destroy(&client->main_buffer);
674
err_free_client:
675
- mw_free(client);
675
+ freez(client);
676
return NULL;
677
}
678
@@ -688,7 +688,7 @@ static void mqtt_ng_destroy_rx_alias_hash(c_rhash hash)
688
void *to_free;
689
while(!c_rhash_iter_uint64_keys(hash, &i, &stored_key)) {
690
c_rhash_get_ptr_by_uint64(hash, stored_key, &to_free);
691
- mw_free(to_free);
691
+ freez(to_free);
692
}
693
c_rhash_destroy(hash);
694
}
@@ -700,7 +700,7 @@ static void mqtt_ng_destroy_tx_alias_hash(c_rhash hash)
700
void *to_free;
701
while(!c_rhash_iter_str_keys(hash, &i, &stored_key)) {
702
c_rhash_get_ptr_by_str(hash, stored_key, &to_free);
703
- mw_free(to_free);
703
+ freez(to_free);
704
}
705
c_rhash_destroy(hash);
706
}
@@ -714,7 +714,7 @@ void mqtt_ng_destroy(struct mqtt_ng_client *client)
714
pthread_rwlock_destroy(&client->tx_topic_aliases.rwlock);
715
mqtt_ng_destroy_rx_alias_hash(client->rx_aliases);
716
717
- mw_free(client);
717
+ freez(client);
718
}
719
720
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)
@@ -730,7 +730,7 @@ int frag_set_external_data(mqtt_wss_log_ctx_t log, struct buffer_fragment *frag,
730
731
switch (ptr2memory_mode(data_free_fnc)) {
732
case MEMCPY:
733
- frag->data = mw_malloc(data_len);
733
+ frag->data = mallocz(data_len);
734
if (frag->data == NULL) {
735
mws_error(log, UNIT_LOG_PREFIX "OOM while malloc @_optimized_add");
736
return 1;
@@ -1408,12 +1408,12 @@ static void mqtt_properties_parser_ctx_reset(struct mqtt_properties_parser_ctx *
1408
struct mqtt_property *f = ctx->head;
1409
ctx->head = ctx->head->next;
1410
if (f->type == MQTT_TYPE_STR || f->type == MQTT_TYPE_STR_PAIR)
1411
- mw_free(f->data.strings[0]);
1411
+ freez(f->data.strings[0]);
1412
if (f->type == MQTT_TYPE_STR_PAIR)
1413
- mw_free(f->data.strings[1]);
1413
+ freez(f->data.strings[1]);
1414
if (f->type == MQTT_TYPE_BIN)
1415
- mw_free(f->data.bindata);
1416
- mw_free(f);
1415
+ freez(f->data.bindata);
1416
+ freez(f);
1417
}
1418
ctx->tail = NULL;
1419
ctx->properties_length = 0;
@@ -1498,7 +1498,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1498
return rc;
1499
case PROPERTY_CREATE:
1500
BUF_READ_CHECK_AT_LEAST(data, 1);
1501
- struct mqtt_property *prop = mw_calloc(1, sizeof(struct mqtt_property));
1501
+ struct mqtt_property *prop = callocz(1, sizeof(struct mqtt_property));
1502
if (ctx->head == NULL) {
1503
ctx->head = prop;
1504
ctx->tail = prop;
@@ -1558,7 +1558,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1558
break;
1559
case PROPERTY_TYPE_STR:
1560
BUF_READ_CHECK_AT_LEAST(data, ctx->tail->bindata_len);
1561
- ctx->tail->data.strings[ctx->str_idx] = mw_malloc(ctx->tail->bindata_len + 1);
1561
+ ctx->tail->data.strings[ctx->str_idx] = mallocz(ctx->tail->bindata_len + 1);
1562
rbuf_pop(data, ctx->tail->data.strings[ctx->str_idx], ctx->tail->bindata_len);
1563
ctx->tail->data.strings[ctx->str_idx][ctx->tail->bindata_len] = 0;
1564
ctx->str_idx++;
@@ -1571,7 +1571,7 @@ static int parse_properties_array(struct mqtt_properties_parser_ctx *ctx, rbuf_t
1571
break;
1572
case PROPERTY_TYPE_BIN:
1573
BUF_READ_CHECK_AT_LEAST(data, ctx->tail->bindata_len);
1574
- ctx->tail->data.bindata = mw_malloc(ctx->tail->bindata_len);
1574
+ ctx->tail->data.bindata = mallocz(ctx->tail->bindata_len);
1575
rbuf_pop(data, ctx->tail->data.bindata, ctx->tail->bindata_len);
1576
ctx->bytes_consumed += ctx->tail->bindata_len;
1577
ctx->state = PROPERTY_NEXT;
@@ -1721,7 +1721,7 @@ static int parse_suback_varhdr(struct mqtt_ng_client *client)
1721
return rc;
1722
parser->mqtt_parsed_len += parser->properties_parser.bytes_consumed;
1723
suback->reason_code_count = parser->mqtt_fixed_hdr_remaining_length - parser->mqtt_parsed_len;
1724
- suback->reason_codes = mw_calloc(suback->reason_code_count, sizeof(*suback->reason_codes));
1724
+ suback->reason_codes = callocz(suback->reason_code_count, sizeof(*suback->reason_codes));
1725
suback->reason_codes_pending = suback->reason_code_count;
1726
parser->varhdr_state = MQTT_PARSE_REASONCODES;
1727
/* FALLTHROUGH */
@@ -1760,7 +1760,7 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1760
parser->varhdr_state = MQTT_PARSE_VARHDR_POST_TOPICNAME;
1761
break;
1762
}
1763
- publish->topic = mw_calloc(1, publish->topic_len + 1 /* add 0x00 */);
1763
+ publish->topic = callocz(1, publish->topic_len + 1 /* add 0x00 */);
1764
if (publish->topic == NULL)
1765
return MQTT_NG_CLIENT_OOM;
1766
parser->varhdr_state = MQTT_PARSE_VARHDR_TOPICNAME;
@@ -1796,7 +1796,7 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1796
/* FALLTHROUGH */
1797
case MQTT_PARSE_PAYLOAD:
1798
if (parser->mqtt_fixed_hdr_remaining_length < parser->mqtt_parsed_len) {
1799
- mw_free(publish->topic);
1799
+ freez(publish->topic);
1800
publish->topic = NULL;
1801
ERROR("Error parsing PUBLISH message");
1802
return MQTT_NG_CLIENT_PROTOCOL_ERROR;
@@ -1808,9 +1808,9 @@ static int parse_publish_varhdr(struct mqtt_ng_client *client)
1808
}
1809
BUF_READ_CHECK_AT_LEAST(parser->received_data, publish->data_len);
1810
1811
- publish->data = mw_malloc(publish->data_len);
1811
+ publish->data = mallocz(publish->data_len);
1812
if (publish->data == NULL) {
1813
- mw_free(publish->topic);
1813
+ freez(publish->topic);
1814
publish->topic = NULL;
1815
return MQTT_NG_CLIENT_OOM;
1816
}
@@ -1867,7 +1867,7 @@ static int parse_data(struct mqtt_ng_client *client)
1867
case MQTT_CPT_SUBACK:
1868
rc = parse_suback_varhdr(client);
1869
if (rc != MQTT_NG_CLIENT_NEED_MORE_BYTES && rc != MQTT_NG_CLIENT_OK_CALL_AGAIN) {
1870
- mw_free(parser->mqtt_packet.suback.reason_codes);
1870
+ freez(parser->mqtt_packet.suback.reason_codes);
1871
}
1872
if (rc == MQTT_NG_CLIENT_PARSE_DONE) {
1873
parser->state = MQTT_PARSE_MQTT_PACKET_DONE;
@@ -2096,8 +2096,8 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2096
#endif
2097
pub = &client->parser.mqtt_packet.publish;
2098
if (pub->qos > 1) {
2099
- mw_free(pub->topic);
2100
- mw_free(pub->data);
2099
+ freez(pub->topic);
2100
+ freez(pub->data);
2101
return MQTT_NG_CLIENT_NOT_IMPL_YET;
2102
}
2103
if ( pub->qos == 1 && (rc = mqtt_ng_puback(client, pub->packet_id, 0)) ) {
@@ -2127,8 +2127,8 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2127
// in case we have property topic alias and we have topic we take over the string
2128
// and add pointer to it into topic alias list
2129
if (prop == NULL)
2130
- mw_free(pub->topic);
2131
- mw_free(pub->data);
2130
+ freez(pub->topic);
2131
+ freez(pub->data);
2132
return MQTT_NG_CLIENT_WANT_WRITE;
2133
case MQTT_CPT_DISCONNECT:
2134
INFO ("Got MQTT DISCONNECT control packet from server. Reason code: %d", (int)client->parser.mqtt_packet.disconnect.reason_code);
@@ -2225,7 +2225,7 @@ int mqtt_ng_set_topic_alias(struct mqtt_ng_client *client, const char *topic)
2225
return idx;
2226
}
2227
2228
- alias = mw_malloc(sizeof(struct topic_alias_data));
2228
+ alias = mallocz(sizeof(struct topic_alias_data));
2229
idx = ++client->tx_topic_aliases.idx_assigned;
2230
alias->idx = idx;
2231
__atomic_store_n(&alias->usage_count, 0, __ATOMIC_SEQ_CST);
src/aclk/mqtt_websockets/mqtt_wss_client.c
+68
-80
@@ -1,5 +1,4 @@
1
// SPDX-License-Identifier: GPL-3.0-only
2
-// Copyright (C) 2020 Timotej Šiškovič
2
3
#ifndef _GNU_SOURCE
4
#define _GNU_SOURCE
@@ -19,9 +18,6 @@
18
19
#include <sys/socket.h>
20
#include <netinet/in.h>
22
-#include <arpa/inet.h>
23
-#include <netinet/tcp.h> //TCP_NODELAY
24
-#include <netdb.h>
21
22
#include <openssl/err.h>
23
#include <openssl/ssl.h>
@@ -107,8 +103,6 @@ struct mqtt_wss_client_struct {
103
104
int mqtt_keepalive;
105
110
- pthread_mutex_t pub_lock;
111
-
106
// signifies that we didn't write all MQTT wanted
107
// us to write during last cycle (e.g. due to buffer
108
// size) and thus we should arm POLLOUT
@@ -121,7 +115,7 @@ struct mqtt_wss_client_struct {
115
void (*msg_callback)(const char *, const void *, size_t, int);
116
void (*puback_callback)(uint16_t packet_id);
117
124
- pthread_mutex_t stat_lock;
118
+ SPINLOCK stat_lock;
119
struct mqtt_wss_stats stats;
120
121
#ifdef MQTT_WSS_DEBUG
@@ -173,14 +167,13 @@ mqtt_wss_client mqtt_wss_new(const char *log_prefix,
167
SSL_library_init();
168
SSL_load_error_strings();
169
176
- mqtt_wss_client client = mw_calloc(1, sizeof(struct mqtt_wss_client_struct));
170
+ mqtt_wss_client client = callocz(1, sizeof(struct mqtt_wss_client_struct));
171
if (!client) {
172
mws_error(log, "OOM alocating mqtt_wss_client");
173
goto fail;
174
}
175
182
- pthread_mutex_init(&client->pub_lock, NULL);
183
- pthread_mutex_init(&client->stat_lock, NULL);
176
+ spinlock_init(&client->stat_lock);
177
178
client->msg_callback = msg_callback;
179
client->puback_callback = puback_callback;
@@ -229,7 +222,7 @@ fail_3:
222
fail_2:
223
ws_client_destroy(client->ws_client);
224
fail_1:
232
- mw_free(client);
225
+ freez(client);
226
fail:
227
mqtt_wss_log_ctx_destroy(log);
228
return NULL;
@@ -253,12 +246,15 @@ void mqtt_wss_destroy(mqtt_wss_client client)
246
// as it "borrows" this pointer and might use it
247
if (client->target_host == client->host)
248
client->target_host = NULL;
249
+
250
if (client->target_host)
257
- mw_free(client->target_host);
251
+ freez(client->target_host);
252
+
253
if (client->host)
259
- mw_free(client->host);
260
- mw_free(client->proxy_passwd);
261
- mw_free(client->proxy_uname);
254
+ freez(client->host);
255
+
256
+ freez(client->proxy_passwd);
257
+ freez(client->proxy_uname);
258
259
if (client->ssl)
260
SSL_free(client->ssl);
@@ -269,11 +265,8 @@ void mqtt_wss_destroy(mqtt_wss_client client)
265
if (client->sockfd > 0)
266
close(client->sockfd);
267
272
- pthread_mutex_destroy(&client->pub_lock);
273
- pthread_mutex_destroy(&client->stat_lock);
274
-
268
mqtt_wss_log_ctx_destroy(client->log);
276
- mw_free(client);
269
+ freez(client);
270
}
271
272
static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
@@ -298,7 +291,7 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
291
mws_error(client->log, "verify error:num=%d:%s:depth=%d:%s", err,
292
X509_verify_cert_error_string(err), depth, err_str);
293
301
- mw_free(err_str);
294
+ freez(err_str);
295
}
296
297
if (!preverify_ok && err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
@@ -362,14 +355,14 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
355
}
356
357
if (http_code != 200) {
365
- ptr = mw_malloc(idx + 1);
358
+ ptr = mallocz(idx + 1);
359
if (!ptr)
360
return 6;
361
rbuf_pop(buf, ptr, idx);
362
ptr[idx] = 0;
363
364
mws_error(client->log, "http_proxy returned error code %d \"%s\"", http_code, ptr);
372
- mw_free(ptr);
365
+ freez(ptr);
366
return 7;
367
}/* else
368
rbuf_bump_tail(buf, idx);*/
@@ -450,7 +443,7 @@ static int http_proxy_connect(mqtt_wss_client client)
443
444
if (client->proxy_uname) {
445
size_t creds_plain_len = strlen(client->proxy_uname) + strlen(client->proxy_passwd) + 2;
453
- char *creds_plain = mw_malloc(creds_plain_len);
446
+ char *creds_plain = mallocz(creds_plain_len);
447
if (!creds_plain) {
448
mws_error(client->log, "OOM creds_plain");
449
rc = 6;
@@ -460,9 +453,9 @@ static int http_proxy_connect(mqtt_wss_client client)
453
// OpenSSL encoder puts newline every 64 output bytes
454
// we remove those but during encoding we need that space in the buffer
455
creds_base64_len += (1+(creds_base64_len/64)) * strlen("\n");
463
- char *creds_base64 = mw_malloc(creds_base64_len + 1);
456
+ char *creds_base64 = mallocz(creds_base64_len + 1);
457
if (!creds_base64) {
465
- mw_free(creds_plain);
458
+ freez(creds_plain);
459
mws_error(client->log, "OOM creds_base64");
460
rc = 6;
461
goto cleanup;
@@ -475,12 +468,12 @@ static int http_proxy_connect(mqtt_wss_client client)
468
469
int b64_len;
470
base64_encode_helper((unsigned char*)creds_base64, &b64_len, (unsigned char*)creds_plain, strlen(creds_plain));
478
- mw_free(creds_plain);
471
+ freez(creds_plain);
472
473
r_buf_ptr = rbuf_get_linear_insert_range(r_buf, &r_buf_linear_insert_capacity);
474
snprintf(r_buf_ptr, r_buf_linear_insert_capacity,"Proxy-Authorization: Basic %s" HTTP_ENDLINE, creds_base64);
475
write(client->sockfd, r_buf_ptr, strlen(r_buf_ptr));
483
- mw_free(creds_base64);
476
+ freez(creds_base64);
477
}
478
write(client->sockfd, HTTP_ENDLINE, strlen(HTTP_ENDLINE));
479
@@ -523,15 +516,14 @@ cleanup:
516
return rc;
517
}
518
526
-int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_connect_params *mqtt_params, int ssl_flags, struct mqtt_wss_proxy *proxy)
519
+int mqtt_wss_connect(
520
+ mqtt_wss_client client,
521
+ char *host,
522
+ int port,
523
+ struct mqtt_connect_params *mqtt_params,
524
+ int ssl_flags,
525
+ struct mqtt_wss_proxy *proxy)
526
{
528
- struct sockaddr_in addr;
529
- memset(&addr, 0, sizeof(addr));
530
- addr.sin_family = AF_INET;
531
-
532
- struct hostent *he;
533
- struct in_addr **addr_list;
534
-
527
if (!mqtt_params) {
528
mws_error(client->log, "mqtt_params can't be null!");
529
return -1;
@@ -545,23 +537,35 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
537
538
if (client->target_host == client->host)
539
client->target_host = NULL;
540
+
541
if (client->target_host)
549
- mw_free(client->target_host);
542
+ freez(client->target_host);
543
+
544
if (client->host)
551
- mw_free(client->host);
545
+ freez(client->host);
546
+
547
+ if (client->proxy_uname) {
548
+ freez(client->proxy_uname);
549
+ client->proxy_uname = NULL;
550
+ }
551
+
552
+ if (client->proxy_passwd) {
553
+ freez(client->proxy_passwd);
554
+ client->proxy_passwd = NULL;
555
+ }
556
557
if (proxy && proxy->type != MQTT_WSS_DIRECT) {
554
- client->host = mw_strdup(proxy->host);
558
+ client->host = strdupz(proxy->host);
559
client->port = proxy->port;
556
- client->target_host = mw_strdup(host);
560
+ client->target_host = strdupz(host);
561
client->target_port = port;
562
client->proxy_type = proxy->type;
563
if (proxy->username)
560
- client->proxy_uname = mw_strdup(proxy->username);
564
+ client->proxy_uname = strdupz(proxy->username);
565
if (proxy->password)
562
- client->proxy_passwd = mw_strdup(proxy->password);
566
+ client->proxy_passwd = strdupz(proxy->password);
567
} else {
564
- client->host = mw_strdup(host);
568
+ client->host = strdupz(host);
569
client->port = port;
570
client->target_host = client->host;
571
client->target_port = port;
@@ -569,30 +573,19 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
573
574
client->ssl_flags = ssl_flags;
575
572
- //TODO gethostbyname -> getaddinfo
573
- // hstrerror -> gai_strerror
574
- if ((he = gethostbyname(client->host)) == NULL) {
575
- mws_error(client->log, "gethostbyname() error \"%s\"", hstrerror(h_errno));
576
- return -1;
577
- }
578
-
579
- addr_list = (struct in_addr **)he->h_addr_list;
580
- if(!addr_list[0]) {
581
- mws_error(client->log, "No IP addr resolved");
582
- return -1;
583
- }
584
- mws_debug(client->log, "Resolved IP: %s", inet_ntoa(*addr_list[0]));
585
- addr.sin_addr = *addr_list[0];
586
- addr.sin_port = htons(client->port);
587
-
576
if (client->sockfd > 0)
577
close(client->sockfd);
590
- client->sockfd = socket(AF_INET, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
591
- if (client->sockfd < 0) {
592
- mws_error(client->log, "Couldn't create socket()");
593
- return -1;
578
+
579
+ char port_str[16];
580
+ snprintf(port_str, sizeof(port_str) -1, "%d", client->port);
581
+ int fd = connect_to_this_ip46(IPPROTO_TCP, SOCK_STREAM, client->host, 0, port_str, NULL);
582
+ if (fd < 0) {
583
+ mws_error(client->log, "Could not connect to remote endpoint \"%s\", port %d.\n", client->host, port);
584
+ return -3;
585
}
586
587
+ client->sockfd = fd;
588
+
589
#ifndef SOCK_CLOEXEC
590
int flags = fcntl(client->sockfd, F_GETFD);
591
if (flags != -1)
@@ -600,19 +593,10 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
593
#endif
594
595
int flag = 1;
603
- int result = setsockopt(client->sockfd,
604
- IPPROTO_TCP,
605
- TCP_NODELAY,
606
- &flag,
607
- sizeof(int));
596
+ int result = setsockopt(client->sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
597
if (result < 0)
598
mws_error(client->log, "Could not dissable NAGLE");
599
611
- if (connect(client->sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
612
- mws_error(client->log, "Could not connect to remote endpoint \"%s\", port %d.\n", client->host, client->port);
613
- return -3;
614
- }
615
-
600
client->poll_fds[POLLFD_SOCKET].fd = client->sockfd;
601
602
if (fcntl(client->sockfd, F_SETFL, fcntl(client->sockfd, F_GETFL, 0) | O_NONBLOCK) == -1) {
@@ -640,6 +624,7 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
624
// free SSL structs from possible previous connections
625
if (client->ssl)
626
SSL_free(client->ssl);
627
+
628
if (client->ssl_ctx)
629
SSL_CTX_free(client->ssl_ctx);
630
@@ -675,6 +660,7 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
660
mws_error(client->log, "SSL could not connect");
661
return -5;
662
}
663
+
664
if (result == -1) {
665
int ec = SSL_get_error(client->ssl, result);
666
if (ec != SSL_ERROR_WANT_READ && ec != SSL_ERROR_WANT_WRITE) {
@@ -693,14 +679,16 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
679
auth.username_free = NULL;
680
auth.password = (char*)mqtt_params->password;
681
auth.password_free = NULL;
682
+
683
struct mqtt_lwt_properties lwt;
684
lwt.will_topic = (char*)mqtt_params->will_topic;
685
lwt.will_topic_free = NULL;
686
lwt.will_message = (void*)mqtt_params->will_msg;
687
lwt.will_message_free = NULL; // TODO expose no copy version to API
688
lwt.will_message_size = mqtt_params->will_msg_len;
702
- lwt.will_qos = (mqtt_params->will_flags & MQTT_WSS_PUB_QOSMASK);
703
- lwt.will_retain = mqtt_params->will_flags & MQTT_WSS_PUB_RETAIN;
689
+ lwt.will_qos = (int) (mqtt_params->will_flags & MQTT_WSS_PUB_QOSMASK);
690
+ lwt.will_retain = (int) mqtt_params->will_flags & MQTT_WSS_PUB_RETAIN;
691
+
692
int ret = mqtt_ng_connect(client->mqtt, &auth, mqtt_params->will_msg ? &lwt : NULL, 1, client->mqtt_keepalive);
693
if (ret) {
694
mws_error(client->log, "Error generating MQTT connect");
@@ -955,9 +943,9 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
943
#ifdef DEBUG_ULTRA_VERBOSE
944
mws_debug(client->log, "SSL_Read: Read %d.", ret);
945
#endif
958
- pthread_mutex_lock(&client->stat_lock);
946
+ spinlock_lock(&client->stat_lock);
947
client->stats.bytes_rx += ret;
960
- pthread_mutex_unlock(&client->stat_lock);
948
+ spinlock_unlock(&client->stat_lock);
949
rbuf_bump_head(client->ws_client->buf_read, ret);
950
} else {
951
int errnobkp = errno;
@@ -1023,9 +1011,9 @@ int mqtt_wss_service(mqtt_wss_client client, int timeout_ms)
1011
#ifdef DEBUG_ULTRA_VERBOSE
1012
mws_debug(client->log, "SSL_Write: Written %d of avail %d.", ret, size);
1013
#endif
1026
- pthread_mutex_lock(&client->stat_lock);
1014
+ spinlock_lock(&client->stat_lock);
1015
client->stats.bytes_tx += ret;
1028
- pthread_mutex_unlock(&client->stat_lock);
1016
+ spinlock_unlock(&client->stat_lock);
1017
rbuf_bump_tail(client->ws_client->buf_write, ret);
1018
} else {
1019
int errnobkp = errno;
@@ -1115,10 +1103,10 @@ int mqtt_wss_subscribe(mqtt_wss_client client, char *topic, int max_qos_level)
1103
struct mqtt_wss_stats mqtt_wss_get_stats(mqtt_wss_client client)
1104
{
1105
struct mqtt_wss_stats current;
1118
- pthread_mutex_lock(&client->stat_lock);
1106
+ spinlock_lock(&client->stat_lock);
1107
current = client->stats;
1108
memset(&client->stats, 0, sizeof(client->stats));
1121
- pthread_mutex_unlock(&client->stat_lock);
1109
+ spinlock_unlock(&client->stat_lock);
1110
mqtt_ng_get_stats(client->mqtt, ¤t.mqtt);
1111
return current;
1112
}
src/aclk/mqtt_websockets/mqtt_wss_log.c
+6
-6
@@ -25,13 +25,13 @@ struct mqtt_wss_log_ctx {
25
#endif
26
mqtt_wss_log_ctx_t mqtt_wss_log_ctx_create(const char *ctx_prefix, mqtt_wss_log_callback_t log_callback)
27
{
28
- mqtt_wss_log_ctx_t ctx = mw_calloc(1, sizeof(struct mqtt_wss_log_ctx));
28
+ mqtt_wss_log_ctx_t ctx = callocz(1, sizeof(struct mqtt_wss_log_ctx));
29
if(!ctx)
30
return NULL;
31
32
if(log_callback) {
33
ctx->extern_log_fnc = log_callback;
34
- ctx->buffer = mw_calloc(1, LOG_BUFFER_SIZE);
34
+ ctx->buffer = callocz(1, LOG_BUFFER_SIZE);
35
if(!ctx->buffer)
36
goto cleanup;
37
@@ -60,15 +60,15 @@ mqtt_wss_log_ctx_t mqtt_wss_log_ctx_create(const char *ctx_prefix, mqtt_wss_log_
60
return ctx;
61
62
cleanup:
63
- mw_free(ctx);
63
+ freez(ctx);
64
return NULL;
65
}
66
67
void mqtt_wss_log_ctx_destroy(mqtt_wss_log_ctx_t ctx)
68
{
69
- mw_free(ctx->ctx_prefix);
70
- mw_free(ctx->buffer);
71
- mw_free(ctx);
69
+ freez(ctx->ctx_prefix);
70
+ freez(ctx->buffer);
71
+ freez(ctx);
72
}
73
74
static inline char severity_to_c(int severity)
src/aclk/mqtt_websockets/ws_client.c
+36
-48
@@ -53,7 +53,7 @@ ws_client *ws_client_new(size_t buf_size, char **host, mqtt_wss_log_ctx_t log)
53
if(!host)
54
return NULL;
55
56
- client = mw_calloc(1, sizeof(ws_client));
56
+ client = callocz(1, sizeof(ws_client));
57
if (!client)
58
return NULL;
59
@@ -87,7 +87,7 @@ cleanup_2:
87
cleanup_1:
88
rbuf_free(client->buf_read);
89
cleanup:
90
- mw_free(client);
90
+ freez(client);
91
return NULL;
92
}
93
@@ -99,7 +99,7 @@ void ws_client_free_headers(ws_client *client)
99
while (ptr) {
100
tmp = ptr;
101
ptr = ptr->next;
102
- mw_free(tmp);
102
+ freez(tmp);
103
}
104
105
client->hs.headers = NULL;
@@ -110,25 +110,28 @@ void ws_client_free_headers(ws_client *client)
110
void ws_client_destroy(ws_client *client)
111
{
112
ws_client_free_headers(client);
113
- mw_free(client->hs.nonce_reply);
114
- mw_free(client->hs.http_reply_msg);
113
+ freez(client->hs.nonce_reply);
114
+ freez(client->hs.http_reply_msg);
115
close(client->entropy_fd);
116
rbuf_free(client->buf_read);
117
rbuf_free(client->buf_write);
118
rbuf_free(client->buf_to_mqtt);
119
- mw_free(client);
119
+ freez(client);
120
}
121
122
void ws_client_reset(ws_client *client)
123
{
124
ws_client_free_headers(client);
125
- mw_free(client->hs.nonce_reply);
125
+ freez(client->hs.nonce_reply);
126
client->hs.nonce_reply = NULL;
127
- mw_free(client->hs.http_reply_msg);
127
+
128
+ freez(client->hs.http_reply_msg);
129
client->hs.http_reply_msg = NULL;
130
+
131
rbuf_flush(client->buf_read);
132
rbuf_flush(client->buf_write);
133
rbuf_flush(client->buf_to_mqtt);
134
+
135
client->state = WS_RAW;
136
client->hs.hdr_state = WS_HDR_HTTP;
137
client->rx.parse_state = WS_FIRST_2BYTES;
@@ -158,31 +161,11 @@ int ws_client_want_write(ws_client *client)
161
return rbuf_bytes_available(client->buf_write);
162
}
163
161
-#define RAND_SRC "/dev/urandom"
162
-static int ws_client_get_nonce(ws_client *client, char *dest, unsigned int size)
163
-{
164
- // we do not need crypto secure random here
165
- // it's just used for protocol negotiation
166
- int rd;
167
- int f = open(RAND_SRC, O_RDONLY | O_CLOEXEC);
168
- if (f < 0) {
169
- ERROR("Error opening \"%s\". Err: \"%s\"", RAND_SRC, strerror(errno));
170
- return -2;
171
- }
172
-
173
- if ((rd = read(f, dest, size)) > 0) {
174
- close(f);
175
- return rd;
176
- }
177
- close(f);
178
- return -1;
179
-}
180
-
164
#define WEBSOCKET_NONCE_SIZE 16
165
#define TEMP_BUF_SIZE 4096
166
int ws_client_start_handshake(ws_client *client)
167
{
185
- char nonce[WEBSOCKET_NONCE_SIZE];
168
+ nd_uuid_t nonce;
169
char nonce_b64[256];
170
char second[TEMP_BUF_SIZE];
171
unsigned int md_len;
@@ -190,16 +173,15 @@ int ws_client_start_handshake(ws_client *client)
173
EVP_MD_CTX *md_ctx;
174
const EVP_MD *md;
175
193
- if(!*client->host) {
176
+ if(!client->host || !*client->host) {
177
ERROR("Hostname has not been set. We should not be able to come here!");
178
return 1;
179
}
180
198
- ws_client_get_nonce(client, nonce, WEBSOCKET_NONCE_SIZE);
181
+ uuid_generate_random(nonce);
182
EVP_EncodeBlock((unsigned char *)nonce_b64, (const unsigned char *)nonce, WEBSOCKET_NONCE_SIZE);
200
- snprintf(second, TEMP_BUF_SIZE, websocket_upgrage_hdr,
201
- *client->host,
202
- nonce_b64);
183
+ snprintf(second, TEMP_BUF_SIZE, websocket_upgrage_hdr, *client->host, nonce_b64);
184
+
185
if(rbuf_bytes_free(client->buf_write) < strlen(second)) {
186
ERROR("Write buffer capacity too low.");
187
return 1;
@@ -236,10 +218,10 @@ int ws_client_start_handshake(ws_client *client)
218
EVP_DigestUpdate(md_ctx, second, strlen(second));
219
EVP_DigestFinal_ex(md_ctx, digest, &md_len);
220
239
- EVP_EncodeBlock((unsigned char *)nonce_b64, digest, md_len);
221
+ EVP_EncodeBlock((unsigned char *)nonce_b64, digest, (int) md_len);
222
241
- mw_free(client->hs.nonce_reply);
242
- client->hs.nonce_reply = mw_strdup(nonce_b64);
223
+ freez(client->hs.nonce_reply);
224
+ client->hs.nonce_reply = strdupz(nonce_b64);
225
226
OPENSSL_free(digest);
227
@@ -263,7 +245,7 @@ int ws_client_start_handshake(ws_client *client)
245
if (rbuf_bytes_available(client->buf_read) < x) \
246
return WS_CLIENT_NEED_MORE_BYTES;
247
266
-#define MAX_HTTP_LINE_LENGTH 1024*4
248
+#define MAX_HTTP_LINE_LENGTH (1024 * 4)
249
#define HTTP_SC_LENGTH 4 // "XXX " http status code as C string
250
#define WS_CLIENT_HTTP_HDR "HTTP/1.1 "
251
#define WS_CONN_ACCEPT "sec-websocket-accept"
@@ -278,11 +260,11 @@ int ws_client_start_handshake(ws_client *client)
260
#error "Buffer too small"
261
#endif
262
281
-#define HTTP_HDR_LINE_CHECK_LIMIT(x) if ((x) >= MAX_HTTP_LINE_LENGTH) \
282
-{ \
283
- ERROR("HTTP line received is too long. Maximum is %d", MAX_HTTP_LINE_LENGTH); \
284
- return WS_CLIENT_PROTOCOL_ERROR; \
285
-}
263
+#define HTTP_HDR_LINE_CHECK_LIMIT(x) \
264
+ if ((x) >= MAX_HTTP_LINE_LENGTH) { \
265
+ ERROR("HTTP line received is too long. Maximum is %d", MAX_HTTP_LINE_LENGTH); \
266
+ return WS_CLIENT_PROTOCOL_ERROR; \
267
+ }
268
269
int ws_client_parse_handshake_resp(ws_client *client)
270
{
@@ -290,6 +272,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
272
int idx_crlf, idx_sep;
273
char *ptr;
274
size_t bytes;
275
+
276
switch (client->hs.hdr_state) {
277
case WS_HDR_HTTP:
278
BUF_READ_CHECK_AT_LEAST(strlen(WS_CLIENT_HTTP_HDR))
@@ -297,6 +280,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
280
rbuf_bump_tail(client->buf_read, strlen(WS_CLIENT_HTTP_HDR));
281
client->hs.hdr_state = WS_HDR_RC;
282
break;
283
+
284
case WS_HDR_RC:
285
BUF_READ_CHECK_AT_LEAST(HTTP_SC_LENGTH); // "XXX " http return code
286
rbuf_pop(client->buf_read, buf, HTTP_SC_LENGTH);
@@ -312,6 +296,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
296
}
297
client->hs.hdr_state = WS_HDR_ENDLINE;
298
break;
299
+
300
case WS_HDR_ENDLINE:
301
ptr = rbuf_find_bytes(client->buf_read, WS_HTTP_NEWLINE, strlen(WS_HTTP_NEWLINE), &idx_crlf);
302
if (!ptr) {
@@ -321,12 +306,13 @@ int ws_client_parse_handshake_resp(ws_client *client)
306
}
307
HTTP_HDR_LINE_CHECK_LIMIT(idx_crlf);
308
324
- client->hs.http_reply_msg = mw_malloc(idx_crlf+1);
309
+ client->hs.http_reply_msg = mallocz(idx_crlf+1);
310
rbuf_pop(client->buf_read, client->hs.http_reply_msg, idx_crlf);
311
client->hs.http_reply_msg[idx_crlf] = 0;
312
rbuf_bump_tail(client->buf_read, strlen(WS_HTTP_NEWLINE));
313
client->hs.hdr_state = WS_HDR_PARSE_HEADERS;
314
break;
315
+
316
case WS_HDR_PARSE_HEADERS:
317
ptr = rbuf_find_bytes(client->buf_read, WS_HTTP_NEWLINE, strlen(WS_HTTP_NEWLINE), &idx_crlf);
318
if (!ptr) {
@@ -357,7 +343,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
343
return WS_CLIENT_PROTOCOL_ERROR;
344
}
345
360
- struct http_header *hdr = mw_calloc(1, sizeof(struct http_header) + idx_crlf); //idx_crlf includes ": " that will be used as 2 \0 bytes
346
+ struct http_header *hdr = callocz(1, sizeof(struct http_header) + idx_crlf); //idx_crlf includes ": " that will be used as 2 \0 bytes
347
hdr->key = ((char*)hdr) + sizeof(struct http_header);
348
hdr->value = hdr->key + idx_sep + 1;
349
@@ -384,6 +370,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
370
}
371
372
break;
373
+
374
case WS_HDR_PARSE_DONE:
375
if (!client->hs.nonce_matched) {
376
ERROR("Missing " WS_CONN_ACCEPT " header");
@@ -398,6 +385,7 @@ int ws_client_parse_handshake_resp(ws_client *client)
385
client->hs.hdr_state = WS_HDR_ALL_DONE;
386
INFO("Websocket Connection Accepted By Server");
387
return WS_CLIENT_PARSING_DONE;
388
+
389
case WS_HDR_ALL_DONE:
390
FATAL("This is error we should never come here!");
391
return WS_CLIENT_PROTOCOL_ERROR;
@@ -642,7 +630,7 @@ int ws_client_process_rx_ws(ws_client *client)
630
break;
631
case WS_PAYLOAD_CONNECTION_CLOSE_MSG:
632
if (!client->rx.specific_data.op_close.reason)
645
- client->rx.specific_data.op_close.reason = mw_malloc(client->rx.payload_length + 1);
633
+ client->rx.specific_data.op_close.reason = mallocz(client->rx.payload_length + 1);
634
635
while (client->rx.payload_processed < client->rx.payload_length) {
636
if (!rbuf_bytes_available(client->buf_read))
@@ -655,7 +643,7 @@ int ws_client_process_rx_ws(ws_client *client)
643
INFO("WebSocket server closed the connection with EC=%d and reason \"%s\"",
644
client->rx.specific_data.op_close.ec,
645
client->rx.specific_data.op_close.reason);
658
- mw_free(client->rx.specific_data.op_close.reason);
646
+ freez(client->rx.specific_data.op_close.reason);
647
client->rx.specific_data.op_close.reason = NULL;
648
client->rx.parse_state = WS_PACKET_DONE;
649
break;
@@ -672,7 +660,7 @@ int ws_client_process_rx_ws(ws_client *client)
660
return WS_CLIENT_INTERNAL_ERROR;
661
}
662
BUF_READ_CHECK_AT_LEAST(client->rx.payload_length);
675
- client->rx.specific_data.ping_msg = mw_malloc(client->rx.payload_length);
663
+ client->rx.specific_data.ping_msg = mallocz(client->rx.payload_length);
664
rbuf_pop(client->buf_read, client->rx.specific_data.ping_msg, client->rx.payload_length);
665
// TODO schedule this instead of sending right away
666
// then attempt to send as soon as buffer space clears up