apps/netutils: add mdns library support

This commit allows an external mDNS library to be included in NuttX.

It originates from here: <https://github.com/mjansson/mdns>

It is declared as being in the Public Domain as per <http://unlicense.org>

Signed-off-by: Tim Hardisty <timh@jti.uk.com>
This commit is contained in:
Tim Hardisty 2025-05-14 15:27:30 +01:00 committed by Xiang Xiao
parent 8ff533beb3
commit 30b1c024a1
6 changed files with 468 additions and 0 deletions

58
include/netutils/mdnsd.h Normal file
View file

@ -0,0 +1,58 @@
/****************************************************************************
* apps/netutils/mdnsd.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_INCLUDE_NETUTILS_MDNSD_H
#define __APPS_INCLUDE_NETUTILS_MDNSD_H
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
int mdnsd_start(FAR char *service_name, FAR char *service_port);
int mdnsd_stop(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __APPS_INCLUDE_NETUTILS_MDNSD_H */

81
netutils/mdns/Kconfig Normal file
View file

@ -0,0 +1,81 @@
config LIB_MDNS
bool "MDNS library"
default n
---help---
Enable the mDNS library. This allows calls to the library to be made.
This external library is "unlicensed" using the methodology from
http://unlicense.org
You should be sure that this license is acceptable for your usage.
By default, the "built-in" demo is added as an application that can
be run from nsh <mdns>.
This is also needed for the optional daemon that allows the demo
app's mDNS functionality to be started and stopped from user
applications. There is an associated example app
(CONFIG_EXAMPLES_MDNSD) to allow the daemon to be tried from nsh.
Ultimately, this should be used simply as a library, and neither the
demo app nor the daemon utilised. If just built as a library,the
relevant header file <mdns.h> is copied to the usual netutils
include location and can be utilised be including it:
#include <netutils/mdns.h>
if LIB_MDNS
config NETUTILS_MDNS
tristate "Enable mdns built-in demo app"
default n
---help---
Enable the author's original built-in MDNS demo app. This allows the
functionality of the library to be demonstrated. Information on using
it is available from the original git repo for this external library:
https://github.com/mjansson/mdns
if NETUTILS_MDNS
config NETUTILS_MDNS_PROGNAME
string "mDNS program name"
default "mdns"
---help---
This is the name of the program that will be used when the NSH ELF
program is installed.
config NETUTILS_MDNS_PRIORITY
int "mDNS task priority"
default 100
config NETUTILS_MDNS_STACKSIZE
int "mDNS stack size"
default DEFAULT_TASK_STACKSIZE
---help---
The default (4KiB) is adequate for simple networks but this will
most likely need to be increased if there are many network devices
attached that could send queries.
config NETUTILS_MDNS_VERBOSE
bool "Enable verbose printf output from built-in mdns demo"
default y
endif
config NETUTILS_MDNS_DAEMON
tristate "Wrap mdns demo app as a daemon, which can be started/stopped"
default n
depends on NETUTILS_MDNS
---help---
This option wraps the mdns demo app as a daemon, so requires
CONFIG_NETUTILS_MDNS to be selected.
There is also an example app (CONFIG_EXAMPLES_MDNSD) to allow the
mdns daemon to be started/stopped via the NuttX shell.
config NETUTILS_MDNS_DAEMON_STOP_SIGNAL
int "Signal used to stop the MDNSD daemon"
default 22
depends on NETUTILS_MDNS_DAEMON
endif #NETUTILS_MDNS

25
netutils/mdns/Make.defs Normal file
View file

@ -0,0 +1,25 @@
############################################################################
# apps/netutils/mdns/Make.defs
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifneq ($(CONFIG_LIB_MDNS),)
CONFIGURED_APPS += $(APPDIR)/netutils/mdns
endif

106
netutils/mdns/Makefile Normal file
View file

@ -0,0 +1,106 @@
############################################################################
# netutils/mdns/Makefile
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
include $(APPDIR)/Make.defs
# mDNS application
############################################################################
# Flags
############################################################################
MDNS_URL ?= "https://github.com/mjansson/mdns/archive"
MDNS_VERSION = main
MDNS_ZIP = $(MDNS_VERSION).zip
MDNS_UNPACKNAME = mdns
UNPACK ?= unzip -q -o
VPATH += $(MDNS_UNPACKNAME)
VPATH += $(MDNS_UNPACKNAME)$(DELIM)posix
DEPPATH += --dep-path $(MDNS_UNPACKNAME)
DEPPATH += --dep-path $(MDNS_UNPACKNAME)$(DELIM)posix
CFLAGS += -Wno-strict-prototypes -Wno-undef -Wno-format
APPS_INCDIR = $(APPDIR)$(DELIM)include$(DELIM)netutils
############################################################################
# Targets
############################################################################
$(MDNS_ZIP):
@echo "Downloading: $(MDNS_URL)/$(MDNS_ZIP)"
$(Q) curl -O -L $(MDNS_URL)/$(MDNS_ZIP)
$(MDNS_UNPACKNAME): $(MDNS_ZIP)
@echo "Unpacking: $(MDNS_ZIP) -> $(MDNS_UNPACKNAME)"
$(Q) $(UNPACK) $(MDNS_ZIP)
$(Q) mv mdns-$(MDNS_VERSION) $(MDNS_UNPACKNAME)
$(Q) cp $(MDNS_UNPACKNAME)$(DELIM)mdns.h $(APPS_INCDIR)
$(Q) patch -p0 < verbose_option.patch # Update to enable non-verbose mode
$(Q) touch $(MDNS_UNPACKNAME)
clean::
$(call DELFILE, $(OBJS))
# Download and unpack tarball if no git repo found
ifeq ($(wildcard $(MDNS_UNPACKNAME)/.git),)
context:: $(MDNS_UNPACKNAME)
distclean::
$(call DELFILE, $(OBJS))
$(call DELDIR, $(MDNS_UNPACKNAME))
$(call DELFILE, $(APPS_INCDIR)$(DELIM)mdns.h)
$(call DELFILE, $(MDNS_ZIP))
endif
############################################################################
# Applications Configuration
############################################################################
include $(APPDIR)/Make.defs
ifneq ($(CONFIG_NETUTILS_MDNS),)
PROGNAME = $(CONFIG_NETUTILS_MDNS_PROGNAME)
PRIORITY = $(CONFIG_NETUTILS_MDNS_PRIORITY)
STACKSIZE = $(CONFIG_NETUTILS_MDNS_STACKSIZE)
MODULE = $(CONFIG_NETUTILS_MDNS)
MAINSRC = mdns/mdns.c
else
CSRCS += mdns/mdns.c
endif
ifneq ($(CONFIG_NETUTILS_MDNS_DAEMON),)
CSRCS += mdnsd.c
endif
# This is an external library so we accept NuttX style violations
CFLAGS += -Wno-undef -Wno-strict-prototypes -Wno-unused-variable \
-Wno-pointer-sign -Wno-unused-but-set-variable -Wno-shadow \
-Wno-format
include $(APPDIR)/Application.mk

