cesanta / mongoose

Embedded Web Server
https://mongoose.ws
Other
10.92k stars 2.7k forks source link

Mongoose on ESP32 and mg_broadcast support #782

Closed nkolban closed 3 years ago

nkolban commented 7 years ago

Howdy folks, ... in a project I need to publish on a WebSocket when an event in my ESP32 occurs. I understand that I am not allowed to simply call mg_send_websocket_frame() in a separate task/thread and that makes sense. I am also of the understanding that the correct way to achieve my goal is to invoke mg_broadcast in my originating thread which will cause an event to be generated in my event handling loop where I can then perform the web socket send.

With this background ... I seem to find that mg_broadcast is disabled by default. I then changed my build process to define MG_ENABLE_BROADCAST and the mg_broadcast() function became present. However, I have not been able to get it to work. When I invoke mg_broadcast, no event is generated.

Is the mg_broadcast functionality working in the ESP32 port of the Mongoose networking library?

cpq commented 7 years ago

mg_broadcast() is using socketpair. A thread that sends a brodcasts writes to the one end of a socketpair, that wakes up and IO thread that reads from another end, and receives a message.

A socketpair is created using loopback, 127.0.0.1.

I have a suspicion that on ESP32, just like on ESP8266, the loopback is not enabled in LWIP. @rojer @alashkin do you have any more state on that?

nkolban commented 7 years ago

When I tried to port Mongoose networking myself back in 2016 I found that 127.0.0.1 wasn't working ... see the following issue ... https://github.com/espressif/esp-idf/issues/114

A poster to that thread claims that 0.0.0.0 works as does the local IP address.

In the ESP-IDF world, there are also other synchronization mechanisms including queues and semaphores at the FreeRTOS level.

If using a 127.0.0.1 socket pair isn't going to work easily on the ESP32, might we consider some ESP32/RTOS alternative mechanism defined at build time?

nkolban commented 7 years ago

Was this issue ever resolved? Is "mg_broadcast" a supported function in ESP32 Mongoose networking?

What I have is a situation where, when I receive an incoming MG_EV_WEBSOCKET_FRAME event, I need to send back a response. I am under the belief that I can't invoke mg_send_websocket_frame() in the event handler that receives the MG_EV_WEBSOCKET_FRAME and hence am looking for a good design to achieve my goal.

klapligehesten commented 7 years ago

Hi Neil. Inspired by the book you wrote on the esp32, i've written a small project where i have worked my way around the above problem by using FreeRTOS queues. see: https://github.com/klapligehesten/esp32_mg_web

Eloquence4 commented 6 years ago

I can confirm that mg_broadcast works on ESP-IDF commit e7dc749e2f953a976325964b5ac49b53c8bafc42

avanbremen commented 6 years ago

@cpq @Eloquence4 @nkolban Could you please share with me how you got mg_broadcast working? I believe the API is pretty straightforward, however I can't get mg_broadcast to work.

I am running a websocket server just fine and I am able to receive data without any issues. To test mg_broadcast (and make sure no other tasks were interfering), I simply created a second task in FreeRTOS which runs every 10 seconds (using vTaskDelay). For testing purposes I created a local (static) struct mg_mgr mgr; in the .c file, so that both tasks can access the Mongoose manager.

I noticed that the task is actually locking up. By adding several debug (ESP_LOGD / LOGI) statements, I was able to identify that mg_broadcast never returns. Within function mg_broadcast (mongoose.c), every function call returns up until the last one: dummy = MG_RECV_FUNC(mgr->ctl[0], (char *) &len, 1, 0);

The callback function that gets passed into mg_broadcast is even called, so we know that mg_mgr_poll wakes up and the callback function is called from within the mg_mgr_poll thread/task. However, MG_RECV_FUNC never returns. I did not make any changes to Mongoose (besides adding #define MG_ENABLE_BROADCAST 1 to enable mg_broadcast functionality), so MG_RECV_FUNC is simply mapped to recv (default).

I validated that LwIP loopback support is enabled, based on the issue @nkolban raised here. Since I did not make any changes to the default project config, loopback support is enabled.

It almost looks like it has something to do with the socketpair struct mg_mgr::ctl that's used to enable inter-process communication via mg_broadcast. But I can't figure out what's causing the function to block and thus lockup the entire task.

I am running Mongoose 6.11 and the latest version of ESP-IDF (I just pulled it from GitHub). I also tested with ESP-IDF v3.0-rc1, older versions of Mongoose, older versions of ESP-IDF and a combination of those.

@nkolban on a side note, I placed Mongoose in its own component folder. I tried defining MG_ENABLE_BROADCAST in the component makefile, using CFLAGS += -DMG_ENABLE_BROADCAST=1. Unfortunately that did not have any effect. When I place this into the project Makefile, it does work. I saw you ran into something similar, did you find a solution?

Thanks!

Eloquence4 commented 6 years ago

This is the example code i used to test mg_broadcast with: https://pastebin.com/tgV8ZcgL I can't really test if the task deletes itself right now, i will comment back when i can.

avanbremen commented 6 years ago

@Eloquence4 thanks for your reply. I am currently working on a small example project that will demonstrate the issue. Perhaps you can spot an issue in the code. I will post asap.

avanbremen commented 6 years ago

@cpq @Eloquence4 I just created a test project that demonstrates the issue, you can find it here. I assume the mg_broadcast callback is called 1 + N times, where N is the number of user sockets. I assume it's called for the loopback socket as well, hence the +1. Can you confirm?

I can also create a new issue, as this issue post dates back to 7 Feb 2017 and my issue is perhaps due to a newer version of Mongoose and/or ESP-IDF.

avanbremen commented 6 years ago

Created a new issue here for clarity's sake.

Update 19-02-2018: The issue has been resolved.

snahmad commented 6 years ago

Not building for me linker error on esp32.

undefined reference to `mg_broadcast'

I have defined

define MG_ENABLE_SYNC_RESOLVER 1

define MG_ENABLE_BROADCAST 1

extern "C" {

include "mongoose.h"

}

Any idea?

cpq commented 3 years ago

Closing this.

The latest code has diverted from the mg_broadcast concept. Instead, it provides a socketpair API for the inter-task comms. See an example at https://github.com/cesanta/mongoose/tree/master/examples/multi-threaded