mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Merge pull request #1242 from edog1973/master
mDNS fixes and enhancements
This commit is contained in:
commit
2d81ee290a
@ -85,21 +85,42 @@ static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251);
|
||||
static const int MDNS_MULTICAST_TTL = 1;
|
||||
static const int MDNS_PORT = 5353;
|
||||
|
||||
MDNSResponder::MDNSResponder() : _conn(0) { _services = 0; _arduinoAuth = false; }
|
||||
struct MDNSService {
|
||||
MDNSService* _next;
|
||||
char _name[32];
|
||||
char _proto[3];
|
||||
uint16_t _port;
|
||||
struct MDNSTxt * _txts;
|
||||
uint16_t _txtLen; // length of all txts
|
||||
};
|
||||
|
||||
struct MDNSTxt{
|
||||
MDNSTxt * _next;
|
||||
String _txt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
MDNSResponder::MDNSResponder() : _conn(0) {
|
||||
_services = 0;
|
||||
_instanceName = "";
|
||||
}
|
||||
MDNSResponder::~MDNSResponder() {}
|
||||
|
||||
bool MDNSResponder::begin(const char* domain){
|
||||
bool MDNSResponder::begin(const char* hostname){
|
||||
// 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.
|
||||
size_t n = strlen(hostname);
|
||||
if (n > 63) { // max size for a single label.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy in domain characters as lowercase
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
_hostName[i] = tolower(domain[i]);
|
||||
_hostName[n] = '\0';
|
||||
// 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) {
|
||||
@ -138,6 +159,48 @@ void MDNSResponder::update() {
|
||||
_parsePacket();
|
||||
}
|
||||
|
||||
|
||||
void MDNSResponder::setInstanceName(String name){
|
||||
if (name.length() > 63) return;
|
||||
else _instanceName = name;
|
||||
}
|
||||
|
||||
|
||||
bool MDNSResponder::addServiceTxt(char *name, char *proto, char *key, char *value){
|
||||
MDNSService* servicePtr;
|
||||
|
||||
uint8_t txtLen = os_strlen(key) + os_strlen(value) + 1; // Add one for equals sign
|
||||
txtLen+=1; //accounts for length byte added when building the txt responce
|
||||
//Find the service
|
||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||
//Checking Service names
|
||||
if(strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
||||
//found a service name match
|
||||
if (servicePtr->_txtLen + txtLen > 1300) return false; //max txt record size
|
||||
MDNSTxt *newtxt = new MDNSTxt;
|
||||
newtxt->_txt = String(key) + "=" + String(value);
|
||||
newtxt->_next = 0;
|
||||
if(servicePtr->_txts == 0) { //no services have been added
|
||||
//Adding First TXT to service
|
||||
servicePtr->_txts = newtxt;
|
||||
servicePtr->_txtLen += txtLen;
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
MDNSTxt * txtPtr = servicePtr->_txts;
|
||||
while(txtPtr->_next !=0) {
|
||||
txtPtr = txtPtr->_next;
|
||||
}
|
||||
//adding another TXT to service
|
||||
txtPtr->_next = newtxt;
|
||||
servicePtr->_txtLen += txtLen;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MDNSResponder::addService(char *name, char *proto, uint16_t port){
|
||||
if(_getServicePort(name, proto) != 0) return;
|
||||
if(os_strlen(name) > 32 || os_strlen(proto) != 3) return; //bad arguments
|
||||
@ -146,8 +209,42 @@ void MDNSResponder::addService(char *name, char *proto, uint16_t port){
|
||||
os_strcpy(srv->_proto, proto);
|
||||
srv->_port = port;
|
||||
srv->_next = 0;
|
||||
if(_services) _services->_next = srv;
|
||||
else _services = srv;
|
||||
srv->_txts = 0;
|
||||
srv->_txtLen = 0;
|
||||
|
||||
if(_services == 0) _services = srv;
|
||||
else{
|
||||
MDNSService* servicePtr = _services;
|
||||
while(servicePtr->_next !=0) servicePtr = servicePtr->_next;
|
||||
servicePtr->_next = srv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MDNSTxt * MDNSResponder::_getServiceTxt(char *name, char *proto){
|
||||
MDNSService* servicePtr;
|
||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||
if(servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
||||
if (servicePtr->_txts == 0) return false;
|
||||
else{
|
||||
return servicePtr->_txts;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t MDNSResponder::_getServiceTxtLen(char *name, char *proto){
|
||||
MDNSService* servicePtr;
|
||||
for (servicePtr = _services; servicePtr; servicePtr = servicePtr->_next) {
|
||||
if(servicePtr->_port > 0 && strcmp(servicePtr->_name, name) == 0 && strcmp(servicePtr->_proto, proto) == 0){
|
||||
if (servicePtr->_txts == 0) return false;
|
||||
else{
|
||||
return servicePtr->_txtLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t MDNSResponder::_getServicePort(char *name, char *proto){
|
||||
@ -172,7 +269,7 @@ uint32_t MDNSResponder::_getOurIp(){
|
||||
return staIpInfo.ip.addr;
|
||||
} else {
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_NO_LOCAL_IP\n");
|
||||
Serial.printf("ERR_NO_LOCAL_IP\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -217,9 +314,11 @@ void MDNSResponder::_parsePacket(){
|
||||
hostNameLen = 0;
|
||||
}
|
||||
|
||||
if(hostNameLen > 0 && strcmp(_hostName, hostName) != 0){
|
||||
if(hostNameLen > 0 && !_hostName.equals(hostName) && !_instanceName.equals(hostName)){
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_NO_HOST: %s\n", hostName);
|
||||
Serial.printf("ERR_NO_HOST: %s\n", hostName);
|
||||
Serial.printf("hostname: %s\n", _hostName.c_str() );
|
||||
Serial.printf("instance: %s\n", _instanceName.c_str() );
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
@ -244,14 +343,14 @@ void MDNSResponder::_parsePacket(){
|
||||
localParsed = true;
|
||||
} else {
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_FQDN: %s\n", serviceName);
|
||||
Serial.printf("ERR_FQDN: %s\n", serviceName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_SERVICE: %s\n", serviceName);
|
||||
Serial.printf("ERR_SERVICE: %s\n", serviceName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
@ -268,7 +367,7 @@ void MDNSResponder::_parsePacket(){
|
||||
protoParsed = true;
|
||||
} else {
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_PROTO: %s\n", protoName);
|
||||
Serial.printf("ERR_PROTO: %s\n", protoName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
@ -285,7 +384,7 @@ void MDNSResponder::_parsePacket(){
|
||||
localParsed = true;
|
||||
} else {
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_FQDN: %s\n", localName);
|
||||
Serial.printf("ERR_FQDN: %s\n", localName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
@ -296,14 +395,14 @@ void MDNSResponder::_parsePacket(){
|
||||
servicePort = _getServicePort(serviceName, protoName);
|
||||
if(servicePort == 0){
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_NO_SERVICE: %s\n", serviceName);
|
||||
Serial.printf("ERR_NO_SERVICE: %s\n", serviceName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
}
|
||||
} else if(serviceNameLen > 0 || protoNameLen > 0){
|
||||
#ifdef MDNS_DEBUG_ERR
|
||||
os_printf("ERR_SERVICE_PROTO: %s\n", serviceName);
|
||||
Serial.printf("ERR_SERVICE_PROTO: %s\n", serviceName);
|
||||
#endif
|
||||
_conn->flush();
|
||||
return;
|
||||
@ -312,7 +411,7 @@ void MDNSResponder::_parsePacket(){
|
||||
// RESPOND
|
||||
|
||||
#ifdef MDNS_DEBUG_RX
|
||||
os_printf("RX: REQ, ID:%u, Q:%u, A:%u, NS:%u, ADD:%u\n", packetHeader[0], packetHeader[2], packetHeader[3], packetHeader[4], packetHeader[5]);
|
||||
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]);
|
||||
#endif
|
||||
|
||||
uint16_t currentType;
|
||||
@ -339,24 +438,24 @@ void MDNSResponder::_parsePacket(){
|
||||
}
|
||||
|
||||
#ifdef MDNS_DEBUG_RX
|
||||
os_printf("REQ: ");
|
||||
if(hostNameLen > 0) os_printf("%s.", hostName);
|
||||
if(serviceNameLen > 0) os_printf("_%s.", serviceName);
|
||||
if(protoNameLen > 0) os_printf("_%s.", protoName);
|
||||
os_printf("local. ");
|
||||
Serial.printf("REQ: ");
|
||||
if(hostNameLen > 0) Serial.printf("%s.", hostName);
|
||||
if(serviceNameLen > 0) Serial.printf("_%s.", serviceName);
|
||||
if(protoNameLen > 0) Serial.printf("_%s.", protoName);
|
||||
Serial.printf("local. ");
|
||||
|
||||
if(currentType == MDNS_TYPE_AAAA) os_printf(" AAAA ");
|
||||
else if(currentType == MDNS_TYPE_A) os_printf(" A ");
|
||||
else if(currentType == MDNS_TYPE_PTR) os_printf(" PTR ");
|
||||
else if(currentType == MDNS_TYPE_SRV) os_printf(" SRV ");
|
||||
else if(currentType == MDNS_TYPE_TXT) os_printf(" TXT ");
|
||||
else os_printf(" 0x%04X ", currentType);
|
||||
if(currentType == MDNS_TYPE_AAAA) Serial.printf(" AAAA ");
|
||||
else if(currentType == MDNS_TYPE_A) Serial.printf(" A ");
|
||||
else if(currentType == MDNS_TYPE_PTR) Serial.printf(" PTR ");
|
||||
else if(currentType == MDNS_TYPE_SRV) Serial.printf(" SRV ");
|
||||
else if(currentType == MDNS_TYPE_TXT) Serial.printf(" TXT ");
|
||||
else Serial.printf(" 0x%04X ", currentType);
|
||||
|
||||
if(currentClass == MDNS_CLASS_IN) os_printf(" IN ");
|
||||
else if(currentClass == MDNS_CLASS_IN_FLUSH_CACHE) os_printf(" IN[F] ");
|
||||
else os_printf(" 0x%04X ", currentClass);
|
||||
if(currentClass == MDNS_CLASS_IN) Serial.printf(" IN ");
|
||||
else if(currentClass == MDNS_CLASS_IN_FLUSH_CACHE) Serial.printf(" IN[F] ");
|
||||
else Serial.printf(" 0x%04X ", currentClass);
|
||||
|
||||
os_printf("\n");
|
||||
Serial.printf("\n");
|
||||
#endif
|
||||
}
|
||||
uint8_t responseMask = 0;
|
||||
@ -371,8 +470,12 @@ void MDNSResponder::_parsePacket(){
|
||||
}
|
||||
|
||||
void MDNSResponder::enableArduino(uint16_t port, bool auth){
|
||||
_arduinoAuth = auth;
|
||||
|
||||
addService("arduino", "tcp", port);
|
||||
addServiceTxt("arduino", "tcp", "tcp_check", "no");
|
||||
addServiceTxt("arduino", "tcp", "ssh_upload", "no");
|
||||
addServiceTxt("arduino", "tcp", "board", ARDUINO_BOARD);
|
||||
addServiceTxt("arduino", "tcp", "auth_upload", (auth) ? "yes":"no");
|
||||
}
|
||||
|
||||
void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint16_t port){
|
||||
@ -380,17 +483,44 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
|
||||
if(replyMask == 0) return;
|
||||
|
||||
#ifdef MDNS_DEBUG_TX
|
||||
os_printf("TX: mask:%01X, service:%s, proto:%s, port:%u\n", replyMask, service, proto, port);
|
||||
Serial.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);
|
||||
|
||||
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
|
||||
@ -402,138 +532,141 @@ void MDNSResponder::_reply(uint8_t replyMask, char * service, char *proto, uint1
|
||||
};
|
||||
_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] = {
|
||||
// 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, (uint8_t)(3 + nameLen), //***DATA LEN (3 + strlen(host))
|
||||
0x00, ptrDataLen, //RData length
|
||||
};
|
||||
_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);
|
||||
_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 Response
|
||||
//TXT Responce
|
||||
if(replyMask & 0x4){
|
||||
if(replyMask & 0x8){
|
||||
uint8_t txtHead[10] = {
|
||||
0xC0, (uint8_t)(36 + serviceLen),//send the name
|
||||
0x00, 0x10, //Type TXT
|
||||
0x80, 0x01, //Class IN, with cache flush
|
||||
//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*>(txtHead), 10);
|
||||
}
|
||||
_conn->append(reinterpret_cast<const char*>(txtAttrs), 10);
|
||||
|
||||
if(strcmp(reinterpret_cast<const char*>("arduino"), service) == 0){
|
||||
//arduino
|
||||
//arduino service dependance should be removed and properties abstracted
|
||||
const char *tcpCheckExtra = "tcp_check=no";
|
||||
uint8_t tcpCheckExtraLen = os_strlen(tcpCheckExtra);
|
||||
|
||||
const char *sshUploadExtra = "ssh_upload=no";
|
||||
uint8_t sshUploadExtraLen = os_strlen(sshUploadExtra);
|
||||
|
||||
char boardName[64];
|
||||
const char *boardExtra = "board=";
|
||||
os_sprintf(boardName, "%s%s", boardExtra, ARDUINO_BOARD);
|
||||
uint8_t boardNameLen = os_strlen(boardName);
|
||||
|
||||
char authUpload[16];
|
||||
const char *authUploadExtra = "auth_upload=";
|
||||
os_sprintf(authUpload, "%s%s", authUploadExtra, reinterpret_cast<const char*>((_arduinoAuth)?"yes":"no"));
|
||||
uint8_t authUploadLen = os_strlen(authUpload);
|
||||
|
||||
uint16_t textDataLen = (1 + boardNameLen) + (1 + tcpCheckExtraLen) + (1 + sshUploadExtraLen) + (1 + authUploadLen);
|
||||
uint8_t txt[2] = {(uint8_t)(textDataLen >> 8), (uint8_t)(textDataLen)}; //DATA LEN
|
||||
_conn->append(reinterpret_cast<const char*>(txt), 2);
|
||||
|
||||
_conn->append(reinterpret_cast<const char*>(&boardNameLen), 1);
|
||||
_conn->append(reinterpret_cast<const char*>(boardName), boardNameLen);
|
||||
_conn->append(reinterpret_cast<const char*>(&authUploadLen), 1);
|
||||
_conn->append(reinterpret_cast<const char*>(authUpload), authUploadLen);
|
||||
_conn->append(reinterpret_cast<const char*>(&tcpCheckExtraLen), 1);
|
||||
_conn->append(reinterpret_cast<const char*>(tcpCheckExtra), tcpCheckExtraLen);
|
||||
_conn->append(reinterpret_cast<const char*>(&sshUploadExtraLen), 1);
|
||||
_conn->append(reinterpret_cast<const char*>(sshUploadExtra), sshUploadExtraLen);
|
||||
} else {
|
||||
//not arduino
|
||||
//we should figure out an API so TXT properties can be added for services
|
||||
uint8_t txt[2] = {0,0};
|
||||
_conn->append(reinterpret_cast<const char*>(txt), 2);
|
||||
//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 Response
|
||||
|
||||
//SRV Responce
|
||||
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);
|
||||
}
|
||||
//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
|
||||
|
||||
uint8_t srv[16] = {
|
||||
//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, (uint8_t)(9 + nameLen), //DATA LEN (9 + strlen(host))
|
||||
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*>(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);
|
||||
_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){
|
||||
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);
|
||||
}
|
||||
//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
|
||||
|
||||
uint8_t aaa[14] = {
|
||||
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
|
||||
(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->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);
|
||||
}
|
||||
|
||||
_conn->send();
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,8 @@ License (MIT license):
|
||||
|
||||
class UdpContext;
|
||||
|
||||
struct MDNSService {
|
||||
MDNSService* _next;
|
||||
char _name[32];
|
||||
char _proto[3];
|
||||
uint16_t _port;
|
||||
};
|
||||
struct MDNSService;
|
||||
struct MDNSTxt;
|
||||
|
||||
class MDNSResponder {
|
||||
public:
|
||||
@ -78,16 +74,34 @@ public:
|
||||
addService(service.c_str(), proto.c_str(), port);
|
||||
}
|
||||
|
||||
bool addServiceTxt(char *name, char *proto, char * key, char * value);
|
||||
void addServiceTxt(const char *name, const char *proto, const char *key,const char * value){
|
||||
addServiceTxt((char *)name, (char *)proto, (char *)key, (char *)value);
|
||||
}
|
||||
void addServiceTxt(String name, String proto, String key, String value){
|
||||
addServiceTxt(name.c_str(), proto.c_str(), key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void enableArduino(uint16_t port, bool auth=false);
|
||||
|
||||
void setInstanceName(String name);
|
||||
void setInstanceName(const char * name){
|
||||
setInstanceName(String(name));
|
||||
}
|
||||
void setInstanceName(char * name){
|
||||
setInstanceName(String(name));
|
||||
}
|
||||
|
||||
private:
|
||||
struct MDNSService * _services;
|
||||
UdpContext* _conn;
|
||||
char _hostName[128];
|
||||
bool _arduinoAuth;
|
||||
String _hostName;
|
||||
String _instanceName;
|
||||
|
||||
uint32_t _getOurIp();
|
||||
uint16_t _getServicePort(char *service, char *proto);
|
||||
MDNSTxt * _getServiceTxt(char *name, char *proto);
|
||||
uint16_t _getServiceTxtLen(char *name, char *proto);
|
||||
void _parsePacket();
|
||||
void _reply(uint8_t replyMask, char * service, char *proto, uint16_t port);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user