]> gitweb.ps.run Git - matrix_esp_thesis/blob - src/matrix_http_esp32.c
remove newline
[matrix_esp_thesis] / src / matrix_http_esp32.c
1 #include <string.h>\r
2 #include <sys/param.h>\r
3 #include <stdlib.h>\r
4 #include <ctype.h>\r
5 #include "esp_log.h"\r
6 #include "nvs_flash.h"\r
7 #include "esp_event.h"\r
8 #include "esp_netif.h"\r
9 // #include "protocol_examples_common.h"\r
10 // #include "protocol_examples_utils.h"\r
11 #include "esp_tls.h"\r
12 #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE\r
13 #include "esp_crt_bundle.h"\r
14 #endif\r
15 \r
16 #if !CONFIG_IDF_TARGET_LINUX\r
17 #include "freertos/FreeRTOS.h"\r
18 #include "freertos/task.h"\r
19 #include "esp_system.h"\r
20 #endif\r
21 \r
22 #include "esp_http_client.h"\r
23 \r
24 /* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem\r
25 \r
26    The PEM file was extracted from the output of this command:\r
27    openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null\r
28 \r
29    The CA root cert is the last cert given in the chain of certs.\r
30 \r
31    To embed it in the app binary, the PEM file is named\r
32    in the component.mk COMPONENT_EMBED_TXTFILES variable.\r
33 */\r
34 // extern const char howsmyssl_com_root_cert_pem_start[] asm("_binary_howsmyssl_com_root_cert_pem_start");\r
35 // extern const char howsmyssl_com_root_cert_pem_end[]   asm("_binary_howsmyssl_com_root_cert_pem_end");\r
36 \r
37 // extern const char postman_root_cert_pem_start[] asm("_binary_postman_root_cert_pem_start");\r
38 // extern const char postman_root_cert_pem_end[]   asm("_binary_postman_root_cert_pem_end");\r
39 \r
40 #include "matrix.h"\r
41 \r
42 #define HTTP_CONNECTION_DATA_SIZE 1024*64\r
43 #define AUTHORIZATION_HEADER_LEN 64\r
44 \r
45 struct MatrixHttpConnection {\r
46     esp_http_client_handle_t client;\r
47 \r
48     const char * host;\r
49     const char * accessToken;\r
50 \r
51     // char data[HTTP_CONNECTION_DATA_SIZE];\r
52     char * data;\r
53     int dataCap;\r
54     int dataLen;\r
55 };\r
56 \r
57 \r
58 static const char *TAG = "HTTP_CLIENT";\r
59 \r
60 esp_err_t _http_event_handler(esp_http_client_event_t *evt)\r
61 {\r
62     vTaskDelay(10/portTICK_PERIOD_MS);\r
63 \r
64     MatrixHttpConnection * hc = (MatrixHttpConnection *)evt->user_data;\r
65     switch(evt->event_id) {\r
66         case HTTP_EVENT_ERROR:\r
67             ESP_LOGD(TAG, "HTTP_EVENT_ERROR");\r
68             break;\r
69         case HTTP_EVENT_ON_CONNECTED:\r
70             ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");\r
71             break;\r
72         case HTTP_EVENT_HEADER_SENT:\r
73             ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");\r
74             break;\r
75         case HTTP_EVENT_ON_HEADER:\r
76             ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);\r
77             break;\r
78         case HTTP_EVENT_ON_DATA:\r
79             ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);\r
80             /*\r
81              *  Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data.\r
82              *  However, event handler can also be used in case chunked encoding is used.\r
83              */\r
84             if (!esp_http_client_is_chunked_response(evt->client)) {\r
85                 ESP_LOGD(TAG, "Non-Chunked Encoding");\r
86             }\r
87             else {\r
88                 ESP_LOGD(TAG, "Chunked Encoding");\r
89             }\r
90 \r
91             int copy_len = 0;\r
92 \r
93             // const int64_t buffer_len = esp_http_client_get_content_length(evt->client);\r
94             // if (buffer_len < hc->dataCap) {\r
95             //     ESP_LOGE(TAG, "Output buffer too small: %" PRIu64 ", data_len: %d", buffer_len, evt->data_len);\r
96             //     return ESP_FAIL;\r
97             // }\r
98             copy_len = MIN(evt->data_len, (hc->dataCap - hc->dataLen));\r
99             if (copy_len) {\r
100                 memcpy(hc->data + hc->dataLen, evt->data, copy_len);\r
101                 hc->data[hc->dataLen + copy_len] = '\0';\r
102             }\r
103 \r
104             hc->dataLen += copy_len;\r
105 \r
106             break;\r
107         case HTTP_EVENT_ON_FINISH:\r
108             ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");\r
109             break;\r
110         case HTTP_EVENT_DISCONNECTED:\r
111             ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");\r
112             int mbedtls_err = 0;\r
113             esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL);\r
114             if (err != 0) {\r
115                 ESP_LOGI(TAG, "Last esp error code: 0x%x", err);\r
116                 ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err);\r
117             }\r
118             break;\r
119         case HTTP_EVENT_REDIRECT:\r
120             ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");\r
121             // esp_http_client_set_header(evt->client, "From", "user@example.com");\r
122             // esp_http_client_set_header(evt->client, "Accept", "text/html");\r
123             // esp_http_client_set_redirection(evt->client);\r
124             break;\r
125     }\r
126     return ESP_OK;\r
127 }\r
128 \r
129 void\r
130 MatrixHttpConnect(\r
131     MatrixHttpConnection * hc)\r
132 {\r
133     esp_http_client_config_t config = {\r
134         .url = hc->host,\r
135         // .query = "esp",\r
136         .event_handler = _http_event_handler,\r
137         .user_data = hc,\r
138         .disable_auto_redirect = true,\r
139         .crt_bundle_attach = esp_crt_bundle_attach,\r
140     };\r
141 \r
142     hc->client = esp_http_client_init(&config);\r
143 \r
144     esp_http_client_set_timeout_ms(hc->client, 20000);\r
145 }\r
146 \r
147 void\r
148 MatrixHttpDisconnect(\r
149     MatrixHttpConnection * hc)\r
150 {\r
151     esp_http_client_cleanup(hc->client);\r
152     hc->client = NULL;\r
153 }\r
154 \r
155 bool\r
156 MatrixHttpInit(\r
157     MatrixHttpConnection ** hc,\r
158     const char * host)\r
159 {\r
160     *hc = (MatrixHttpConnection *)calloc(1, sizeof(MatrixHttpConnection));\r
161     \r
162     (*hc)->host = host;\r
163 \r
164     MatrixHttpConnect(*hc);\r
165 \r
166     return true;\r
167 }\r
168 \r
169 bool\r
170 MatrixHttpDeinit(\r
171     MatrixHttpConnection ** hc)\r
172 {\r
173     MatrixHttpDisconnect(*hc);\r
174 \r
175     free(*hc);\r
176     *hc = NULL;\r
177 \r
178     return true;\r
179 }\r
180 \r
181 bool\r
182 MatrixHttpSetAccessToken(\r
183     MatrixHttpConnection * hc,\r
184     const char * accessToken)\r
185 {\r
186     hc->accessToken = accessToken;\r
187 \r
188     return true;\r
189 }\r
190 \r
191 bool\r
192 MatrixHttpGet(\r
193     MatrixHttpConnection * hc,\r
194     const char * url,\r
195     char * outResponseBuffer, int outResponseCap,\r
196     bool authenticated)\r
197 {\r
198     static char authorizationHeader[AUTHORIZATION_HEADER_LEN];\r
199     if (authenticated)\r
200         snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,\r
201             "Bearer %s", hc->accessToken);\r
202     else\r
203         authorizationHeader[0] = '\0';\r
204 \r
205     hc->data = outResponseBuffer;\r
206     hc->dataCap = outResponseCap;\r
207     hc->dataLen = 0;\r
208 \r
209     static char hostAndUrl[MAX_URL_LEN];\r
210     snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);\r
211     \r
212     esp_http_client_set_url(hc->client, hostAndUrl);\r
213     esp_http_client_set_method(hc->client, HTTP_METHOD_GET);\r
214     if (authenticated)\r
215         esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);\r
216     esp_err_t err = esp_http_client_perform(hc->client);\r
217     if (err == ESP_OK) {\r
218         ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRIu64,\r
219                 esp_http_client_get_status_code(hc->client),\r
220                 esp_http_client_get_content_length(hc->client));\r
221     } else {\r
222         ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));\r
223     }\r
224     // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);\r
225 \r
226     return true;\r
227 }\r
228 \r
229 bool\r
230 MatrixHttpPost(\r
231     MatrixHttpConnection * hc,\r
232     const char * url,\r
233     const char * requestBuffer,\r
234     char * outResponseBuffer, int outResponseCap,\r
235     bool authenticated)\r
236 {\r
237     static char authorizationHeader[AUTHORIZATION_HEADER_LEN];\r
238     if (authenticated)\r
239         snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,\r
240             "Bearer %s", hc->accessToken);\r
241     else\r
242         authorizationHeader[0] = '\0';\r
243 \r
244     hc->data = outResponseBuffer;\r
245     hc->dataCap = outResponseCap;\r
246     hc->dataLen = 0;\r
247 \r
248     static char hostAndUrl[MAX_URL_LEN];\r
249     snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);\r
250     \r
251     esp_http_client_set_url(hc->client, hostAndUrl);\r
252     esp_http_client_set_method(hc->client, HTTP_METHOD_POST);\r
253     if (authenticated)\r
254         esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);\r
255     esp_http_client_set_header(hc->client, "Content-Type", "application/json");\r
256     esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer));\r
257     esp_err_t err = esp_http_client_perform(hc->client);\r
258     if (err == ESP_OK) {\r
259         ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %"PRIu64,\r
260                 esp_http_client_get_status_code(hc->client),\r
261                 esp_http_client_get_content_length(hc->client));\r
262     } else {\r
263         ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));\r
264     }\r
265     // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);\r
266 \r
267     return true;\r
268 }\r
269 \r
270 bool\r
271 MatrixHttpPut(\r
272     MatrixHttpConnection * hc,\r
273     const char * url,\r
274     const char * requestBuffer,\r
275     char * outResponseBuffer, int outResponseCap,\r
276     bool authenticated)\r
277 {\r
278     static char authorizationHeader[AUTHORIZATION_HEADER_LEN];\r
279     if (authenticated)\r
280         snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN,\r
281             "Bearer %s", hc->accessToken);\r
282     else\r
283         authorizationHeader[0] = '\0';\r
284 \r
285     hc->data = outResponseBuffer;\r
286     hc->dataCap = outResponseCap;\r
287     hc->dataLen = 0;\r
288 \r
289     static char hostAndUrl[MAX_URL_LEN];\r
290     snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url);\r
291     \r
292     esp_http_client_set_url(hc->client, hostAndUrl);\r
293     esp_http_client_set_method(hc->client, HTTP_METHOD_PUT);\r
294     if (authenticated)\r
295         esp_http_client_set_header(hc->client, "Authorization", authorizationHeader);\r
296     esp_http_client_set_header(hc->client, "Content-Type", "application/json");\r
297     esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer));\r
298     esp_err_t err = esp_http_client_perform(hc->client);\r
299     if (err == ESP_OK) {\r
300         ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %"PRIu64,\r
301                 esp_http_client_get_status_code(hc->client),\r
302                 esp_http_client_get_content_length(hc->client));\r
303     } else {\r
304         ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err));\r
305     }\r
306     // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen);\r
307 \r
308     return true;\r
309 }\r