Skip to content

Added support for querying host IP numbers with the new method #2585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 115 additions & 11 deletions libraries/ESP8266mDNS/ESP8266mDNS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Copyright (c) 2013 Tony DiCola ([email protected])
ESP8266 port (c) 2015 Ivan Grokhotkov ([email protected])
MDNS-SD Suport 2015 Hristo Gochkov
Extended MDNS-SD support 2016 Lars Englund ([email protected])

Host query support 2016 Erland Lewin ([email protected])

License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down Expand Up @@ -376,6 +376,100 @@ int MDNSResponder::queryService(char *service, char *proto) {
return _getNumAnswers();
}

// do not pass "<host>.local", but just "<host>"
IPAddress MDNSResponder::queryHost(const char *host)
{
#ifdef MDNS_DEBUG_TX
Serial.printf("queryHost %s\n", host);
#endif

if (_query != 0) {
os_free(_query);
_query = 0;
}
_query = (struct MDNSQuery*)(os_malloc(sizeof(struct MDNSQuery)));
os_strncpy(_query->_service, host, sizeof( _query->_service) - 1);
_query->_service[ sizeof( _query->_service ) - 1 ] = '\0';

_newQuery = true;

//local string
char localName[] = "local";
size_t localNameLen = 5;

//terminator
// char terminator[] = "\0";

// Write the header
_conn->flush();
uint8_t head[12] = {
0x00, 0x00, //ID = 0
0x00, 0x00, //Flags = response + authoritative answer
0x00, 0x01, //Question count
0x00, 0x00, //Answer count
0x00, 0x00, //Name server records
0x00, 0x00 //Additional records
};
_conn->append(reinterpret_cast<const char*>(head), 12);

// Only supports sending one PTR query
// Send the Name field (eg. "_http._tcp.local")
uint8_t hostNameLen = os_strlen( host );

_conn->append( (const char *) &hostNameLen, 1 ); // reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service
_conn->append( host, hostNameLen ); // reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service
_conn->append( (const char *) &localNameLen, 1 ); // reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto
_conn->append( localName, localNameLen ); // reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto
// _conn->append(reinterpret_cast<const char*>(&localNameLen), 1); // lenght of "local"
// _conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local"
// _conn->append( reinterpret_cast<const char*>(&terminator), 1); // terminator
_conn->append( "", 1 ); // terminator

//Send the type and class
uint8_t ptrAttrs[4] = {
0x00, 0x01, //HOST address record query
0x00, 0x01 //Class IN
};
_conn->append(reinterpret_cast<const char*>(ptrAttrs), 4);
_waitingForAnswers = true;

#ifdef MDNS_DEBUG_TX
Serial.printf("Before send, have %d answers.\n", _getNumAnswers() );
#endif

_conn->send();

#ifdef MDNS_DEBUG_TX
Serial.println("Waiting for answers..");
#endif

unsigned long startTime = millis();
// It is simplest for the user if we don't make timeout a parameter, but we could
// in milliseconds
int timeout = 2000;

// _newQuery is set to false when the first packet is received, only after that can we trust getNumAnswers
while( ((millis() - startTime) < timeout ) && (_newQuery || _getNumAnswers() == 0 ))
delay(1);

#ifdef MDNS_DEBUG_RX
Serial.printf( "MDNS host query took %d ms, num answers=%d\n", millis() - startTime, _getNumAnswers() );
#endif
_waitingForAnswers = false;

if( _getNumAnswers() > 0 )
{
MDNSAnswer *answer = _getAnswerFromIdx(0);

if( answer == NULL )
return IPAddress();
else
return IPAddress(answer->ip);
}
else
return IPAddress();
}

String MDNSResponder::hostname(int idx) {
MDNSAnswer *answer = _getAnswerFromIdx(idx);
if (answer == 0) {
Expand Down Expand Up @@ -515,15 +609,9 @@ void MDNSResponder::_parsePacket(){
}

int numAnswers = packetHeader[3] + packetHeader[5];
// Assume that the PTR answer always comes first and that it is always accompanied by a TXT, SRV, AAAA (optional) and A answer in the same packet.
if (numAnswers < 4) {
#ifdef MDNS_DEBUG_RX
Serial.printf("Expected a packet with 4 or more answers, got %u\n", numAnswers);
#endif
_conn->flush();
return;
}


/* Previously, packets with numAnswers < 4 were rejected, but host lookups
/* can return only one answers */
uint8_t tmp8;
uint16_t answerPort = 0;
uint8_t answerIp[4] = { 0,0,0,0 };
Expand Down Expand Up @@ -584,6 +672,14 @@ void MDNSResponder::_parsePacket(){
#endif
}
}
else if (strcmp( serviceName, _query->_service) == 0 ) {
// it is the response to a host address query
serviceMatch = true;
#ifdef MDNS_DEBUG_RX
Serial.printf("found matching host: %s\n", _query->_service);
#endif
}

stringsRead++;
} while (true);

Expand Down Expand Up @@ -671,6 +767,12 @@ void MDNSResponder::_parsePacket(){
for (int i = 0; i < 4; i++) {
answerIp[i] = _conn_read8();
}
#ifdef MDNS_DEBUG_RX
Serial.printf("A "); // , tmp8);
for (int n = 0; n < 4; n++)
Serial.printf("%s%d", (n == 0 ) ? "" : ".", answerIp[n] );
Serial.printf("\n");
#endif
}
else {
#ifdef MDNS_DEBUG_RX
Expand All @@ -680,7 +782,9 @@ void MDNSResponder::_parsePacket(){
(void)_conn_read8();
}

if ((partsCollected == 0x0F) && serviceMatch) {
/* Previously, required partsCollected = 0x0f, but that will not be the
case for host lookups */
if( serviceMatch) {
#ifdef MDNS_DEBUG_RX
Serial.println("All answers parsed, adding to _answers list..");
#endif
Expand Down
4 changes: 4 additions & 0 deletions libraries/ESP8266mDNS/ESP8266mDNS.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Version 1.1
Copyright (c) 2013 Tony DiCola ([email protected])
ESP8266 port (c) 2015 Ivan Grokhotkov ([email protected])
Extended MDNS-SD support 2016 Lars Englund ([email protected])
Host query support 2016 Erland Lewin ([email protected])

This is a simple implementation of multicast DNS query support for an Arduino
running on ESP8266 chip. Only support for resolving address queries is currently
Expand Down Expand Up @@ -89,6 +90,9 @@ class MDNSResponder {
int queryService(String service, String proto){
return queryService(service.c_str(), proto.c_str());
}

IPAddress queryHost(const char *host);

String hostname(int idx);
IPAddress IP(int idx);
uint16_t port(int idx);
Expand Down
2 changes: 2 additions & 0 deletions libraries/ESP8266mDNS/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ begin KEYWORD2
update KEYWORD2
addService KEYWORD2
enableArduino KEYWORD2
queryService KEYWORD2
queryHost KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down