Implements cloud initiated disconnect command (#11723)
Timotej S committed
Nov 9, 2021 at 13:42 UTC
f2826332672c2486c643ffcc5ecf67c647491cde
10 files changed
+91
-5
CMakeLists.txt
+1
@@ -1135,6 +1135,7 @@ endfunction()
1135
1136
set(ACLK_NG_PROTO_DEFS
1137
aclk/aclk-schemas/proto/aclk/v1/lib.proto
1138
+ aclk/aclk-schemas/proto/agent/v1/disconnect.proto
1139
aclk/aclk-schemas/proto/agent/v1/connection.proto
1140
aclk/aclk-schemas/proto/alarm/v1/config.proto
1141
aclk/aclk-schemas/proto/alarm/v1/stream.proto
Makefile.am
+7
@@ -680,6 +680,7 @@ ACLK_NG_FILES += \
680
681
ACLK_NG_PROTO_DEFINITIONS = \
682
aclk/aclk-schemas/proto/aclk/v1/lib.proto \
683
+ aclk/aclk-schemas/proto/agent/v1/disconnect.proto \
684
aclk/aclk-schemas/proto/agent/v1/connection.proto \
685
aclk/aclk-schemas/proto/alarm/v1/config.proto \
686
aclk/aclk-schemas/proto/alarm/v1/stream.proto \
@@ -710,6 +711,8 @@ ACLK_NG_PROTO_BUILT_FILES = aclk/aclk-schemas/proto/agent/v1/connection.pb.cc \
711
aclk/aclk-schemas/proto/chart/v1/config.pb.h \
712
aclk/aclk-schemas/proto/aclk/v1/lib.pb.cc \
713
aclk/aclk-schemas/proto/aclk/v1/lib.pb.h \
714
+ aclk/aclk-schemas/proto/agent/v1/disconnect.pb.cc \
715
+ aclk/aclk-schemas/proto/agent/v1/disconnect.pb.h \
716
aclk/aclk-schemas/proto/alarm/v1/config.pb.cc \
717
aclk/aclk-schemas/proto/alarm/v1/config.pb.h \
718
aclk/aclk-schemas/proto/alarm/v1/stream.pb.cc \
@@ -754,6 +757,10 @@ aclk/aclk-schemas/proto/aclk/v1/lib.pb.cc \
757
aclk/aclk-schemas/proto/aclk/v1/lib.pb.h: aclk/aclk-schemas/proto/aclk/v1/lib.proto
758
$(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
759
760
+aclk/aclk-schemas/proto/agent/v1/disconnect.pb.cc \
761
+aclk/aclk-schemas/proto/agent/v1/disconnect.pb.h: aclk/aclk-schemas/proto/agent/v1/disconnect.proto
762
+ $(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
763
+
764
aclk/aclk-schemas/proto/alarm/v1/config.pb.cc \
765
aclk/aclk-schemas/proto/alarm/v1/config.pb.h: aclk/aclk-schemas/proto/alarm/v1/config.proto
766
$(PROTOC) -I=aclk/aclk-schemas --cpp_out=$(builddir)/aclk/aclk-schemas $^
aclk/aclk-schemas
+1
-1
@@ -1 +1 @@
1
-Subproject commit ff110970c006170b01b51a15bf6cdc219ce1dcf5
1
+Subproject commit 72d0a600dccf965b939a1ae4f7818d0ac896842a
aclk/aclk.c
+14
-2
@@ -24,6 +24,7 @@
24
#define ACLK_STABLE_TIMEOUT 3 // Minimum delay to mark AGENT as stable
25
26
int aclk_pubacks_per_conn = 0; // How many PubAcks we got since MQTT conn est.
27
+int disconnect_req = 0;
28
29
int aclk_alert_reloaded = 1; //1 on startup, and again on health_reload
30
@@ -218,7 +219,7 @@ static void msg_callback(const char *topic, const void *msg, size_t msglen, int
219
error("Received message on unexpected topic %s", topic);
220
221
if (aclk_shared_state.mqtt_shutdown_msg_id > 0) {
221
- error("Link is shutting down. Ignoring message.");
222
+ error("Link is shutting down. Ignoring incoming message.");
223
return;
224
}
225
@@ -234,7 +235,7 @@ static void msg_callback_new(const char *topic, const void *msg, size_t msglen,
235
debug(D_ACLK, "Got Message From Broker Topic \"%s\" QOS %d", topic, qos);
236
237
if (aclk_shared_state.mqtt_shutdown_msg_id > 0) {
237
- error("Link is shutting down. Ignoring message.");
238
+ error("Link is shutting down. Ignoring incoming message.");
239
return;
240
}
241
@@ -293,6 +294,8 @@ static int read_query_thread_count()
294
return threads;
295
}
296
297
+void aclk_graceful_disconnect(mqtt_wss_client client);
298
+
299
/* Keeps connection alive and handles all network comms.
300
* Returns on error or when netdata is shutting down.
301
* @param client instance of mqtt_wss_client
@@ -310,6 +313,15 @@ static int handle_connection(mqtt_wss_client client)
313
return 1;
314
}
315
316
+ if (disconnect_req) {
317
+ disconnect_req = 0;
318
+ aclk_graceful_disconnect(client);
319
+ aclk_queue_unlock();
320
+ aclk_shared_state.mqtt_shutdown_msg_id = -1;
321
+ aclk_shared_state.mqtt_shutdown_msg_rcvd = 0;
322
+ return 1;
323
+ }
324
+
325
// mqtt_wss_service will return faster than in one second
326
// if there is enough work to do
327
time_t now = now_monotonic_sec();
aclk/aclk.h
+2
@@ -12,6 +12,8 @@
12
13
extern time_t aclk_block_until;
14
15
+extern int disconnect_req;
16
+
17
extern aclk_env_t *aclk_env;
18
19
void *aclk_main(void *ptr);
aclk/aclk_query_queue.c
+7
@@ -193,3 +193,10 @@ void aclk_queue_lock(void)
193
aclk_query_queue.block_push = 1;
194
ACLK_QUEUE_UNLOCK;
195
}
196
+
197
+void aclk_queue_unlock(void)
198
+{
199
+ ACLK_QUEUE_LOCK;
200
+ aclk_query_queue.block_push = 0;
201
+ ACLK_QUEUE_UNLOCK;
202
+}
aclk/aclk_query_queue.h
+1
@@ -91,6 +91,7 @@ aclk_query_t aclk_queue_pop(void);
91
void aclk_queue_flush(void);
92
93
void aclk_queue_lock(void);
94
+void aclk_queue_unlock(void);
95
96
#define QUEUE_IF_PAYLOAD_PRESENT(query) \
97
if (likely(query->data.bin_payload.payload)) { \
aclk/aclk_rx_msgs.c
+18
@@ -416,6 +416,24 @@ void aclk_handle_new_cloud_msg(const char *message_type, const char *msg, size_t
416
destroy_send_alarm_snapshot(sas);
417
return;
418
}
419
+ if (!strcmp(message_type, "DisconnectReq")) {
420
+ struct disconnect_cmd *cmd = parse_disconnect_cmd(msg, msg_len);
421
+ if (!cmd)
422
+ return;
423
+ if (cmd->permaban) {
424
+ error ("Cloud Banned This Agent!");
425
+ aclk_disable_runtime = 1;
426
+ }
427
+ info ("Cloud requested disconnect (EC=%u, \"%s\")", (unsigned int)cmd->error_code, cmd->error_description);
428
+ if (cmd->reconnect_after_s > 0) {
429
+ aclk_block_until = now_monotonic_sec() + cmd->reconnect_after_s;
430
+ info ("Cloud asks not to reconnect for %u seconds. We shall honor that request", (unsigned int)cmd->reconnect_after_s);
431
+ }
432
+ disconnect_req = 1;
433
+ freez(cmd->error_description);
434
+ freez(cmd);
435
+ return;
436
+ }
437
error ("Unknown new cloud arch message type received \"%s\"", message_type);
438
}
439
#endif
aclk/schema-wrappers/connection.cc
+31
-2
@@ -1,6 +1,7 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
#include "proto/agent/v1/connection.pb.h"
4
+#include "proto/agent/v1/disconnect.pb.h"
5
#include "connection.h"
6
7
#include "schema_wrapper_utils.h"
@@ -8,15 +9,17 @@
9
#include <sys/time.h>
10
#include <stdlib.h>
11
12
+using namespace agent::v1;
13
+
14
char *generate_update_agent_connection(size_t *len, const update_agent_connection_t *data)
15
{
13
- agent::v1::UpdateAgentConnection connupd;
16
+ UpdateAgentConnection connupd;
17
18
connupd.set_claim_id(data->claim_id);
19
connupd.set_reachable(data->reachable);
20
connupd.set_session_id(data->session_id);
21
19
- connupd.set_update_source((data->lwt) ? agent::v1::CONNECTION_UPDATE_SOURCE_LWT : agent::v1::CONNECTION_UPDATE_SOURCE_AGENT);
22
+ connupd.set_update_source((data->lwt) ? CONNECTION_UPDATE_SOURCE_LWT : CONNECTION_UPDATE_SOURCE_AGENT);
23
24
struct timeval tv;
25
gettimeofday(&tv, NULL);
@@ -32,3 +35,29 @@ char *generate_update_agent_connection(size_t *len, const update_agent_connectio
35
36
return msg;
37
}
38
+
39
+struct disconnect_cmd *parse_disconnect_cmd(const char *data, size_t len) {
40
+ DisconnectReq req;
41
+ struct disconnect_cmd *res;
42
+
43
+ if (!req.ParseFromArray(data, len))
44
+ return NULL;
45
+
46
+ res = (struct disconnect_cmd *)calloc(1, sizeof(struct disconnect_cmd));
47
+
48
+ if (!res)
49
+ return NULL;
50
+
51
+ res->reconnect_after_s = req.reconnect_after_seconds();
52
+ res->permaban = req.permaban();
53
+ res->error_code = req.error_code();
54
+ if (req.error_description().c_str()) {
55
+ res->error_description = strdup(req.error_description().c_str());
56
+ if (!res->error_description) {
57
+ free(res);
58
+ return NULL;
59
+ }
60
+ }
61
+
62
+ return res;
63
+}
aclk/schema-wrappers/connection.h
+9
@@ -27,6 +27,15 @@ typedef struct {
27
28
char *generate_update_agent_connection(size_t *len, const update_agent_connection_t *data);
29
30
+struct disconnect_cmd {
31
+ uint64_t reconnect_after_s;
32
+ int permaban;
33
+ uint32_t error_code;
34
+ char *error_description;
35
+};
36
+
37
+struct disconnect_cmd *parse_disconnect_cmd(const char *data, size_t len);
38
+
39
#ifdef __cplusplus
40
}
41
#endif