Prechádzať zdrojové kódy

Merge branch 'feature/esp_http_server_on_linux' into 'master'

Feature/esp http server on linux

Closes IDF-6608

See merge request espressif/esp-idf!21960
Mahavir Jain 2 rokov pred
rodič
commit
4ee6eda12e

+ 25 - 3
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()

+ 1 - 0
components/esp_http_server/include/esp_http_server.h

@@ -15,6 +15,7 @@
 #include <sdkconfig.h>
 #include <esp_err.h>
 #include <esp_event.h>
+#include <esp_event_base.h>
 
 #ifdef __cplusplus
 extern "C" {

+ 8 - 0
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 */

+ 10 - 2
components/esp_http_server/src/httpd_main.c

@@ -11,6 +11,7 @@
 #include <esp_log.h>
 #include <esp_err.h>
 #include <assert.h>
+#include <netinet/tcp.h>
 
 #include <esp_http_server.h>
 #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;
     }
 

+ 19 - 14
components/esp_http_server/src/httpd_parse.c

@@ -6,6 +6,11 @@
 
 
 #include <stdlib.h>
+#include <string.h>
+#if __has_include(<bsd/string.h>)
+// for strlcpy
+#include <bsd/string.h>
+#endif
 #include <sys/param.h>
 #include <esp_log.h>
 #include <esp_err.h>
@@ -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;
 }
 

+ 7 - 6
components/esp_http_server/src/httpd_txrx.c

@@ -11,6 +11,7 @@
 
 #include <esp_http_server.h>
 #include "esp_httpd_priv.h"
+#include <netinet/tcp.h>
 
 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;

+ 6 - 6
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 */

+ 55 - 0
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 <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#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

+ 11 - 2
components/esp_http_server/src/util/ctrl_sock.c

@@ -10,9 +10,18 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#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);

+ 1 - 1
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 "."

+ 6 - 2
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)

+ 6 - 1
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})

+ 42 - 10
examples/protocols/http_server/simple/main/main.c

@@ -7,19 +7,27 @@
    CONDITIONS OF ANY KIND, either express or implied.
 */
 
-#include <esp_wifi.h>
-#include <esp_event.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
 #include <esp_log.h>
-#include <esp_system.h>
 #include <nvs_flash.h>
 #include <sys/param.h>
-#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 <esp_http_server.h>
+#include "esp_event.h"
+#include "esp_netif.h"
+#include "esp_tls.h"
+
+#if !CONFIG_IDF_TARGET_LINUX
+#include <esp_wifi.h>
+#include <esp_system.h>
+#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);
+    }
 }

+ 1 - 6
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;
 }

+ 0 - 14
examples/protocols/linux_stubs/esp_stubs/include/nvs_flash.h

@@ -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);

+ 1 - 1
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)