131 lines
3.0 KiB
C
131 lines
3.0 KiB
C
#include "web_server.h"
|
|
#include "web_uri_module.h"
|
|
|
|
#include <esp_http_server.h>
|
|
#include <esp_event.h>
|
|
|
|
#include <esp_system.h>
|
|
#include <esp_log.h>
|
|
#include <sys/unistd.h>
|
|
|
|
#define TAG "web server"
|
|
|
|
#define MAKE_U32(b0, b1, b2, b3) ((b0) | (b1) << 8 | (b2) << 16 | (b3) << 24)
|
|
#define URI_WS_STR MAKE_U32('/', 'w', 's', '\0')
|
|
#define URI_API_STR MAKE_U32('/', 'a', 'p', 'i')
|
|
|
|
static httpd_handle_t http_server = NULL;
|
|
|
|
/**
|
|
* 3 types of ref:
|
|
* - 1. "/"
|
|
* - 2. "/entry"
|
|
* - 3. "/dir/"
|
|
* 4 types of target
|
|
* - 1. "/.*"
|
|
* - 2. "/entry"
|
|
* - 2. "/dir/"
|
|
* - 3. "/dir/.*"
|
|
* */
|
|
static bool uri_match(const char *reference_uri, const char *uri_to_match, size_t match_upto)
|
|
{
|
|
const uint32_t *ptr32_ref = (const uint32_t *) reference_uri;
|
|
const uint32_t *ptr32_target = (const uint32_t *) uri_to_match;
|
|
size_t ref_length;
|
|
|
|
/* optimized for /ws quick access */
|
|
if (likely(match_upto == 3)) {
|
|
if (likely(*ptr32_ref == URI_WS_STR)) {
|
|
ESP_LOGI(TAG, "cmp ws");
|
|
return *ptr32_target == *ptr32_ref;
|
|
}
|
|
}
|
|
|
|
/* ref should be shorter than target */
|
|
ref_length = strlen(reference_uri);
|
|
if (ref_length > match_upto) {
|
|
ESP_LOGI(TAG, "no match length");
|
|
return false;
|
|
}
|
|
|
|
// strict matching "/entry" for ref = "/entry"
|
|
if (ref_length == match_upto) {
|
|
if (memcmp(reference_uri, uri_to_match, ref_length) == 0) {
|
|
ESP_LOGI(TAG, "strict match %s", reference_uri);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// if ref = /dir/ targets are /dir/ and /dir/*
|
|
if (reference_uri[ref_length - 1] == '/' && ref_length > 1) {
|
|
if (memcmp(reference_uri, uri_to_match, ref_length) == 0) {
|
|
ESP_LOGI(TAG, "match /dir/");
|
|
return true;
|
|
} else {
|
|
ESP_LOGI(TAG, "no match /dir/");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* Fall back to root pages */
|
|
// match /* when ref if /
|
|
if (reference_uri[ref_length - 1] == '/') {
|
|
ESP_LOGI(TAG, "match /");
|
|
return true;
|
|
}
|
|
|
|
ESP_LOGI(TAG, "fall back false");
|
|
return false;
|
|
}
|
|
|
|
static int8_t opened_socket = 0;
|
|
|
|
static esp_err_t web_server_on_open(httpd_handle_t hd, int sockfd)
|
|
{
|
|
opened_socket++;
|
|
printf("%d open, now: %d\n", sockfd, opened_socket);
|
|
return ESP_OK;
|
|
}
|
|
|
|
static void web_server_on_close(httpd_handle_t hd, int sockfd)
|
|
{
|
|
opened_socket--;
|
|
printf("%d closed, now: %d\n", sockfd, opened_socket);
|
|
close(sockfd);
|
|
}
|
|
|
|
void start_webserver(void)
|
|
{
|
|
httpd_handle_t server = NULL;
|
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
|
int err;
|
|
|
|
config.enable_so_linger = true;
|
|
config.linger_timeout = 0;
|
|
config.lru_purge_enable = true;
|
|
config.uri_match_fn = uri_match;
|
|
config.open_fn = web_server_on_open;
|
|
config.close_fn = web_server_on_close;
|
|
|
|
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
|
if ((err = httpd_start(&server, &config) != ESP_OK)) {
|
|
ESP_LOGE(TAG, "Error starting server!");
|
|
ESP_ERROR_CHECK(err);
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Registering URI handlers");
|
|
uri_module_init(server);
|
|
http_server = server;
|
|
}
|
|
|
|
static esp_err_t stop_webserver(httpd_handle_t server)
|
|
{
|
|
// Stop the httpd server
|
|
return httpd_stop(server);
|
|
}
|
|
|
|
int server_is_running()
|
|
{
|
|
return http_server != NULL;
|
|
}
|