summaryrefslogtreecommitdiffstats
path: root/aclk/https_client.h
blob: 0b97fbb02531889b90965133fbc1aca1b11730bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_HTTPS_CLIENT_H
#define NETDATA_HTTPS_CLIENT_H

#include "libnetdata/libnetdata.h"

#include "mqtt_websockets/c-rbuf/include/ringbuffer.h"
#include "mqtt_websockets/c_rhash/include/c_rhash.h"

typedef enum http_req_type {
    HTTP_REQ_GET = 0,
    HTTP_REQ_POST,
    HTTP_REQ_CONNECT
} http_req_type_t;

typedef struct {
    http_req_type_t request_type;

    char *host;
    int port;
    char *url;

    time_t timeout_s; //timeout in seconds for the network operation (send/recv)

    void *payload;
    size_t payload_size;

    char *proxy_host;
    int proxy_port;
    const char *proxy_username;
    const char *proxy_password;
} https_req_t;

typedef struct {
    int http_code;

    void *payload;
    size_t payload_size;
} https_req_response_t;


// Non feature complete URL parser
// feel free to extend when needed
// currently implements only what ACLK
// needs
// proto://host[:port]/path
typedef struct {
    char *proto;
    char *host;
    int port;
    char* path;
} url_t;

int url_parse(const char *url, url_t *parsed);
void url_t_destroy(url_t *url);

void https_req_response_free(https_req_response_t *res);
void https_req_response_init(https_req_response_t *res);

#define HTTPS_REQ_RESPONSE_T_INITIALIZER            \
    {                                               \
        .http_code = 0,                             \
        .payload = NULL,                            \
        .payload_size = 0                           \
    }

#define HTTPS_REQ_T_INITIALIZER                     \
    {                                               \
        .request_type = HTTP_REQ_GET,               \
        .host = NULL,                               \
        .port = 443,                                \
        .url = NULL,                                \
        .timeout_s = 30,                            \
        .payload = NULL,                            \
        .payload_size = 0,                          \
        .proxy_host = NULL,                         \
        .proxy_port = 8080                          \
    }

int https_request(https_req_t *request, https_req_response_t *response);

// we expose previously internal parser as this is usefull also from
// other parts of the code
enum http_parse_state {
    HTTP_PARSE_INITIAL = 0,
    HTTP_PARSE_HEADERS,
    HTTP_PARSE_CONTENT
};

typedef uint32_t parse_ctx_flags_t;

#define HTTP_PARSE_FLAG_DONT_WAIT_FOR_CONTENT ((parse_ctx_flags_t)0x01)

#define HTTP_PARSE_FLAGS_DEFAULT ((parse_ctx_flags_t)0)

typedef struct {
    parse_ctx_flags_t flags;

    enum http_parse_state state;
    int content_length;
    int http_code;

    c_rhash headers;

    // for chunked data only
    char *chunked_response;
    size_t chunked_response_size;
    size_t chunked_response_written;

    enum chunked_content_state {
        CHUNKED_CONTENT_CHUNK_SIZE = 0,
        CHUNKED_CONTENT_CHUNK_DATA,
        CHUNKED_CONTENT_CHUNK_END_CRLF,
        CHUNKED_CONTENT_FINAL_CRLF
    } chunked_content_state;

    size_t chunk_size;
    size_t chunk_got;
} http_parse_ctx;

void http_parse_ctx_create(http_parse_ctx *ctx);
void http_parse_ctx_destroy(http_parse_ctx *ctx);

typedef enum {
    HTTP_PARSE_ERROR = -1,
    HTTP_PARSE_NEED_MORE_DATA = 0,
    HTTP_PARSE_SUCCESS = 1
} http_parse_rc;

http_parse_rc parse_http_response(rbuf_t buf, http_parse_ctx *parse_ctx);

const char *get_http_header_by_name(http_parse_ctx *ctx, const char *name);

#endif /* NETDATA_HTTPS_CLIENT_H */