i would like to implement EventSource in http server, which requires me to keep the connections open and send data to them at later time.
I tried several aproaches so far:
- getting `fd` and `hd` from `req`, storing them and using them later from another function later with `http_default_send`... this doesnt seem to work
- using `httpd_queue_work` function inside request handler, with the idea that it can be an infinite task checking some kind of queue and outputing that uising `http_default_send` ... this also doesn't work
- ussing `httpd_queue_work` from the other function that should send the data, doesn't seem to work either
at this point i am kind of lost and am not sure how to approach this, any help would be very appreciated
here is my current code:
Code: Select all
#include "logging.h"
#include "esp_http_server.h"
static int pre_start_mem, post_stop_mem;
extern int httpd_default_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_len, int flags);
//httpd_req_t* log_clients[4] = {nullptr, nullptr, nullptr, nullptr};
//int log_clients[4] = { -1, -1, -1, -1 };
struct async_resp_arg {
httpd_handle_t hd;
int fd;
};
struct async_resp_arg *log_clients[4] = {nullptr, nullptr, nullptr, nullptr};
static char buffer[512];
static int written = 0;
static void xlog_web_async(void *arg) {
struct async_resp_arg *resp_arg = (struct async_resp_arg *)arg;
httpd_handle_t hd = resp_arg->hd;
int fd = resp_arg->fd;
httpd_default_send(hd, fd, "event: start\ndata: test\n\n", sizeof("event: start\ndata: test\n\n"), 0);
// for (;;) {
// printf("waiting");
// vTaskDelay( 1000 / portTICK_PERIOD_MS);
// }
// free(arg);
}
int vprintf_logging(const char *format, va_list arg)
{
vprintf(format, arg);
strcpy(buffer, "event: esp32\ndata: ");
written = 19;
written += vsnprintf(buffer+written, 511-written, format, arg);
strcpy(buffer+written, "\n\n");
written += 3;
for (int i = 0; i < 4; i++) {
if (log_clients[i] != nullptr) {
printf("sending event to client on slot %d\n", i);
httpd_queue_work(log_clients[i]->hd, xlog_web_async, log_clients[i]);
// check if its still connected
// if (nolongerconnected) { log_clients[i] = nullptr; continue; }
//httpd_default_send(log_clients[i]->hd, log_clients[i]->fd, buffer, written, 0);
//fwrite(log_clients[i], buffer, written);
//fwrite(log_clients[i], "\n\n");
}
}
return 0;
}
void xlog_web(httpd_req_t *req) { // this is request handler for http server
int i = 0;
while (log_clients[i] != nullptr && i < 4) {
i++;
}
if (log_clients[i] != nullptr) {
printf("all logging client slots taken\n");
httpd_resp_set_status(req, "404");
httpd_resp_sendstr_chunk(req, nullptr);
return;
}
printf("using logging client slot %d\n", i);
//log_clients[i] = (httpd_req_t*)malloc(sizeof(httpd_req_t));
//log_clients[i] = httpd_req_to_sockfd(req);
//memcpy((void*)(log_clients[i]), req, sizeof(httpd_req_t));
httpd_resp_set_hdr(req, "Content-Type", "text/event-stream;charset=UTF-8");
httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_set_status(req, "200");
httpd_resp_sendstr_chunk(req, "\n");
httpd_resp_sendstr_chunk(req, "event: start\ndata: test\n\n");
log_clients[i] = (async_resp_arg*)malloc(sizeof(struct async_resp_arg));
log_clients[i]->hd = req->handle;
log_clients[i]->fd = httpd_req_to_sockfd(req);
if (log_clients[i]->fd < 0) {
printf("wrong fd\n");
free(log_clients[i]);
return;
}
}
void init_logging() {
esp_log_set_vprintf(vprintf_logging);
}