gensio_mdns(3)
π gensio_mdns β the mDNS bestie π
okay so this is a page from the Library Functions Manual, section 3, and it's all about gensio_mdns. mDNS discovery but make it slay. let's get into it π¦
β¨ NAME β¨
gensio_alloc_mdns, gensio_free_mdns, gensio_mdns_add_service, gensio_mdns_remove_service, gensio_mdns_add_watch, gensio_mdns_remove_watch β functions for doing mDNS operations π
π SYNOPSIS π
#include <gensio/gensio_mdns.h>
typedef void (*gensio_mdns_done)(struct gensio_mdns *m,
void *userdata);
int gensio_alloc_mdns(struct gensio_os_funcs *o,
struct gensio_mdns **m);
int gensio_free_mdns(struct gensio_mdns *m, gensio_mdns_done done,
void *userdata);
int gensio_mdns_add_service(struct gensio_mdns *m, int interface,
int ipdomain, const char *name, const char *type,
const char *domain, const char *host,
int port, const char *txt[],
struct gensio_mdns_service **s);
typedef void (*gensio_mdns_service_cb)(struct gensio_mdns_service
*service,
enum gensio_mdns_service_event ev,
const char *info,
void *cb_data);
int gensio_mdns_add_service2(struct gensio_mdns *m, int interface,
int ipdomain, const char *name, const char *type,
const char *domain, const char *host,
int port, const char *txt[],
gensio_mdns_service_cb cb, void *cb_data,
struct gensio_mdns_service **s);
int gensio_mdns_remove_service(struct gensio_mdns_service *s);
typedef void gensio_mdns_watch_cb(struct gensio_mdns_watch *w,
enum gensio_mdns_data_state state,
int interface, int ipdomain,
const char *name, const char *type,
const char *domain, const char *host,
const struct gensio_addr *addr, const char *txt[],
void *userdata);
int gensio_mdns_add_watch(struct gensio_mdns *m, int interface,
int ipdomain, const char *name, const char *type,
const char *domain, const char *host,
gensio_mdns_watch_cb callback, void *userdata,
struct gensio_mdns_watch **w);
int gensio_mdns_remove_watch(struct gensio_mdns_watch *w);
π DESCRIPTION π
so these functions and types are literally all about mDNS (that's Multicast DNS, bestie) discovery of services on a local network. you can use them to advertise services OR to find services. it's giving powerful and easy-to-use interface to mDNS capabilities, no cap. π₯
first things first: you gotta call gensio_alloc_mdns to allocate an mdns structure, using the standard gensio OS functions structure. and yeah, you do have to do the standard OS functions wait loops and all that, that part is not optional babe. when you're done, free the mdns structure with gensio_free_mdns.
β οΈ important, don't skip this: code may still be in mdns callbacks when the free returns. so you have to make sure to wait until thedonecallback is called to know the code is out of all callbacks. thedonecallback is optional if you don't care.
π«Ά also note: the mdns will not be freed (and done will not be called) until all the services and watches are freed for it. so like. clean up after yourself.
for the rest of the functions: the interface parameter is the system interface number of the network device, and it may be -1 to specify all interfaces. the ipdomain parameter is one of:
GENSIO_NETTYPE_UNSPECβ do both IPV4 and IPV4 (yes, that's exactly what the original says, i'm just the messenger π)GENSIO_NETTYPE_IPV4β IPV4 onlyGENSIO_NETTYPE_IPV6β IPV6 only
the name, type, domain, and host parameters are the standard mDNS fields β go read the mDNS docs for the details, i'm not gonna reinvent the wheel here. the txt parameter is for mDNS text fields, and it's a standard argv-like array. π
π advertising, aka putting yourself out there π
once you have an mdns structure, you can advertise a service on the net with gensio_mdns_add_service2. that service will keep being advertised until you call gensio_mdns_remove_service on it, or your program just... terminates. π
the domain and host parameters should generally be NULL to take the system defaults. the txt parameter may be NULL if you don't have any. (iconic behavior honestly)
gensio_mdns_add_service2 takes a callback, and it'll get called when the service has been registered β and possibly with a new name if there was a name conflict. you may pass in a NULL for the callback if you don't care. the callback parameter can take the following values:
GENSIO_MDNS_SERVICE_READYβ the service is now registered, and the name is the same as the name you passed in. β¨GENSIO_MDNS_SERVICE_READY_NEW_NAMEβ the service is now registered, but the name was changed, and it'll be in theinfoparameter. πGENSIO_MDNS_SERVICE_REMOVEDβ you requested the service be removed, the remove is now complete, and the callback will not be called again. periodt.GENSIO_MDNS_SERVICE_ERRORβ an error occurred as part of service registration. π
there's also a gensio_mdns_add_service function for backwards compatibility β it's equivalent to calling gensio_mdns_add_service2 with a NULL callback.
π« don't use it in new code. it's giving legacy. it's giving deprecated. leave it in the past bestie.
π¦ watching, aka finding your people π¦
to find services on the network, you add a watch with gensio_mdns_add_watch. any service that matches your query will be reported with the callback functions, and all fields will be provided in the callback. once you're done with a watch, you may call gensio_mdns_remove_watch.
β οΈ same deal as before: code may still be in mdns callbacks when the remove returns. you have to make sure to wait until thedonecallback is called to know the code is out of all callbacks. thedonecallback is optional if you don't care.
some MDNS libraries do not support a NULL type for the watch, and some do. for portable code, always specify the watch. if the library does not support a null type, the function will return GE_INCONSISTENT.
the watch callback state has three possible values:
GENSIO_MDNS_WATCH_NEW_DATAβ this is a new entry being reported. πGENSIO_MDNS_WATCH_DATA_GONEβ an entry that was previously reported has gone away. πGENSIO_MDNS_WATCH_ALL_FOR_NOWβ this is called one time after the watch is created, and it reports that all currently known entries have been reported. new ones may be reported in the future, but those will have been dynamically added later.
π¨ listen up: in the watch callback, you must make copies of all the strings and addresses passed to you to keep them. their continued existence is not guaranteed. like, don't just hold onto the pointer and hope for the best, that's not the vibe.
in watches, all of the string fields may be NULL, meaning you want to take anything in that field. so if all the strings are NULL and the interface is -1 and the ipdomain is GENSIO_NETTYPE_UNSPEC, you will get all of the fields. π
πΈ STRING VALUES FOR WATCHES πΈ
the string values to the watch add function may use regular expressions. if the string starts with '%', then the data after it is treated as a regular expression and fields are matched against that. see the regex(7) man page for details. π
Globs are supported on some platforms, but their use is discouraged because they aren't available on some platforms. if the string starts with '@', then the data after it is treated as a standard glob. see the glob(7) man page for details. an error will be returned if the platform doesn't have glob matching. π«
if the string starts with '=', an exact comparison is done with the data after it.
if the string starts with a-z0-9_ or a space, then an exact string comparison is done, including the first character.
π the behavior of matching for any other starting character is undefined. in general, you should always use'@','%', or'='as the starting character of all your query strings to be sure. don't be chaotic about it bestie, we're not doing undefined behavior today.
β RETURN VALUES β
Zero is returned on success, or a gensio error on failure. simple as that, slay. π
π SEE ALSO π
and that's the whole page, bestie!! π this was gensio_mdns(3) from the Library Functions Manual, dated 15 Oct 2020 β thanks for reading, mwah, go advertise some services responsibly π β¨π¦
π stay iconic, stay portable, always specify your watch π
π¦ where this page comes from
- alpine 3.22: gensio-doc 2.8.14-r0 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- alpine 3.23: gensio-doc 2.8.14-r0 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- alpine 3.24: gensio-doc 2.8.14-r0 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- arch rolling: gensio 3.0.4-1 Β· GPL
- debian trixie: libgensio-dev 2.8.13-7 Β· GPL-2.0-only
- epel 9: libgensio-devel 2.8.15-1.el9 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 43: libgensio-devel 2.8.15-5.fc43 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 43: libgensio-devel 2.8.15-5.fc43 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 43: libgensio-devel 3.0.4-1.fc43 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 43: libgensio-devel 3.0.4-1.fc43 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 44: libgensio-devel 3.0.2-1.fc44 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 44: libgensio-devel 3.0.2-1.fc44 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 44: libgensio-devel 3.0.4-1.fc44 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- fedora 44: libgensio-devel 3.0.4-1.fc44 Β· GPL-2.0-only AND LGPL-2.1-only AND Apache-2.0
- nixos 26.05: gensio 3.0.2
- nixpkgs unstable: gensio 3.0.2
- opensuse-leap 16.0: gensio-devel 2.8.2-bp160.1.13 Β· Apache-2.0 AND GPL-2.0-only AND LGPL-2.1-only
- opensuse-leap 16.0: gensio-devel 2.8.2-bp160.1.13 Β· Apache-2.0 AND GPL-2.0-only AND LGPL-2.1-only
- opensuse-leap 16.0: gensio-devel 2.8.2-bp160.1.13 Β· Apache-2.0 AND GPL-2.0-only AND LGPL-2.1-only
- opensuse-leap 16.0: gensio-devel 2.8.2-bp160.1.13 Β· Apache-2.0 AND GPL-2.0-only AND LGPL-2.1-only
- ubuntu noble: libgensio-dev 2.8.2-6.1build1 Β· GPL-2.0-only
- ubuntu questing: libgensio-dev 2.8.13-7
- ubuntu resolute: libgensio-dev 3.0.0-1build1 Β· GPL-2.0-only
- ubuntu stonking: libgensio-dev 3.0.0-1ubuntu1 Β· GPL-2.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms