forked from espressif/esp-idf
http_server: websocket server to support async send
This commit is contained in:
@@ -41,7 +41,7 @@ menu "HTTP Server"
|
||||
|
||||
config HTTPD_WS_SUPPORT
|
||||
bool "WebSocket server support"
|
||||
default y
|
||||
default n
|
||||
help
|
||||
This sets the WebSocket server support.
|
||||
|
||||
|
||||
@@ -1514,6 +1514,23 @@ esp_err_t httpd_ws_recv_frame(httpd_req_t *req, httpd_ws_frame_t *pkt, size_t ma
|
||||
*/
|
||||
esp_err_t httpd_ws_send_frame(httpd_req_t *req, httpd_ws_frame_t *pkt);
|
||||
|
||||
/**
|
||||
* @brief Low level send of a WebSocket frame out of the scope of current request
|
||||
* using internally configured httpd send function
|
||||
*
|
||||
* This API should rarely be called directly, with an exception of asynchronous send using httpd_queue_work.
|
||||
*
|
||||
* @param[in] hd Server instance data
|
||||
* @param[in] fd Socket descriptor for sending data
|
||||
* @param[in] frame WebSocket frame
|
||||
* @return
|
||||
* - ESP_OK : On successful
|
||||
* - ESP_FAIL : When socket errors occurs
|
||||
* - ESP_ERR_INVALID_STATE : Handshake was already done beforehand
|
||||
* - ESP_ERR_INVALID_ARG : Argument is invalid (null or non-WebSocket)
|
||||
*/
|
||||
esp_err_t httpd_ws_send_frame_async(httpd_handle_t hd, int fd, httpd_ws_frame_t *frame);
|
||||
|
||||
#endif /* CONFIG_HTTPD_WS_SUPPORT */
|
||||
/** End of WebSocket related stuff
|
||||
* @}
|
||||
|
||||
@@ -690,7 +690,9 @@ static void init_req_aux(struct httpd_req_aux *ra, httpd_config_t *config)
|
||||
ra->first_chunk_sent = 0;
|
||||
ra->req_hdrs_count = 0;
|
||||
ra->resp_hdrs_count = 0;
|
||||
#if CONFIG_HTTPD_WS_SUPPORT
|
||||
ra->ws_handshake_detect = false;
|
||||
#endif
|
||||
memset(ra->resp_hdrs, 0, config->max_resp_headers * sizeof(struct resp_hdr));
|
||||
}
|
||||
|
||||
@@ -703,11 +705,13 @@ static void httpd_req_cleanup(httpd_req_t *r)
|
||||
httpd_sess_free_ctx(ra->sd->ctx, ra->sd->free_ctx);
|
||||
}
|
||||
|
||||
#if CONFIG_HTTPD_WS_SUPPORT
|
||||
/* Close the socket when a WebSocket Close request is received */
|
||||
if (ra->sd->ws_close) {
|
||||
ESP_LOGD(TAG, LOG_FMT("Try closing WS connection at FD: %d"), ra->sd->fd);
|
||||
httpd_sess_trigger_close(r->handle, ra->sd->fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Retrieve session info from the request into the socket database. */
|
||||
ra->sd->ctx = r->sess_ctx;
|
||||
|
||||
@@ -279,7 +279,6 @@ esp_err_t httpd_uri(struct httpd_data *hd)
|
||||
{
|
||||
httpd_uri_t *uri = NULL;
|
||||
httpd_req_t *req = &hd->hd_req;
|
||||
struct httpd_req_aux *aux = req->aux;
|
||||
struct http_parser_url *res = &hd->hd_req_aux.url_parse_res;
|
||||
|
||||
/* For conveying URI not found/method not allowed */
|
||||
@@ -313,6 +312,7 @@ esp_err_t httpd_uri(struct httpd_data *hd)
|
||||
|
||||
/* Final step for a WebSocket handshake verification */
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
struct httpd_req_aux *aux = req->aux;
|
||||
if (uri->is_websocket && aux->ws_handshake_detect && uri->method == HTTP_GET) {
|
||||
ESP_LOGD(TAG, LOG_FMT("Responding WS handshake to sock %d"), aux->sd->fd);
|
||||
esp_err_t ret = httpd_ws_respond_server_handshake(&hd->hd_req);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#ifdef CONFIG_HTTPD_WS_SUPPORT
|
||||
|
||||
#define TAG "httpd_ws"
|
||||
static const char *TAG="httpd_ws";
|
||||
|
||||
/*
|
||||
* Bit masks for WebSocket frames.
|
||||
@@ -266,6 +266,11 @@ esp_err_t httpd_ws_send_frame(httpd_req_t *req, httpd_ws_frame_t *frame)
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
return httpd_ws_send_frame_async(req->handle, httpd_req_to_sockfd(req), frame);
|
||||
}
|
||||
|
||||
esp_err_t httpd_ws_send_frame_async(httpd_handle_t hd, int fd, httpd_ws_frame_t *frame)
|
||||
{
|
||||
if (!frame) {
|
||||
ESP_LOGW(TAG, LOG_FMT("Argument is invalid"));
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -299,15 +304,20 @@ esp_err_t httpd_ws_send_frame(httpd_req_t *req, httpd_ws_frame_t *frame)
|
||||
/* WebSocket server does not required to mask response payload, so leave the MASK bit as 0. */
|
||||
header_buf[1] &= (~HTTPD_WS_MASK_BIT);
|
||||
|
||||
struct sock_db *sess = httpd_sess_get(hd, fd);
|
||||
if (!sess) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Send off header */
|
||||
if (httpd_send(req, (const char *)header_buf, tx_len) < 0) {
|
||||
if (sess->send_fn(hd, fd, (const char *)header_buf, tx_len, 0) < 0) {
|
||||
ESP_LOGW(TAG, LOG_FMT("Failed to send WS header"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Send off payload */
|
||||
if(frame->len > 0 && frame->payload != NULL) {
|
||||
if (httpd_send(req, (const char *)frame->payload, frame->len) < 0) {
|
||||
if (sess->send_fn(hd, fd, (const char *)frame->payload, frame->len, 0) < 0) {
|
||||
ESP_LOGW(TAG, LOG_FMT("Failed to send WS payload"));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user