diff --git a/EXmDNS.cpp b/EXmDNS.cpp new file mode 100644 index 00000000..559f09ca --- /dev/null +++ b/EXmDNS.cpp @@ -0,0 +1,139 @@ + +#include +#include "EthernetInterface.h" +#include "EXmDNS.h" +#include "DIAG.h" +static IPAddress mdnsMulticastIPAddr = IPAddress(224, 0, 0, 251); +#define MDNS_SERVER_PORT 5353 + +MDNS::MDNS(EthernetUDP& udp) { + _udp = &udp; +} +MDNS::~MDNS() { + _udp->stop(); +} +int MDNS::begin(const IPAddress& ip, char* name) { + // if we were called very soon after the board was booted, we need to give the + // EthernetShield (WIZnet) some time to come up. Hence, we delay until millis() is at + // least 3000. This is necessary, so that if we need to add a service record directly + // after begin, the announce packet does not get lost in the bowels of the WIZnet chip. + //while (millis() < 3000) + // delay(100); + + _ipAddress = ip; + _name = name; + return _udp->beginMulticast(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)) { + return; + } + lastrun = now; + DNSHeader_t dnsHeader = { 0 }; + + _udp->beginPacket(mdnsMulticastIPAddr, MDNS_SERVER_PORT); + + // dns header + dnsHeader.flags = lwip_htons(0x8400); // Response, authorative + dnsHeader.answerCount = lwip_htons(4 /*5*/); + _udp->write((uint8_t*)&dnsHeader, sizeof(DNSHeader_t)); + // rr #1 + _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 + _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)); + + 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); + _udp->write(buf, 10); + + byte srv[6]; + // priority and weight + srv[0] = srv[1] = srv[2] = srv[3] = 0; + // port + *((uint16_t*)(srv+4)) = lwip_htons(_servicePort); + _udp->write(srv, 6); + // target + _udp->write(_serviceName, _serviceName[0]+1); + _udp->write(dns_rr_local, strlen(dns_rr_local)+1); + + // rr #4 + _udp->write(_serviceName, _serviceName[0]+1); + _udp->write(dns_rr_local, strlen(dns_rr_local)+1); + + buf[1] = 0x01; // recycle most of buf but here A + *((uint16_t*)(buf+8)) = lwip_htons(4); + _udp->write(buf, 10); + byte ip[4]; + ip[0] = _ipAddress[0]; + ip[1] = _ipAddress[1]; + ip[2] = _ipAddress[2]; + ip[3] = _ipAddress[3]; + _udp->write(ip, 4); + + _udp->endPacket(); + _udp->flush(); + // +} diff --git a/EXmDNS.h b/EXmDNS.h new file mode 100644 index 00000000..769a0553 --- /dev/null +++ b/EXmDNS.h @@ -0,0 +1,20 @@ +typedef enum _MDNSServiceProtocol_t +{ + MDNSServiceTCP, + MDNSServiceUDP +} MDNSServiceProtocol_t; + +class MDNS { +public: + MDNS(EthernetUDP& udp); + ~MDNS(); + int begin(const IPAddress& ip, char* name); + int addServiceRecord(const char* name, uint16_t port, MDNSServiceProtocol_t proto); + void run(); +private: + EthernetUDP *_udp; + IPAddress _ipAddress; + char* _name; + char* _serviceName; + int _servicePort; +};