diff --git a/components/esp_http_server/CMakeLists.txt b/components/esp_http_server/CMakeLists.txt index c660da3aa5..418f210acd 100644 --- a/components/esp_http_server/CMakeLists.txt +++ b/components/esp_http_server/CMakeLists.txt @@ -1,3 +1,16 @@ +set(priv_req mbedtls) +set(priv_inc_dir "src/util") +set(requires http_parser) +if(NOT ${IDF_TARGET} STREQUAL "linux") + list(APPEND priv_req lwip esp_timer) + list(APPEND priv_inc_dir "src/port/esp32") + list(APPEND requires esp_event) +else() + list(APPEND priv_inc_dir "src/port/linux") + list(APPEND priv_req pthread) + list(APPEND requires linux) +endif() + idf_component_register(SRCS "src/httpd_main.c" "src/httpd_parse.c" "src/httpd_sess.c" @@ -6,6 +19,15 @@ idf_component_register(SRCS "src/httpd_main.c" "src/httpd_ws.c" "src/util/ctrl_sock.c" INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "src/port/esp32" "src/util" - REQUIRES esp_event http_parser # for http_parser.h - PRIV_REQUIRES lwip mbedtls esp_timer) + PRIV_INCLUDE_DIRS ${priv_inc_dir} + REQUIRES ${requires} + PRIV_REQUIRES ${priv_req}) + +if(${IDF_TARGET} STREQUAL "linux") + find_library(LIB_BSD bsd) + if(LIB_BSD) + target_link_libraries(${COMPONENT_LIB} PRIVATE ${LIB_BSD}) + elseif(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + message(WARNING "Missing LIBBSD library. Install libbsd-dev package and/or check linker directories.") + endif() +endif() diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index 3826a40c9a..39c2a82a31 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/components/esp_http_server/src/esp_httpd_priv.h b/components/esp_http_server/src/esp_httpd_priv.h index 7aa47241bb..b84905eefe 100644 --- a/components/esp_http_server/src/esp_httpd_priv.h +++ b/components/esp_http_server/src/esp_httpd_priv.h @@ -22,6 +22,14 @@ extern "C" { #endif +#if CONFIG_NEWLIB_NANO_FORMAT +#define NEWLIB_NANO_COMPAT_FORMAT PRIu32 +#define NEWLIB_NANO_COMPAT_CAST(size_t_var) (uint32_t)size_t_var +#else +#define NEWLIB_NANO_COMPAT_FORMAT "zu" +#define NEWLIB_NANO_COMPAT_CAST(size_t_var) size_t_var +#endif + /* Size of request data block/chunk (not to be confused with chunked encoded data) * that is received and parsed in one turn of the parsing process. This should not * exceed the scratch buffer size and should at least be 8 bytes */ diff --git a/components/esp_http_server/src/httpd_main.c b/components/esp_http_server/src/httpd_main.c index c93d8b3bdf..db1500039e 100644 --- a/components/esp_http_server/src/httpd_main.c +++ b/components/esp_http_server/src/httpd_main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "esp_httpd_priv.h" @@ -19,6 +20,13 @@ #include "freertos/semphr.h" #endif +#if defined(CONFIG_LWIP_MAX_SOCKETS) +#define HTTPD_MAX_SOCKETS CONFIG_LWIP_MAX_SOCKETS +#else +/* LwIP component is not included into the build, use a default value */ +#define HTTPD_MAX_SOCKETS 15 +#endif + static const int DEFAULT_KEEP_ALIVE_IDLE = 5; static const int DEFAULT_KEEP_ALIVE_INTERVAL= 5; static const int DEFAULT_KEEP_ALIVE_COUNT= 3; @@ -476,10 +484,10 @@ esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config) * 3) for receiving control messages over UDP * So the total number of required sockets is max_open_sockets + 3 */ - if (CONFIG_LWIP_MAX_SOCKETS < config->max_open_sockets + 3) { + if (HTTPD_MAX_SOCKETS < config->max_open_sockets + 3) { ESP_LOGE(TAG, "Config option max_open_sockets is too large (max allowed %d, 3 sockets used by HTTP server internally)\n\t" "Either decrease this or configure LWIP_MAX_SOCKETS to a larger value", - CONFIG_LWIP_MAX_SOCKETS - 3); + HTTPD_MAX_SOCKETS - 3); return ESP_ERR_INVALID_ARG; } diff --git a/components/esp_http_server/src/httpd_parse.c b/components/esp_http_server/src/httpd_parse.c index 9c27c297a5..aceb832f21 100644 --- a/components/esp_http_server/src/httpd_parse.c +++ b/components/esp_http_server/src/httpd_parse.c @@ -6,6 +6,11 @@ #include +#include +#if __has_include() +// for strlcpy +#include +#endif #include #include #include @@ -72,8 +77,8 @@ static esp_err_t verify_url (http_parser *parser) } if (sizeof(r->uri) < (length + 1)) { - ESP_LOGW(TAG, LOG_FMT("URI length (%d) greater than supported (%d)"), - length, sizeof(r->uri)); + ESP_LOGW(TAG, LOG_FMT("URI length (%"NEWLIB_NANO_COMPAT_FORMAT") greater than supported (%"NEWLIB_NANO_COMPAT_FORMAT")"), + NEWLIB_NANO_COMPAT_CAST(length), NEWLIB_NANO_COMPAT_CAST(sizeof(r->uri))); parser_data->error = HTTPD_414_URI_TOO_LONG; return ESP_FAIL; } @@ -126,12 +131,12 @@ static esp_err_t cb_url(http_parser *parser, return ESP_FAIL; } - ESP_LOGD(TAG, LOG_FMT("processing url = %.*s"), length, at); + ESP_LOGD(TAG, LOG_FMT("processing url = %.*s"), (int)length, at); /* Update length of URL string */ if ((parser_data->last.length += length) > HTTPD_MAX_URI_LEN) { - ESP_LOGW(TAG, LOG_FMT("URI length (%d) greater than supported (%d)"), - parser_data->last.length, HTTPD_MAX_URI_LEN); + ESP_LOGW(TAG, LOG_FMT("URI length (%"NEWLIB_NANO_COMPAT_FORMAT") greater than supported (%d)"), + NEWLIB_NANO_COMPAT_CAST(parser_data->last.length), HTTPD_MAX_URI_LEN); parser_data->error = HTTPD_414_URI_TOO_LONG; parser_data->status = PARSING_FAILED; return ESP_FAIL; @@ -149,7 +154,7 @@ static esp_err_t pause_parsing(http_parser *parser, const char* at) * and hence needs to be read again later for parsing */ ssize_t unparsed = parser_data->raw_datalen - (at - ra->scratch); if (unparsed < 0) { - ESP_LOGE(TAG, LOG_FMT("parsing beyond valid data = %d"), -unparsed); + ESP_LOGE(TAG, LOG_FMT("parsing beyond valid data = %d"), (int)(-unparsed)); return ESP_ERR_INVALID_STATE; } @@ -157,7 +162,7 @@ static esp_err_t pause_parsing(http_parser *parser, const char* at) * receiving again with httpd_recv_with_opt() later when * read_block() executes */ if (unparsed && (unparsed != httpd_unrecv(r, at, unparsed))) { - ESP_LOGE(TAG, LOG_FMT("data too large for un-recv = %d"), unparsed); + ESP_LOGE(TAG, LOG_FMT("data too large for un-recv = %d"), (int)unparsed); return ESP_FAIL; } @@ -181,7 +186,7 @@ static size_t continue_parsing(http_parser *parser, size_t length) * so we must skip that before parsing resumes */ length = MIN(length, data->pre_parsed); data->pre_parsed -= length; - ESP_LOGD(TAG, LOG_FMT("skip pre-parsed data of size = %d"), length); + ESP_LOGD(TAG, LOG_FMT("skip pre-parsed data of size = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(length)); http_parser_pause(parser, 0); data->paused = false; @@ -241,7 +246,7 @@ static esp_err_t cb_header_field(http_parser *parser, const char *at, size_t len return ESP_FAIL; } - ESP_LOGD(TAG, LOG_FMT("processing field = %.*s"), length, at); + ESP_LOGD(TAG, LOG_FMT("processing field = %.*s"), (int)length, at); /* Update length of header string */ parser_data->last.length += length; @@ -285,7 +290,7 @@ static esp_err_t cb_header_value(http_parser *parser, const char *at, size_t len return ESP_FAIL; } - ESP_LOGD(TAG, LOG_FMT("processing value = %.*s"), length, at); + ESP_LOGD(TAG, LOG_FMT("processing value = %.*s"), (int)length, at); /* Update length of header string */ parser_data->last.length += length; @@ -366,7 +371,7 @@ static esp_err_t cb_headers_complete(http_parser *parser) parser->content_length : 0); ESP_LOGD(TAG, LOG_FMT("bytes read = %" PRId32 ""), parser->nread); - ESP_LOGD(TAG, LOG_FMT("content length = %zu"), r->content_len); + ESP_LOGD(TAG, LOG_FMT("content length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(r->content_len)); /* Handle upgrade requests - only WebSocket is supported for now */ if (parser->upgrade) { @@ -582,14 +587,14 @@ static int parse_block(http_parser *parser, size_t offset, size_t length) /* http_parser error */ data->error = HTTPD_400_BAD_REQUEST; data->status = PARSING_FAILED; - ESP_LOGW(TAG, LOG_FMT("incomplete (%d/%d) with parser error = %d"), - nparsed, length, parser->http_errno); + ESP_LOGW(TAG, LOG_FMT("incomplete (%"NEWLIB_NANO_COMPAT_FORMAT"/%"NEWLIB_NANO_COMPAT_FORMAT") with parser error = %d"), + NEWLIB_NANO_COMPAT_CAST(nparsed), NEWLIB_NANO_COMPAT_CAST(length), parser->http_errno); return -1; } /* Return with the total length of the request packet * that has been parsed till now */ - ESP_LOGD(TAG, LOG_FMT("parsed block size = %d"), offset + nparsed); + ESP_LOGD(TAG, LOG_FMT("parsed block size = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST((offset + nparsed))); return offset + nparsed; } diff --git a/components/esp_http_server/src/httpd_txrx.c b/components/esp_http_server/src/httpd_txrx.c index 192e738d71..b7e6ee6f78 100644 --- a/components/esp_http_server/src/httpd_txrx.c +++ b/components/esp_http_server/src/httpd_txrx.c @@ -11,6 +11,7 @@ #include #include "esp_httpd_priv.h" +#include static const char *TAG = "httpd_txrx"; @@ -96,14 +97,14 @@ static size_t httpd_recv_pending(httpd_req_t *r, char *buf, size_t buf_len) int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending) { - ESP_LOGD(TAG, LOG_FMT("requested length = %d"), buf_len); + ESP_LOGD(TAG, LOG_FMT("requested length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(buf_len)); size_t pending_len = 0; struct httpd_req_aux *ra = r->aux; /* First fetch pending data from local buffer */ if (ra->sd->pending_len > 0) { - ESP_LOGD(TAG, LOG_FMT("pending length = %d"), ra->sd->pending_len); + ESP_LOGD(TAG, LOG_FMT("pending length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(ra->sd->pending_len)); pending_len = httpd_recv_pending(r, buf, buf_len); buf += pending_len; buf_len -= pending_len; @@ -132,7 +133,7 @@ int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_aft return ret; } - ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len); + ESP_LOGD(TAG, LOG_FMT("received length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST((ret + pending_len))); return ret + pending_len; } @@ -151,7 +152,7 @@ size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len) * such that it is right aligned inside the buffer */ size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len; memcpy(ra->sd->pending_data + offset, buf, ra->sd->pending_len); - ESP_LOGD(TAG, LOG_FMT("length = %d"), ra->sd->pending_len); + ESP_LOGD(TAG, LOG_FMT("length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(ra->sd->pending_len)); return ra->sd->pending_len; } @@ -360,7 +361,7 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len /* Sending chunked content */ char len_str[10]; - snprintf(len_str, sizeof(len_str), "%x\r\n", buf_len); + snprintf(len_str, sizeof(len_str), "%lx\r\n", (long)buf_len); if (httpd_send_all(r, len_str, strlen(len_str)) != ESP_OK) { return ESP_ERR_HTTPD_RESP_SEND; } @@ -529,7 +530,7 @@ int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len) } struct httpd_req_aux *ra = r->aux; - ESP_LOGD(TAG, LOG_FMT("remaining length = %d"), ra->remaining_len); + ESP_LOGD(TAG, LOG_FMT("remaining length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(ra->remaining_len)); if (buf_len > ra->remaining_len) { buf_len = ra->remaining_len; diff --git a/components/esp_http_server/src/httpd_ws.c b/components/esp_http_server/src/httpd_ws.c index ffc6a5a1f2..01e16b62b6 100644 --- a/components/esp_http_server/src/httpd_ws.c +++ b/components/esp_http_server/src/httpd_ws.c @@ -153,7 +153,7 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *suppor char subprotocol[50] = { '\0' }; if (httpd_req_get_hdr_value_str(req, "Sec-WebSocket-Protocol", subprotocol, sizeof(subprotocol) - 1) == ESP_ERR_HTTPD_RESULT_TRUNC) { - ESP_LOGW(TAG, "Sec-WebSocket-Protocol length exceeded buffer size of %d, was trunctated", sizeof(subprotocol)); + ESP_LOGW(TAG, "Sec-WebSocket-Protocol length exceeded buffer size of %"NEWLIB_NANO_COMPAT_FORMAT", was trunctated", NEWLIB_NANO_COMPAT_CAST(sizeof(subprotocol))); } @@ -175,7 +175,7 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *suppor int r = snprintf(tx_buf + fmt_len, sizeof(tx_buf) - fmt_len, "Sec-WebSocket-Protocol: %s\r\n", supported_subprotocol); if (r <= 0) { ESP_LOGE(TAG, "Error in response generation" - "(snprintf of subprotocol returned %d, buffer size: %d", r, sizeof(tx_buf)); + "(snprintf of subprotocol returned %d, buffer size: %"NEWLIB_NANO_COMPAT_FORMAT, r, NEWLIB_NANO_COMPAT_CAST(sizeof(tx_buf))); return ESP_FAIL; } @@ -183,7 +183,7 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *suppor if (fmt_len >= sizeof(tx_buf)) { ESP_LOGE(TAG, "Error in response generation" - "(snprintf of subprotocol returned %d, desired response len: %d, buffer size: %d", r, fmt_len, sizeof(tx_buf)); + "(snprintf of subprotocol returned %d, desired response len: %d, buffer size: %"NEWLIB_NANO_COMPAT_FORMAT, r, fmt_len, NEWLIB_NANO_COMPAT_CAST(sizeof(tx_buf))); return ESP_FAIL; } } @@ -191,13 +191,13 @@ esp_err_t httpd_ws_respond_server_handshake(httpd_req_t *req, const char *suppor int r = snprintf(tx_buf + fmt_len, sizeof(tx_buf) - fmt_len, "\r\n"); if (r <= 0) { ESP_LOGE(TAG, "Error in response generation" - "(snprintf of subprotocol returned %d, buffer size: %d", r, sizeof(tx_buf)); + "(snprintf of subprotocol returned %d, buffer size: %"NEWLIB_NANO_COMPAT_FORMAT, r, NEWLIB_NANO_COMPAT_CAST(sizeof(tx_buf))); return ESP_FAIL; } fmt_len += r; if (fmt_len >= sizeof(tx_buf)) { ESP_LOGE(TAG, "Error in response generation" - "(snprintf of header terminal returned %d, desired response len: %d, buffer size: %d", r, fmt_len, sizeof(tx_buf)); + "(snprintf of header terminal returned %d, desired response len: %d, buffer size: %"NEWLIB_NANO_COMPAT_FORMAT, r, fmt_len, NEWLIB_NANO_COMPAT_CAST(sizeof(tx_buf))); return ESP_FAIL; } @@ -354,7 +354,7 @@ esp_err_t httpd_ws_recv_frame(httpd_req_t *req, httpd_ws_frame_t *frame, size_t offset += read_len; left_len -= read_len; - ESP_LOGD(TAG, "Frame length: %d, Bytes Read: %d", frame->len, offset); + ESP_LOGD(TAG, "Frame length: %"NEWLIB_NANO_COMPAT_FORMAT", Bytes Read: %"NEWLIB_NANO_COMPAT_FORMAT, NEWLIB_NANO_COMPAT_CAST(frame->len), NEWLIB_NANO_COMPAT_CAST(offset)); } /* Unmask payload */ diff --git a/components/esp_http_server/src/port/linux/osal.h b/components/esp_http_server/src/port/linux/osal.h new file mode 100644 index 0000000000..dd2df6aaee --- /dev/null +++ b/components/esp_http_server/src/port/linux/osal.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OS_SUCCESS ESP_OK +#define OS_FAIL ESP_FAIL + +typedef TaskHandle_t othread_t; + +static inline int httpd_os_thread_create(othread_t *thread, + const char *name, uint16_t stacksize, int prio, + void (*thread_routine)(void *arg), void *arg, + BaseType_t core_id) +{ + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setstacksize(&thread_attr, stacksize); + int ret = pthread_create((pthread_t *)thread, &thread_attr, (void*)thread_routine, arg); + if (ret == 0) { + return OS_SUCCESS; + } + return OS_FAIL; +} + +/* Only self delete is supported */ +static inline void httpd_os_thread_delete(void) +{ + int x; + pthread_exit((void *)&x); +} + +static inline void httpd_os_thread_sleep(int msecs) +{ + usleep(msecs * 1000); +} + +static inline othread_t httpd_os_thread_handle(void) +{ + return (othread_t)pthread_self(); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_http_server/src/util/ctrl_sock.c b/components/esp_http_server/src/util/ctrl_sock.c index 83ffc8c90b..65d6e7f972 100644 --- a/components/esp_http_server/src/util/ctrl_sock.c +++ b/components/esp_http_server/src/util/ctrl_sock.c @@ -10,9 +10,18 @@ #include #include #include +#include "sdkconfig.h" #include "ctrl_sock.h" +#if CONFIG_IDF_TARGET_LINUX +#define IPV4_ENABLED 1 +#define IPV6_ENABLED 1 +#else // CONFIG_IDF_TARGET_LINUX +#define IPV4_ENABLED CONFIG_LWIP_IPV4 +#define IPV6_ENABLED CONFIG_LWIP_IPV6 +#endif // !CONFIG_IDF_TARGET_LINUX + /* Control socket, because in some network stacks select can't be woken up any * other way */ @@ -25,7 +34,7 @@ int cs_create_ctrl_sock(int port) int ret; struct sockaddr_storage addr = {}; -#ifdef CONFIG_LWIP_IPV4 +#if IPV4_ENABLED struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; addr4->sin_family = AF_INET; addr4->sin_port = htons(port); @@ -53,7 +62,7 @@ int cs_send_to_ctrl_sock(int send_fd, int port, void *data, unsigned int data_le { int ret; struct sockaddr_storage to_addr = {}; -#ifdef CONFIG_LWIP_IPV4 +#if IPV4_ENABLED struct sockaddr_in *addr4 = (struct sockaddr_in *)&to_addr; addr4->sin_family = AF_INET; addr4->sin_port = htons(port); diff --git a/examples/protocols/esp_http_client/main/CMakeLists.txt b/examples/protocols/esp_http_client/main/CMakeLists.txt index cc80568867..70ed376538 100644 --- a/examples/protocols/esp_http_client/main/CMakeLists.txt +++ b/examples/protocols/esp_http_client/main/CMakeLists.txt @@ -3,7 +3,7 @@ # (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) set(requires "") if(${IDF_TARGET} STREQUAL "linux") - list(APPEND requires esp_stubs esp-tls esp_http_client protocol_examples_common) + list(APPEND requires esp_stubs esp-tls esp_http_client protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "esp_http_client_example.c" INCLUDE_DIRS "." diff --git a/examples/protocols/http_server/simple/CMakeLists.txt b/examples/protocols/http_server/simple/CMakeLists.txt index 62cb350dd4..33574050bb 100644 --- a/examples/protocols/http_server/simple/CMakeLists.txt +++ b/examples/protocols/http_server/simple/CMakeLists.txt @@ -2,9 +2,13 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -# (Not part of the boilerplate) -# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +if(${IDF_TARGET} STREQUAL "linux") + list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/" + "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs") + set(COMPONENTS main) +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(simple) diff --git a/examples/protocols/http_server/simple/main/CMakeLists.txt b/examples/protocols/http_server/simple/main/CMakeLists.txt index cf2c455cb5..28894fd56e 100644 --- a/examples/protocols/http_server/simple/main/CMakeLists.txt +++ b/examples/protocols/http_server/simple/main/CMakeLists.txt @@ -1,2 +1,7 @@ +set(requires "") +if(${IDF_TARGET} STREQUAL "linux") + list(APPEND requires esp_stubs esp-tls esp_http_server protocol_examples_common nvs_flash) +endif() idf_component_register(SRCS "main.c" - INCLUDE_DIRS ".") + INCLUDE_DIRS "." + REQUIRES ${requires}) diff --git a/examples/protocols/http_server/simple/main/main.c b/examples/protocols/http_server/simple/main/main.c index eddc0cb9e4..4a0678a39c 100644 --- a/examples/protocols/http_server/simple/main/main.c +++ b/examples/protocols/http_server/simple/main/main.c @@ -7,19 +7,27 @@ CONDITIONS OF ANY KIND, either express or implied. */ -#include -#include +#include +#include +#include #include -#include #include #include -#include "nvs_flash.h" #include "esp_netif.h" -#include "esp_eth.h" #include "protocol_examples_common.h" #include "protocol_examples_utils.h" #include "esp_tls_crypto.h" #include +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_tls.h" + +#if !CONFIG_IDF_TARGET_LINUX +#include +#include +#include "nvs_flash.h" +#include "esp_eth.h" +#endif // !CONFIG_IDF_TARGET_LINUX #define EXAMPLE_HTTP_QUERY_KEY_MAX_LEN (64) @@ -40,11 +48,16 @@ typedef struct { static char *http_auth_basic(const char *username, const char *password) { - int out; + size_t out; char *user_info = NULL; char *digest = NULL; size_t n = 0; - asprintf(&user_info, "%s:%s", username, password); + int rc = asprintf(&user_info, "%s:%s", username, password); + if (rc < 0) { + ESP_LOGE(TAG, "asprintf() returned: %d", rc); + return NULL; + } + if (!user_info) { ESP_LOGE(TAG, "No enough memory for user information"); return NULL; @@ -58,7 +71,7 @@ static char *http_auth_basic(const char *username, const char *password) digest = calloc(1, 6 + n + 1); if (digest) { strcpy(digest, "Basic "); - esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info)); + esp_crypto_base64_encode((unsigned char *)digest + 6, n, &out, (const unsigned char *)user_info, strlen(user_info)); } free(user_info); return digest; @@ -105,7 +118,12 @@ static esp_err_t basic_auth_get_handler(httpd_req_t *req) httpd_resp_set_status(req, HTTPD_200); httpd_resp_set_type(req, "application/json"); httpd_resp_set_hdr(req, "Connection", "keep-alive"); - asprintf(&basic_auth_resp, "{\"authenticated\": true,\"user\": \"%s\"}", basic_auth_info->username); + int rc = asprintf(&basic_auth_resp, "{\"authenticated\": true,\"user\": \"%s\"}", basic_auth_info->username); + if (rc < 0) { + ESP_LOGE(TAG, "asprintf() returned: %d", rc); + free(auth_credentials); + return ESP_FAIL; + } if (!basic_auth_resp) { ESP_LOGE(TAG, "No enough memory for basic authorization response"); free(auth_credentials); @@ -351,6 +369,13 @@ static httpd_handle_t start_webserver(void) { httpd_handle_t server = NULL; httpd_config_t config = HTTPD_DEFAULT_CONFIG(); +#if CONFIG_IDF_TARGET_LINUX + // Setting port as 8001 when building for Linux. Port 80 can be used only by a priviliged user in linux. + // So when a unpriviliged user tries to run the application, it throws bind error and the server is not started. + // Port 8001 can be used by an unpriviliged user as well. So the application will not throw bind error and the + // server will be started. + config.server_port = 8001; +#endif // !CONFIG_IDF_TARGET_LINUX config.lru_purge_enable = true; // Start the httpd server @@ -371,6 +396,7 @@ static httpd_handle_t start_webserver(void) return NULL; } +#if !CONFIG_IDF_TARGET_LINUX static esp_err_t stop_webserver(httpd_handle_t server) { // Stop the httpd server @@ -400,7 +426,7 @@ static void connect_handler(void* arg, esp_event_base_t event_base, *server = start_webserver(); } } - +#endif // !CONFIG_IDF_TARGET_LINUX void app_main(void) { @@ -419,6 +445,7 @@ void app_main(void) /* Register event handlers to stop the server when Wi-Fi or Ethernet is disconnected, * and re-start it upon connection. */ +#if !CONFIG_IDF_TARGET_LINUX #ifdef CONFIG_EXAMPLE_CONNECT_WIFI ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server)); ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server)); @@ -427,7 +454,12 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server)); ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server)); #endif // CONFIG_EXAMPLE_CONNECT_ETHERNET +#endif // !CONFIG_IDF_TARGET_LINUX /* Start the server for the first time */ server = start_webserver(); + + while (server) { + sleep(5); + } } diff --git a/examples/protocols/linux_stubs/esp_stubs/esp_stubs.c b/examples/protocols/linux_stubs/esp_stubs/esp_stubs.c index 989162f74e..cd2216f89f 100644 --- a/examples/protocols/linux_stubs/esp_stubs/esp_stubs.c +++ b/examples/protocols/linux_stubs/esp_stubs/esp_stubs.c @@ -15,12 +15,7 @@ esp_err_t esp_netif_init(void) return ESP_OK; } -esp_err_t nvs_flash_init(void) -{ - return ESP_OK; -} - -esp_err_t nvs_flash_erase(void) +esp_err_t example_connect(void) { return ESP_OK; } diff --git a/examples/protocols/linux_stubs/esp_stubs/include/nvs_flash.h b/examples/protocols/linux_stubs/esp_stubs/include/nvs_flash.h deleted file mode 100644 index 87ebc96a33..0000000000 --- a/examples/protocols/linux_stubs/esp_stubs/include/nvs_flash.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include "esp_err.h" - -#define ESP_ERR_NVS_BASE 0x1100 /*!< Starting number of error codes */ -#define ESP_ERR_NVS_NO_FREE_PAGES (ESP_ERR_NVS_BASE + 0x0d) /*!< NVS partition doesn't contain any empty pages. This may happen if NVS partition was truncated. Erase the whole partition and call nvs_flash_init again. */ -#define ESP_ERR_NVS_NEW_VERSION_FOUND (ESP_ERR_NVS_BASE + 0x10) /*!< NVS partition contains data in new format and cannot be recognized by this version of code */ - -esp_err_t nvs_flash_init(void); - -esp_err_t nvs_flash_erase(void); diff --git a/examples/protocols/sockets/tcp_client/main/CMakeLists.txt b/examples/protocols/sockets/tcp_client/main/CMakeLists.txt index ce931f8b55..721b9c9316 100644 --- a/examples/protocols/sockets/tcp_client/main/CMakeLists.txt +++ b/examples/protocols/sockets/tcp_client/main/CMakeLists.txt @@ -1,5 +1,5 @@ if(${IDF_TARGET} STREQUAL "linux") - set(requires esp_stubs protocol_examples_common) + set(requires esp_stubs protocol_examples_common nvs_flash) endif() if("${CONFIG_EXAMPLE_IPV4}" STREQUAL y)