mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-22 21:23:07 +03:00
Basic query (and answer parsing) working
This commit is contained in:
parent
1c9f9c3a6d
commit
d46f84821e
@ -5,6 +5,7 @@ Version 1.1
|
|||||||
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
||||||
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
|
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
|
||||||
MDNS-SD Suport 2015 Hristo Gochkov
|
MDNS-SD Suport 2015 Hristo Gochkov
|
||||||
|
Extended MDNS-SD support 2016 Lars Englund
|
||||||
|
|
||||||
|
|
||||||
License (MIT license):
|
License (MIT license):
|
||||||
@ -104,6 +105,7 @@ struct MDNSTxt{
|
|||||||
MDNSResponder::MDNSResponder() : _conn(0) {
|
MDNSResponder::MDNSResponder() : _conn(0) {
|
||||||
_services = 0;
|
_services = 0;
|
||||||
_instanceName = "";
|
_instanceName = "";
|
||||||
|
p_answer_function_ = NULL;
|
||||||
}
|
}
|
||||||
MDNSResponder::~MDNSResponder() {}
|
MDNSResponder::~MDNSResponder() {}
|
||||||
|
|
||||||
@ -221,6 +223,90 @@ void MDNSResponder::addService(char *name, char *proto, uint16_t port){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MDNSResponder::queryService(char *service, void(*p_answer_function)(const char*)) {
|
||||||
|
Serial.print("queryService: ");
|
||||||
|
Serial.println(service);
|
||||||
|
p_answer_function_ = p_answer_function;
|
||||||
|
|
||||||
|
// TODO: copy _reply() to new method called _query() that sends out a PTR query
|
||||||
|
// Relevant RFCs
|
||||||
|
// https://tools.ietf.org/html/rfc1035
|
||||||
|
// https://tools.ietf.org/html/rfc6762
|
||||||
|
// https://tools.ietf.org/html/rfc6763
|
||||||
|
|
||||||
|
|
||||||
|
// Example query sent by node.js for _lalala._tcp.local
|
||||||
|
//0000 00 00 00 00 00 01 00 00 00 00 00 00 07 5f 6c 61 ............._la
|
||||||
|
//0010 6c 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 lala._tcp.local.
|
||||||
|
//0020 00 0c 00 01 ....
|
||||||
|
|
||||||
|
//String instanceName = _instanceName;
|
||||||
|
//size_t instanceNameLen = instanceName.length();
|
||||||
|
|
||||||
|
//String hostName = _hostName;
|
||||||
|
//size_t hostNameLen = hostName.length();
|
||||||
|
|
||||||
|
//char underscore[] = "_";
|
||||||
|
|
||||||
|
// build service name with _
|
||||||
|
char serviceName[] = "_esp";
|
||||||
|
size_t serviceNameLen = 4;
|
||||||
|
|
||||||
|
//build proto name with _
|
||||||
|
char protoName[] = "_tcp";
|
||||||
|
size_t protoNameLen = 4;
|
||||||
|
|
||||||
|
//local string
|
||||||
|
char localName[] = "local";
|
||||||
|
size_t localNameLen = 5;
|
||||||
|
|
||||||
|
//terminator
|
||||||
|
char terminator[] = "\0";
|
||||||
|
|
||||||
|
uint8_t questionCount = 1;
|
||||||
|
|
||||||
|
// Write the header
|
||||||
|
_conn->flush();
|
||||||
|
uint8_t head[12] = {
|
||||||
|
0x00, 0x00, //ID = 0
|
||||||
|
0x00, 0x00, //Flags = response + authoritative answer
|
||||||
|
0x00, questionCount, //Question count
|
||||||
|
0x00, 0x00, //Answer count
|
||||||
|
0x00, 0x00, //Name server records
|
||||||
|
0x00, 0x00 //Additional records
|
||||||
|
};
|
||||||
|
_conn->append(reinterpret_cast<const char*>(head), 12);
|
||||||
|
|
||||||
|
// PTR Query
|
||||||
|
//if(replyMask & 0x8){
|
||||||
|
// Send the Name field (eg. "_http._tcp.local")
|
||||||
|
_conn->append(reinterpret_cast<const char*>(&serviceNameLen), 1); // lenght of "_" + service
|
||||||
|
_conn->append(reinterpret_cast<const char*>(serviceName), serviceNameLen); // "_" + service
|
||||||
|
_conn->append(reinterpret_cast<const char*>(&protoNameLen), 1); // lenght of "_" + proto
|
||||||
|
_conn->append(reinterpret_cast<const char*>(protoName), protoNameLen); // "_" + proto
|
||||||
|
_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 and class
|
||||||
|
//uint8_t ptrDataLen = instanceNameLen + serviceNameLen + protoNameLen + localNameLen + 5; // 5 is four label sizes and the terminator
|
||||||
|
uint8_t ptrAttrs[4] = {
|
||||||
|
0x00, 0x0c, //PTR record query
|
||||||
|
0x00, 0x01 //Class IN
|
||||||
|
};
|
||||||
|
_conn->append(reinterpret_cast<const char*>(ptrAttrs), 4);
|
||||||
|
//}
|
||||||
|
|
||||||
|
_conn->send();
|
||||||
|
|
||||||
|
/*const char *answer = "Hello from MDNSResponder!";
|
||||||
|
|
||||||
|
if (p_answer_function_) {
|
||||||
|
// Since a callback function has been registered, execute it.
|
||||||
|
p_answer_function_(answer);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto){
|
MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto){
|
||||||
MDNSService* servicePtr;
|
MDNSService* servicePtr;
|
||||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||||
@ -298,6 +384,95 @@ void MDNSResponder::_parsePacket(){
|
|||||||
for(i=0; i<6; i++) packetHeader[i] = _conn_read16();
|
for(i=0; i<6; i++) packetHeader[i] = _conn_read16();
|
||||||
|
|
||||||
if((packetHeader[1] & 0x8000) != 0){ //not parsing responses yet
|
if((packetHeader[1] & 0x8000) != 0){ //not parsing responses yet
|
||||||
|
|
||||||
|
Serial.println("Response parsing");
|
||||||
|
Serial.printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]);
|
||||||
|
|
||||||
|
int numAnswers = packetHeader[3];
|
||||||
|
|
||||||
|
// TODO: parse answers and call p_answer_function_ with host (.local), IP, port,
|
||||||
|
// http://www.ietf.org/rfc/rfc1035.txt
|
||||||
|
|
||||||
|
// TODO: Parse 4 answers in 1 packet (that's what this library sends out, check if node.js mqtt advertisment sends out different answers (use esp8266_mdns to check)):
|
||||||
|
// 1. PTR - ignore for now (gives domain name (instance.service) (ex. Domain Name: ESP_81CC47._lalala._tcp.local))
|
||||||
|
// 2. TXT - ignore for now
|
||||||
|
// 3. SRV - gives service name, protocol, port and target host
|
||||||
|
// 4. A - gives ip addr of target host
|
||||||
|
|
||||||
|
/*
|
||||||
|
PTR
|
||||||
|
0000 07 5f 6c 61 6c 61 6c 61 04 5f 74 63 70 05 6c 6f ._lalala._tcp.lo
|
||||||
|
0010 63 61 6c 00 00 0c 00 01 00 00 11 94 00 1f 0a 45 cal............E
|
||||||
|
0020 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c 61 6c SP_81CC47._lalal
|
||||||
|
0030 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 a._tcp.local.
|
||||||
|
*/
|
||||||
|
uint8_t tmp8;
|
||||||
|
uint16_t tmp16;
|
||||||
|
uint32_t tmp32;
|
||||||
|
|
||||||
|
while (numAnswers--) {
|
||||||
|
Serial.println("Parsing answer..");
|
||||||
|
// Skip name
|
||||||
|
tmp8 = _conn_read8();
|
||||||
|
if (tmp8 & 0xC0) { // Compressed
|
||||||
|
tmp8 = _conn_read8();
|
||||||
|
}
|
||||||
|
else { // Not compressed
|
||||||
|
while (tmp8 != 0x00) {
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.print(tmp8);
|
||||||
|
_conn_readS(hostName, tmp8);
|
||||||
|
Serial.printf("%s ", hostName);
|
||||||
|
tmp8 = _conn_read8();
|
||||||
|
if (tmp8 & 0xC0) { // Compressed
|
||||||
|
tmp8 = _conn_read8();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint16_t type = _conn_read16(); // Read type
|
||||||
|
if (type == MDNS_TYPE_PTR) {
|
||||||
|
Serial.println("Got a PTR answer!");
|
||||||
|
}
|
||||||
|
if (type == MDNS_TYPE_TXT) {
|
||||||
|
Serial.println("Got a TXT answer!");
|
||||||
|
}
|
||||||
|
if (type == MDNS_TYPE_SRV) {
|
||||||
|
Serial.println("Got a SRV answer!");
|
||||||
|
}
|
||||||
|
if (type == MDNS_TYPE_A) {
|
||||||
|
Serial.println("Got a A answer!");
|
||||||
|
}
|
||||||
|
tmp16 = _conn_read16(); // Skip class
|
||||||
|
tmp32 = _conn_read32(); // Skip ttl
|
||||||
|
tmp16 = _conn_read16(); // Skip rdlength
|
||||||
|
Serial.println("\nskip ");
|
||||||
|
Serial.print(tmp16);
|
||||||
|
_conn_readS(hostName, tmp16); // Skip rdata
|
||||||
|
Serial.printf("%s ", hostName);
|
||||||
|
}
|
||||||
|
Serial.println("All answers parsed!");
|
||||||
|
/*
|
||||||
|
TXT
|
||||||
|
0000 0a 45 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c .ESP_81CC47._lal
|
||||||
|
0010 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 ala._tcp.local..
|
||||||
|
0020 10 00 01 00 00 11 94 00 00 .........
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRV
|
||||||
|
0000 0a 45 53 50 5f 38 31 43 43 34 37 07 5f 6c 61 6c .ESP_81CC47._lal
|
||||||
|
0010 61 6c 61 04 5f 74 63 70 05 6c 6f 63 61 6c 00 00 ala._tcp.local..
|
||||||
|
0020 21 80 01 00 00 00 78 00 18 00 00 00 00 1f 90 0a !.....x.........
|
||||||
|
0030 65 73 70 5f 38 31 63 63 34 37 05 6c 6f 63 61 6c esp_81cc47.local
|
||||||
|
0040 00 .
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
A
|
||||||
|
0000 0a 65 73 70 5f 38 31 63 63 34 37 05 6c 6f 63 61 .esp_81cc47.loca
|
||||||
|
0010 6c 00 00 01 80 01 00 00 00 78 00 04 c0 a8 01 0c l........x......
|
||||||
|
*/
|
||||||
|
|
||||||
_conn->flush();
|
_conn->flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ ESP8266 Multicast DNS (port of CC3000 Multicast DNS library)
|
|||||||
Version 1.1
|
Version 1.1
|
||||||
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
||||||
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
|
ESP8266 port (c) 2015 Ivan Grokhotkov (ivan@esp8266.com)
|
||||||
|
Extended MDNS-SD support 2016 Lars Englund
|
||||||
|
|
||||||
This is a simple implementation of multicast DNS query support for an Arduino
|
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
|
running on ESP8266 chip. Only support for resolving address queries is currently
|
||||||
@ -82,6 +83,14 @@ public:
|
|||||||
addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void queryService(char *service, void(*p_answer_function)(const char*));
|
||||||
|
void queryService(const char *service, void(*p_answer_function)(const char*)){
|
||||||
|
queryService((char *)service, p_answer_function);
|
||||||
|
}
|
||||||
|
void queryService(String service, void(*p_answer_function)(const char*)){
|
||||||
|
queryService(service.c_str(), p_answer_function);
|
||||||
|
}
|
||||||
|
|
||||||
void enableArduino(uint16_t port, bool auth=false);
|
void enableArduino(uint16_t port, bool auth=false);
|
||||||
|
|
||||||
void setInstanceName(String name);
|
void setInstanceName(String name);
|
||||||
@ -97,6 +106,8 @@ private:
|
|||||||
UdpContext* _conn;
|
UdpContext* _conn;
|
||||||
String _hostName;
|
String _hostName;
|
||||||
String _instanceName;
|
String _instanceName;
|
||||||
|
// Pointer to function that gets called for every incoming answer.
|
||||||
|
void(*p_answer_function_)(const char*);
|
||||||
|
|
||||||
uint32_t _getOurIp();
|
uint32_t _getOurIp();
|
||||||
uint16_t _getServicePort(char *service, char *proto);
|
uint16_t _getServicePort(char *service, char *proto);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user