Преглед изворни кода

esp_http_server: Added support for esp_events

Harshit Malpani пре 3 година
родитељ
комит
0885d8542d

+ 1 - 1
components/esp_http_server/CMakeLists.txt

@@ -7,7 +7,7 @@ idf_component_register(SRCS "src/httpd_main.c"
                             "src/util/ctrl_sock.c"
                     INCLUDE_DIRS "include"
                     PRIV_INCLUDE_DIRS "src/port/esp32" "src/util"
-                    REQUIRES http_parser # for http_parser.h
+                    REQUIRES esp_event http_parser # for http_parser.h
                     PRIV_REQUIRES lwip mbedtls esp_timer)
 
 target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

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

@@ -14,6 +14,7 @@
 #include <http_parser.h>
 #include <sdkconfig.h>
 #include <esp_err.h>
+#include <esp_event.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -21,6 +22,29 @@ extern "C" {
 
 #define ESP_HTTPD_DEF_CTRL_PORT         (32768)    /*!< HTTP Server control socket port*/
 
+ESP_EVENT_DECLARE_BASE(ESP_HTTP_SERVER_EVENT);
+
+/**
+ * @brief   HTTP Server events id
+ */
+typedef enum {
+    HTTP_SERVER_EVENT_ERROR = 0,       /*!< This event occurs when there are any errors during execution */
+    HTTP_SERVER_EVENT_START,           /*!< This event occurs when HTTP Server is started */
+    HTTP_SERVER_EVENT_ON_CONNECTED,    /*!< Once the HTTP Server has been connected to the client, no data exchange has been performed */
+    HTTP_SERVER_EVENT_ON_HEADER,       /*!< Occurs when receiving each header sent from the client */
+    HTTP_SERVER_EVENT_HEADERS_SENT,     /*!< After sending all the headers to the client */
+    HTTP_SERVER_EVENT_ON_DATA,         /*!< Occurs when receiving data from the client */
+    HTTP_SERVER_EVENT_SENT_DATA,       /*!< Occurs when an ESP HTTP server session is finished */
+    HTTP_SERVER_EVENT_DISCONNECTED,    /*!< The connection has been disconnected */
+    HTTP_SERVER_EVENT_STOP,            /*!< This event occurs when HTTP Server is stopped */
+} esp_http_server_event_id_t;
+
+/** Argument structure for HTTP_SERVER_EVENT_ON_DATA and HTTP_SERVER_EVENT_SENT_DATA event */
+typedef struct {
+    int fd;         /*!< Session socket file descriptor */
+    int data_len;   /*!< Data length */
+} esp_http_server_event_data;
+
 /*
 note: esp_https_server.h includes a customized copy of this
 initializer that should be kept in sync

+ 6 - 0
components/esp_http_server/src/esp_httpd_priv.h

@@ -544,6 +544,12 @@ esp_err_t httpd_sess_trigger_close_(httpd_handle_t handle, struct sock_db *sessi
  * @}
  */
 
+/**
+ * @brief Function to dispatch events in default event loop
+ *
+ */
+void esp_http_server_dispatch_event(int32_t event_id, const void* event_data, size_t event_data_size);
+
 #ifdef __cplusplus
 }
 #endif

+ 14 - 0
components/esp_http_server/src/httpd_main.c

@@ -30,6 +30,16 @@ typedef struct {
 
 static const char *TAG = "httpd";
 
+ESP_EVENT_DEFINE_BASE(ESP_HTTP_SERVER_EVENT);
+
+void esp_http_server_dispatch_event(int32_t event_id, const void* event_data, size_t event_data_size)
+{
+    esp_err_t err = esp_event_post(ESP_HTTP_SERVER_EVENT, event_id, event_data, event_data_size, portMAX_DELAY);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to post esp_http_server event: %s", esp_err_to_name(err));
+    }
+}
+
 static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
 {
     /* If no space is available for new session, close the least recently used one */
@@ -101,6 +111,7 @@ static esp_err_t httpd_accept_conn(struct httpd_data *hd, int listen_fd)
         goto exit;
     }
     ESP_LOGD(TAG, LOG_FMT("complete"));
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ON_CONNECTED, &new_fd, sizeof(int));
     return ESP_OK;
 exit:
     close(new_fd);
@@ -507,6 +518,8 @@ esp_err_t httpd_start(httpd_handle_t *handle, const httpd_config_t *config)
     }
 
     *handle = (httpd_handle_t)hd;
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_START, NULL, 0);
+
     return ESP_OK;
 }
 
