@cryptotaxi247 / netdata-1 / commits / 9f0c8c400

Fix proxy connect response (#18017)

* Fix proxy connect response * Handle CONNECT to mqtt * Fix typo

Stelios Fragkakis committed Jun 27, 2024 at 16:41 UTC 9f0c8c400e15d4200529551957309f8ffc27805a
4 files changed +47 -31
src/aclk/https_client.c
+35 -24
@@ -23,9 +23,9 @@ static const char *http_req_type_to_str(http_req_type_t req) {
23
24 #define TRANSFER_ENCODING_CHUNKED (-2)
25
26 -void http_parse_ctx_create(http_parse_ctx *ctx)
26 +void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state)
27 {
28 - ctx->state = HTTP_PARSE_INITIAL;
28 + ctx->state = parse_state;
29 ctx->content_length = -1;
30 ctx->http_code = 0;
31 ctx->headers = c_rhash_new(0);
@@ -51,6 +51,7 @@ void http_parse_ctx_destroy(http_parse_ctx *ctx)
51
52 #define HTTP_LINE_TERM "\x0D\x0A"
53 #define RESP_PROTO "HTTP/1.1 "
54 +#define RESP_PROTO10 "HTTP/1.0 "
55 #define HTTP_KEYVAL_SEPARATOR ": "
56 #define HTTP_HDR_BUFFER_SIZE 1024
57 #define PORT_STR_MAX_BYTES 12
@@ -244,10 +245,20 @@ http_parse_rc parse_http_response(rbuf_t buf, http_parse_ctx *parse_ctx)
245 if (parse_ctx->state != HTTP_PARSE_CONTENT && !rbuf_find_bytes(buf, HTTP_LINE_TERM, strlen(HTTP_LINE_TERM), &idx))
246 return HTTP_PARSE_NEED_MORE_DATA;
247 switch (parse_ctx->state) {
248 + case HTTP_PARSE_PROXY_CONNECT:
249 case HTTP_PARSE_INITIAL:
250 if (rbuf_memcmp_n(buf, RESP_PROTO, strlen(RESP_PROTO))) {
249 - netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO);
250 - return HTTP_PARSE_ERROR;
251 + if (parse_ctx->state == HTTP_PARSE_PROXY_CONNECT) {
252 + if (rbuf_memcmp_n(buf, RESP_PROTO10, strlen(RESP_PROTO10))) {
253 + netdata_log_error(
254 + "Expected response to start with \"%s\" or \"%s\"", RESP_PROTO, RESP_PROTO10);
255 + return HTTP_PARSE_ERROR;
256 + }
257 + }
258 + else {
259 + netdata_log_error("Expected response to start with \"%s\"", RESP_PROTO);
260 + return HTTP_PARSE_ERROR;
261 + }
262 }
263 rbuf_bump_tail(buf, strlen(RESP_PROTO));
264 if (rbuf_pop(buf, rc, 4) != 4) {
@@ -489,36 +500,36 @@ static int read_parse_response(https_req_ctx_t *ctx) {
500 return 0;
501 }
502
503 +static const char *http_methods[] = {
504 + [HTTP_REQ_GET] = "GET ",
505 + [HTTP_REQ_POST] = "POST ",
506 + [HTTP_REQ_CONNECT] = "CONNECT ",
507 +};
508 +
509 +
510 #define TX_BUFFER_SIZE 8192
511 #define RX_BUFFER_SIZE (TX_BUFFER_SIZE*2)
512 static int handle_http_request(https_req_ctx_t *ctx) {
513 BUFFER *hdr = buffer_create(TX_BUFFER_SIZE, &netdata_buffers_statistics.buffers_aclk);
514 int rc = 0;
515
498 - http_parse_ctx_create(&ctx->parse_ctx);
516 + http_req_type_t req_type = ctx->request->request_type;
517
500 - // Prepare data to send
501 - switch (ctx->request->request_type) {
502 - case HTTP_REQ_CONNECT:
503 - buffer_strcat(hdr, "CONNECT ");
504 - break;
505 - case HTTP_REQ_GET:
506 - buffer_strcat(hdr, "GET ");
507 - break;
508 - case HTTP_REQ_POST:
509 - buffer_strcat(hdr, "POST ");
510 - break;
511 - default:
512 - netdata_log_error("Unknown HTTPS request type!");
513 - rc = 1;
514 - goto err_exit;
518 + if (req_type >= HTTP_REQ_INVALID) {
519 + netdata_log_error("Unknown HTTPS request type!");
520 + rc = 1;
521 + goto err_exit;
522 }
523 + buffer_strcat(hdr, http_methods[req_type]);
524
517 - if (ctx->request->request_type == HTTP_REQ_CONNECT) {
525 + if (req_type == HTTP_REQ_CONNECT) {
526 buffer_strcat(hdr, ctx->request->host);
527 buffer_sprintf(hdr, ":%d", ctx->request->port);
520 - } else {
528 + http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_PROXY_CONNECT);
529 + }
530 + else {
531 buffer_strcat(hdr, ctx->request->url);
532 + http_parse_ctx_create(&ctx->parse_ctx, HTTP_PARSE_INITIAL);
533 }
534
535 buffer_strcat(hdr, HTTP_1_1 HTTP_ENDL);
@@ -527,7 +538,7 @@ static int handle_http_request(https_req_ctx_t *ctx) {
538 buffer_sprintf(hdr, "Host: %s\x0D\x0A", ctx->request->host);
539 buffer_strcat(hdr, "User-Agent: Netdata/rocks newhttpclient\x0D\x0A");
540
530 - if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
541 + if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
542 buffer_sprintf(hdr, "Content-Length: %zu\x0D\x0A", ctx->request->payload_size);
543 }
544 if (ctx->request->proxy_username) {
@@ -558,7 +569,7 @@ static int handle_http_request(https_req_ctx_t *ctx) {
569 goto err_exit;
570 }
571
561 - if (ctx->request->request_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
572 + if (req_type == HTTP_REQ_POST && ctx->request->payload && ctx->request->payload_size) {
573 if (https_client_write_all(ctx, ctx->request->payload, ctx->request->payload_size)) {
574 netdata_log_error("Couldn't write payload into SSL connection");
575 rc = 3;
src/aclk/https_client.h
+5 -3
@@ -11,7 +11,8 @@
11 typedef enum http_req_type {
12 HTTP_REQ_GET = 0,
13 HTTP_REQ_POST,
14 - HTTP_REQ_CONNECT
14 + HTTP_REQ_CONNECT,
15 + HTTP_REQ_INVALID
16 } http_req_type_t;
17
18 typedef struct {
@@ -82,7 +83,8 @@ int https_request(https_req_t *request, https_req_response_t *response);
83 // we expose previously internal parser as this is usefull also from
84 // other parts of the code
85 enum http_parse_state {
85 - HTTP_PARSE_INITIAL = 0,
86 + HTTP_PARSE_PROXY_CONNECT = 0,
87 + HTTP_PARSE_INITIAL,
88 HTTP_PARSE_HEADERS,
89 HTTP_PARSE_CONTENT
90 };
@@ -118,7 +120,7 @@ typedef struct {
120 size_t chunk_got;
121 } http_parse_ctx;
122
121 -void http_parse_ctx_create(http_parse_ctx *ctx);
123 +void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state);
124 void http_parse_ctx_destroy(http_parse_ctx *ctx);
125
126 typedef enum {
src/aclk/mqtt_websockets/mqtt_wss_client.c
+6 -3
@@ -314,6 +314,7 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
314
315 #define PROXY_CONNECT "CONNECT"
316 #define PROXY_HTTP "HTTP/1.1"
317 +#define PROXY_HTTP10 "HTTP/1.0"
318 #define HTTP_ENDLINE "\x0D\x0A"
319 #define HTTP_HDR_TERMINATOR "\x0D\x0A\x0D\x0A"
320 #define HTTP_CODE_LEN 4
@@ -326,14 +327,16 @@ static int http_parse_reply(mqtt_wss_client client, rbuf_t buf)
327 int idx;
328
329 if (rbuf_memcmp_n(buf, PROXY_HTTP, strlen(PROXY_HTTP))) {
329 - mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\"");
330 - return 1;
330 + if (rbuf_memcmp_n(buf, PROXY_HTTP10, strlen(PROXY_HTTP10))) {
331 + mws_error(client->log, "http_proxy expected reply with \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
332 + return 1;
333 + }
334 }
335
336 rbuf_bump_tail(buf, strlen(PROXY_HTTP));
337
338 if (!rbuf_pop(buf, http_code_s, 1) || http_code_s[0] != 0x20) {
336 - mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\"");
339 + mws_error(client->log, "http_proxy missing space after \"" PROXY_HTTP "\" or \"" PROXY_HTTP10 "\"");
340 return 2;
341 }
342
src/streaming/sender.c
+1 -1
@@ -672,7 +672,7 @@ static int rrdpush_http_upgrade_prelude(RRDHOST *host, struct sender_state *s) {
672 rbuf_push(buf, http, bytes);
673
674 http_parse_ctx ctx;
675 - http_parse_ctx_create(&ctx);
675 + http_parse_ctx_create(&ctx, HTTP_PARSE_INITIAL);
676 ctx.flags |= HTTP_PARSE_FLAG_DONT_WAIT_FOR_CONTENT;
677
678 int rc;