From 0c794f19d203baac9538e2fd74836a7f597535fb Mon Sep 17 00:00:00 2001 From: cpq Date: Tue, 24 Feb 2026 16:07:10 +0000 Subject: [PATCH] Obtain IP adress for MDNS automatically --- mongoose.c | 97 +++++++++++++++++++++-------- mongoose.h | 17 +++-- src/dns.c | 66 +++++++++++++------- src/dns.h | 17 +++-- src/sock.c | 31 ++++++++- tutorials/udp/mdns-client/main.c | 5 -- tutorials/udp/mdns-sd-server/main.c | 13 ++-- tutorials/udp/mdns-server/main.c | 32 ++++++++-- 8 files changed, 193 insertions(+), 85 deletions(-) diff --git a/mongoose.c b/mongoose.c index 9fde97e4..1d308740 100644 --- a/mongoose.c +++ b/mongoose.c @@ -260,7 +260,8 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) { memcpy(&dm->addr.addr.ip, &buf[ofs - 4], 4); dm->resolved = true; break; // Return success - } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && rr.aclass == 1) { + } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && + rr.aclass == 1) { dm->addr.is_ip6 = true; memcpy(&dm->addr.addr.ip, &buf[ofs - 16], 16); dm->resolved = true; @@ -379,7 +380,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, uint16_t id; mg_random(&id, sizeof(uint16_t)); // TODO(): traverse reqs and check id != reqs->txnid; repeat otherwise - if (reqs != NULL) id = (uint16_t) (reqs->txnid + 1); // no collision + if (reqs != NULL) id = (uint16_t) (reqs->txnid + 1); // no collision d->txnid = id; d->next = reqs; c->mgr->active_dns_requests = d; @@ -423,13 +424,26 @@ static uint8_t *build_name(struct mg_str *name, uint8_t *p) { return p; } -static uint8_t *build_a_record(struct mg_connection *c, uint8_t *p) { +void mg_getlocaddr(struct mg_connection *, struct mg_addr *, struct mg_addr *); + +static uint8_t *build_a_record(struct mg_connection *c, uint8_t *p, + struct mg_addr *addr) { memcpy(p, mdns_answer, sizeof(mdns_answer)), p += sizeof(mdns_answer); + if (addr != NULL && !addr->is_ip6) { + memcpy(p, &addr->addr.ip4, 4), p += 4; + } else { #if MG_ENABLE_TCPIP - memcpy(p, &c->mgr->ifp->ip, 4), p += 4; + memcpy(p, &c->mgr->ifp->ip, 4), p += 4; #else - memcpy(p, c->data, 4), p += 4; + struct mg_addr loc, to; + memset(&loc, 0, sizeof(loc)); + to.is_ip6 = false; + to.port = mg_htons(5353); + to.addr.ip4 = MG_IPV4(224, 0, 0, 51); + mg_getlocaddr(c, &to, &loc); + memcpy(p, &loc.addr.ip4, 4), p += 4; #endif + } return p; } @@ -523,7 +537,7 @@ static void handle_mdns_query(struct mg_connection *c) { qh->num_questions = mg_htons(1); // parser sanity mg_dns_parse_name(c->recv.buf, c->recv.len, 12, name, sizeof(name)); name_len = (uint8_t) strlen(name); // verify it ends in .local - if (strcmp(".local", &name[name_len - 6]) != 0 || + if (name_len <= 6 || strcmp(".local", &name[name_len - 6]) != 0 || (rr.aclass != 1 && rr.aclass != 0xff)) return; name[name_len -= 6] = '\0'; // remove .local @@ -545,7 +559,8 @@ static void handle_mdns_query(struct mg_connection *c) { ("PTR request for %s", req.is_listing ? "services listing" : name)); req.reqname = mg_str_n(name, name_len); } else if (rr.atype == MG_DNS_RTYPE_SRV || rr.atype == MG_DNS_RTYPE_TXT) { - MG_DEBUG(("%s request for %s", rr.atype == MG_DNS_RTYPE_SRV ? "SRV" : "TXT", name)); + MG_DEBUG(("%s request for %s", + rr.atype == MG_DNS_RTYPE_SRV ? "SRV" : "TXT", name)); // if possible, check it starts with our name, users will check it ends // in a service name they handle if (c->fn_data != NULL) { @@ -602,7 +617,7 @@ static void handle_mdns_query(struct mg_connection *c) { offset = mg_htons((uint16_t) (o - buf)); memcpy(p, &offset, 2); // point to target name, in record *p |= 0xC0, p += 2; - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } else if (rr.atype == MG_DNS_RTYPE_TXT) { p = build_srv_name(p, req.r); p = build_txt_record(p, req.r); @@ -619,16 +634,17 @@ static void handle_mdns_query(struct mg_connection *c) { offset = mg_htons((uint16_t) (o - buf)); memcpy(p, &offset, 2); // point to target name, in record *p |= 0xC0, p += 2; - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } else { // A requested // RFC-6762 6: 0 Auth, 0 Additional RRs if (respname->buf == NULL || respname->len == 0) return; p = build_name(respname, p); - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } if (!req.is_unicast) mg_multicast_restore(c, (uint8_t *) &c->loc); mg_send(c, buf, (size_t) (p - buf)); // And send it! - MG_DEBUG(("mDNS %c response sent", req.is_unicast ? 'U' : 'M')); + MG_DEBUG(("%M > %M", mg_print_ip_port, &c->loc, mg_print_ip_port, &c->rem)); + MG_DEBUG(("mDNS %s response sent", req.is_unicast ? "unicast" : "mcast")); } } @@ -641,22 +657,27 @@ static void handle_mdns_response(struct mg_connection *c) { MG_VERBOSE(("mDNS response parsed, result=%d", (int) n)); if (n > 0) { // RFC-6762 Appendix C, RFC2181 11: m(n + 1-63), max 255 + 0x0 - char name[256]; + char name[256]; uint8_t name_len; struct mg_mdns_resp resp; memset(&resp, 0, sizeof(resp)); if (rh->num_answers > mg_htons(1)) MG_DEBUG(("ignoring > 1 answers")); mg_dns_parse_name(c->recv.buf, c->recv.len, 12, name, sizeof(name)); name_len = (uint8_t) strlen(name); // verify it ends in .local - MG_VERBOSE(("RR %u %u %s", (unsigned int) rr.atype, (unsigned int) rr.aclass, name)); - if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && (rr.aclass & 0x7FFF) == 1) { + MG_VERBOSE(("RR %u %u %s", (unsigned int) rr.atype, + (unsigned int) rr.aclass, name)); + if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && + (rr.aclass & 0x7FFF) == 1) { resp.addr.is_ip6 = false; - memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 4, 4); - MG_DEBUG(("A response from %.*s = %M", name_len, name, mg_print_ip, &resp.addr)); -// } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && (rr.aclass & 0x7FFF) == 1) { -// resp.addr.is_ip6 = true; -// memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 16], 16); -// MG_DEBUG(("AAAA response from %.*s = %M", name_len, name, mg_print_ip, &resp.addr)); + memcpy(resp.addr.addr.ip, (char *) (rh + 1) + n - 4, 4); + MG_DEBUG(("A response from %.*s = %M", name_len, name, mg_print_ip, + &resp.addr)); + // } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && + // (rr.aclass & 0x7FFF) == 1) { + // resp.addr.is_ip6 = true; + // memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 16], 16); + // MG_DEBUG(("AAAA response from %.*s = %M", name_len, name, + // mg_print_ip, &resp.addr)); } else { return; } @@ -697,9 +718,10 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, mg_event_handler_t fn, return c; } -bool mg_mdns_query(struct mg_connection *c, const char *name, unsigned int rtype) { +bool mg_mdns_query(struct mg_connection *c, const char *name, + unsigned int rtype) { struct mg_str name_; - name_.buf = (char *)name, name_.len = strlen(name); + name_.buf = (char *) name, name_.len = strlen(name); mg_multicast_restore(c, (uint8_t *) &c->loc); (void) rtype; return mg_dns_send(c, &name_, 0, false); @@ -10417,15 +10439,17 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { a->is_ip6 = is_ip6; - a->port = usa->sin.sin_port; - memcpy(&a->addr.ip, &usa->sin.sin_addr, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (is_ip6) { memcpy(a->addr.ip, &usa->sin6.sin6_addr, sizeof(a->addr.ip)); a->port = usa->sin6.sin6_port; a->scope_id = (uint8_t) usa->sin6.sin6_scope_id; - } + } else #endif + { + a->port = usa->sin.sin_port; + memcpy(&a->addr.ip, &usa->sin.sin_addr, sizeof(uint32_t)); + } } static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { @@ -10436,6 +10460,29 @@ static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { } } +// Get the local 'addr' the stack will use to connect to 'to' +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr); +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr) { + union usa usa; + socklen_t slen; + MG_SOCKET_TYPE fd; + int rc, af = to->is_ip6 ? AF_INET6 : AF_INET; + fd = socket(af, SOCK_DGRAM, IPPROTO_UDP); + if (fd == MG_INVALID_SOCKET) { + mg_error(c, "socket(): %d", MG_SOCK_ERR(-1)); + return; + } + // NOTE(): TI-RTOS NDK may require binding + slen = tousa(to, &usa); + if ((rc = connect(fd, &usa.sa, slen)) != 0) { + mg_error(c, "connect: %d", MG_SOCK_ERR(rc)); + return; + } + setlocaddr(fd, addr); + closesocket(fd); +} + + static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == MG_IO_WAIT) { // Do nothing diff --git a/mongoose.h b/mongoose.h index eedb63a8..4c729777 100644 --- a/mongoose.h +++ b/mongoose.h @@ -2950,12 +2950,11 @@ size_t mg_mqtt_next_prop(struct mg_mqtt_message *, struct mg_mqtt_prop *, -#define MG_DNS_RTYPE_A 1 -#define MG_DNS_RTYPE_PTR 12 -#define MG_DNS_RTYPE_TXT 16 -#define MG_DNS_RTYPE_AAAA 28 -#define MG_DNS_RTYPE_SRV 33 - +#define MG_DNS_RTYPE_A 1 +#define MG_DNS_RTYPE_PTR 12 +#define MG_DNS_RTYPE_TXT 16 +#define MG_DNS_RTYPE_AAAA 28 +#define MG_DNS_RTYPE_SRV 33 // Mongoose sends DNS queries that contain only one question: // either A (IPv4) or AAAA (IPv6) address lookup. @@ -2998,7 +2997,7 @@ struct mg_mdns_req { struct mg_dnssd_record *r; struct mg_str reqname; // requested name in RR struct mg_str respname; // actual name to use in response - struct mg_addr addr; + struct mg_addr *addr; // actual address to use in response bool is_listing; bool is_resp; bool is_unicast; @@ -3006,10 +3005,10 @@ struct mg_mdns_req { struct mg_mdns_resp { struct mg_dns_rr *rr; -// TODO(scaprile )struct mg_str srvcproto; struct mg_str txt; uint16_t port; ? + // TODO(scaprile )struct mg_str srvcproto; struct mg_str txt; uint16_t port; ? struct mg_str name; struct mg_addr addr; -// TODO(scaprile); bool has_A; bool has_PTR; bool has_SRV; bool has_TXT; ? + // TODO(scaprile); bool has_A; bool has_PTR; bool has_SRV; bool has_TXT; ? }; void mg_resolve(struct mg_connection *, const char *url); diff --git a/src/dns.c b/src/dns.c index c0aca29e..846462fb 100644 --- a/src/dns.c +++ b/src/dns.c @@ -139,7 +139,8 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) { memcpy(&dm->addr.addr.ip, &buf[ofs - 4], 4); dm->resolved = true; break; // Return success - } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && rr.aclass == 1) { + } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && + rr.aclass == 1) { dm->addr.is_ip6 = true; memcpy(&dm->addr.addr.ip, &buf[ofs - 16], 16); dm->resolved = true; @@ -258,7 +259,7 @@ static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, uint16_t id; mg_random(&id, sizeof(uint16_t)); // TODO(): traverse reqs and check id != reqs->txnid; repeat otherwise - if (reqs != NULL) id = (uint16_t) (reqs->txnid + 1); // no collision + if (reqs != NULL) id = (uint16_t) (reqs->txnid + 1); // no collision d->txnid = id; d->next = reqs; c->mgr->active_dns_requests = d; @@ -302,13 +303,26 @@ static uint8_t *build_name(struct mg_str *name, uint8_t *p) { return p; } -static uint8_t *build_a_record(struct mg_connection *c, uint8_t *p) { +void mg_getlocaddr(struct mg_connection *, struct mg_addr *, struct mg_addr *); + +static uint8_t *build_a_record(struct mg_connection *c, uint8_t *p, + struct mg_addr *addr) { memcpy(p, mdns_answer, sizeof(mdns_answer)), p += sizeof(mdns_answer); + if (addr != NULL && !addr->is_ip6) { + memcpy(p, &addr->addr.ip4, 4), p += 4; + } else { #if MG_ENABLE_TCPIP - memcpy(p, &c->mgr->ifp->ip, 4), p += 4; + memcpy(p, &c->mgr->ifp->ip, 4), p += 4; #else - memcpy(p, c->data, 4), p += 4; + struct mg_addr loc, to; + memset(&loc, 0, sizeof(loc)); + to.is_ip6 = false; + to.port = mg_htons(5353); + to.addr.ip4 = MG_IPV4(224, 0, 0, 51); + mg_getlocaddr(c, &to, &loc); + memcpy(p, &loc.addr.ip4, 4), p += 4; #endif + } return p; } @@ -402,7 +416,7 @@ static void handle_mdns_query(struct mg_connection *c) { qh->num_questions = mg_htons(1); // parser sanity mg_dns_parse_name(c->recv.buf, c->recv.len, 12, name, sizeof(name)); name_len = (uint8_t) strlen(name); // verify it ends in .local - if (strcmp(".local", &name[name_len - 6]) != 0 || + if (name_len <= 6 || strcmp(".local", &name[name_len - 6]) != 0 || (rr.aclass != 1 && rr.aclass != 0xff)) return; name[name_len -= 6] = '\0'; // remove .local @@ -424,7 +438,8 @@ static void handle_mdns_query(struct mg_connection *c) { ("PTR request for %s", req.is_listing ? "services listing" : name)); req.reqname = mg_str_n(name, name_len); } else if (rr.atype == MG_DNS_RTYPE_SRV || rr.atype == MG_DNS_RTYPE_TXT) { - MG_DEBUG(("%s request for %s", rr.atype == MG_DNS_RTYPE_SRV ? "SRV" : "TXT", name)); + MG_DEBUG(("%s request for %s", + rr.atype == MG_DNS_RTYPE_SRV ? "SRV" : "TXT", name)); // if possible, check it starts with our name, users will check it ends // in a service name they handle if (c->fn_data != NULL) { @@ -481,7 +496,7 @@ static void handle_mdns_query(struct mg_connection *c) { offset = mg_htons((uint16_t) (o - buf)); memcpy(p, &offset, 2); // point to target name, in record *p |= 0xC0, p += 2; - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } else if (rr.atype == MG_DNS_RTYPE_TXT) { p = build_srv_name(p, req.r); p = build_txt_record(p, req.r); @@ -498,16 +513,17 @@ static void handle_mdns_query(struct mg_connection *c) { offset = mg_htons((uint16_t) (o - buf)); memcpy(p, &offset, 2); // point to target name, in record *p |= 0xC0, p += 2; - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } else { // A requested // RFC-6762 6: 0 Auth, 0 Additional RRs if (respname->buf == NULL || respname->len == 0) return; p = build_name(respname, p); - p = build_a_record(c, p); + p = build_a_record(c, p, req.addr); } if (!req.is_unicast) mg_multicast_restore(c, (uint8_t *) &c->loc); mg_send(c, buf, (size_t) (p - buf)); // And send it! - MG_DEBUG(("mDNS %c response sent", req.is_unicast ? 'U' : 'M')); + MG_DEBUG(("%M > %M", mg_print_ip_port, &c->loc, mg_print_ip_port, &c->rem)); + MG_DEBUG(("mDNS %s response sent", req.is_unicast ? "unicast" : "mcast")); } } @@ -520,22 +536,27 @@ static void handle_mdns_response(struct mg_connection *c) { MG_VERBOSE(("mDNS response parsed, result=%d", (int) n)); if (n > 0) { // RFC-6762 Appendix C, RFC2181 11: m(n + 1-63), max 255 + 0x0 - char name[256]; + char name[256]; uint8_t name_len; struct mg_mdns_resp resp; memset(&resp, 0, sizeof(resp)); if (rh->num_answers > mg_htons(1)) MG_DEBUG(("ignoring > 1 answers")); mg_dns_parse_name(c->recv.buf, c->recv.len, 12, name, sizeof(name)); name_len = (uint8_t) strlen(name); // verify it ends in .local - MG_VERBOSE(("RR %u %u %s", (unsigned int) rr.atype, (unsigned int) rr.aclass, name)); - if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && (rr.aclass & 0x7FFF) == 1) { + MG_VERBOSE(("RR %u %u %s", (unsigned int) rr.atype, + (unsigned int) rr.aclass, name)); + if (rr.alen == 4 && rr.atype == MG_DNS_RTYPE_A && + (rr.aclass & 0x7FFF) == 1) { resp.addr.is_ip6 = false; - memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 4, 4); - MG_DEBUG(("A response from %.*s = %M", name_len, name, mg_print_ip, &resp.addr)); -// } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && (rr.aclass & 0x7FFF) == 1) { -// resp.addr.is_ip6 = true; -// memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 16], 16); -// MG_DEBUG(("AAAA response from %.*s = %M", name_len, name, mg_print_ip, &resp.addr)); + memcpy(resp.addr.addr.ip, (char *) (rh + 1) + n - 4, 4); + MG_DEBUG(("A response from %.*s = %M", name_len, name, mg_print_ip, + &resp.addr)); + // } else if (rr.alen == 16 && rr.atype == MG_DNS_RTYPE_AAAA && + // (rr.aclass & 0x7FFF) == 1) { + // resp.addr.is_ip6 = true; + // memcpy(resp.addr.addr.ip, (char *)(rh + 1) + n - 16], 16); + // MG_DEBUG(("AAAA response from %.*s = %M", name_len, name, + // mg_print_ip, &resp.addr)); } else { return; } @@ -576,9 +597,10 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, mg_event_handler_t fn, return c; } -bool mg_mdns_query(struct mg_connection *c, const char *name, unsigned int rtype) { +bool mg_mdns_query(struct mg_connection *c, const char *name, + unsigned int rtype) { struct mg_str name_; - name_.buf = (char *)name, name_.len = strlen(name); + name_.buf = (char *) name, name_.len = strlen(name); mg_multicast_restore(c, (uint8_t *) &c->loc); (void) rtype; return mg_dns_send(c, &name_, 0, false); diff --git a/src/dns.h b/src/dns.h index c4f618ff..1819c86d 100644 --- a/src/dns.h +++ b/src/dns.h @@ -3,12 +3,11 @@ #include "net.h" #include "str.h" -#define MG_DNS_RTYPE_A 1 -#define MG_DNS_RTYPE_PTR 12 -#define MG_DNS_RTYPE_TXT 16 -#define MG_DNS_RTYPE_AAAA 28 -#define MG_DNS_RTYPE_SRV 33 - +#define MG_DNS_RTYPE_A 1 +#define MG_DNS_RTYPE_PTR 12 +#define MG_DNS_RTYPE_TXT 16 +#define MG_DNS_RTYPE_AAAA 28 +#define MG_DNS_RTYPE_SRV 33 // Mongoose sends DNS queries that contain only one question: // either A (IPv4) or AAAA (IPv6) address lookup. @@ -51,7 +50,7 @@ struct mg_mdns_req { struct mg_dnssd_record *r; struct mg_str reqname; // requested name in RR struct mg_str respname; // actual name to use in response - struct mg_addr addr; + struct mg_addr *addr; // actual address to use in response bool is_listing; bool is_resp; bool is_unicast; @@ -59,10 +58,10 @@ struct mg_mdns_req { struct mg_mdns_resp { struct mg_dns_rr *rr; -// TODO(scaprile )struct mg_str srvcproto; struct mg_str txt; uint16_t port; ? + // TODO(scaprile )struct mg_str srvcproto; struct mg_str txt; uint16_t port; ? struct mg_str name; struct mg_addr addr; -// TODO(scaprile); bool has_A; bool has_PTR; bool has_SRV; bool has_TXT; ? + // TODO(scaprile); bool has_A; bool has_PTR; bool has_SRV; bool has_TXT; ? }; void mg_resolve(struct mg_connection *, const char *url); diff --git a/src/sock.c b/src/sock.c index 753f8345..77fca2f9 100644 --- a/src/sock.c +++ b/src/sock.c @@ -72,15 +72,17 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { a->is_ip6 = is_ip6; - a->port = usa->sin.sin_port; - memcpy(&a->addr.ip, &usa->sin.sin_addr, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (is_ip6) { memcpy(a->addr.ip, &usa->sin6.sin6_addr, sizeof(a->addr.ip)); a->port = usa->sin6.sin6_port; a->scope_id = (uint8_t) usa->sin6.sin6_scope_id; - } + } else #endif + { + a->port = usa->sin.sin_port; + memcpy(&a->addr.ip, &usa->sin.sin_addr, sizeof(uint32_t)); + } } static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { @@ -91,6 +93,29 @@ static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) { } } +// Get the local 'addr' the stack will use to connect to 'to' +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr); +void mg_getlocaddr(struct mg_connection *c, struct mg_addr *to, struct mg_addr *addr) { + union usa usa; + socklen_t slen; + MG_SOCKET_TYPE fd; + int rc, af = to->is_ip6 ? AF_INET6 : AF_INET; + fd = socket(af, SOCK_DGRAM, IPPROTO_UDP); + if (fd == MG_INVALID_SOCKET) { + mg_error(c, "socket(): %d", MG_SOCK_ERR(-1)); + return; + } + // NOTE(): TI-RTOS NDK may require binding + slen = tousa(to, &usa); + if ((rc = connect(fd, &usa.sa, slen)) != 0) { + mg_error(c, "connect: %d", MG_SOCK_ERR(rc)); + return; + } + setlocaddr(fd, addr); + closesocket(fd); +} + + static void iolog(struct mg_connection *c, char *buf, long n, bool r) { if (n == MG_IO_WAIT) { // Do nothing diff --git a/tutorials/udp/mdns-client/main.c b/tutorials/udp/mdns-client/main.c index 8aca7d1e..ab2540c2 100644 --- a/tutorials/udp/mdns-client/main.c +++ b/tutorials/udp/mdns-client/main.c @@ -15,7 +15,6 @@ static void mdns_ev_handler(struct mg_connection *c, int ev, void *ev_data) { } int main(void) { - uint32_t response_ip = inet_addr("192.168.69.11"); struct mg_mgr mgr; static struct mg_connection *c; mg_log_set(MG_LL_DEBUG); // Set log level @@ -24,10 +23,6 @@ int main(void) { // Desired name must NOT have any dots in it, nor a domain c = mg_mdns_listen(&mgr, mdns_ev_handler, "Mongoose"); // Start mDNS server if (c == NULL) return 1; - // if not using our built-in TCP/IP stack, pass the IP address you want to - // use as a response, this depends on your underlying TCP/IP stack and number - // of interfaces available - memcpy(c->data, &response_ip, sizeof(response_ip)); if (!mg_mdns_query(c, s_theone, MG_DNS_RTYPE_A)) return 1; for (;;) mg_mgr_poll(&mgr, 1000); // Event loop diff --git a/tutorials/udp/mdns-sd-server/main.c b/tutorials/udp/mdns-sd-server/main.c index 5ff26e70..b09af9a0 100644 --- a/tutorials/udp/mdns-sd-server/main.c +++ b/tutorials/udp/mdns-sd-server/main.c @@ -15,7 +15,10 @@ // Desired name must NOT have any dots in it, nor a domain #define MDNS_NAME "mongoose-device" #define WEB_SERVER_ADDR "http://0.0.0.0:8000" // port is hardcoded below -#define RESPONSE_IP "192.168.69.11" + +// When not using our built-in TCP/IP stack, Mongoose responds with the address +// of the interface in which the request came in. If, for some reason, you want +// to use some other address, fill req->addr. See: mdns-client advanced example #ifdef ADVANCED_EXAMPLE // A TXT record data containing JSON, if actually needed. @@ -80,7 +83,8 @@ static void mdns_ev_handler(struct mg_connection *c, int ev, void *ev_data) { req->rr->atype == MG_DNS_RTYPE_TXT) { // Mongoose already checked the host name for us, otherwise we need to do // that ourselves first, then check for service name in db - struct mg_dnssd_record *r = (struct mg_dnssd_record *) dnssd_lookup(req->reqname); + struct mg_dnssd_record *r = + (struct mg_dnssd_record *) dnssd_lookup(req->reqname); if (r == NULL) return; req->r = r; req->is_resp = true; @@ -107,17 +111,12 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) { int main(void) { struct mg_mgr mgr; static struct mg_connection *c; - uint32_t response_ip = inet_addr(RESPONSE_IP); mg_log_set(MG_LL_DEBUG); // Set log level mg_mgr_init(&mgr); // Initialise event manager c = mg_mdns_listen(&mgr, mdns_ev_handler, MDNS_NAME); if (c == NULL) return 1; - // if not using our built-in TCP/IP stack, pass the IP address you want to - // use as a response, this depends on your underlying TCP/IP stack and number - // of interfaces available - memcpy(c->data, &response_ip, sizeof(response_ip)); mg_http_listen(&mgr, WEB_SERVER_ADDR, http_ev_handler, NULL); diff --git a/tutorials/udp/mdns-server/main.c b/tutorials/udp/mdns-server/main.c index 9f579530..8de6beaa 100644 --- a/tutorials/udp/mdns-server/main.c +++ b/tutorials/udp/mdns-server/main.c @@ -3,23 +3,45 @@ #include "mongoose.h" +#ifdef ADVANCED_EXAMPLE +static void mdns_ev_handler(struct mg_connection *c, int ev, void *ev_data); +#endif + int main(void) { - uint32_t response_ip = inet_addr("192.168.69.11"); struct mg_mgr mgr; static struct mg_connection *c; mg_log_set(MG_LL_DEBUG); // Set log level mg_mgr_init(&mgr); // Initialise event manager // Desired name must NOT have any dots in it, nor a domain +#ifndef ADVANCED_EXAMPLE c = mg_mdns_listen(&mgr, NULL, "Mongoose"); // Start mDNS server +#else + c = mg_mdns_listen(&mgr, mdns_ev_handler, "Mongoose"); // Start mDNS server +#endif if (c == NULL) return 1; - // if not using our built-in TCP/IP stack, pass the IP address you want to - // use as a response, this depends on your underlying TCP/IP stack and number - // of interfaces available - memcpy(c->data, &response_ip, sizeof(response_ip)); for (;;) mg_mgr_poll(&mgr, 1000); // Event loop mg_mgr_free(&mgr); return 0; } + +// When not using our built-in TCP/IP stack, Mongoose responds with the address +// of the interface in which the request came in. If, for some reason, you want +// to use some other address, catch the MG_EV_MDNS_REQ event for MG_DNS_RTYPE_A +// requests, and fill your desired address +#ifdef ADVANCED_EXAMPLE +static void mdns_ev_handler(struct mg_connection *c, int ev, void *ev_data) { + if (ev == MG_EV_MDNS_REQ) { + struct mg_mdns_req *req = (struct mg_mdns_req *) ev_data; + if (req->rr->atype == MG_DNS_RTYPE_A) { + struct mg_addr myaddr; + memset(&myaddr, 0, sizeof(myaddr)); + myaddr.addr.ip4 = MG_IPV4(1, 2, 3, 4); + req->addr = &myaddr; + } + } + (void) c; +} +#endif