@@ -556,5 +569,6 @@ esp_err_t httpd_stop(httpd_handle_t handle)
     vSemaphoreDelete(hd->ctrl_sock_semaphore);
 #endif
     httpd_delete(hd);
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_STOP, NULL, 0);
     return ESP_OK;
 }

+ 1 - 0
components/esp_http_server/src/httpd_parse.c

@@ -401,6 +401,7 @@ static esp_err_t cb_headers_complete(http_parser *parser)
 
     parser_data->status = PARSING_BODY;
     ra->remaining_len = r->content_len;
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ON_HEADER, &(ra->sd->fd), sizeof(int));
     return ESP_OK;
 }
 

+ 1 - 0
components/esp_http_server/src/httpd_sess.c

@@ -370,6 +370,7 @@ void httpd_sess_delete(struct httpd_data *hd, struct sock_db *session)
     } else {
         close(session->fd);
     }
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_DISCONNECTED, &session->fd, sizeof(int));
 
     // clear all contexts
     httpd_sess_clear_ctx(session);

+ 18 - 0
components/esp_http_server/src/httpd_txrx.c

@@ -281,6 +281,7 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len)
     if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
         return ESP_ERR_HTTPD_RESP_SEND;
     }
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_HEADERS_SENT, &(ra->sd->fd), sizeof(int));
 
     /* Sending content */
     if (buf && buf_len) {
@@ -288,6 +289,11 @@ esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, ssize_t buf_len)
             return ESP_ERR_HTTPD_RESP_SEND;
         }
     }
+    esp_http_server_event_data evt_data = {
+        .fd = ra->sd->fd,
+        .data_len = buf_len,
+    };
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_SENT_DATA, &evt_data, sizeof(esp_http_server_event_data));
     return ESP_OK;
 }
 
@@ -369,6 +375,12 @@ esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, ssize_t buf_len
     if (httpd_send_all(r, "\r\n", strlen("\r\n")) != ESP_OK) {
         return ESP_ERR_HTTPD_RESP_SEND;
     }
+    esp_http_server_event_data evt_data = {
+        .fd = ra->sd->fd,
+        .data_len = buf_len,
+    };
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_SENT_DATA, &evt_data, sizeof(esp_http_server_event_data));
+
     return ESP_OK;
 }
 
@@ -465,6 +477,7 @@ esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_code_t error, const ch
         }
     }
 #endif
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ERROR, &error, sizeof(httpd_err_code_t));
 
     return ret;
 }
@@ -532,6 +545,11 @@ int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
     }
     ra->remaining_len -= ret;
     ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret);
+    esp_http_server_event_data evt_data = {
+        .fd = ra->sd->fd,
+        .data_len = ret,
+    };
+    esp_http_server_dispatch_event(HTTP_SERVER_EVENT_ON_DATA, &evt_data, sizeof(esp_http_server_event_data));
     return ret;
 }
 

+ 17 - 0
docs/en/api-reference/protocols/esp_http_server.rst

@@ -158,6 +158,23 @@ Websocket Server
 The HTTP server component provides websocket support. The websocket feature can be enabled in menuconfig using the :ref:`CONFIG_HTTPD_WS_SUPPORT` option. Please refer to the :example:`protocols/http_server/ws_echo_server` example which demonstrates usage of the websocket feature.
 
 
+Event Handling
+--------------
+
+ESP HTTP Server has various events for which a handler can be triggered by :doc:`the Event Loop library <../system/esp_event>` when the particular event occurs. The handler has to be registered using :cpp:func:`esp_event_handler_register`. This helps in event handling for ESP HTTP Server.
+:cpp:enum:`esp_http_server_event_id_t` has all the events which can happen for ESP HTTP Server.
+
+Expected data type for different ESP HTTP Server events in event loop:
+    - HTTP_SERVER_EVENT_ERROR           :   ``httpd_err_code_t``
+    - HTTP_SERVER_EVENT_START           :   ``NULL``
+    - HTTP_SERVER_EVENT_ON_CONNECTED    :   ``int``
+    - HTTP_SERVER_EVENT_ON_HEADER       :   ``int``
+    - HTTP_SERVER_EVENT_HEADERS_SENT    :   ``int``
+    - HTTP_SERVER_EVENT_ON_DATA         :   ``esp_http_server_event_data``
+    - HTTP_SERVER_EVENT_SENT_DATA       :   ``esp_http_server_event_data``
+    - HTTP_SERVER_EVENT_DISCONNECTED    :   ``int``
+    - HTTP_SERVER_EVENT_STOP            :   ``NULL``
+
 API Reference
 -------------