/* SPDX-License-Identifier: GPL-3.0-only */ /* mDNS runtime service; its lifecycle is owned by wifi_manager. */ #include "mdns_service.h" #include #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "mdns.h" static SemaphoreHandle_t s_mutex; static mdns_config_t s_config; static bool s_component_initialized; static bool s_initialization_failed; static bool s_announced; static esp_err_t s_last_error; static void lock_service(void) { (void)xSemaphoreTake(s_mutex, portMAX_DELAY); } static void unlock_service(void) { (void)xSemaphoreGive(s_mutex); } static void make_hostname(const mdns_config_t *config, char *hostname, size_t size) { (void)snprintf(hostname, size, "sak-%s", config->suffix); } esp_err_t mdns_service_init(const mdns_config_t *config) { if (mdns_config_validate(config) != ESP_OK) { return ESP_ERR_INVALID_ARG; } if (s_mutex != NULL) { return ESP_ERR_INVALID_STATE; } s_mutex = xSemaphoreCreateMutex(); if (s_mutex == NULL) { return ESP_ERR_NO_MEM; } s_config = *config; s_last_error = ESP_OK; return ESP_OK; } esp_err_t mdns_service_get_config(mdns_config_t *config) { if (config == NULL || s_mutex == NULL) { return ESP_ERR_INVALID_STATE; } lock_service(); *config = s_config; unlock_service(); return ESP_OK; } esp_err_t mdns_service_set_config(const mdns_config_t *config) { if (s_mutex == NULL || mdns_config_validate(config) != ESP_OK) { return ESP_ERR_INVALID_ARG; } lock_service(); s_config = *config; unlock_service(); return ESP_OK; } esp_err_t mdns_service_get_snapshot(mdns_service_snapshot_t *snapshot) { if (snapshot == NULL || s_mutex == NULL) { return ESP_ERR_INVALID_STATE; } lock_service(); memset(snapshot, 0, sizeof(*snapshot)); snapshot->initialized = true; snapshot->announced = s_announced; memcpy(snapshot->suffix, s_config.suffix, s_config.suffix_len); make_hostname(&s_config, snapshot->hostname, sizeof(snapshot->hostname)); snapshot->last_error = s_last_error; unlock_service(); return ESP_OK; } esp_err_t mdns_service_start(void) { if (s_mutex == NULL) { return ESP_ERR_INVALID_STATE; } lock_service(); if (s_component_initialized) { s_announced = true; unlock_service(); return ESP_OK; } if (s_initialization_failed) { esp_err_t error = s_last_error; unlock_service(); return error; } mdns_config_t config = s_config; unlock_service(); esp_err_t error = mdns_init(); if (error == ESP_OK) { char hostname[MDNS_CONFIG_SUFFIX_MAX_LEN + 5U] = {0}; make_hostname(&config, hostname, sizeof(hostname)); error = mdns_hostname_set(hostname); if (error == ESP_OK) { error = mdns_instance_name_set("ESP32 Serial Swiss Army Knife"); } if (error != ESP_OK) { mdns_free(); } } lock_service(); s_component_initialized = error == ESP_OK; s_initialization_failed = error != ESP_OK; s_announced = error == ESP_OK; s_last_error = error; unlock_service(); return error; } void mdns_service_stop(void) { if (s_mutex == NULL) { return; } lock_service(); s_announced = false; unlock_service(); } esp_err_t mdns_service_reannounce(void) { if (s_mutex == NULL) { return ESP_ERR_INVALID_STATE; } lock_service(); if (!s_component_initialized) { esp_err_t error = s_initialization_failed ? s_last_error : ESP_ERR_INVALID_STATE; unlock_service(); return error; } mdns_config_t config = s_config; unlock_service(); char hostname[MDNS_CONFIG_SUFFIX_MAX_LEN + 5U] = {0}; make_hostname(&config, hostname, sizeof(hostname)); esp_err_t error = mdns_hostname_set(hostname); lock_service(); s_last_error = error; unlock_service(); return error; }