ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
mdns.h File Reference

Go to the source code of this file.

Data Structures

struct  asciichat_mdns_service_t
 Service information for advertisement. More...
 
struct  asciichat_mdns_discovery_t
 Discovered service information. More...
 

Typedefs

typedef struct asciichat_mdns_t asciichat_mdns_t
 opaque mDNS context handle
 
typedef void(* asciichat_mdns_discovery_callback_fn) (const asciichat_mdns_discovery_t *service, void *user_data)
 Callback for discovered services.
 

Functions

asciichat_mdns_tasciichat_mdns_init (void)
 Initialize mDNS context.
 
void asciichat_mdns_shutdown (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.
 

Typedef Documentation

◆ asciichat_mdns_discovery_callback_fn

typedef void(* asciichat_mdns_discovery_callback_fn) (const asciichat_mdns_discovery_t *service, void *user_data)

Callback for discovered services.

Parameters
serviceDiscovered service information
user_dataUser pointer passed to query

Definition at line 107 of file mdns.h.

◆ asciichat_mdns_t

opaque mDNS context handle

Definition at line 59 of file mdns.h.

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 75 of file mdns.c.

75 {
76 if (!mdns || !service) {
77 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context or service is NULL");
78 }
79
80 if (!service->name || !service->type || !service->host) {
81 return SET_ERRNO(ERROR_INVALID_PARAM, "Service name, type, or host is NULL");
82 }
83
84 log_info("Advertising mDNS service: %s (%s:%d)", service->name, service->host, service->port);
85
86 /* TODO: Implement actual advertisement using mdns library
87 * This will involve creating service records and sending announcements
88 * The mdns library provides mdns_announce_* functions for this
89 */
90 return ASCIICHAT_OK;
91}
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_INVALID_PARAM
#define log_info(...)
Log an INFO message.
const char * type
Definition mdns.h:70
const char * host
Definition mdns.h:72
const char * name
Definition mdns.h:66

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

Referenced by main().

◆ 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 279 of file mdns.c.

279 {
280 if (!mdns) {
281 return -1;
282 }
283 return mdns->socket_fd;
284}
int socket_fd
Definition mdns.c:19

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 30 of file mdns.c.

30 {
32 if (!mdns) {
33 SET_ERRNO(ERROR_MEMORY, "Failed to allocate mDNS context");
34 return NULL;
35 }
36
37 memset(mdns, 0, sizeof(asciichat_mdns_t));
38
39 /* Allocate I/O buffer for mDNS packets */
41 if (!mdns->buffer) {
42 SAFE_FREE(mdns);
43 SET_ERRNO(ERROR_MEMORY, "Failed to allocate mDNS buffer");
44 return NULL;
45 }
47
48 /* Open IPv4 mDNS socket */
49 mdns->socket_fd = mdns_socket_open_ipv4(NULL);
50 if (mdns->socket_fd < 0) {
51 SAFE_FREE(mdns->buffer);
52 SAFE_FREE(mdns);
53 SET_ERRNO(ERROR_NETWORK_BIND, "Failed to open mDNS socket");
54 return NULL;
55 }
56
57 log_info("mDNS context initialized (socket: %d, buffer: %zu bytes)", mdns->socket_fd, mdns->buffer_capacity);
58 return mdns;
59}
#define SAFE_FREE(ptr)
Definition common.h:320
#define SAFE_MALLOC(size, cast)
Definition common.h:208
unsigned char uint8_t
Definition common.h:56
@ ERROR_NETWORK_BIND
Definition error_codes.h:70
@ ERROR_MEMORY
Definition error_codes.h:53
#define MDNS_BUFFER_SIZE
mDNS packet buffer size (4KB should handle most service records)
Definition mdns.c:28
Internal mDNS context structure.
Definition mdns.c:18
size_t buffer_capacity
Definition mdns.c:23
uint8_t * buffer
Definition mdns.c:22

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

Referenced by discovery_mdns_query(), main(), and server_main().

◆ 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 219 of file mdns.c.

220 {
221 if (!mdns || !service_type || !callback) {
222 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid mDNS query parameters");
223 }
224
225 /* Validate service type is non-empty and has minimum length
226 * Prevents underflow bug in mdns library when processing empty strings
227 */
228 size_t service_type_len = strlen(service_type);
229 if (service_type_len == 0) {
230 return SET_ERRNO(ERROR_INVALID_PARAM, "Service type cannot be empty");
231 }
232
233 mdns->callback = callback;
234 mdns->callback_data = user_data;
235
236 log_info("Starting mDNS query for: %s", service_type);
237
238 /* Send PTR query for service type (one-shot query)
239 * PTR query discovers all instances of a service type
240 * mdns_query_send returns the query ID for response filtering
241 */
242 int query_id = mdns_query_send(mdns->socket_fd, MDNS_RECORDTYPE_PTR, service_type, service_type_len, mdns->buffer,
243 mdns->buffer_capacity, 0);
244
245 if (query_id <= 0) {
246 return SET_ERRNO(ERROR_NETWORK, "mDNS query send failed for %s (query_id=%d)", service_type, query_id);
247 }
248
249 mdns->query_id = (uint16_t)query_id;
250 log_debug("mDNS query sent for service type: %s (query_id: %d)", service_type, query_id);
251
252 return ASCIICHAT_OK;
253}
unsigned short uint16_t
Definition common.h:57
@ ERROR_NETWORK
Definition error_codes.h:69
#define log_debug(...)
Log a DEBUG message.
asciichat_mdns_discovery_callback_fn callback
Definition mdns.c:20
uint16_t query_id
Definition mdns.c:24
void * callback_data
Definition mdns.c:21

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_shutdown()

void asciichat_mdns_shutdown ( asciichat_mdns_t mdns)

Shutdown mDNS context and cleanup.

Parameters
mdnsContext to cleanup

Definition at line 61 of file mdns.c.

61 {
62 if (!mdns) {
63 return;
64 }
65
66 if (mdns->socket_fd >= 0) {
67 mdns_socket_close(mdns->socket_fd);
68 }
69
70 SAFE_FREE(mdns->buffer);
71 SAFE_FREE(mdns);
72 log_info("mDNS context shutdown");
73}

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

Referenced by discovery_mdns_query(), main(), and server_main().

◆ 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 93 of file mdns.c.

93 {
94 if (!mdns || !service_name) {
95 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context or service name is NULL");
96 }
97
98 log_info("Stopped advertising service: %s", service_name);
99
100 /* TODO: Implement actual unadvertisement
101 * This will involve sending goodbye records with TTL=0
102 */
103 return ASCIICHAT_OK;
104}

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 255 of file mdns.c.

255 {
256 if (!mdns) {
257 return SET_ERRNO(ERROR_INVALID_PARAM, "mDNS context is NULL");
258 }
259
260 /* Process incoming mDNS packets (responses from previous queries)
261 * mdns_query_recv processes all records received since last call
262 * The callback function (mdns_record_callback) is invoked for each record
263 */
264 int num_records =
265 mdns_query_recv(mdns->socket_fd, mdns->buffer, mdns->buffer_capacity, mdns_record_callback, mdns, mdns->query_id);
266
267 if (num_records < 0) {
268 return SET_ERRNO(ERROR_NETWORK, "Failed to receive mDNS query responses");
269 }
270
271 if (num_records > 0) {
272 log_debug("Processed %d mDNS records", num_records);
273 }
274
275 (void)timeout_ms;
276 return ASCIICHAT_OK;
277}

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().