bool MDNSResponder::begin(const char* hostname){ // Open the MDNS socket if it isn't already open. size_t n = strlen(hostname); if (n > 63) { // max size for a single label. return false; } // Copy in hostname characters as lowercase _hostName = hostname; _hostName.toLowerCase(); // If instance name is not already set copy hostname to instance name if (_instanceName.equals("") ) _instanceName=hostname; // Open the MDNS socket if it isn't already open. if (!_conn) { uint32_t ourIp = _getOurIp(); if(ourIp == 0){ return false; } ip_addr_t ifaddr; ifaddr.addr = ourIp; ip_addr_t multicast_addr; multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR; if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) { return false; } _conn = new UdpContext; _conn->ref(); if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) { return false; } _conn->setMulticastInterface(ifaddr); _conn->setMulticastTTL(MDNS_MULTICAST_TTL); _conn->onRx(std::bind(&MDNSResponder::update, this)); _conn->connect(multicast_addr, MDNS_PORT); } return true; }
bool MDNSResponder::begin(const char* domain){ // Open the MDNS socket if it isn't already open. size_t n = strlen(domain); if (n > 255) { // Can only handle domains that are 255 chars in length. return false; } // Copy in domain characters as lowercase for (int i = 0; i < n; ++i) _hostName[i] = tolower(domain[i]); _hostName[n] = '\0'; os_strcpy(_boardName, ARDUINO_BOARD); // Open the MDNS socket if it isn't already open. if (!_conn) { uint32_t ourIp = _getOurIp(); if(ourIp == 0){ return false; } ip_addr_t ifaddr; ifaddr.addr = ourIp; ip_addr_t multicast_addr; multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR; if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) { return false; } _conn = new UdpContext; _conn->ref(); if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) { return false; } _conn->setMulticastInterface(ifaddr); _conn->setMulticastTTL(MDNS_MULTICAST_TTL); _conn->onRx(std::bind(&MDNSResponder::update, this)); _conn->connect(multicast_addr, MDNS_PORT); } return true; }
bool MDNSResponder::_listen() { // Open the MDNS socket if it isn't already open. if (!_conn) { uint32_t ourIp = _getOurIp(); if (ourIp == 0) { #ifdef MDNS_DEBUG_RX Serial.println("MDNS: no IP address to listen on"); #endif return false; } #ifdef MDNS_DEBUG_RX Serial.print("MDNS listening on IP: "); Serial.println(IPAddress(ourIp)); #endif ip_addr_t ifaddr; ifaddr.addr = ourIp; ip_addr_t multicast_addr; multicast_addr.addr = (uint32_t)MDNS_MULTICAST_ADDR; if (igmp_joingroup(&ifaddr, &multicast_addr) != ERR_OK) { return false; } _conn = new UdpContext; _conn->ref(); if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) { return false; } _conn->setMulticastInterface(ifaddr); _conn->setMulticastTTL(MDNS_MULTICAST_TTL); _conn->onRx(std::bind(&MDNSResponder::update, this)); _conn->connect(multicast_addr, MDNS_PORT); } return true; }
void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){ int i; if(replyMask == 0) return; #ifdef MDNS_DEBUG_TX Serial.printf("TX: mask:%01X, service:%s, proto:%s, port:%u\n", replyMask, service, proto, port); #endif String instanceName = _instanceName; size_t instanceNameLen = instanceName.length(); String hostName = _hostName; size_t hostNameLen = hostName.length(); char underscore[] = "_"; // build service name with _ char serviceName[os_strlen(service)+2]; os_strcpy(serviceName,underscore); os_strcat(serviceName, service); size_t serviceNameLen = os_strlen(serviceName); //build proto name with _ char protoName[5]; os_strcpy(protoName,underscore); os_strcat(protoName, proto); size_t protoNameLen = 4; //local string char localName[] = "local"; size_t localNameLen = 5; //terminator char terminator[] = "\0"; uint8_t answerCount = 0; for(i=0;i<4;i++){ if(replyMask & (1 << i)) answerCount++; } //Write the header _conn->flush(); uint8_t head[12] = { 0x00, 0x00, //ID = 0 0x84, 0x00, //Flags = response + authoritative answer 0x00, 0x00, //Question count 0x00, answerCount, //Answer count 0x00, 0x00, //Name server records 0x00, 0x00, //Additional records }; _conn->append(reinterpret_cast<const char*>(head), 12); // PTR Response if(replyMask & 0x8){ // Send the Name field (ie. "_http._tcp.local") _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_http" _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_tcp" _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator //Send the type, class, ttl and rdata length uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator uint8_t ptrAttrs[10] = { 0x00, 0x0c, //PTR record query 0x00, 0x01, //Class IN 0x00, 0x00, 0x11, 0x94, //TTL 4500 0x00, ptrDataLen, //RData length }; _conn->append(reinterpret_cast<const char*>(ptrAttrs), 10); //Send the RData (ie. "My IOT device._http._tcp.local") _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // lenght of "My IOT device" _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_http" _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_tcp" _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator } //TXT Responce if(replyMask & 0x4){ //Send the name field (ie. "My IOT device._http._tcp.local") _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // lenght of "My IOT device" _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_http" _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_tcp" _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator //Send the type, class, ttl and rdata length uint8_t txtDataLen = _getServiceTxtLen(service,proto); uint8_t txtAttrs[10] = { 0x00, 0x10, //TXT record query 0x00, 0x01, //Class IN 0x00, 0x00, 0x11, 0x94, //TTL 4500 0x00, txtDataLen, //RData length }; _conn->append(reinterpret_cast<const char*>(txtAttrs), 10); //Send the RData MDNSTxt * txtPtr = _getServiceTxt(service,proto); while(txtPtr !=0){ uint8_t txtLen = txtPtr->_txt.length(); _conn->append(reinterpret_cast<const char*>(&txtLen), 1); // lenght of txt _conn->append(reinterpret_cast<const char*>(txtPtr->_txt.c_str()), txtLen);// the txt txtPtr = txtPtr->_next; } } //SRV Responce if(replyMask & 0x2){ //Send the name field (ie. "My IOT device._http._tcp.local") _conn->append(reinterpret_cast<const char*>(&instanceNameLen), 1); // lenght of "My IOT device" _conn->append(reinterpret_cast<const char*>(instanceName.c_str()), instanceNameLen);// "My IOT device" _conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_http" _conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_http" _conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_tcp" _conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_tcp" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator //Send the type, class, ttl, rdata length, priority and weight uint8_t srvDataSize = hostNameLen + localNameLen + 3; // 3 is 2 lable size bytes and the terminator srvDataSize += 6; // Size of Priority, weight and port uint8_t srvAttrs[10] = { 0x00, 0x21, //Type SRV 0x80, 0x01, //Class IN, with cache flush 0x00, 0x00, 0x00, 0x78, //TTL 120 0x00, srvDataSize, //RData length }; _conn->append(reinterpret_cast<const char*>(srvAttrs), 10); //Send the RData Priority weight and port uint8_t srvRData[6] = { 0x00, 0x00, //Priority 0 0x00, 0x00, //Weight 0 (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) }; _conn->append(reinterpret_cast<const char*>(srvRData), 6); //Send the RData (ie. "esp8266.local") _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // lenght of "esp8266" _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator } // A Response if(replyMask & 0x1){ //Send the RData (ie. "esp8266.local") _conn->append(reinterpret_cast<const char*>(&hostNameLen), 1); // lenght of "esp8266" _conn->append(reinterpret_cast<const char*>(hostName.c_str()), hostNameLen);// "esp8266" _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght "local" _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local" _conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator uint32_t ip = _getOurIp(); uint8_t aaaAttrs[10] = { 0x00, 0x01, //TYPE A 0x80, 0x01, //Class IN, with cache flush 0x00, 0x00, 0x00, 0x78, //TTL 120 0x00, 0x04, //DATA LEN }; _conn->append(reinterpret_cast<const char*>(aaaAttrs), 10); // Send RData uint8_t aaaRData[4] = { (uint8_t)(ip & 0xFF), //IP first octet (uint8_t)((ip >> 8) & 0xFF), //IP second octet (uint8_t)((ip >> 16) & 0xFF), //IP third octet (uint8_t)((ip >> 24) & 0xFF) //IP fourth octet }; _conn->append(reinterpret_cast<const char*>(aaaRData), 4); }
void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){ int i; if(replyMask == 0) return; #ifdef MDNS_DEBUG_TX os_printf("TX: mask:%01X, service:%s, proto:%s, port:%u\n", replyMask, service, proto, port); #endif char nameLen = os_strlen(_hostName); size_t serviceLen = os_strlen(service); uint8_t answerCount = 0; for(i=0;i<4;i++){ if(replyMask & (1 << i)) answerCount++; } _conn->flush(); uint8_t head[12] = { 0x00, 0x00, //ID = 0 0x84, 0x00, //Flags = response + authoritative answer 0x00, 0x00, //Question count 0x00, answerCount, //Answer count 0x00, 0x00, //Name server records 0x00, 0x00, //Additional records }; _conn->append(reinterpret_cast<const char*>(head), 12); if((replyMask & 0x8) == 0){ _conn->append(reinterpret_cast<const char*>(&nameLen), 1); _conn->append(reinterpret_cast<const char*>(_hostName), nameLen); } if(replyMask & 0xE){ uint8_t servHead[2] = {(uint8_t)(serviceLen+1), '_'}; uint8_t protoHead[2] = {0x4, '_'}; _conn->append(reinterpret_cast<const char*>(servHead), 2); _conn->append(reinterpret_cast<const char*>(service), serviceLen); _conn->append(reinterpret_cast<const char*>(protoHead), 2); _conn->append(reinterpret_cast<const char*>(proto), 3); } uint8_t local[7] = { 0x05, //strlen(_local) 0x6C, 0x6F, 0x63, 0x61, 0x6C, //local 0x00, //End of domain }; _conn->append(reinterpret_cast<const char*>(local), 7); // PTR Response if(replyMask & 0x8){ uint8_t ptr[10] = { 0x00, 0x0c, //PTR record query 0x00, 0x01, //Class IN 0x00, 0x00, 0x11, 0x94, //TTL 4500 0x00, (uint8_t)(3 + nameLen), //***DATA LEN (3 + strlen(host)) }; _conn->append(reinterpret_cast<const char*>(ptr), 10); _conn->append(reinterpret_cast<const char*>(&nameLen), 1); _conn->append(reinterpret_cast<const char*>(_hostName), nameLen); uint8_t ptrTail[2] = {0xC0, 0x0C}; _conn->append(reinterpret_cast<const char*>(ptrTail), 2); } // TXT Response if(replyMask & 0x4){ if(replyMask & 0x8){//send the name uint8_t txtHead[2] = {0xC0, (uint8_t)(36 + serviceLen)}; _conn->append(reinterpret_cast<const char*>(txtHead), 2); } uint8_t boardNameLen = os_strlen(_boardName); uint8_t txt[24] = { 0x00, 0x10, //Type TXT 0x80, 0x01, //Class IN, with cache flush 0x00, 0x00, 0x11, 0x94, //TTL 4500 0x00, 0x0e, //DATA LEN (uint8_t)(6 + boardNameLen), //strlen(board=) + strlen(boardName) 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3d //board= }; _conn->append(reinterpret_cast<const char*>(txt), 17); _conn->append(reinterpret_cast<const char*>(_boardName), boardNameLen); } // SRV Response if(replyMask & 0x2){ if(replyMask & 0xC){//send the name uint8_t srvHead[2] = {0xC0, 0x0C}; if(replyMask & 0x8) srvHead[1] = 36 + serviceLen; _conn->append(reinterpret_cast<const char*>(srvHead), 2); } uint8_t srv[16] = { 0x00, 0x21, //Type SRV 0x80, 0x01, //Class IN, with cache flush 0x00, 0x00, 0x00, 0x78, //TTL 120 0x00, (uint8_t)(9 + nameLen), //DATA LEN (9 + strlen(host)) 0x00, 0x00, //Priority 0 0x00, 0x00, //Weight 0 (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF) }; _conn->append(reinterpret_cast<const char*>(srv), 16); _conn->append(reinterpret_cast<const char*>(&nameLen), 1); _conn->append(reinterpret_cast<const char*>(_hostName), nameLen); uint8_t srvTail[2] = {0xC0, (uint8_t)(20 + serviceLen + nameLen)}; if(replyMask & 0x8) srvTail[1] = 19 + serviceLen; _conn->append(reinterpret_cast<const char*>(srvTail), 2); } // A Response if(replyMask & 0x1){ uint32_t ip = _getOurIp(); if(replyMask & 0x2){//send the name (no compression for now) _conn->append(reinterpret_cast<const char*>(&nameLen), 1); _conn->append(reinterpret_cast<const char*>(_hostName), nameLen); _conn->append(reinterpret_cast<const char*>(local), 7); } uint8_t aaa[14] = { 0x00, 0x01, //TYPE A 0x80, 0x01, //Class IN, with cache flush 0x00, 0x00, 0x00, 0x78, //TTL 120 0x00, 0x04, //DATA LEN (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) }; _conn->append(reinterpret_cast<const char*>(aaa), 14); } _conn->send(); }