From 286fa90ee93db82ebee7d94dfcfd72f65fa20d10 Mon Sep 17 00:00:00 2001
From: Marko Mikulicic <mkm@cesanta.com>
Date: Wed, 28 Sep 2016 09:42:38 +0100
Subject: [PATCH] Simple mDNS + DNS-SD impl

Main TODOs:
1. the spec requires the impl to resend the reply once and
   to send gratuitous updates

2. advertise our clubby services as DNS-SD sub-services.

---

Tested with:

1. https://play.google.com/store/apps/details?id=com.grokkt.android.bonjour&hl=en
2. https://play.google.com/store/apps/details?id=com.druk.bonjour.browser&hl=en
3. osx `dns-sd`

Works well enough; it doesn't have some glitches due the fact that we
don't retransmit yet and we don't send gratuitous updates.

PUBLISHED_FROM=38d7a50beb274d4aeeda5b0b58e44dfa0789da84
---
 docs/c-api/dns.h/intro.md                    |  1 +
 docs/c-api/dns.h/mg_dns_encode_name.md       | 10 ++++++++++
 docs/c-api/dns.h/mg_dns_encode_record.md     |  6 +++---
 examples/mcast_udp_server/mcast_udp_server.c |  7 +++++++
 mongoose.c                                   |  2 +-
 mongoose.h                                   | 14 +++++++++++---
 6 files changed, 33 insertions(+), 7 deletions(-)
 create mode 100644 docs/c-api/dns.h/mg_dns_encode_name.md

diff --git a/docs/c-api/dns.h/intro.md b/docs/c-api/dns.h/intro.md
index 5f52c16f9..538674617 100644
--- a/docs/c-api/dns.h/intro.md
+++ b/docs/c-api/dns.h/intro.md
@@ -8,6 +8,7 @@ items:
   - { name: mg_dns_insert_header.md }
   - { name: mg_dns_copy_questions.md }
   - { name: mg_dns_encode_record.md }
+  - { name: mg_dns_encode_name.md }
   - { name: mg_parse_dns.md }
   - { name: mg_dns_uncompress_name.md }
   - { name: mg_set_protocol_dns.md }
diff --git a/docs/c-api/dns.h/mg_dns_encode_name.md b/docs/c-api/dns.h/mg_dns_encode_name.md
new file mode 100644
index 000000000..1b0e2a781
--- /dev/null
+++ b/docs/c-api/dns.h/mg_dns_encode_name.md
@@ -0,0 +1,10 @@
+---
+title: "mg_dns_encode_name()"
+decl_name: "mg_dns_encode_name"
+symbol_kind: "func"
+signature: |
+  int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len);
+---
+
+Encodes a DNS name. 
+
diff --git a/docs/c-api/dns.h/mg_dns_encode_record.md b/docs/c-api/dns.h/mg_dns_encode_record.md
index a892e5de5..c52cf26f3 100644
--- a/docs/c-api/dns.h/mg_dns_encode_record.md
+++ b/docs/c-api/dns.h/mg_dns_encode_record.md
@@ -15,11 +15,11 @@ are taken from the parameters, encoded in the appropriate format depending on
 record type and stored in the IO buffer. The encoded values might contain
 offsets within the IO buffer. It's thus important that the IO buffer doesn't
 get trimmed while a sequence of records are encoded while preparing a DNS
-*reply.
+reply.
 
 This function doesn't update the `name` and `rdata` pointers in the `rr`
-*struct
-because they might be invalidated as soon as the IO buffer grows again.
+struct because they might be invalidated as soon as the IO buffer grows
+again.
 
 Returns the number of bytes appened or -1 in case of error. 
 
diff --git a/examples/mcast_udp_server/mcast_udp_server.c b/examples/mcast_udp_server/mcast_udp_server.c
index 4c0b2c9fe..6cbc79836 100644
--- a/examples/mcast_udp_server/mcast_udp_server.c
+++ b/examples/mcast_udp_server/mcast_udp_server.c
@@ -28,6 +28,13 @@ static void ev_handler(struct mg_connection *nc, int ev, void *p) {
   struct mbuf *io = &nc->recv_mbuf;
   (void) p;
   switch (ev) {
+    case MG_EV_POLL: {
+      const char *peer;
+      peer = inet_ntoa(nc->sa.sin.sin_addr);
+      printf("nc->sa: %s %d\n", peer, ntohs(nc->sa.sin.sin_port));
+
+      break;
+    }
     case MG_EV_RECV:
       printf("Received (%zu bytes): '%.*s'\n", io->len, (int) io->len, io->buf);
       mbuf_remove(io, io->len);
diff --git a/mongoose.c b/mongoose.c
index 69f6a2a0e..e072b49a9 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -8455,7 +8455,7 @@ int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg) {
   return mbuf_append(io, begin, end - begin);
 }
 
-static int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len) {
+int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len) {
   const char *s;
   unsigned char n;
   size_t pos = io->len;
diff --git a/mongoose.h b/mongoose.h
index 5118fa76f..37dd05724 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -3223,7 +3223,10 @@ extern "C" {
 
 #define MG_DNS_A_RECORD 0x01     /* Lookup IP address */
 #define MG_DNS_CNAME_RECORD 0x05 /* Lookup CNAME */
+#define MG_DNS_PTR_RECORD 0x0c   /* Lookup PTR */
+#define MG_DNS_TXT_RECORD 0x10   /* Lookup TXT */
 #define MG_DNS_AAAA_RECORD 0x1c  /* Lookup IPv6 address */
+#define MG_DNS_SRV_RECORD 0x21   /* Lookup SRV */
 #define MG_DNS_MX_RECORD 0x0f    /* Lookup mail server for domain */
 
 #define MG_MAX_DNS_QUESTIONS 32
@@ -3308,11 +3311,11 @@ int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
  * record type and stored in the IO buffer. The encoded values might contain
  * offsets within the IO buffer. It's thus important that the IO buffer doesn't
  * get trimmed while a sequence of records are encoded while preparing a DNS
- *reply.
+ * reply.
  *
  * This function doesn't update the `name` and `rdata` pointers in the `rr`
- *struct
- * because they might be invalidated as soon as the IO buffer grows again.
+ * struct because they might be invalidated as soon as the IO buffer grows
+ * again.
  *
  * Returns the number of bytes appened or -1 in case of error.
  */
@@ -3320,6 +3323,11 @@ int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
                          const char *name, size_t nlen, const void *rdata,
                          size_t rlen);
 
+/*
+ * Encodes a DNS name.
+ */
+int mg_dns_encode_name(struct mbuf *io, const char *name, size_t len);
+
 /* Low-level: parses a DNS response. */
 int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
 
-- 
GitLab