15#include <netinet/in.h>
28#define MDNS_BUFFER_SIZE (4 * 1024)
49 mdns->
socket_fd = mdns_socket_open_ipv4(NULL);
76 if (!mdns || !service) {
80 if (!service->
name || !service->
type || !service->
host) {
94 if (!mdns || !service_name) {
98 log_info(
"Stopped advertising service: %s", service_name);
112static int mdns_record_callback(
int sock,
const struct sockaddr *from,
size_t addrlen, mdns_entry_type_t entry,
114 size_t size,
size_t name_offset,
size_t name_length,
size_t record_offset,
115 size_t record_length,
void *user_data) {
123 if (entry != MDNS_ENTRYTYPE_ANSWER) {
128 memset(&discovery, 0,
sizeof(discovery));
134 size_t offset = name_offset;
135 mdns_string_extract(data, size, &offset, discovery.
type,
sizeof(discovery.
type));
139 case MDNS_RECORDTYPE_PTR: {
143 offset = record_offset;
144 mdns_string_extract(data, size, &offset, discovery.
name,
sizeof(discovery.
name));
149 case MDNS_RECORDTYPE_SRV: {
154 mdns_record_srv_t srv =
155 mdns_record_parse_srv(data, size, record_offset, record_length, discovery.
host,
sizeof(discovery.
host));
156 discovery.
port = srv.port;
157 log_debug(
"mDNS SRV: %s -> %s:%u (TTL: %u)", discovery.
type, discovery.
host, srv.port, ttl);
161 case MDNS_RECORDTYPE_A: {
165 struct sockaddr_in addr_in;
166 mdns_record_parse_a(data, size, record_offset, record_length, &addr_in);
170 snprintf(discovery.
ipv4,
sizeof(discovery.
ipv4),
"%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
175 case MDNS_RECORDTYPE_AAAA: {
179 struct sockaddr_in6 addr_in6;
180 mdns_record_parse_aaaa(data, size, record_offset, record_length, &addr_in6);
184 snprintf(discovery.
ipv6,
sizeof(discovery.
ipv6),
185 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", bytes[0], bytes[1], bytes[2],
186 bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12],
187 bytes[13], bytes[14], bytes[15]);
192 case MDNS_RECORDTYPE_TXT: {
198 discovery.
txt[0] =
'\0';
203 log_debug(
"mDNS unknown record type: %u", rtype);
221 if (!mdns || !service_type || !callback) {
228 size_t service_type_len = strlen(service_type);
229 if (service_type_len == 0) {
236 log_info(
"Starting mDNS query for: %s", service_type);
242 int query_id = mdns_query_send(mdns->
socket_fd, MDNS_RECORDTYPE_PTR, service_type, service_type_len, mdns->
buffer,
250 log_debug(
"mDNS query sent for service type: %s (query_id: %d)", service_type, query_id);
267 if (num_records < 0) {
271 if (num_records > 0) {
272 log_debug(
"Processed %d mDNS records", num_records);
#define SAFE_MALLOC(size, cast)
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
asciichat_error_t
Error and exit codes - unified status values (0-255)
#define log_info(...)
Log an INFO message.
#define log_debug(...)
Log a DEBUG message.
asciichat_error_t asciichat_mdns_update(asciichat_mdns_t *mdns, int timeout_ms)
Process pending mDNS events (must be called regularly)
asciichat_error_t asciichat_mdns_unadvertise(asciichat_mdns_t *mdns, const char *service_name)
Stop advertising a service.
#define MDNS_BUFFER_SIZE
mDNS packet buffer size (4KB should handle most service records)
void asciichat_mdns_shutdown(asciichat_mdns_t *mdns)
Shutdown mDNS context and cleanup.
asciichat_mdns_t * asciichat_mdns_init(void)
Initialize mDNS context.
int asciichat_mdns_get_socket(asciichat_mdns_t *mdns)
Get the socket file descriptor for integration with select/poll.
asciichat_error_t asciichat_mdns_query(asciichat_mdns_t *mdns, const char *service_type, asciichat_mdns_discovery_callback_fn callback, void *user_data)
Query for services on the local network.
asciichat_error_t asciichat_mdns_advertise(asciichat_mdns_t *mdns, const asciichat_mdns_service_t *service)
Advertise a service on the local network.
void(* asciichat_mdns_discovery_callback_fn)(const asciichat_mdns_discovery_t *service, void *user_data)
Callback for discovered services.
Cross-platform socket interface for ascii-chat.
Discovered service information.
Service information for advertisement.
Internal mDNS context structure.
asciichat_mdns_discovery_callback_fn callback