X-Git-Url: https://gitweb.ps.run/matrix_esp_thesis/blobdiff_plain/9eaa420b7bf51cc81c50e7f4ca0f256498a07c86..8ceca98f04b88798794748572fce184b92144d2d:/src/matrix_http_esp32.c diff --git a/src/matrix_http_esp32.c b/src/matrix_http_esp32.c new file mode 100644 index 0000000..3faf9f5 --- /dev/null +++ b/src/matrix_http_esp32.c @@ -0,0 +1,315 @@ +#include +#include +#include +#include +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +// #include "protocol_examples_common.h" +// #include "protocol_examples_utils.h" +#include "esp_tls.h" +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE +#include "esp_crt_bundle.h" +#endif + +#if !CONFIG_IDF_TARGET_LINUX +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#endif + +#include "esp_http_client.h" + +/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem + + The PEM file was extracted from the output of this command: + openssl s_client -showcerts -connect www.howsmyssl.com:443 user_data; + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + /* + * Check for chunked encoding is added as the URL for chunked encoding used in this example returns binary data. + * However, event handler can also be used in case chunked encoding is used. + */ + if (!esp_http_client_is_chunked_response(evt->client)) { + ESP_LOGD(TAG, "Non-Chunked Encoding"); + } + else { + ESP_LOGD(TAG, "Chunked Encoding"); + } + + int copy_len = 0; + + // const int64_t buffer_len = esp_http_client_get_content_length(evt->client); + // if (buffer_len < hc->dataCap) { + // ESP_LOGE(TAG, "Output buffer too small: %" PRIu64 ", data_len: %d", buffer_len, evt->data_len); + // return ESP_FAIL; + // } + copy_len = MIN(evt->data_len, (hc->dataCap - hc->dataLen)); + if (copy_len) { + memcpy(hc->data + hc->dataLen, evt->data, copy_len); + } + + hc->dataLen += copy_len; + + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); + int mbedtls_err = 0; + esp_err_t err = esp_tls_get_and_clear_last_error((esp_tls_error_handle_t)evt->data, &mbedtls_err, NULL); + if (err != 0) { + ESP_LOGI(TAG, "Last esp error code: 0x%x", err); + ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); + } + break; + case HTTP_EVENT_REDIRECT: + ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); + // esp_http_client_set_header(evt->client, "From", "user@example.com"); + // esp_http_client_set_header(evt->client, "Accept", "text/html"); + // esp_http_client_set_redirection(evt->client); + break; + } + return ESP_OK; +} + +void +MatrixHttpConnect( + MatrixHttpConnection * hc) +{ + esp_http_client_config_t config = { + .url = hc->host, + // .query = "esp", + .event_handler = _http_event_handler, + .user_data = hc, + .disable_auto_redirect = true, + .crt_bundle_attach = esp_crt_bundle_attach, + }; + + hc->client = esp_http_client_init(&config); + + esp_http_client_set_timeout_ms(hc->client, 10000); +} + +void +MatrixHttpDisconnect( + MatrixHttpConnection * hc) +{ + esp_http_client_cleanup(hc->client); + hc->client = NULL; +} + +bool +MatrixHttpInit( + MatrixHttpConnection ** hc, + const char * host) +{ + *hc = (MatrixHttpConnection *)calloc(1, sizeof(MatrixHttpConnection)); + + (*hc)->host = host; + (*hc)->dataLen = 0; + + MatrixHttpConnect(*hc); + + return true; +} + +bool +MatrixHttpDeinit( + MatrixHttpConnection ** hc) +{ + MatrixHttpDisconnect(*hc); + + free(*hc); + *hc = NULL; + + return true; +} + +bool +MatrixHttpSetAccessToken( + MatrixHttpConnection * hc, + const char * accessToken) +{ + hc->accessToken = accessToken; + + return true; +} + +bool +MatrixHttpGet( + MatrixHttpConnection * hc, + const char * url, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("GET %s%s\n", hc->host, url); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_GET); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +} + +bool +MatrixHttpPost( + MatrixHttpConnection * hc, + const char * url, + const char * requestBuffer, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("POST %s%s\n%s\n", hc->host, url, requestBuffer); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_POST); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_http_client_set_header(hc->client, "Content-Type", "application/json"); + esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +} + +bool +MatrixHttpPut( + MatrixHttpConnection * hc, + const char * url, + const char * requestBuffer, + char * outResponseBuffer, int outResponseCap, + bool authenticated) +{ + static char authorizationHeader[AUTHORIZATION_HEADER_LEN]; + if (authenticated) + snprintf(authorizationHeader, AUTHORIZATION_HEADER_LEN, + "Bearer %s", hc->accessToken); + else + authorizationHeader[0] = '\0'; + + printf("PUT %s%s\n%s\n", hc->host, url, requestBuffer); + + hc->data = outResponseBuffer; + hc->dataCap = outResponseCap; + hc->dataLen = 0; + + static char hostAndUrl[MAX_URL_LEN]; + snprintf(hostAndUrl, MAX_URL_LEN, "%s%s", hc->host, url); + + esp_http_client_set_url(hc->client, hostAndUrl); + esp_http_client_set_method(hc->client, HTTP_METHOD_PUT); + if (authenticated) + esp_http_client_set_header(hc->client, "Authorization", authorizationHeader); + esp_http_client_set_header(hc->client, "Content-Type", "application/json"); + esp_http_client_set_post_field(hc->client, requestBuffer, strlen(requestBuffer)); + esp_err_t err = esp_http_client_perform(hc->client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %"PRIu64, + esp_http_client_get_status_code(hc->client), + esp_http_client_get_content_length(hc->client)); + } else { + ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err)); + } + // ESP_LOG_BUFFER_HEX(TAG, hc->data, hc->dataLen); + + return true; +}