182
netutils/mdns/mdnsd.c Normal file
View file

@ -0,0 +1,182 @@
/****************************************************************************
* apps/netutils/mdns/mdnsd.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <limits.h>
#include <semaphore.h>
#include <debug.h> /* For nerr, info */
#include "netutils/netlib.h"
#include "netutils/mdnsd.h"
#include <spawn.h>
/****************************************************************************
* Preprocessor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* This enumeration describes the state of the MDNSD daemon */
enum mdnsd_daemon_e
{
MDNSD_NOT_RUNNING = 0,
MDNSD_STARTING,
MDNSD_RUNNING,
MDNSD_STOP_REQUESTED,
};
struct mdnsd_config_s
{
pid_t pid; /* Task ID of the spawned MDNSD daemon */
enum mdnsd_daemon_e state; /* State of the daemon */
sem_t lock; /* Used to protect the whole structure */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
struct mdnsd_config_s g_mdnsd_config =
{
-1,
MDNSD_NOT_RUNNING,
SEM_INITIALIZER(1),
};
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
int mdnsd_stop(void)
{
int ret;
sem_wait(&g_mdnsd_config.lock);
if (g_mdnsd_config.state == MDNSD_RUNNING)
{
g_mdnsd_config.state = MDNSD_STOP_REQUESTED;
do
{
ret = (kill(g_mdnsd_config.pid,
CONFIG_NETUTILS_MDNS_DAEMON_STOP_SIGNAL));
if (ret < 0)
{
nerr("ERROR: kill pid %d failed: %d\n",
g_mdnsd_config.pid, errno);
break;
}
}
while (g_mdnsd_config.state == MDNSD_STOP_REQUESTED);
}
g_mdnsd_config.state = MDNSD_NOT_RUNNING;
sem_post(&g_mdnsd_config.lock);
return OK;
}
int mdnsd_start(FAR char *service_name, FAR char *service_port)
{
int ret;
char hostname_buffer[HOST_NAME_MAX];
const char *hostname = "nuttx";
FAR char *argv[7];
/* Are we in a non-running state? */
sem_wait(&g_mdnsd_config.lock);
if (g_mdnsd_config.state == MDNSD_NOT_RUNNING)
{
g_mdnsd_config.state = MDNSD_STARTING;
/* Configure our mDNS service */
/* The mdns library function will check the hostname too, but this
* ensures the default is our, not the library author's, choice.
*/
if (gethostname(hostname_buffer, HOST_NAME_MAX) == 0)
{
if (strlen(hostname_buffer) != 0)
{
hostname = hostname_buffer;
}
}
argv[0] = "--service";
argv[1] = service_name;
argv[2] = "--hostname";
argv[3] = (char *)hostname;
argv[4] = "--port";
argv[5] = service_port;
argv[6] = NULL;
/* Spawn mdns app */
ret = posix_spawn(&g_mdnsd_config.pid, /* Returned Task ID */
"mdns", /* Task Path */
NULL, /* File actions */
NULL, /* Attributes */
argv, /* Arguments */
NULL); /* No */
if (ret < 0)
{
int errval = errno;
syslog(LOG_ERR, "Failed to spawn mdns daemon\n");
g_mdnsd_config.state = MDNSD_NOT_RUNNING;
return -errval;
}
ninfo("Started\n");
g_mdnsd_config.state = MDNSD_RUNNING;
}
sem_post(&g_mdnsd_config.lock);
return OK;
}

View file

@ -0,0 +1,16 @@
--- mdns/mdns.c
+++ mdns/mdns/mdns.c
@@ -22,7 +22,9 @@
// Alias some things to simulate recieving data to fuzz library
#if defined(MDNS_FUZZING)
#define recvfrom(sock, buffer, capacity, flags, src_addr, addrlen) ((mdns_ssize_t)capacity)
-#define printf
+#endif
+#if defined(MDNS_FUZZING) || !defined(CONFIG_NETUTILS_MDNS_VERBOSE)
+#define printf(...)
#endif
#include "mdns.h"
--
2.34.1