ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
mdns.c File Reference

mDNS service discovery implementation for ascii-chat More...

Go to the source code of this file.

Data Structures

struct  asciichat_mdns_t
 Internal mDNS context structure. More...
 

Macros

#define MDNS_BUFFER_SIZE   (4 * 1024)
 mDNS packet buffer size (4KB should handle most service records)
 

Functions

asciichat_mdns_t * asciichat_mdns_init (void)
 Initialize mDNS context.
 
void asciichat_mdns_destroy (asciichat_mdns_t *mdns)
 Shutdown mDNS context and cleanup.
 
asciichat_error_t asciichat_mdns_advertise (asciichat_mdns_t *mdns, const asciichat_mdns_service_t *service)
 Advertise a service on the local network.
 
asciichat_error_t asciichat_mdns_unadvertise (asciichat_mdns_t *mdns, const char *service_name)
 Stop advertising a service.
 
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_update (asciichat_mdns_t *mdns, int timeout_ms)
 Process pending mDNS events (must be called regularly)
 
int asciichat_mdns_get_socket (asciichat_mdns_t *mdns)
 Get the socket file descriptor for integration with select/poll.
 

Detailed Description

mDNS service discovery implementation for ascii-chat

Wraps the mdns library (https://github.com/mjansson/mdns) with ascii-chat specific API. This implementation provides service advertisement and discovery for LAN-based sessions.

Definition in file network/mdns/mdns.c.

Macro Definition Documentation

◆ MDNS_BUFFER_SIZE

#define MDNS_BUFFER_SIZE   (4 * 1024)

mDNS packet buffer size (4KB should handle most service records)

Definition at line 34 of file network/mdns/mdns.c.

Function Documentation

◆ asciichat_mdns_advertise()

asciichat_error_t asciichat_mdns_advertise ( asciichat_mdns_t *  mdns,
const asciichat_mdns_service_t *  service 
)

Advertise a service on the local network.

Parameters
mdnsmDNS context
serviceService to advertise
Returns
ASCIICHAT_OK on success, error code otherwise
Note
The service structure should remain valid until unadvertised

Definition at line 85 of file network/mdns/mdns.c.

85 {
86 if (!mdns || !service) {
87 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context or service is NULL");
88 }
89
90 if (!service->name || !service->type || !service->host) {
91 return SET_ERRNO(ERROR_INVALID_PARAM, "Service name, type, or host is NULL");
92 }
93
94 log_debug("Advertising mDNS service: %s (%s:%d)", service->name, service->host, service->port);
95
96 /* TODO: Implement actual advertisement using mdns library
97 * This will involve creating service records and sending announcements
98 * The mdns library provides mdns_announce_* functions for this
99 */
100 return ASCIICHAT_OK;
101}
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548

References ASCIICHAT_OK, ERROR_INVALID_PARAM, asciichat_mdns_service_t::host, log_debug, asciichat_mdns_service_t::name, asciichat_mdns_service_t::port, SET_ERRNO, and asciichat_mdns_service_t::type.

Referenced by session_server_like_mdns_advertise().

◆ asciichat_mdns_destroy()

void asciichat_mdns_destroy ( asciichat_mdns_t *  mdns)

Shutdown mDNS context and cleanup.

Parameters
mdnsContext to cleanup

Definition at line 71 of file network/mdns/mdns.c.

71 {
72 if (!mdns) {
73 return;
74 }
75
76 if (mdns->socket_fd >= 0) {
77 mdns_socket_close(mdns->socket_fd);
78 }
79
80 SAFE_FREE(mdns->buffer);
81 SAFE_FREE(mdns);
82 log_debug("mDNS context shutdown");
83}
#define SAFE_FREE(ptr)
Definition common.h:376

References asciichat_mdns_t::buffer, log_debug, SAFE_FREE, and asciichat_mdns_t::socket_fd.

Referenced by discovery_mdns_query(), and session_server_like_run().

◆ asciichat_mdns_get_socket()

int asciichat_mdns_get_socket ( asciichat_mdns_t *  mdns)

Get the socket file descriptor for integration with select/poll.

Parameters
mdnsmDNS context
Returns
Socket descriptor, or -1 on error
Note
Useful for integrating mDNS into existing event loops

Definition at line 289 of file network/mdns/mdns.c.

289 {
290 if (!mdns) {
291 return -1;
292 }
293 return mdns->socket_fd;
294}

References asciichat_mdns_t::socket_fd.

◆ asciichat_mdns_init()

asciichat_mdns_t * asciichat_mdns_init ( void  )

Initialize mDNS context.

Returns
Opaque mDNS context, or NULL on error

Definition at line 36 of file network/mdns/mdns.c.

36 {
38 if (!mdns) {
39 SET_ERRNO(ERROR_MEMORY, "Failed to allocate mDNS context");
40 return NULL;
41 }
42
43 memset(mdns, 0, sizeof(asciichat_mdns_t));
44
45 /* Allocate I/O buffer for mDNS packets */
47 if (!mdns->buffer) {
48 SAFE_FREE(mdns);
49 SET_ERRNO(ERROR_MEMORY, "Failed to allocate mDNS buffer");
50 return NULL;
51 }
53
54 /* Open IPv4 mDNS socket */
55 mdns->socket_fd = mdns_socket_open_ipv4(NULL);
56 if (mdns->socket_fd < 0) {
57 SAFE_FREE(mdns->buffer);
58 SAFE_FREE(mdns);
59 SET_ERRNO(ERROR_NETWORK_BIND, "Failed to open mDNS socket");
60 return NULL;
61 }
62
63 log_dev("mDNS context initialized (socket: %d, buffer: %zu bytes)", mdns->socket_fd, mdns->buffer_capacity);
64
65 // Register mDNS context for debugging
66 NAMED_REGISTER_CONTEXT(mdns, "asciichat_mdns", "mdns_context", NULL);
67
68 return mdns;
69}
#define SAFE_MALLOC(size, cast)
Definition common.h:264
unsigned char uint8_t
Definition common.h:56
#define NAMED_REGISTER_CONTEXT(context, context_type, name, parent_ptr)
Register a generic context with automatic format specifier.
@ ERROR_NETWORK_BIND
Definition error_codes.h:78
@ ERROR_MEMORY
Definition error_codes.h:56
#define log_dev(...)
Log a DEV message (most verbose, development only)
Definition log/log.h:534
#define MDNS_BUFFER_SIZE
mDNS packet buffer size (4KB should handle most service records)
Internal mDNS context structure.

References asciichat_mdns_t::buffer, asciichat_mdns_t::buffer_capacity, ERROR_MEMORY, ERROR_NETWORK_BIND, log_dev, MDNS_BUFFER_SIZE, NAMED_REGISTER_CONTEXT, SAFE_FREE, SAFE_MALLOC, SET_ERRNO, and asciichat_mdns_t::socket_fd.

Referenced by discovery_mdns_query(), and session_server_like_run().

◆ asciichat_mdns_query()

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.

Parameters
mdnsmDNS context
service_typeService type to query (e.g., "_ascii-chat._tcp.local")
callbackFunction to call for each discovered service
user_dataUser pointer passed to callback
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 229 of file network/mdns/mdns.c.

230 {
231 if (!mdns || !service_type || !callback) {
232 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid mDNS query parameters");
233 }
234
235 /* Validate service type is non-empty and has minimum length
236 * Prevents underflow bug in mdns library when processing empty strings
237 */
238 size_t service_type_len = strlen(service_type);
239 if (service_type_len == 0) {
240 return SET_ERRNO(ERROR_INVALID_PARAM, "Service type cannot be empty");
241 }
242
243 mdns->callback = callback;
244 mdns->callback_data = user_data;
245
246 log_info("Starting mDNS query for: %s", service_type);
247
248 /* Send PTR query for service type (one-shot query)
249 * PTR query discovers all instances of a service type
250 * mdns_query_send returns the query ID for response filtering
251 */
252 int query_id = mdns_query_send(mdns->socket_fd, MDNS_RECORDTYPE_PTR, service_type, service_type_len, mdns->buffer,
253 mdns->buffer_capacity, 0);
254
255 if (query_id < 0) {
256 return SET_ERRNO(ERROR_NETWORK, "mDNS query send failed for %s (query_id=%d)", service_type, query_id);
257 }
258
259 mdns->query_id = (uint16_t)query_id;
260 log_debug("mDNS query sent for service type: %s (query_id: %d)", service_type, query_id);
261
262 return ASCIICHAT_OK;
263}
unsigned short uint16_t
Definition common.h:57
@ ERROR_NETWORK
Definition error_codes.h:77
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
asciichat_mdns_discovery_callback_fn callback

References ASCIICHAT_OK, asciichat_mdns_t::buffer, asciichat_mdns_t::buffer_capacity, asciichat_mdns_t::callback, asciichat_mdns_t::callback_data, ERROR_INVALID_PARAM, ERROR_NETWORK, log_debug, log_info, asciichat_mdns_t::query_id, SET_ERRNO, and asciichat_mdns_t::socket_fd.

Referenced by discovery_mdns_query().

◆ asciichat_mdns_unadvertise()

asciichat_error_t asciichat_mdns_unadvertise ( asciichat_mdns_t *  mdns,
const char *  service_name 
)

Stop advertising a service.

Parameters
mdnsmDNS context
service_nameService instance name to unadvertise
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 103 of file network/mdns/mdns.c.

103 {
104 if (!mdns || !service_name) {
105 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context or service name is NULL");
106 }
107
108 log_info("Stopped advertising service: %s", service_name);
109
110 /* TODO: Implement actual unadvertisement
111 * This will involve sending goodbye records with TTL=0
112 */
113 return ASCIICHAT_OK;
114}

References ASCIICHAT_OK, ERROR_INVALID_PARAM, log_info, and SET_ERRNO.

◆ asciichat_mdns_update()

asciichat_error_t asciichat_mdns_update ( asciichat_mdns_t *  mdns,
int  timeout_ms 
)

Process pending mDNS events (must be called regularly)

This should be called from the main event loop to:

  • Send advertisement packets
  • Receive and parse query responses
  • Invoke discovery callbacks
Parameters
mdnsmDNS context
timeout_msMaximum time to block (0 = non-blocking)
Returns
ASCIICHAT_OK on success, error code otherwise

Definition at line 265 of file network/mdns/mdns.c.

265 {
266 if (!mdns) {
267 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context is NULL");
268 }
269
270 /* Process incoming mDNS packets (responses from previous queries)
271 * mdns_query_recv processes all records received since last call
272 * The callback function (mdns_record_callback) is invoked for each record
273 */
274 int num_records =
275 mdns_query_recv(mdns->socket_fd, mdns->buffer, mdns->buffer_capacity, mdns_record_callback, mdns, mdns->query_id);
276
277 if (num_records < 0) {
278 return SET_ERRNO(ERROR_NETWORK, "Failed to receive mDNS query responses");
279 }
280
281 if (num_records > 0) {
282 log_debug("Processed %d mDNS records", num_records);
283 }
284
285 (void)timeout_ms;
286 return ASCIICHAT_OK;
287}

References ASCIICHAT_OK, asciichat_mdns_t::buffer, asciichat_mdns_t::buffer_capacity, ERROR_INVALID_PARAM, ERROR_NETWORK, log_debug, asciichat_mdns_t::query_id, SET_ERRNO, and asciichat_mdns_t::socket_fd.

Referenced by discovery_mdns_query().