mdns: allow mutiple instances with same service type

This commit is contained in:
Jiacheng Guo 2021-09-13 19:33:02 +08:00
parent b59902f4d1
commit b7a99f4658
4 changed files with 99 additions and 11 deletions

View File

@ -84,4 +84,10 @@ menu "mDNS"
This option creates a new thread to serve receiving packets (TODO).
This option uses additional N sockets, where N is number of interfaces.
config MDNS_MULTIPLE_INSTANCE
bool "Multiple instances under the same service type"
default y
help
Enables adding multiple service instances under the same service type.
endmenu

View File

@ -187,7 +187,10 @@ esp_err_t mdns_instance_name_set(const char * instance_name);
* @note The value length of txt items will be automatically decided by strlen
*
* @param instance_name instance name to set. If NULL,
* global instance name or hostname will be used
* global instance name or hostname will be used.
* Note that MDNS_MULTIPLE_INSTANCE config option
* needs to be enabled for adding multiple instances
* with the same instance type.
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param port service port
@ -209,6 +212,9 @@ esp_err_t mdns_service_add(const char * instance_name, const char * service_type
*
* @param instance_name instance name to set. If NULL,
* global instance name or hostname will be used
* Note that MDNS_MULTIPLE_INSTANCE config option
* needs to be enabled for adding multiple instances
* with the same instance type.
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param hostname service hostname. If NULL, local hostname will be used.
@ -238,6 +244,22 @@ esp_err_t mdns_service_add_for_host(const char * instance_name, const char * ser
*/
bool mdns_service_exists(const char * service_type, const char * proto, const char * hostname);
/**
* @brief Check whether a service has been added.
*
* @param instance instance name
* @param service_type service type (_http, _ftp, etc)
* @param proto service protocol (_tcp, _udp)
* @param hostname service hostname. If NULL, checks for the local hostname.
*
* @return
* - true Correspondding service has been added.
* - false Service not found.
*/
bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto,
const char *hostname);
/**
* @brief Remove service from mDNS server
*

View File

@ -231,15 +231,8 @@ esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet)
return ESP_OK;
}
/**
* @brief Get the service name of a service
*/
static const char * _mdns_get_service_instance_name(mdns_service_t * service)
static const char *_mdns_get_default_instance_name(void)
{
if (service && !_str_null_or_empty(service->instance)) {
return service->instance;
}
if (_mdns_server && !_str_null_or_empty(_mdns_server->instance)) {
return _mdns_server->instance;
}
@ -251,6 +244,49 @@ static const char * _mdns_get_service_instance_name(mdns_service_t * service)
return NULL;
}
/**
* @brief Get the service name of a service
*/
static const char * _mdns_get_service_instance_name(const mdns_service_t * service)
{
if (service && !_str_null_or_empty(service->instance)) {
return service->instance;
}
return _mdns_get_default_instance_name();
}
static bool _mdns_instance_name_match(const char *lhs, const char *rhs)
{
if (lhs == NULL) {
lhs = _mdns_get_default_instance_name();
}
if (rhs == NULL) {
rhs = _mdns_get_default_instance_name();
}
return !strcasecmp(lhs, rhs);
}
static bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service,
const char *proto, const char *hostname)
{
return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) &&
!strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname));
}
static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto,
const char *hostname)
{
mdns_srv_item_t *s = _mdns_server->services;
while (s) {
if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) {
return s;
}
s = s->next;
}
return NULL;
}
/**
* @brief reads MDNS FQDN into mdns_name_t structure
* FQDN is in format: [hostname.|[instance.]_service._proto.]local.
@ -1428,7 +1464,13 @@ static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_
mdns_parsed_question_t *q = parsed_packet->questions;
while (q) {
shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe;
if (q->service && q->proto) {
if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) {
mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL);
if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) {
_mdns_free_tx_packet(packet);
return;
}
} else if (q->service && q->proto) {
mdns_srv_item_t *service = _mdns_server->services;
while (service) {
if (_mdns_service_match(service->service, q->service, q->proto, NULL)) {
@ -2667,7 +2709,12 @@ static bool _mdns_name_is_ours(mdns_name_t * name)
}
//find the service
mdns_srv_item_t * service = _mdns_get_service_item(name->service, name->proto, NULL);
mdns_srv_item_t * service;
if (_str_null_or_empty(name->host)) {
service = _mdns_get_service_item(name->service, name->proto, NULL);
} else {
service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL);
}
if (!service) {
return false;
}
@ -4948,7 +4995,11 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service,
return ESP_ERR_NO_MEM;
}
#if CONFIG_MDNS_MULTIPLE_INSTANCE
mdns_srv_item_t * item = _mdns_get_service_item_instance(instance, service, proto, hostname);
#else
mdns_srv_item_t * item = _mdns_get_service_item(service, proto, hostname);
#endif // CONFIG_MDNS_MULTIPLE_INSTANCE
if (item) {
return ESP_ERR_INVALID_ARG;
}
@ -5011,6 +5062,12 @@ bool mdns_service_exists(const char * service_type, const char * proto, const ch
return _mdns_get_service_item(service_type, proto, hostname) != NULL;
}
bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto,
const char *hostname)
{
return _mdns_get_service_item_instance(instance, service_type, proto, hostname) != NULL;
}
esp_err_t mdns_service_port_set_for_host(const char * service, const char * proto, const char * hostname, uint16_t port)
{
if (!_mdns_server || !_mdns_server->services || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) {

View File

@ -53,6 +53,9 @@ static void initialise_mdns(void)
//initialize service
ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3) );
#if CONFIG_MDNS_MULTIPLE_INSTANCE
ESP_ERROR_CHECK( mdns_service_add("ESP32-WebServer1", "_http", "_tcp", 80, NULL, 0) );
#endif
#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST
char *delegated_hostname;