/* SPDX-License-Identifier: GPL-3.0-only */ #include #include #include #include #include #include #include #include #include typedef int esp_err_t; enum { ESP_OK, ESP_FAIL, ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_STATE, ESP_ERR_NO_MEM, ESP_ERR_TIMEOUT, ESP_ERR_NOT_SUPPORTED }; typedef void *httpd_handle_t; typedef struct { int unused; } httpd_uri_t; struct httpd_req_aux; typedef struct { httpd_handle_t handle; struct httpd_req_aux *aux; } httpd_req_t; struct sock_db { int fd; uint64_t lru_counter; bool for_async_req, ws_handshake_done, ws_close; size_t pending_len; int (*pending_fn)(httpd_handle_t, int); }; struct httpd_req_aux { struct sock_db *sd; size_t remaining_len; }; struct httpd_data { struct { unsigned max_open_sockets; } config; struct { void *handle; } hd_td; struct sock_db *hd_sd; struct httpd_req_aux hd_req_aux; httpd_req_t hd_req; uint64_t lru_counter; }; static bool owner; static unsigned lock_depth, shutdown_calls, select_calls; static int shutdown_error, select_error, tls_pending[FD_SETSIZE]; static int64_t now_us; static void *httpd_os_thread_handle(void) { return owner ? (void *)1 : (void *)2; } typedef int portMUX_TYPE; #define portMUX_INITIALIZER_UNLOCKED 0 #define taskENTER_CRITICAL(lock) do { (void)(lock); assert(!lock_depth); ++lock_depth; } while (0) #define taskEXIT_CRITICAL(lock) do { (void)(lock); assert(lock_depth == 1); --lock_depth; } while (0) static int64_t esp_timer_get_time(void) { assert(!lock_depth); return now_us; } static void (*delay_hook)(void); static void vTaskDelay(int ticks) { assert(!lock_depth && ticks == 1); now_us += 100000; if (delay_hook) delay_hook(); } typedef void *esp_timer_handle_t; typedef struct { void (*callback)(void *); const char *name; bool skip_unhandled_events; } esp_timer_create_args_t; static esp_err_t timer_create_error, timer_start_error, queue_error; static unsigned timer_creates, timer_starts, timer_deletes, queue_calls; static void (*timer_callback)(void *), (*queued_work)(void *); static void *queued_arg; static void (*queue_hook)(void); static bool inline_work; static esp_err_t esp_timer_create(const esp_timer_create_args_t *args, esp_timer_handle_t *timer) { assert(!lock_depth && args->skip_unhandled_events); ++timer_creates; if (timer_create_error) return timer_create_error; timer_callback = args->callback; *timer = (void *)3; return ESP_OK; } static esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, int64_t period) { assert(!lock_depth && timer && period == 1000000); ++timer_starts; return timer_start_error; } static esp_err_t esp_timer_delete(esp_timer_handle_t timer) { assert(!lock_depth && timer); ++timer_deletes; return ESP_OK; } static esp_err_t httpd_queue_work(httpd_handle_t, void (*)(void *), void *); typedef struct { int fd; bool get_error; } esp_tls_t; enum { HTTPD_SSL_USER_CB_SESS_CREATE, HTTPD_SSL_USER_CB_SESS_CLOSE }; typedef struct { esp_tls_t *tls; unsigned user_cb_state; } esp_https_server_user_cb_arg_t; static esp_err_t esp_tls_get_conn_sockfd(esp_tls_t *tls, int *fd) { assert(owner && !lock_depth); *fd = tls->fd; return tls->get_error ? ESP_FAIL : ESP_OK; } static int test_select(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) { assert(owner && !lock_depth && !w && !e && t && !t->tv_sec && !t->tv_usec); ++select_calls; return select_error ? -1 : select(n, r, w, e, t); } static int test_shutdown(int fd, int how) { assert(owner && !lock_depth && how == SHUT_RDWR); ++shutdown_calls; return shutdown_error ? -1 : shutdown(fd, how); } #define select test_select #define shutdown test_shutdown #define CONFIG_HTTPD_PURGE_BUF_LEN 32 #define ESP_LOGD(...) ((void)0) #define ESP_LOG_BUFFER_HEX_LEVEL(...) ((void)0) #define MIN(a, b) ((a) < (b) ? (a) : (b)) static esp_err_t httpd_req_new(struct httpd_data *, struct sock_db *); static int httpd_req_recv(httpd_req_t *, char *, size_t); static void httpd_req_cleanup(httpd_req_t *);