diff --git a/EXmDNS.cpp b/EXmDNS.cpp index 559f09c..b4fc200 100644 --- a/EXmDNS.cpp +++ b/EXmDNS.cpp @@ -2,15 +2,49 @@ #include #include "EthernetInterface.h" #include "EXmDNS.h" -#include "DIAG.h" + +// fixed values for mDNS static IPAddress mdnsMulticastIPAddr = IPAddress(224, 0, 0, 251); #define MDNS_SERVER_PORT 5353 +// dotToLen() +// converts stings of form ".foo.barbar.x" to a string with the +// dots replaced with lenght. So string above would result in +// "\x03foo\x06barbar\x01x" in C notation. If not NULL, *substr +// will point to the beginning of the last component, in this +// example that would be "\x01x". +// +static void dotToLen(char *str, char **substr) { + char *dotplace = NULL; + char *s; + byte charcount = 0; + for (s = str;/*see break*/ ; s++) { + if (*s == '.' || *s == '\0') { + // take care of accumulated + if (dotplace != NULL && charcount != 0) { + *dotplace = charcount; + } + if (*s == '\0') + break; + if (substr && *s == '.') + *substr = s; + // set new values + dotplace = s; + charcount = 0; + } else { + charcount++; + } + } +} + MDNS::MDNS(EthernetUDP& udp) { _udp = &udp; } MDNS::~MDNS() { _udp->stop(); + if (_name) free(_name); + if (_serviceName) free(_serviceName); + if (_serviceProto) free(_serviceProto); } int MDNS::begin(const IPAddress& ip, char* name) { // if we were called very soon after the board was booted, we need to give the @@ -21,56 +55,53 @@ int MDNS::begin(const IPAddress& ip, char* name) { // delay(100); _ipAddress = ip; - _name = name; + _name = (char *)malloc(strlen(name +2)); + byte n; + for(n = 0; nbeginMulticast(mdnsMulticastIPAddr, MDNS_SERVER_PORT); } + int MDNS::addServiceRecord(const char* name, uint16_t port, MDNSServiceProtocol_t proto) { // we ignore proto, assume TCP _serviceName = (char *)malloc(strlen(name +2)); - DIAG("name %d %s", strlen(name), name); byte n; for(n = 0; n 10000)) { + if (!(now - lastrun > BROADCASTTIME * 1000UL)) { return; } lastrun = now; @@ -80,33 +111,39 @@ void MDNS::run() { // dns header dnsHeader.flags = lwip_htons(0x8400); // Response, authorative - dnsHeader.answerCount = lwip_htons(4 /*5*/); + dnsHeader.answerCount = lwip_htons(4 /*5 if TXT but we do not do that */); _udp->write((uint8_t*)&dnsHeader, sizeof(DNSHeader_t)); - // rr #1 + + // rr #1, the PTR record from generic _services.x.local to service.x.local _udp->write((uint8_t*)dns_rr_services, sizeof(dns_rr_services)); + byte buf[10]; buf[0] = 0x00; buf[1] = 0x0c; //PTR buf[2] = 0x00; buf[3] = 0x01; //IN *((uint32_t*)(buf+4)) = lwip_htonl(120); //TTL in sec - *((uint16_t*)(buf+8)) = lwip_htons(sizeof(dns_rr_withrottle)); - _udp->write(buf, 10); - _udp->write(dns_rr_withrottle, sizeof(dns_rr_withrottle)); - // rr #2 - _udp->write(dns_rr_withrottle, sizeof(dns_rr_withrottle)); - *((uint16_t*)(buf+8)) = lwip_htons(strlen(_serviceName) + sizeof(dns_rr_withrottle)); // recycle most of buf + *((uint16_t*)(buf+8)) = lwip_htons( _serviceProto[0] + 1 + strlen(dns_rr_tcplocal) + 1); _udp->write(buf, 10); - _udp->write(_serviceName, _serviceName[0]+1); - _udp->write(dns_rr_withrottle, sizeof(dns_rr_withrottle)); - // rr #3 - _udp->write(_serviceName, _serviceName[0]+1); - _udp->write(dns_rr_withrottle, sizeof(dns_rr_withrottle)); + _udp->write(_serviceProto,_serviceProto[0]+1); + _udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1); + + // rr #2, the PTR record from proto.x to name.proto.x + _udp->write(_serviceProto,_serviceProto[0]+1); + _udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1); + *((uint16_t*)(buf+8)) = lwip_htons(strlen(_serviceName) + strlen(dns_rr_tcplocal) + 1); // recycle most of buf + _udp->write(buf, 10); + + _udp->write(_serviceName, strlen(_serviceName)); + _udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1); + // rr #3, the SRV record for the service that points to local name + _udp->write(_serviceName, strlen(_serviceName)); + _udp->write(dns_rr_tcplocal, strlen(dns_rr_tcplocal)+1); buf[1] = 0x21; // recycle most of buf but here SRV buf[2] = 0x80; // cache flush - *((uint16_t*)(buf+8)) = lwip_htons(strlen(_serviceName) + strlen(dns_rr_local) + 1 + 6); + *((uint16_t*)(buf+8)) = lwip_htons(strlen(_name) + strlen(dns_rr_local) + 1 + 6); _udp->write(buf, 10); byte srv[6]; @@ -116,11 +153,11 @@ void MDNS::run() { *((uint16_t*)(srv+4)) = lwip_htons(_servicePort); _udp->write(srv, 6); // target - _udp->write(_serviceName, _serviceName[0]+1); + _udp->write(_name, _name[0]+1); _udp->write(dns_rr_local, strlen(dns_rr_local)+1); - // rr #4 - _udp->write(_serviceName, _serviceName[0]+1); + // rr #4, the A record for the name.local + _udp->write(_name, _name[0]+1); _udp->write(dns_rr_local, strlen(dns_rr_local)+1); buf[1] = 0x01; // recycle most of buf but here A diff --git a/EXmDNS.h b/EXmDNS.h index 769a055..fd50a2a 100644 --- a/EXmDNS.h +++ b/EXmDNS.h @@ -1,3 +1,6 @@ + +#define BROADCASTTIME 15 //seconds + typedef enum _MDNSServiceProtocol_t { MDNSServiceTCP, @@ -16,5 +19,6 @@ private: IPAddress _ipAddress; char* _name; char* _serviceName; + char* _serviceProto; int _servicePort; }; diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index a2e292d..26be378 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -132,9 +132,8 @@ void EthernetInterface::setup() #ifdef DO_MDNS if (!mdns.begin(Ethernet.localIP(), WIFI_HOSTNAME)) DIAG("mdns.begin fail"); // hostname - mdns.addServiceRecord(WIFI_HOSTNAME, IP_PORT, MDNSServiceTCP); - // Not sure if we need to run it once, but just in case! - mdns.run(); + mdns.addServiceRecord(WIFI_HOSTNAME "._withrottle", IP_PORT, MDNSServiceTCP); + mdns.run(); // run it right away to get out info ASAP #endif connected=true; }