Cette bibliothèque fournit une bibliothèque mDNS et DNS-DS multiplateforme uniquement en-tête en C. Le dernier code source est toujours disponible sur
https://github.com/mjansson/mdns
Cette bibliothèque est mise dans le domaine public ; vous pouvez le redistribuer et/ou le modifier sans aucune restriction.
Créé par Mattias Jansson (@maniccoder)
Serveur Discord pour les discussions https://discord.gg/M8BwTQrt6c
La bibliothèque effectue la découverte et le service DNS-SD ainsi que les requêtes et réponses mDNS à enregistrement unique. Aucune allocation de mémoire n'est effectuée par la bibliothèque, tous les tampons utilisés doivent être transmis par l'appelant. Les données personnalisées à utiliser dans le traitement peuvent être transmises à l'aide d'un pointeur opaque de données utilisateur.
Le fichier exécutable de test mdns.c
démontre l'utilisation de toutes les fonctionnalités, y compris la découverte, les requêtes et la réponse du service. La documentation ici est intentionnellement clairsemée, l'exemple de code est bien documenté et devrait fournir tous les détails.
Le socket pour la communication mDNS peut être ouvert par la bibliothèque en utilisant mdns_socket_open_ipv4
ou mdns_socket_open_ipv6
, ou en initialisant un socket existant avec mdns_socket_setup_ipv4
ou mdns_socket_setup_ipv6
. Les fonctions d'ouverture/de configuration du socket initialiseront le socket avec une adhésion multicast (y compris le bouclage) et la définiront en mode non bloquant.
Appelez mdns_socket_close
pour fermer un socket ouvert avec mdns_socket_open_ipv4
ou mdns_socket_open_ipv6
.
Pour ouvrir/configurer le socket pour des requêtes ponctuelles, vous pouvez transmettre une adresse de socket de pointeur nul ou définir le port dans l'adresse de socket transmise sur 0. Cela liera le socket à un port UDP local éphémère aléatoire, comme l'exigent les RFC pour requêtes ponctuelles. Vous ne devez PAS vous lier au port 5353 lorsque vous effectuez des requêtes ponctuelles (voir la RFC pour plus de détails).,
Pour ouvrir/configurer le socket pour le service, en répondant aux requêtes entrantes, vous devez transmettre une structure d'adresse de socket avec le port défini sur 5353 (défini par MDNS_PORT dans l'en-tête). Vous ne pouvez choisir aucun autre port ou vous ne recevrez aucune requête entrante.
Pour effectuer une découverte ou des requêtes sur l'interface réseau par défaut, vous pouvez transmettre un pointeur nul comme adresse de socket dans les fonctions de création/configuration de socket. Cela liera le socket à l’interface réseau par défaut. Sinon, vous devez énumérer les interfaces disponibles et transmettre l'adresse de socket appropriée à la fonction de création/configuration. Voir l'exemple de programme dans mdns.c
pour un exemple d'implémentation de cette opération pour IPv4 et IPv6.
Si vous souhaitez effectuer une réponse de service mDNS aux requêtes entrantes, vous n'avez pas besoin d'énumérer les interfaces pour effectuer une réponse de service sur toutes les interfaces, car les sockets reçoivent des données de toutes les interfaces. Voir l'exemple de programme dans mdns.c
pour un exemple de configuration d'un socket de service pour IPv4 et IPv6.
Pour envoyer une demande de découverte de service DNS-SD, utilisez mdns_discovery_send
. Cela enverra un seul paquet de multidiffusion (un seul enregistrement de question PTR pour _services._dns-sd._udp.local.
) demandant une réponse unicast.
Pour lire les réponses de découverte, utilisez mdns_discovery_recv
. Tous les enregistrements reçus depuis le dernier appel seront redirigés vers le rappel fourni dans l'appel de fonction. Le type d'entrée sera l'un des MDNS_ENTRYTYPE_ANSWER
, MDNS_ENTRYTYPE_AUTHORITY
et MDNS_ENTRYTYPE_ADDITIONAL
.
Pour envoyer une requête mDNS unique pour un seul enregistrement, utilisez mdns_query_send
. Cela enverra un seul paquet de multidiffusion pour l'enregistrement et le nom donnés (par exemple l'enregistrement PTR pour _http._tcp.local.
). Vous pouvez éventuellement transmettre un ID de requête pour la requête pour un filtrage ultérieur des réponses (même si cela est déconseillé par la RFC), ou transmettre 0 pour être entièrement conforme. La fonction renvoie l'ID de requête associé à cette requête, qui, s'il est différent de zéro, peut être utilisé pour filtrer les réponses dans mdns_query_recv
. Si le socket est lié au port 5353, une réponse multicast est demandée, sinon une réponse unicast.
Pour lire les réponses aux requêtes, utilisez mdns_query_recv
. Tous les enregistrements reçus depuis le dernier appel seront redirigés vers le rappel fourni dans l'appel de fonction. Si le paramètre query_id
est différent de zéro, la fonction filtrera toute réponse avec un ID de requête qui ne correspond pas à l'ID de requête donné. Le type d'entrée sera l'un des MDNS_ENTRYTYPE_ANSWER
, MDNS_ENTRYTYPE_AUTHORITY
et MDNS_ENTRYTYPE_ADDITIONAL
.
Notez qu'un socket ouvert pour des requêtes ponctuelles depuis un port éphémère ne recevra aucune réponse non sollicitée (annonces) car celles-ci sont envoyées en multidiffusion sur le port 5353.
Pour envoyer plusieurs requêtes dans le même paquet, utilisez mdns_multiquery_send
qui prend un tableau et un nombre de noms de services et de types d'enregistrements à interroger.
Pour écouter les requêtes DNS-SD entrantes et les requêtes mDNS, le socket peut être ouvert/configuré sur l'interface par défaut en passant 0 comme adresse de socket dans l'appel aux fonctions d'ouverture/de configuration du socket (le socket recevra les données de toutes les interfaces réseau). Appelez ensuite mdns_socket_listen
soit lors de la notification des données entrantes, soit en définissant le mode de blocage et en appelant mdns_socket_listen
pour bloquer jusqu'à ce que les données soient disponibles et analysées.
Le type d'entrée transmis au rappel sera MDNS_ENTRYTYPE_QUESTION
et le type d'enregistrement indique avec quel enregistrement répondre. L'exemple de programme répond aux enregistrements SRV, PTR, A et AAAA. Utilisez la fonction mdns_string_extract
pour obtenir la chaîne de nom de l'enregistrement de service demandé.
Si le nom de l'enregistrement de service est _services._dns-sd._udp.local.
vous devez utiliser mdns_discovery_answer
pour envoyer les enregistrements des services que vous fournissez (DNS-SD).
Si le nom de l'enregistrement de service est un service que vous fournissez, utilisez mdns_query_answer_unicast
ou mdns_query_answer_multicast
en fonction de l'indicateur de type de réponse dans la question pour renvoyer les détails du service en réponse à la requête.
Voir l'implémentation de l'exécutable de test pour plus de détails sur la façon de gérer les paramètres des fonctions données.
Si vous fournissez un service mDNS écoutant et répondant aux requêtes sur le port 5353, il est encouragé à envoyer une annonce au démarrage de votre service (en tant que réponse non sollicitée). Utilisez mdns_announce_multicast
pour annoncer les enregistrements de votre service au démarrage et mdns_goodbye_multicast
pour annoncer la fin du service à la résiliation.
Le fichier mdns.c
contient une implémentation exécutable de test utilisant la bibliothèque pour effectuer des requêtes DNS-SD et mDNS. Compilez dans un exécutable et exécutez pour voir les options de ligne de commande pour les modes découverte, requête et service.
cl mdns.c /Zi /Fdmdns.pdb /link /out:mdns.exe ws2_32.lib iphlpapi.lib
gcc -o mdns mdns.c
clang -o mdns mdns.c
FetchContent
ou installez et find_package
mdns/20200130
et find_package
-> https://conan.io/center/mdns/20200130vcpkg install mdns
et find_package