adds child query support to ACLK (#10030)
* allows cloud to query children
Timotej S committed
Dec 1, 2020 at 18:27 UTC
37d599cb65cb3c433dfd9aa2a129261c53e1f72a
4 files changed
+74
-23
aclk/aclk_common.h
-2
@@ -98,8 +98,6 @@ const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type);
98
#define ACLK_PROXY_ENV "env"
99
#define ACLK_PROXY_CONFIG_VAR "proxy"
100
101
-#define ACLK_CLOUD_REQ_V2_PREFIX "GET /api/v1/"
102
-
101
ACLK_PROXY_TYPE aclk_verify_proxy(const char *string);
102
const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type);
103
void safe_log_proxy_censor(char *proxy);
aclk/aclk_query.c
+8
-4
@@ -60,8 +60,11 @@ static void aclk_query_free(struct aclk_query *this_query)
60
freez(this_query->topic);
61
if (likely(this_query->query))
62
freez(this_query->query);
63
- if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2)
64
- freez(this_query->data);
63
+ if(this_query->data && this_query->cmd == ACLK_CMD_CLOUD_QUERY_2) {
64
+ struct aclk_cloud_req_v2 *del = (struct aclk_cloud_req_v2 *)this_query->data;
65
+ freez(del->data);
66
+ freez(del);
67
+ }
68
if (likely(this_query->msg_id))
69
freez(this_query->msg_id);
70
freez(this_query);
@@ -396,6 +399,7 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
399
int retval = 0;
400
usec_t t;
401
BUFFER *local_buffer = NULL;
402
+ struct aclk_cloud_req_v2 *cloud_req = (struct aclk_cloud_req_v2 *)this_query->data;
403
404
#ifdef NETDATA_WITH_ZLIB
405
int z_ret;
@@ -422,11 +426,11 @@ static int aclk_execute_query_v2(struct aclk_query *this_query)
426
mysep = strrchr(this_query->query, '/');
427
428
// execute the query
425
- t = aclk_web_api_request_v1(localhost, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
429
+ t = aclk_web_api_request_v1(cloud_req->host, w, mysep ? mysep + 1 : "noop", this_query->created_boot_time);
430
431
#ifdef NETDATA_WITH_ZLIB
432
// check if gzip encoding can and should be used
429
- if ((start = strstr((char *)this_query->data, WEB_HDR_ACCEPT_ENC))) {
433
+ if ((start = strstr(cloud_req->data, WEB_HDR_ACCEPT_ENC))) {
434
start += strlen(WEB_HDR_ACCEPT_ENC);
435
end = strstr(start, "\x0D\x0A");
436
start = strstr(start, "gzip");
aclk/aclk_query.h
+5
@@ -25,6 +25,11 @@ struct aclk_query_threads {
25
int count;
26
};
27
28
+struct aclk_cloud_req_v2 {
29
+ char *data;
30
+ RRDHOST *host;
31
+};
32
+
33
void *aclk_query_main_thread(void *ptr);
34
int aclk_queue_query(char *token, void *data, char *msg_type, char *query, int run_after, int internal, ACLK_CMD cmd);
35
aclk/aclk_rx_msgs.c
+61
-17
@@ -15,18 +15,55 @@ static inline int aclk_extract_v2_data(char *payload, char **data)
15
return 0;
16
}
17
18
-static inline int aclk_v2_payload_get_query(const char *payload, struct aclk_request *req)
18
+#define ACLK_GET_REQ "GET "
19
+#define ACLK_CHILD_REQ "/host/"
20
+#define ACLK_CLOUD_REQ_V2_PREFIX "/api/v1/"
21
+#define STRNCMP_CONSTANT_PREFIX(str, const_pref) strncmp(str, const_pref, strlen(const_pref))
22
+static inline int aclk_v2_payload_get_query(struct aclk_cloud_req_v2 *cloud_req, struct aclk_request *req)
23
{
20
- const char *start, *end;
24
+ const char *start, *end, *ptr;
25
+ char uuid_str[UUID_STR_LEN];
26
+ uuid_t uuid;
27
22
- if(strncmp(payload, ACLK_CLOUD_REQ_V2_PREFIX, strlen(ACLK_CLOUD_REQ_V2_PREFIX))) {
23
- errno = 0;
28
+ errno = 0;
29
+
30
+ if(STRNCMP_CONSTANT_PREFIX(cloud_req->data, ACLK_GET_REQ)) {
31
+ error("Only accepting GET HTTP requests from CLOUD");
32
+ return 1;
33
+ }
34
+ start = ptr = cloud_req->data + strlen(ACLK_GET_REQ);
35
+
36
+ if(!STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CHILD_REQ)) {
37
+ ptr += strlen(ACLK_CHILD_REQ);
38
+ if(strlen(ptr) < UUID_STR_LEN) {
39
+ error("the child id in URL too short \"%s\"", start);
40
+ return 1;
41
+ }
42
+
43
+ strncpyz(uuid_str, ptr, UUID_STR_LEN - 1);
44
+
45
+ for(int i = 0; i < UUID_STR_LEN && uuid_str[i]; i++)
46
+ uuid_str[i] = tolower(uuid_str[i]);
47
+
48
+ if(ptr[0] && uuid_parse(uuid_str, uuid)) {
49
+ error("Got Child query (/host/XXX/...) host id \"%s\" doesn't look like valid GUID", uuid_str);
50
+ return 1;
51
+ }
52
+ ptr += UUID_STR_LEN - 1;
53
+
54
+ cloud_req->host = rrdhost_find_by_guid(uuid_str, 0);
55
+ if(!cloud_req->host) {
56
+ error("Cannot find host with GUID \"%s\"", uuid_str);
57
+ return 1;
58
+ }
59
+ }
60
+
61
+ if(STRNCMP_CONSTANT_PREFIX(ptr, ACLK_CLOUD_REQ_V2_PREFIX)) {
62
error("Only accepting requests that start with \"%s\" from CLOUD.", ACLK_CLOUD_REQ_V2_PREFIX);
63
return 1;
64
}
27
- start = payload + 4;
65
29
- if(!(end = strstr(payload, " HTTP/1.1\x0D\x0A"))) {
66
+ if(!(end = strstr(ptr, " HTTP/1.1\x0D\x0A"))) {
67
errno = 0;
68
error("Doesn't look like HTTP GET request.");
69
return 1;
@@ -88,6 +125,7 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
125
{
126
HTTP_CHECK_AGENT_INITIALIZED();
127
128
+ struct aclk_cloud_req_v2 *cloud_req;
129
char *data;
130
131
errno = 0;
@@ -104,32 +142,38 @@ static int aclk_handle_cloud_request_v2(struct aclk_request *cloud_to_agent, cha
142
return 1;
143
}
144
107
- if (unlikely(aclk_v2_payload_get_query(data, cloud_to_agent))) {
145
+ cloud_req = mallocz(sizeof(struct aclk_cloud_req_v2));
146
+ cloud_req->data = data;
147
+ cloud_req->host = localhost;
148
+
149
+ if (unlikely(aclk_v2_payload_get_query(cloud_req, cloud_to_agent))) {
150
error("Could not extract payload from query");
109
- freez(data);
110
- return 1;
151
+ goto cleanup;
152
}
153
154
if (unlikely(!cloud_to_agent->callback_topic)) {
155
error("Missing callback_topic");
115
- freez(data);
116
- return 1;
156
+ goto cleanup;
157
}
158
159
if (unlikely(!cloud_to_agent->msg_id)) {
160
error("Missing msg_id");
121
- freez(data);
122
- return 1;
161
+ goto cleanup;
162
}
163
164
// aclk_queue_query takes ownership of data pointer
165
if (unlikely(aclk_queue_query(
127
- cloud_to_agent->callback_topic, data, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
128
- ACLK_CMD_CLOUD_QUERY_2)))
129
- debug(D_ACLK, "ACLK failed to queue incoming \"http\" message");
166
+ cloud_to_agent->callback_topic, cloud_req, cloud_to_agent->msg_id, cloud_to_agent->payload, 0, 0,
167
+ ACLK_CMD_CLOUD_QUERY_2))) {
168
+ error("ACLK failed to queue incoming \"http\" v2 message");
169
+ goto cleanup;
170
+ }
171
131
- UNUSED(cloud_to_agent);
172
return 0;
173
+cleanup:
174
+ freez(cloud_req->data);
175
+ freez(cloud_req);
176
+ return 1;
177
}
178
179
// This handles `version` message from cloud used to negotiate