Page 1 of 1

How to call a function outside httpd_ws.c file in esp-idf

Posted: Tue May 18, 2021 7:38 am
by Baldhead
Hi,

I implemented a simple keep alive mechanism for my websocket server and i need call a function from "httpd_ws.c" to a file in my project folder, but the compiler show: "fatal error: my_keep_alive.h: No such file or directory".

How can i do this ?

Partial code(last function) from "httpd_ws.c"

Code: Select all

#include "my_keep_alive.h"  // my include


esp_err_t httpd_ws_get_frame_type(httpd_req_t *req)
{
    esp_err_t ret = httpd_ws_check_req(req);
    if (ret != ESP_OK) {
        return ret;
    }

    struct httpd_req_aux *aux = req->aux;
    if (aux == NULL) {
        ESP_LOGW(TAG, LOG_FMT("Invalid Aux pointer"));
        return ESP_ERR_INVALID_ARG;
    }

    /* Read the first byte from the frame to get the FIN flag and Opcode */
    /* Please refer to RFC6455 Section 5.2 for more details */
    uint8_t first_byte = 0;
    if (httpd_recv_with_opt(req, (char *)&first_byte, sizeof(first_byte), false) <= 0) {
        /* If the recv() return code is <= 0, then this socket FD is invalid (i.e. a broken connection) */
        /* Here we mark it as a Close message and close it later. */
        ESP_LOGW(TAG, LOG_FMT("Failed to read header byte (socket FD invalid), closing socket now"));
        aux->ws_final = true;
        aux->ws_type = HTTPD_WS_TYPE_CLOSE;
        return ESP_OK;
    }

    ESP_LOGD(TAG, LOG_FMT("First byte received: 0x%02X"), first_byte);

    /* Decode the FIN flag and Opcode from the byte */
    aux->ws_final = (first_byte & HTTPD_WS_FIN_BIT) != 0;
    aux->ws_type = (first_byte & HTTPD_WS_OPCODE_BITS);

    /* Reply to PING. For PONG and CLOSE, it will be handled elsewhere. */
    if(aux->ws_type == HTTPD_WS_TYPE_PING) {
        ESP_LOGD(TAG, LOG_FMT("Got a WS PING frame, Replying PONG..."));

        /* Read the rest of the PING frame, for PONG to reply back. */
        /* Please refer to RFC6455 Section 5.5.2 for more details */
        httpd_ws_frame_t frame;
        uint8_t frame_buf[128] = { 0 };
        memset(&frame, 0, sizeof(httpd_ws_frame_t));
        frame.payload = frame_buf;

        if(httpd_ws_recv_frame(req, &frame, 126) != ESP_OK) {
            ESP_LOGD(TAG, LOG_FMT("Cannot receive the full PING frame"));
            return ESP_ERR_INVALID_STATE;
        }




// my code
        int sockfd = httpd_req_to_sockfd(req);         
        clear_Keep_Alive_timeout_counter( sockfd );
//




        /* Now turn the frame to PONG */
        frame.type = HTTPD_WS_TYPE_PONG;
        return httpd_ws_send_frame(req, &frame);
    }

    return ESP_OK;
}

Thank's.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Wed May 19, 2021 5:27 am
by Baldhead
Some suggestion of @espressif team will be apreciated.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Wed May 19, 2021 8:45 am
by ESP_Sprite
Is the http_ws.c thing in a a separate component? If so, you may need to do some CMakeLists.txt of that component to require your project main dir (I think PRIV_REQUIRES "main" might do it). Not sure as a dependency like that is kind-of odd: normally your project depends on everything else and no components explicitly depend onb your project.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Wed May 19, 2021 10:13 pm
by Baldhead
Hi,

I only put this instructions inside "CMakeLists.txt" of "esp_http_server" esp-idf component:
SRCS "C:/esp32Projects/WSS_SERVER_AND_UI_INTEGRATION/components/communication/my_wss_server/src/my_keep_alive.c"
INCLUDE_DIRS "C:/esp32Projects/WSS_SERVER_AND_UI_INTEGRATION/components/communication/my_wss_server/src/include"


"CMakeLists.txt" of "esp_http_server" esp-idf component:

Code: Select all

idf_component_register( SRCS "src/httpd_main.c"
                            	     "src/httpd_parse.c"
                            	     "src/httpd_sess.c"
                                     "src/httpd_txrx.c"
                                     "src/httpd_uri.c"
                                     "src/httpd_ws.c"
                                     "src/util/ctrl_sock.c"					
                                     INCLUDE_DIRS "include"
                                     PRIV_INCLUDE_DIRS "src/port/esp32" "src/util"
                                     REQUIRES nghttp # for http_parser.h
                                     PRIV_REQUIRES lwip mbedtls esp_timer

SRCS "C:/esp32Projects/WSS_SERVER_AND_UI_INTEGRATION/components/communication/my_wss_server/src/my_keep_alive.c"
INCLUDE_DIRS "C:/esp32Projects/WSS_SERVER_AND_UI_INTEGRATION/components/communication/my_wss_server/src/include"					 
)

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Wed May 19, 2021 11:45 pm
by ESP_Sprite
You could try to add 'main' to the list of PRIV_INCLUDES.

But to be honest, all of this has a code smell. As an alternative, it would be nicer to add a keepalive function pointer member to the httpd_config_t configuration struct; you could use that to specify a custom keepalive function at runtime. That stops your code for having this messy upwards dependency.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Thu May 20, 2021 12:11 am
by Baldhead
Yes, good suggestion, but if i update the esp-idf, i will need to update httpd_config_t configuration struct again too.

it would be interesting if espressif definitely created this member within the structure in future releases of esp-idf.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Thu May 20, 2021 5:59 am
by ESP_Sprite
Baldhead wrote:
Thu May 20, 2021 12:11 am
it would be interesting if espressif definitely created this member within the structure in future releases of esp-idf.
It depends on the use case the capability of having your own keepalive handler (or whatever it is you're trying to do) fullfills. If it's something that can already be done in a different way or something that's only needed in some hyper-specific scenario, it's not likely to go into ESP-IDF. If it's something that can be useful in general, you can make a case for inclusion in an issue on the ESP-IDF Github repo, or (even better) write what you think would work best and use a pull request so we can see if we can pull it in.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Fri May 21, 2021 4:26 pm
by ESP_cermak
Hi @Baldhead

Have you checked the keep-alive mechanism in the `wss` example (from https_server)?
https://github.com/espressif/esp-idf/tr ... sl-support

It's implemented in the main component and uses only public includes from the ws interface of the http-server. You can directly use the `keep_alive` API here:
https://github.com/espressif/esp-idf/bl ... ep_alive.h

Or you can check how it accessed the required ws payload and the related structures and perhaps use the same approach.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Mon May 24, 2021 7:58 pm
by Baldhead
Thank's @ESP_cermak and @ESP_Sprite.

Re: How to call a function outside httpd_ws.c file in esp-idf

Posted: Sat Jul 01, 2023 7:42 pm
by su-Koch
was so helpfull. had the exact same issue. Checking the example now to get it working.