Added Software

This commit is contained in:
Joachim Hummel
2022-06-19 11:10:04 +00:00
parent c729e2062b
commit e76db08b77
199 changed files with 69643 additions and 0 deletions

View File

@ -0,0 +1,61 @@
ESP8266 Multicast DNS
=====================
A port of CC3000 Multicast DNS library (version 1.1)
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 implemented.
Requirements
------------
- ESP8266WiFi library
- MDNS support in your operating system/client machines:
- For Mac OSX support is built in through Bonjour already.
- For Linux, install `Avahi <http://avahi.org/>`__.
- For Windows, install
`Bonjour <http://www.apple.com/support/bonjour/>`__.
Usage
-----
1. Download this repository as a zip (button on the right) and follow
`these instructions to install into
Arduino <http://arduino.cc/en/Guide/Libraries>`__.
2. Include the ESP8266mDNS library in the sketch.
3. Call MDNS.begin method in the sketch's setup and provide a domain
name (without the '.local' suffix, i.e. just provide 'foo' to resolve
'foo.local'). Optionally provide the IP address to advertise and time
to live (in seconds) for the DNS record -- the default is 1 hour.
4. To advertise DNS-SD services, call MDNS.addService(service, proto,
port), where service and proto are strings with service and protocol
name (e.g. "http", "tcp"), and port is an integer port number for
this service (e.g. 80).
See the included MDNS + HTTP server sketch for a full example.
License
-------
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com) ESP8266 port (c)
2015 Ivan Grokhotkov (ivan@esp8266.com)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,268 @@
/*
ESP8266 mDNS responder clock
This example demonstrates two features of the LEA MDNSResponder:
1. The host and service domain negotiation process that ensures
the uniqueness of the finally choosen host and service domain name.
2. The dynamic MDNS service TXT feature
A 'clock' service in announced via the MDNS responder and the current
time is set as a TXT item (eg. 'curtime=Mon Oct 15 19:54:35 2018').
The time value is updated every second!
The ESP is initially announced to clients as 'esp8266.local', if this host domain
is already used in the local network, another host domain is negociated. Keep an
eye to the serial output to learn the final host domain for the clock service.
The service itself is is announced as 'host domain'._espclk._tcp.local.
As the service uses port 80, a very simple HTTP server is installed also to deliver
a small web page containing a greeting and the current time (not updated).
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
Point your browser to 'host domain'.local to see this web page.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to the ESP8266 board
- Install host software:
- For Linux, install Avahi (http://avahi.org/).
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
- For Mac OSX and iOS support is built in through Bonjour already.
- Use a MDNS/Bonjour browser like 'Discovery' to find the clock service in your local
network and see the current time updates.
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <time.h>
#include <PolledTimeout.h>
#include <ESP8266mDNS.h>
/*
Global defines and vars
*/
#define TIMEZONE_OFFSET 1 // CET
#define DST_OFFSET 1 // CEST
#define UPDATE_CYCLE (1 * 1000) // every second
#define SERVICE_PORT 80 // HTTP port
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
char* pcHostDomain = 0; // Negociated host domain
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the clock service in the MDNS responder
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
ESP8266WebServer server(SERVICE_PORT);
/*
getTimeString
*/
const char* getTimeString(void) {
static char acTimeString[32];
time_t now = time(nullptr);
ctime_r(&now, acTimeString);
size_t stLength;
while (((stLength = strlen(acTimeString))) &&
('\n' == acTimeString[stLength - 1])) {
acTimeString[stLength - 1] = 0; // Remove trailing line break...
}
return acTimeString;
}
/*
setClock
Set time via NTP
*/
void setClock(void) {
configTime((TIMEZONE_OFFSET * 3600), (DST_OFFSET * 3600), "pool.ntp.org", "time.nist.gov", "time.windows.com");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr); // Secs since 01.01.1970 (when uninitalized starts with (8 * 3600 = 28800)
while (now < 8 * 3600 * 2) { // Wait for realistic value
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
Serial.printf("Current time: %s\n", getTimeString());
}
/*
setStationHostname
*/
bool setStationHostname(const char* p_pcHostname) {
if (p_pcHostname) {
WiFi.hostname(p_pcHostname);
Serial.printf("setDeviceHostname: Station hostname is set to '%s'\n", p_pcHostname);
}
return true;
}
/*
MDNSDynamicServiceTxtCallback
Add a dynamic MDNS TXT item 'ct' to the clock service.
The callback function is called every time, the TXT items for the clock service
are needed.
This can be triggered by calling MDNS.announce().
*/
void MDNSDynamicServiceTxtCallback(const MDNSResponder::hMDNSService p_hService) {
Serial.println("MDNSDynamicServiceTxtCallback");
if (hMDNSService == p_hService) {
Serial.printf("Updating curtime TXT item to: %s\n", getTimeString());
MDNS.addDynamicServiceTxt(p_hService, "curtime", getTimeString());
}
}
/*
MDNSProbeResultCallback
Probe result callback for the host domain.
If the domain is free, the host domain is set and the clock service is
added.
If the domain is already used, a new name is created and the probing is
restarted via p_pMDNSResponder->setHostname().
*/
void hostProbeResult(String p_pcDomainName, bool p_bProbeResult) {
Serial.println("MDNSProbeResultCallback");
Serial.printf("MDNSProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!"));
if (true == p_bProbeResult) {
// Set station hostname
setStationHostname(pcHostDomain);
if (!bHostDomainConfirmed) {
// Hostname free -> setup clock service
bHostDomainConfirmed = true;
if (!hMDNSService) {
// Add a 'clock.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain
hMDNSService = MDNS.addService(0, "espclk", "tcp", SERVICE_PORT);
if (hMDNSService) {
// Add a simple static MDNS service TXT item
MDNS.addServiceTxt(hMDNSService, "port#", SERVICE_PORT);
// Set the callback function for dynamic service TXTs
MDNS.setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback);
}
}
}
} else {
// Change hostname, use '-' as divider between base name and index
if (MDNSResponder::indexDomain(pcHostDomain, "-", 0)) {
MDNS.setHostname(pcHostDomain);
} else {
Serial.println("MDNSProbeResultCallback: FAILED to update hostname!");
}
}
}
/*
handleHTTPClient
*/
void handleHTTPRequest() {
Serial.println("");
Serial.println("HTTP Request");
// Get current time
time_t now = time(nullptr);;
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
String s;
s = "<!DOCTYPE HTML>\r\n<html>Hello from ";
s += WiFi.hostname() + " at " + WiFi.localIP().toString();
// Simple addition of the current time
s += "\r\nCurrent time is: ";
s += getTimeString();
// done :-)
s += "</html>\r\n\r\n";
Serial.println("Sending 200");
server.send(200, "text/html", s);
}
/*
setup
*/
void setup(void) {
Serial.begin(115200);
// Connect to WiFi network
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Sync clock
setClock();
// Setup MDNS responder
MDNS.setHostProbeResultCallback(hostProbeResult);
// Init the (currently empty) host domain string with 'esp8266'
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
(!MDNS.begin(pcHostDomain))) {
Serial.println("Error setting up MDNS responder!");
while (1) { // STOP
delay(1000);
}
}
Serial.println("MDNS responder started");
// Setup HTTP server
server.on("/", handleHTTPRequest);
server.begin();
Serial.println("HTTP server started");
}
/*
loop
*/
void loop(void) {
// Check if a request has come in
server.handleClient();
// Allow MDNS processing
MDNS.update();
static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE);
if (timeout.expired()) {
if (hMDNSService) {
// Just trigger a new MDNS announcement, this will lead to a call to
// 'MDNSDynamicServiceTxtCallback', which will update the time TXT item
MDNS.announce();
}
}
}

View File

@ -0,0 +1,269 @@
/*
ESP8266 mDNS responder clock
This example demonstrates two features of the LEA clsLEAMDNSHost:
1. The host and service domain negotiation process that ensures
the uniqueness of the finally chosen host and service domain name.
2. The dynamic MDNS service TXT feature
A 'clock' service in announced via the MDNS responder and the current
time is set as a TXT item (eg. 'curtime=Mon Oct 15 19:54:35 2018').
The time value is updated every second!
The ESP is initially announced to clients as 'esp8266.local', if this host domain
is already used in the local network, another host domain is negotiated. Keep an
eye on the serial output to learn the final host domain for the clock service.
The service itself is is announced as 'host domain'._espclk._tcp.local.
As the service uses port 80, a very simple HTTP server is also installed to deliver
a small web page containing a greeting and the current time (not updated).
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
Point your browser to 'host domain'.local to see this web page.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to the ESP8266 board
- Install host software:
- For Linux, install Avahi (http://avahi.org/).
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
- For Mac OSX and iOS support is built in through Bonjour already.
- Use a MDNS/Bonjour browser like 'Discovery' to find the clock service in your local
network and see the current time updates.
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <LwipIntf.h>
#include <time.h>
#include <PolledTimeout.h>
// uses API MDNSApiVersion::LEAv2
#define NO_GLOBAL_MDNS // our MDNS is defined below
#include <ESP8266mDNS.h>
/*
Global defines and vars
*/
#define TIMEZONE_OFFSET 1 // CET
#define DST_OFFSET 1 // CEST
#define UPDATE_CYCLE (1 * 1000) // every second
#define START_AP_AFTER_MS 10000 // start AP after delay
#define SERVICE_PORT 80 // HTTP port
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
#ifndef APSSID
#define APSSID "ap4mdnsClock"
#define APPSK "mdnsClock"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
clsLEAMDNSHost MDNSRESP; // MDNS responder
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the clock service in the MDNS responder
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
ESP8266WebServer server(SERVICE_PORT);
/*
getTimeString
*/
const char* getTimeString(void) {
static char acTimeString[32];
time_t now = time(nullptr);
ctime_r(&now, acTimeString);
size_t stLength;
while (((stLength = strlen(acTimeString))) &&
('\n' == acTimeString[stLength - 1])) {
acTimeString[stLength - 1] = 0; // Remove trailing line break...
}
return acTimeString;
}
/*
setClock
Set time via NTP
*/
void setClock(void) {
configTime((TIMEZONE_OFFSET * 3600), (DST_OFFSET * 3600), "pool.ntp.org", "time.nist.gov", "time.windows.com");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr); // Secs since 01.01.1970 (when uninitalized starts with (8 * 3600 = 28800)
while (now < 8 * 3600 * 2) { // Wait for realistic value
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
Serial.printf("Current time: %s\n", getTimeString());
}
/*
setStationHostname
*/
bool setStationHostname(const char* p_pcHostname) {
if (p_pcHostname) {
WiFi.hostname(p_pcHostname);
Serial.printf("setDeviceHostname: Station hostname is set to '%s'\n", p_pcHostname);
}
return true;
}
/*
MDNSDynamicServiceTxtCallback
Add a dynamic MDNS TXT item 'ct' to the clock service.
The callback function is called every time, the TXT items for the clock service
are needed.
This can be triggered by calling MDNSRESP.announce().
*/
void MDNSDynamicServiceTxtCallback(const clsLEAMDNSHost::hMDNSService& p_hService) {
Serial.println("MDNSDynamicServiceTxtCallback");
if (hMDNSService == &p_hService) {
Serial.printf("Updating curtime TXT item to: %s\n", getTimeString());
hMDNSService->addDynamicServiceTxt("curtime", getTimeString());
}
}
/*
handleHTTPClient
*/
void handleHTTPRequest() {
Serial.println("");
Serial.println("HTTP Request");
// Get current time
time_t now = time(nullptr);;
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
String s;
s.reserve(300);
s = "<!DOCTYPE HTML>\r\n<html>Hello from ";
s += WiFi.hostname() + " at " + WiFi.localIP().toString();
// Simple addition of the current time
s += "\r\nCurrent time is: ";
s += getTimeString();
// done :-)
s += "</html>\r\n\r\n";
Serial.println("Sending 200");
server.send(200, "text/html", s);
}
/*
setup
*/
void setup(void) {
Serial.begin(115200);
// Connect to WiFi network
WiFi.persistent(false);
// useless informative callback
if (!LwipIntf::stateUpCB([](netif * nif) {
Serial.printf("New interface %c%c/%d is up\n",
nif->name[0],
nif->name[1],
netif_get_index(nif));
})) {
Serial.println("Error: could not add informative callback\n");
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Sync clock
setClock();
// Setup MDNS responder
// Init the (currently empty) host domain string with 'leamdnsv2'
if (MDNSRESP.begin("leamdnsv2",
[](clsLEAMDNSHost & p_rMDNSHost, const char* p_pcDomainName, bool p_bProbeResult)->void {
if (p_bProbeResult) {
Serial.printf("mDNSHost_AP::ProbeResultCallback: '%s' is %s\n", p_pcDomainName, (p_bProbeResult ? "FREE" : "USED!"));
// Unattended added service
hMDNSService = p_rMDNSHost.addService(0, "espclk", "tcp", 80);
hMDNSService->addDynamicServiceTxt("curtime", getTimeString());
hMDNSService->setDynamicServiceTxtCallback(MDNSDynamicServiceTxtCallback);
} else {
// Change hostname, use '-' as divider between base name and index
MDNSRESP.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName, "-", 0));
}
})) {
Serial.println("mDNS-AP started");
} else {
Serial.println("FAILED to start mDNS-AP");
}
// Setup HTTP server
server.on("/", handleHTTPRequest);
server.begin();
Serial.println("HTTP server started");
}
/*
loop
*/
void loop(void) {
// Check if a request has come in
server.handleClient();
// Allow MDNS processing
MDNSRESP.update();
static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE);
if (timeout.expired()) {
if (hMDNSService) {
// Just trigger a new MDNS announcement, this will lead to a call to
// 'MDNSDynamicServiceTxtCallback', which will update the time TXT item
Serial.printf("Announce trigger from user\n");
MDNSRESP.announce();
}
}
static bool AP_started = false;
if (!AP_started && millis() > START_AP_AFTER_MS) {
AP_started = true;
Serial.printf("Starting AP...\n");
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(APSSID, APPSK);
Serial.printf("AP started...(%s:%s, %s)\n",
WiFi.softAPSSID().c_str(),
WiFi.softAPPSK().c_str(),
WiFi.softAPIP().toString().c_str());
}
}

View File

@ -0,0 +1,270 @@
/*
ESP8266 mDNS Responder Service Monitor
This example demonstrates two features of the LEA MDNSResponder:
1. The host and service domain negotiation process that ensures
the uniqueness of the finally choosen host and service domain name.
2. The dynamic MDNS service lookup/query feature.
A list of 'HTTP' services in the local network is created and kept up to date.
In addition to this, a (very simple) HTTP server is set up on port 80
and announced as a service.
The ESP itself is initially announced to clients as 'esp8266.local', if this host domain
is already used in the local network, another host domain is negociated. Keep an
eye to the serial output to learn the final host domain for the HTTP service.
The service itself is is announced as 'host domain'._http._tcp.local.
The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated).
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
Point your browser to 'host domain'.local to see this web page.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to the ESP8266 board
- Install host software:
- For Linux, install Avahi (http://avahi.org/).
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
- For Mac OSX and iOS support is built in through Bonjour already.
- Use a browser like 'Safari' to see the page at http://'host domain'.local.
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
/*
Global defines and vars
*/
#define SERVICE_PORT 80 // HTTP port
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
char* pcHostDomain = 0; // Negociated host domain
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the http service in the MDNS responder
MDNSResponder::hMDNSServiceQuery hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder
const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>";
String strHTTPServices = cstrNoHTTPServices;
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
ESP8266WebServer server(SERVICE_PORT);
/*
setStationHostname
*/
bool setStationHostname(const char* p_pcHostname) {
if (p_pcHostname) {
WiFi.hostname(p_pcHostname);
Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname);
return true;
}
return false;
}
/*
MDNSServiceQueryCallback
*/
void MDNSServiceQueryCallback(MDNSResponder::MDNSServiceInfo serviceInfo, MDNSResponder::AnswerType answerType, bool p_bSetContent) {
String answerInfo;
switch (answerType) {
case MDNSResponder::AnswerType::ServiceDomain :
answerInfo = "ServiceDomain " + String(serviceInfo.serviceDomain());
break;
case MDNSResponder::AnswerType::HostDomainAndPort :
answerInfo = "HostDomainAndPort " + String(serviceInfo.hostDomain()) + ":" + String(serviceInfo.hostPort());
break;
case MDNSResponder::AnswerType::IP4Address :
answerInfo = "IP4Address ";
for (IPAddress ip : serviceInfo.IP4Adresses()) {
answerInfo += "- " + ip.toString();
};
break;
case MDNSResponder::AnswerType::Txt :
answerInfo = "TXT " + String(serviceInfo.strKeyValue());
for (auto kv : serviceInfo.keyValues()) {
answerInfo += "\nkv : " + String(kv.first) + " : " + String(kv.second);
}
break;
default :
answerInfo = "Unknown Answertype";
}
Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted");
}
/*
MDNSServiceProbeResultCallback
Probe result callback for Services
*/
void serviceProbeResult(String p_pcServiceName,
const MDNSResponder::hMDNSService p_hMDNSService,
bool p_bProbeResult) {
(void) p_hMDNSService;
Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcServiceName.c_str(), (p_bProbeResult ? "succeeded." : "failed!"));
}
/*
MDNSHostProbeResultCallback
Probe result callback for the host domain.
If the domain is free, the host domain is set and the http service is
added.
If the domain is already used, a new name is created and the probing is
restarted via p_pMDNSResponder->setHostname().
*/
void hostProbeResult(String p_pcDomainName, bool p_bProbeResult) {
Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!"));
if (true == p_bProbeResult) {
// Set station hostname
setStationHostname(pcHostDomain);
if (!bHostDomainConfirmed) {
// Hostname free -> setup clock service
bHostDomainConfirmed = true;
if (!hMDNSService) {
// Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain
hMDNSService = MDNS.addService(0, "http", "tcp", SERVICE_PORT);
if (hMDNSService) {
MDNS.setServiceProbeResultCallback(hMDNSService, serviceProbeResult);
// Add some '_http._tcp' protocol specific MDNS service TXT items
// See: http://www.dns-sd.org/txtrecords.html#http
MDNS.addServiceTxt(hMDNSService, "user", "");
MDNS.addServiceTxt(hMDNSService, "password", "");
MDNS.addServiceTxt(hMDNSService, "path", "/");
}
// Install dynamic 'http.tcp' service query
if (!hMDNSServiceQuery) {
hMDNSServiceQuery = MDNS.installServiceQuery("http", "tcp", MDNSServiceQueryCallback);
if (hMDNSServiceQuery) {
Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n");
} else {
Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n");
}
}
}
}
} else {
// Change hostname, use '-' as divider between base name and index
if (MDNSResponder::indexDomain(pcHostDomain, "-", 0)) {
MDNS.setHostname(pcHostDomain);
} else {
Serial.println("MDNSProbeResultCallback: FAILED to update hostname!");
}
}
}
/*
HTTP request function (not found is handled by server)
*/
void handleHTTPRequest() {
Serial.println("");
Serial.println("HTTP Request");
IPAddress ip = WiFi.localIP();
String ipStr = ip.toString();
String s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from ";
s += WiFi.hostname() + ".local at " + WiFi.localIP().toString() + "</h3></head>";
s += "<br/><h4>Local HTTP services are :</h4>";
s += "<ol>";
for (auto info : MDNS.answerInfo(hMDNSServiceQuery)) {
s += "<li>";
s += info.serviceDomain();
if (info.hostDomainAvailable()) {
s += "<br/>Hostname: ";
s += String(info.hostDomain());
s += (info.hostPortAvailable()) ? (":" + String(info.hostPort())) : "";
}
if (info.IP4AddressAvailable()) {
s += "<br/>IP4:";
for (auto ip : info.IP4Adresses()) {
s += " " + ip.toString();
}
}
if (info.txtAvailable()) {
s += "<br/>TXT:<br/>";
for (auto kv : info.keyValues()) {
s += "\t" + String(kv.first) + " : " + String(kv.second) + "<br/>";
}
}
s += "</li>";
}
s += "</ol><br/>";
Serial.println("Sending 200");
server.send(200, "text/html", s);
Serial.println("Done with request");
}
/*
setup
*/
void setup(void) {
Serial.begin(115200);
Serial.setDebugOutput(false);
// Connect to WiFi network
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup HTTP server
server.on("/", handleHTTPRequest);
// Setup MDNS responders
MDNS.setHostProbeResultCallback(hostProbeResult);
// Init the (currently empty) host domain string with 'esp8266'
if ((!MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
(!MDNS.begin(pcHostDomain))) {
Serial.println(" Error setting up MDNS responder!");
while (1) { // STOP
delay(1000);
}
}
Serial.println("MDNS responder started");
// Start HTTP server
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
// Check if a request has come in
server.handleClient();
// Allow MDNS processing
MDNS.update();
}

View File

@ -0,0 +1,259 @@
/*
ESP8266 mDNS Responder Service Monitor
This example demonstrates two features of the LEA clsLEAMDNSHost:
1. The host and service domain negotiation process that ensures
the uniqueness of the finally choosen host and service domain name.
2. The dynamic MDNS service lookup/query feature.
A list of 'HTTP' services in the local network is created and kept up to date.
In addition to this, a (very simple) HTTP server is set up on port 80
and announced as a service.
The ESP itself is initially announced to clients as 'esp8266.local', if this host domain
is already used in the local network, another host domain is negociated. Keep an
eye to the serial output to learn the final host domain for the HTTP service.
The service itself is is announced as 'host domain'._http._tcp.local.
The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated).
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
Point your browser to 'host domain'.local to see this web page.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to the ESP8266 board
- Install host software:
- For Linux, install Avahi (http://avahi.org/).
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
- For Mac OSX and iOS support is built in through Bonjour already.
- Use a browser like 'Safari' to see the page at http://'host domain'.local.
*/
// THIS IS A WORK IN PROGRESS: some TODOs need completion
#ifndef STASSID
#define STASSID "ssid"
#define STAPSK "psk"
#endif
#ifndef APSSID
#define APSSID "esp8266"
//#define APPSK "psk"
#endif
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#define NO_GLOBAL_MDNS // our MDNS is defined below
#include <ESP8266mDNS.h>
/*
Global defines and vars
*/
#define SERVICE_PORT 80 // HTTP port
clsLEAMDNSHost MDNS; // MDNS responder
char* pcHostDomain = 0; // Negociated host domain
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
clsLEAMDNSHost::clsService* hMDNSService = 0; // The handle of the http service in the MDNS responder
clsLEAMDNSHost::clsQuery* hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder
const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>";
String strHTTPServices = cstrNoHTTPServices;
// HTTP server at port 'SERVICE_PORT' will respond to HTTP requests
ESP8266WebServer server(SERVICE_PORT);
/*
setStationHostname
*/
bool setStationHostname(const char* p_pcHostname) {
if (p_pcHostname) {
WiFi.hostname(p_pcHostname);
Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname);
return true;
}
return false;
}
void MDNSServiceQueryCallback(const clsLEAMDNSHost::clsQuery& p_Query,
const clsLEAMDNSHost::clsQuery::clsAnswer& p_Answer,
clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType p_QueryAnswerTypeFlags,
bool p_bSetContent) {
(void)p_Query;
String answerInfo;
switch (p_QueryAnswerTypeFlags) {
case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::ServiceDomain):
answerInfo = "ServiceDomain " + String(p_Answer.m_ServiceDomain.c_str());
break;
case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::HostDomainPort):
answerInfo = "HostDomainAndPort " + String(p_Answer.m_HostDomain.c_str()) + ":" + String(p_Answer.m_u16Port);
break;
case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::IPv4Address):
answerInfo = "IP4Address ";
for (auto ip : p_Answer.m_IPv4Addresses) {
answerInfo += "- " + ip->m_IPAddress.toString();
};
break;
case static_cast<clsLEAMDNSHost::clsQuery::clsAnswer::typeQueryAnswerType>(clsLEAMDNSHost::clsQuery::clsAnswer::enuQueryAnswerType::Txts):
answerInfo = "TXT ";
for (auto kv : p_Answer.m_Txts.m_Txts) {
answerInfo += "\nkv : " + String(kv->m_pcKey) + " : " + String(kv->m_pcValue);
}
break;
default :
answerInfo = "Unknown Answertype " + String(p_QueryAnswerTypeFlags);
}
Serial.printf("Answer %s %s\n", answerInfo.c_str(), p_bSetContent ? "Modified" : "Deleted");
}
/*
MDNSServiceProbeResultCallback
Probe result callback for Services
*/
void serviceProbeResult(clsLEAMDNSHost::clsService& p_rMDNSService,
const char* p_pcInstanceName,
bool p_bProbeResult) {
(void)p_rMDNSService;
Serial.printf("MDNSServiceProbeResultCallback: Service %s probe %s\n", p_pcInstanceName, (p_bProbeResult ? "succeeded." : "failed!"));
}
/*
MDNSHostProbeResultCallback
Probe result callback for the host domain.
If the domain is free, the host domain is set and the http service is
added.
If the domain is already used, a new name is created and the probing is
restarted via p_pclsLEAMDNSHost->setHostname().
*/
void hostProbeResult(clsLEAMDNSHost & p_rMDNSHost, String p_pcDomainName, bool p_bProbeResult) {
(void)p_rMDNSHost;
Serial.printf("MDNSHostProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName.c_str(), (p_bProbeResult ? "free" : "already USED!"));
if (true == p_bProbeResult) {
// Set station hostname
setStationHostname(pcHostDomain);
if (!bHostDomainConfirmed) {
// Hostname free -> setup clock service
bHostDomainConfirmed = true;
if (!hMDNSService) {
// Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain
hMDNSService = MDNS.addService(0, "http", "tcp", SERVICE_PORT, serviceProbeResult);
if (hMDNSService) {
hMDNSService->setProbeResultCallback(serviceProbeResult);
// MDNS.setServiceProbeResultCallback(hMDNSService, serviceProbeResult);
// Add some '_http._tcp' protocol specific MDNS service TXT items
// See: http://www.dns-sd.org/txtrecords.html#http
hMDNSService->addServiceTxt("user", "");
hMDNSService->addServiceTxt("password", "");
hMDNSService->addServiceTxt("path", "/");
}
// Install dynamic 'http.tcp' service query
if (!hMDNSServiceQuery) {
hMDNSServiceQuery = MDNS.installServiceQuery("http", "tcp", MDNSServiceQueryCallback);
if (hMDNSServiceQuery) {
Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n");
} else {
Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n");
}
}
}
}
} else {
// Change hostname, use '-' as divider between base name and index
MDNS.setHostName(clsLEAMDNSHost::indexDomainName(p_pcDomainName.c_str(), "-", 0));
}
}
/*
HTTP request function (not found is handled by server)
*/
void handleHTTPRequest() {
Serial.println("");
Serial.println("HTTP Request");
IPAddress ip = server.client().localIP();
String ipStr = ip.toString();
String s;
s.reserve(200 /* + service listed */);
s = "<!DOCTYPE HTML>\r\n<html><h3><head>Hello from ";
s += WiFi.hostname() + ".local at " + server.client().localIP().toString() + "</h3></head>";
s += "<br/><h4>Local HTTP services are :</h4>";
s += "<ol>";
// TODO: list services
s += "</ol><br/>";
Serial.println("Sending 200");
server.send(200, "text/html", s);
Serial.println("Done with request");
}
/*
setup
*/
void setup(void) {
Serial.begin(115200);
Serial.setDebugOutput(false);
Serial.println("");
Serial.println("THIS IS A WORK IN PROGRESS: some TODOs need completion");
Serial.println("");
// Connect to WiFi network
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(APSSID);
WiFi.begin(STASSID, STAPSK);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(STASSID);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup HTTP server
server.on("/", handleHTTPRequest);
// Setup MDNS responders
MDNS.setProbeResultCallback(hostProbeResult);
// Init the (currently empty) host domain string with 'leamdnsv2'
MDNS.begin("leamdnsv2");
Serial.println("MDNS responder started");
// Start HTTP server
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
// Check if a request has come in
server.handleClient();
// Allow MDNS processing
MDNS.update();
}

View File

@ -0,0 +1,248 @@
/**
@file OTA-mDNS-LittleFS.ino
@author Pascal Gollor (http://www.pgollor.de/cms/)
@date 2015-09-18
changelog:
2015-10-22:
- Use new ArduinoOTA library.
- loadConfig function can handle different line endings
- remove mDNS studd. ArduinoOTA handle it.
*/
#ifndef APSSID
#define APSSID "your-apssid"
#define APPSK "your-password"
#endif
#ifndef STASSID
#define STASSID "your-sta"
#define STAPSK "your-password"
#endif
// includes
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <FS.h>
#include <LittleFS.h>
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
/**
@brief mDNS and OTA Constants
@{
*/
#define HOSTNAME "ESP8266-OTA-" ///< Hostname. The setup function adds the Chip ID at the end.
/// @}
/**
@brief Default WiFi connection information.
@{
*/
const char* ap_default_ssid = APSSID; ///< Default SSID.
const char* ap_default_psk = APPSK; ///< Default PSK.
/// @}
/// Uncomment the next line for verbose output over UART.
//#define SERIAL_VERBOSE
/**
@brief Read WiFi connection information from file system.
@param ssid String pointer for storing SSID.
@param pass String pointer for storing PSK.
@return True or False.
The config file have to containt the WiFi SSID in the first line
and the WiFi PSK in the second line.
Line seperator can be \r\n (CR LF) \r or \n.
*/
bool loadConfig(String *ssid, String *pass) {
// open file for reading.
File configFile = LittleFS.open("/cl_conf.txt", "r");
if (!configFile) {
Serial.println("Failed to open cl_conf.txt.");
return false;
}
// Read content from config file.
String content = configFile.readString();
configFile.close();
content.trim();
// Check if ther is a second line available.
int8_t pos = content.indexOf("\r\n");
uint8_t le = 2;
// check for linux and mac line ending.
if (pos == -1) {
le = 1;
pos = content.indexOf("\n");
if (pos == -1) {
pos = content.indexOf("\r");
}
}
// If there is no second line: Some information is missing.
if (pos == -1) {
Serial.println("Infvalid content.");
Serial.println(content);
return false;
}
// Store SSID and PSK into string vars.
*ssid = content.substring(0, pos);
*pass = content.substring(pos + le);
ssid->trim();
pass->trim();
#ifdef SERIAL_VERBOSE
Serial.println("----- file content -----");
Serial.println(content);
Serial.println("----- file content -----");
Serial.println("ssid: " + *ssid);
Serial.println("psk: " + *pass);
#endif
return true;
} // loadConfig
/**
@brief Save WiFi SSID and PSK to configuration file.
@param ssid SSID as string pointer.
@param pass PSK as string pointer,
@return True or False.
*/
bool saveConfig(String *ssid, String *pass) {
// Open config file for writing.
File configFile = LittleFS.open("/cl_conf.txt", "w");
if (!configFile) {
Serial.println("Failed to open cl_conf.txt for writing");
return false;
}
// Save SSID and PSK.
configFile.println(*ssid);
configFile.println(*pass);
configFile.close();
return true;
} // saveConfig
/**
@brief Arduino setup function.
*/
void setup() {
String station_ssid = "";
String station_psk = "";
Serial.begin(115200);
delay(100);
Serial.println("\r\n");
Serial.print("Chip ID: 0x");
Serial.println(ESP.getChipId(), HEX);
// Set Hostname.
String hostname(HOSTNAME);
hostname += String(ESP.getChipId(), HEX);
WiFi.hostname(hostname);
// Print hostname.
Serial.println("Hostname: " + hostname);
//Serial.println(WiFi.hostname());
// Initialize file system.
if (!LittleFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
// Load wifi connection information.
if (! loadConfig(&station_ssid, &station_psk)) {
station_ssid = STASSID;
station_psk = STAPSK;
Serial.println("No WiFi connection information available.");
}
// Check WiFi connection
// ... check mode
if (WiFi.getMode() != WIFI_STA) {
WiFi.mode(WIFI_STA);
delay(10);
}
// ... Compare file config with sdk config.
if (WiFi.SSID() != station_ssid || WiFi.psk() != station_psk) {
Serial.println("WiFi config changed.");
// ... Try to connect to WiFi station.
WiFi.begin(station_ssid.c_str(), station_psk.c_str());
// ... Pritn new SSID
Serial.print("new SSID: ");
Serial.println(WiFi.SSID());
// ... Uncomment this for debugging output.
//WiFi.printDiag(Serial);
} else {
// ... Begin with sdk config.
WiFi.begin();
}
Serial.println("Wait for WiFi connection.");
// ... Give ESP 10 seconds to connect to station.
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) {
Serial.write('.');
//Serial.print(WiFi.status());
delay(500);
}
Serial.println();
// Check connection
if (WiFi.status() == WL_CONNECTED) {
// ... print IP Address
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("Can not connect to WiFi station. Go into AP mode.");
// Go into software AP mode.
WiFi.mode(WIFI_AP);
delay(10);
WiFi.softAP(ap_default_ssid, ap_default_psk);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
}
// Start OTA server.
ArduinoOTA.setHostname((const char *)hostname.c_str());
ArduinoOTA.begin();
}
/**
@brief Arduino loop function.
*/
void loop() {
// Handle OTA server.
ArduinoOTA.handle();
}

View File

@ -0,0 +1,2 @@
YOUR_SSID
YOUR_PSK

View File

@ -0,0 +1,80 @@
/*
ESP8266 mDNS-SD responder and query sample
This is an example of announcing and finding services.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to two ESP8266 boards
- The last one powered on should now find the other.
*/
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
char hostString[16] = {0};
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("\r\nsetup()");
sprintf(hostString, "ESP_%06X", ESP.getChipId());
Serial.print("Hostname: ");
Serial.println(hostString);
WiFi.hostname(hostString);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (!MDNS.begin(hostString)) {
Serial.println("Error setting up MDNS responder!");
}
Serial.println("mDNS responder started");
MDNS.addService("esp", "tcp", 8080); // Announce esp tcp service on port 8080
Serial.println("Sending mDNS query");
int n = MDNS.queryService("esp", "tcp"); // Send out query for esp tcp services
Serial.println("mDNS query done");
if (n == 0) {
Serial.println("no services found");
} else {
Serial.print(n);
Serial.println(" service(s) found");
for (int i = 0; i < n; ++i) {
// Print details for each service found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i));
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
}
}
Serial.println();
Serial.println("loop() next");
}
void loop() {
// put your main code here, to run repeatedly:
MDNS.update();
}

View File

@ -0,0 +1,124 @@
/*
ESP8266 mDNS responder sample
This is an example of an HTTP server that is accessible
via http://esp8266.local URL thanks to mDNS responder.
Instructions:
- Update WiFi SSID and password as necessary.
- Flash the sketch to the ESP8266 board
- Install host software:
- For Linux, install Avahi (http://avahi.org/).
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
- For Mac OSX and iOS support is built in through Bonjour already.
- Point your browser to http://esp8266.local, you should see a response.
*/
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
// TCP server at port 80 will respond to HTTP requests
WiFiServer server(80);
void setup(void) {
Serial.begin(115200);
// Connect to WiFi network
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Set up mDNS responder:
// - first argument is the domain name, in this example
// the fully-qualified domain name is "esp8266.local"
// - second argument is the IP address to advertise
// we send our IP address on the WiFi network
if (!MDNS.begin("esp8266")) {
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
// Start TCP (HTTP) server
server.begin();
Serial.println("TCP server started");
// Add service to MDNS-SD
MDNS.addService("http", "tcp", 80);
}
void loop(void) {
MDNS.update();
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
Serial.println("");
Serial.println("New client");
// Wait for data from client to become available
while (client.connected() && !client.available()) {
delay(1);
}
// Read the first line of HTTP request
String req = client.readStringUntil('\r');
// First line of HTTP request looks like "GET /path HTTP/1.1"
// Retrieve the "/path" part by finding the spaces
int addr_start = req.indexOf(' ');
int addr_end = req.indexOf(' ', addr_start + 1);
if (addr_start == -1 || addr_end == -1) {
Serial.print("Invalid request: ");
Serial.println(req);
return;
}
req = req.substring(addr_start + 1, addr_end);
Serial.print("Request: ");
Serial.println(req);
client.flush();
String s;
if (req == "/") {
IPAddress ip = WiFi.localIP();
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
s += ipStr;
s += "</html>\r\n\r\n";
Serial.println("Sending 200");
} else {
s = "HTTP/1.1 404 Not Found\r\n\r\n";
Serial.println("Sending 404");
}
client.print(s);
Serial.println("Done with client");
}

View File

@ -0,0 +1,25 @@
#######################################
# Syntax Coloring Map For Ultrasound
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
ESP8266mDNS KEYWORD1
MDNSResponder KEYWORD1
MDNS KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
update KEYWORD2
addService KEYWORD2
enableArduino KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,10 @@
name=ESP8266mDNS
version=1.2
author=multiple, see files
maintainer=LaborEtArs
sentence=Creates a mDNS responder.
paragraph=Creates a mDNS responder to ensure host domain uniqueness in local networks and to allow for mDNS service discovery and announcment.
category=Communication
url=https://github.com/LaborEtArs/ESP8266mDNS
architectures=esp8266
dot_a_linkage=true

View File

@ -0,0 +1,33 @@
/*
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <ESP8266mDNS.h>
/*
MDNS responder global instance
Class type that is instantiated depends on the type mapping in ESP8266mDNS.h
*/
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS)
MDNSResponder MDNS;
#endif

View File

@ -0,0 +1,64 @@
/*
ESP8266mDNS.h - mDNSResponder for ESP8266 family
This file is part of the esp8266 core for Arduino environment.
Legacy_ESP8266mDNS:
The well known, thouroughly tested (yet no flawless) default mDNS library for the ESP8266 family
LEA_ESP8266mDNS:
An (currently) experimental mDNS implementation, that supports a lot more of mDNS features than Legacy_ESP8266mDNS, like:
- Presenting a DNS-SD service to interested observers, eg. a http server by presenting _http._tcp service
- Support for multi-level compressed names in input; in output only a very simple one-leven full-name compression is implemented
- Probing host and service domains for uniqueness in the local network
- Tiebreaking while probing is supported in a very minimalistic way (the 'higher' IP address wins the tiebreak)
- Announcing available services after successful probing
- Using fixed service TXT items or
- Using dynamic service TXT items for presented services (via callback)
- Remove services (and un-announcing them to the observers by sending goodbye-messages)
- Static queries for DNS-SD services (creating a fixed answer set after a certain timeout period)
- Dynamic queries for DNS-SD services with cached and updated answers and user notifications
- Support for multi-homed client host domains
See 'LEA_ESP8266mDNS/EPS8266mDNS.h' for more implementation details and usage informations.
See 'examples/mDNS_Clock' and 'examples/mDNS_ServiceMonitor' for implementation examples of the advanced features.
LEA_ESP8266mDNS is (mostly) client source code compatible to 'Legacy_ESP8266mDNS', so it could be
use as a 'drop-in' replacement in existing projects.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ESP8266MDNS_H
#define __ESP8266MDNS_H
enum class MDNSApiVersion { LEA, LEAv2 };
#include "LEAmDNS.h" // LEA
#include "LEAmDNS2Host.h" // LEAv2 - API updated
// clsLEAMDNSHost replaces MDNSResponder in LEAv2
using clsLEAMDNSHost = esp8266::experimental::clsLEAMDNSHost;
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS)
// Maps the implementation to use to the global namespace type
using MDNSResponder = esp8266::MDNSImplementation::MDNSResponder; // LEA
//using MDNSResponder = clsLEAMDNSHost; // LEAv2
extern MDNSResponder MDNS;
#endif
#endif // __ESP8266MDNS_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
/*
LEAmDNS2Host_Debug.h
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ESP8266mDNS.h"
#include "LEAmDNS2Host.h"
#include "LEAmDNS2_Priv.h"
namespace esp8266
{
namespace experimental
{
#ifdef DEBUG_ESP_PORT
/*
clsLEAmDNS2_Host::_DH
*/
const char* clsLEAMDNSHost::_DH(const clsLEAMDNSHost::clsService* p_pService /*= 0*/) const
{
static char acBuffer[16 + 64];
*acBuffer = 0;
sprintf_P(acBuffer, PSTR("[mDNS]"));
if (p_pService)
{
strcat_P(acBuffer, PSTR(">"));
strcat(acBuffer, _service2String(p_pService));
}
return acBuffer;
}
/*
clsLEAmDNS2_Host::_service2String
*/
const char* clsLEAMDNSHost::_service2String(const clsLEAMDNSHost::clsService* p_pService) const
{
static char acBuffer[64];
*acBuffer = 0;
if (p_pService)
{
sprintf_P(acBuffer, PSTR("%s.%s%s.%s%s.local"),
(p_pService->m_pcInstanceName ? : "-"),
(p_pService->m_pcType ? ('_' == *(p_pService->m_pcType) ? "" : "_") : "-"),
(p_pService->m_pcType ? : "-"),
(p_pService->m_pcProtocol ? ('_' == *(p_pService->m_pcProtocol) ? "" : "_") : "-"),
(p_pService->m_pcProtocol ? : "-"));
}
return acBuffer;
}
/*
clsLEAmDNS2_Host::_printRRDomain
*/
bool clsLEAMDNSHost::_printRRDomain(const clsLEAMDNSHost::clsRRDomain& p_RRDomain) const
{
//DEBUG_OUTPUT.printf_P(PSTR("Domain: "));
const char* pCursor = p_RRDomain.m_acName;
uint8_t u8Length = *pCursor++;
if (u8Length)
{
while (u8Length)
{
for (uint8_t u = 0; u < u8Length; ++u)
{
DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++));
}
u8Length = *pCursor++;
if (u8Length)
{
DEBUG_OUTPUT.printf_P(PSTR("."));
}
}
}
else // empty domain
{
DEBUG_OUTPUT.printf_P(PSTR("-empty-"));
}
//DEBUG_OUTPUT.printf_P(PSTR("\n"));
return true;
}
/*
clsLEAmDNS2_Host::_printRRAnswer
*/
bool clsLEAMDNSHost::_printRRAnswer(const clsLEAMDNSHost::clsRRAnswer& p_RRAnswer) const
{
DEBUG_OUTPUT.printf_P(PSTR("%s RRAnswer: "), _DH());
_printRRDomain(p_RRAnswer.m_Header.m_Domain);
DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL);
switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag
{
#ifdef MDNS_IPV4_SUPPORT
case DNS_RRTYPE_A:
DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const clsRRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str());
break;
#endif
case DNS_RRTYPE_PTR:
DEBUG_OUTPUT.printf_P(PSTR("PTR "));
_printRRDomain(((const clsRRAnswerPTR*)&p_RRAnswer)->m_PTRDomain);
break;
case DNS_RRTYPE_TXT:
{
size_t stTxtLength = ((const clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength();
char* pTxts = new char[stTxtLength];
if (pTxts)
{
((/*const c_str()!!*/clsRRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts);
DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts);
delete[] pTxts;
}
break;
}
#ifdef MDNS2_IPV6_SUPPORT
case DNS_RRTYPE_AAAA:
DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((clsRRAnswerAAAA*&)p_RRAnswer)->m_IPAddress.toString().c_str());
break;
#endif
case DNS_RRTYPE_SRV:
DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const clsRRAnswerSRV*)&p_RRAnswer)->m_u16Port);
_printRRDomain(((const clsRRAnswerSRV*)&p_RRAnswer)->m_SRVDomain);
break;
default:
DEBUG_OUTPUT.printf_P(PSTR("generic "));
break;
}
DEBUG_OUTPUT.printf_P(PSTR("\n"));
return true;
}
/*
clsLEAmDNS2_Host::_RRType2Name
*/
const char* clsLEAMDNSHost::_RRType2Name(uint16_t p_u16RRType) const
{
static char acRRName[16];
*acRRName = 0;
switch (p_u16RRType & (~0x8000)) // Topmost bit might carry 'cache flush' flag
{
#ifdef MDNS_IPV4_SUPPORT
case DNS_RRTYPE_A: strcpy_P(acRRName, PSTR("A")); break;
#endif
case DNS_RRTYPE_PTR: strcpy_P(acRRName, PSTR("PTR")); break;
case DNS_RRTYPE_TXT: strcpy_P(acRRName, PSTR("TXT")); break;
#ifdef MDNS2_IPV6_SUPPORT
case DNS_RRTYPE_AAAA: strcpy_P(acRRName, PSTR("AAAA")); break;
#endif
case DNS_RRTYPE_SRV: strcpy_P(acRRName, PSTR("SRV")); break;
case clsConsts::u8DNS_RRTYPE_NSEC: strcpy_P(acRRName, PSTR("NSEC")); break;
case DNS_RRTYPE_ANY: strcpy_P(acRRName, PSTR("ANY")); break;
default: sprintf_P(acRRName, PSTR("Unknown(0x%04X"), p_u16RRType); // MAX 15!
}
return acRRName;
}
/*
clsLEAmDNS2_Host::_RRClass2String
*/
const char* clsLEAMDNSHost::_RRClass2String(uint16_t p_u16RRClass,
bool p_bIsQuery) const
{
static char acClassString[16];
*acClassString = 0;
if (p_u16RRClass & 0x0001)
{
strcat_P(acClassString, PSTR("IN ")); // 3
}
if (p_u16RRClass & 0x8000)
{
strcat_P(acClassString, (p_bIsQuery ? PSTR("UNICAST ") : PSTR("FLUSH "))); // 8/6
}
return acClassString; // 11
}
/*
clsLEAmDNS2_Host::_replyFlags2String
*/
const char* clsLEAMDNSHost::_replyFlags2String(uint32_t p_u32ReplyFlags) const
{
static char acFlagsString[64];
*acFlagsString = 0;
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::A))
{
strcat_P(acFlagsString, PSTR("A ")); // 2
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv4))
{
strcat_P(acFlagsString, PSTR("PTR_IPv4 ")); // 7
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_IPv6))
{
strcat_P(acFlagsString, PSTR("PTR_IPv6 ")); // 7
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::AAAA))
{
strcat_P(acFlagsString, PSTR("AAAA ")); // 5
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_TYPE))
{
strcat_P(acFlagsString, PSTR("PTR_TYPE ")); // 9
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::PTR_NAME))
{
strcat_P(acFlagsString, PSTR("PTR_NAME ")); // 9
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::TXT))
{
strcat_P(acFlagsString, PSTR("TXT ")); // 4
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::SRV))
{
strcat_P(acFlagsString, PSTR("SRV ")); // 4
}
if (p_u32ReplyFlags & static_cast<uint32_t>(enuContentFlag::NSEC))
{
strcat_P(acFlagsString, PSTR("NSEC ")); // 5
}
if (0 == p_u32ReplyFlags)
{
strcpy_P(acFlagsString, PSTR("none"));
}
// Remove trailing spaces
while ((*acFlagsString) &&
(' ' == acFlagsString[strlen(acFlagsString) - 1]))
{
acFlagsString[strlen(acFlagsString) - 1] = 0;
}
return acFlagsString; // 63
}
/*
clsLEAmDNS2_Host::_NSECBitmap2String
*/
const char* clsLEAMDNSHost::_NSECBitmap2String(const clsNSECBitmap* p_pNSECBitmap) const
{
static char acFlagsString[32];
*acFlagsString = 0;
#ifdef MDNS_IPV4_SUPPORT
if (p_pNSECBitmap->getBit(DNS_RRTYPE_A))
{
strcat_P(acFlagsString, PSTR("A ")); // 2
}
#endif
if (p_pNSECBitmap->getBit(DNS_RRTYPE_PTR))
{
strcat_P(acFlagsString, PSTR("PTR ")); // 4
}
#ifdef MDNS2_IPV6_SUPPORT
if (p_pNSECBitmap->getBit(DNS_RRTYPE_AAAA))
{
strcat_P(acFlagsString, PSTR("AAAA ")); // 5
}
#endif
if (p_pNSECBitmap->getBit(DNS_RRTYPE_TXT))
{
strcat_P(acFlagsString, PSTR("TXT ")); // 4
}
if (p_pNSECBitmap->getBit(DNS_RRTYPE_SRV))
{
strcat_P(acFlagsString, PSTR("SRV ")); // 4
}
if (p_pNSECBitmap->getBit(clsConsts::u8DNS_RRTYPE_NSEC))
{
strcat_P(acFlagsString, PSTR("NSEC ")); // 5
}
if (!*acFlagsString)
{
strcpy_P(acFlagsString, PSTR("none"));
}
return acFlagsString; // 31
}
#endif // DEBUG_ESP_PORT
} // namespace MDNSImplementation
} // namespace esp8266

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,262 @@
/*
LEAmDNS2_Backbone.cpp
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "ESP8266mDNS.h"
#include "LEAmDNS2Host.h"
#include "LEAmDNS2_Priv.h"
namespace esp8266
{
namespace experimental
{
/*
clsLEAmDNS2_Host::clsBackbone::clsBackbone constructor
*/
clsLEAMDNSHost::clsBackbone::clsBackbone(void)
: m_pUDPContext(0),
m_bDelayUDPProcessing(false),
m_u32DelayedDatagrams(0),
m_uniqueHost(0)
{
}
/*
clsLEAmDNS2_Host::clsBackbone::clsBackbone destructor
*/
clsLEAMDNSHost::clsBackbone::~clsBackbone(void)
{
_releaseUDPContext();
}
/*
clsLEAmDNS2_Host::clsBackbone::init
*/
bool clsLEAMDNSHost::clsBackbone::init(void)
{
return _allocUDPContext();
}
/*
clsLEAmDNS2_Host::clsBackbone::addHost
*/
UdpContext* clsLEAMDNSHost::clsBackbone::addHost(clsLEAMDNSHost* p_pHost)
{
UdpContext* pUDPContext = nullptr;
if ((m_pUDPContext) && (p_pHost) && (m_uniqueHost == nullptr))
{
m_uniqueHost = p_pHost;
pUDPContext = m_pUDPContext;
}
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s addHost: %s to add host!\n"), _DH(), (pUDPContext ? "Succeeded" : "FAILED")););
return pUDPContext;
}
/*
clsLEAmDNS2_Host::clsBackbone::removeHost
*/
bool clsLEAMDNSHost::clsBackbone::removeHost(clsLEAMDNSHost* p_pHost)
{
bool bResult = false;
if ((p_pHost) && (m_uniqueHost == p_pHost))
{
m_uniqueHost = nullptr;
bResult = true;
}
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s removeHost: %s to remove host!\n"), _DH(), (bResult ? "Succeeded" : "FAILED")););
return bResult;
}
/*
clsLEAmDNS2_Host::clsBackbone::hostCount
*/
size_t clsLEAMDNSHost::clsBackbone::hostCount(void) const
{
return m_uniqueHost == nullptr ? 0 : 1;
}
/*
clsLEAMDNSHost::clsBackbone::::setDelayUDPProcessing
When executing _sendMessage, with multiple or larger messages, sometimes the ESP IP stack seems
to need a small delay to get the job done. To allow for this delay, a 'delay' was added after one
send operation. However, while 'taking' this delay, sometimes a UDP datagram is received and
processed (which might cause another send operation or change global states).
To avoid 're-entry-like' problems, UDP processing might be blocked for a short period of time.
*/
bool clsLEAMDNSHost::clsBackbone::setDelayUDPProcessing(bool p_bDelayUDPProcessing)
{
if (m_bDelayUDPProcessing != p_bDelayUDPProcessing)
{
m_bDelayUDPProcessing = p_bDelayUDPProcessing;
if ((!m_bDelayUDPProcessing) &&
(m_u32DelayedDatagrams))
{
DEBUG_EX_INFO2(if (6 <= m_u32DelayedDatagrams) DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams););
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s setDelayUDPProcessing: Processing %u delayed datagram(s)\n"), _DH(), m_u32DelayedDatagrams););
_processUDPInput();
}
m_u32DelayedDatagrams = 0;
}
return true;
}
/*
clsLEAmDNS2_Host::clsBackbone::_allocUDPContext
*/
bool clsLEAMDNSHost::clsBackbone::_allocUDPContext(void)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext\n"), _DH()););
if (_releaseUDPContext())
{
m_pUDPContext = new UdpContext;
if (m_pUDPContext)
{
m_pUDPContext->ref();
//ip_set_option(m_pUDPContext->pcb(), SOF_REUSEADDR);
//udp_bind_netif(m_pUDPContext->pcb(), m_pNetIf);
if (m_pUDPContext->listen(IP_ANY_TYPE, DNS_MQUERY_PORT))
{
// This is NOT the TTL (Time-To-Live) for MDNS records, but the subnet level distance MDNS records should travel.
// 1 sets the subnet distance to 'local', which is default for MDNS.
// (Btw.: 255 would set it to 'as far as possible' -> internet), however, RFC 3171 seems to force 255 instead
const uint8_t c_u8MulticastTTL = 255;//1;//255;
m_pUDPContext->setMulticastTTL(c_u8MulticastTTL);
m_pUDPContext->onRx(std::bind(&clsLEAMDNSHost::clsBackbone::_processUDPInput, this));
/* m_pUDPContext->onRx([&](void)->void
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext::onRx Received data!\n"), _DH()););
});*/
m_pUDPContext->connect(IP_ANY_TYPE, DNS_MQUERY_PORT);
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: Succeeded to alloc UDPContext!\n"), _DH()););
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to make UDPContext listening!\n"), _DH()););
_releaseUDPContext();
}
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED to alloc UDPContext!\n"), _DH()););
}
}
DEBUG_EX_ERR(if (!m_pUDPContext) DEBUG_OUTPUT.printf_P(PSTR("%s _allocUDPContext: FAILED!\n"), _DH()););
return (0 != m_pUDPContext);
}
/*
clsLEAmDNS2_Host::clsBackbone::_releaseUDPContext
*/
bool clsLEAMDNSHost::clsBackbone::_releaseUDPContext(void)
{
if (m_pUDPContext)
{
m_pUDPContext->unref();
m_pUDPContext = nullptr;
}
return true;
}
/*
clsLEAmDNS2_Host::clsBackbone::_processUDPInput
Called in SYS context!
*/
bool clsLEAMDNSHost::clsBackbone::_processUDPInput(void)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput\n"), _DH()););
bool bResult = true;
if (!m_bDelayUDPProcessing)
{
while ((m_pUDPContext) &&
(m_pUDPContext->next()))
{
clsLEAMDNSHost* pHost = _findHost();
bResult = pHost->_processUDPInput();
DEBUG_EX_INFO2_IF(!bResult,
DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: FAILED to process UDP input!\n"), _DH()));
DEBUG_EX_ERR_IF((-1) != m_pUDPContext->peek(),
DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: !!!! CONTENT LEFT IN UDP BUFFER !!!!\n"),
_DH()));
m_pUDPContext->flush();
}
}
else
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("%s _processUDPInput: Delaying datagram!\n"), _DH()););
++m_u32DelayedDatagrams;
}
return bResult;
}
/*
MISC
*/
#if not defined ESP_8266_MDNS_INCLUDE || defined DEBUG_ESP_PORT
/*
clsLEAmDNS2_Host::clsBackbone::_DH
*/
const char* clsLEAMDNSHost::clsBackbone::_DH(void) const
{
static char acBuffer[20] = { 0, };
if (!acBuffer[0])
{
strcpy_P(acBuffer, PSTR("[mDNS::backbone]"));
}
return acBuffer;
}
#endif
} // namespace MDNSImplementation
} // namespace esp8266

View File

@ -0,0 +1,115 @@
/*
LEAmDNS_Priv.h
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef MDNS2_PRIV_H
#define MDNS2_PRIV_H
/*
LWIP_OPEN_SRC
*/
#ifndef LWIP_OPEN_SRC
#define LWIP_OPEN_SRC
#endif
/*
Enable class debug functions
*/
#define ESP_8266_MDNS_INCLUDE
//#define DEBUG_ESP_MDNS_RESPONDER // force debug, arduino IDE uses DEBUG_ESP_MDNS
/*
Enable/disable debug trace macros
*/
#if defined(DEBUG_ESP_PORT)
#define DEBUG_ESP_MDNS_ERR
#endif
#if defined(DEBUG_ESP_PORT) && (defined(DEBUG_ESP_MDNS) || defined(DEBUG_ESP_MDNS_RESPONDER))
#define DEBUG_ESP_MDNS_INFO
#define DEBUG_ESP_MDNS_INFO2
//#define DEBUG_ESP_MDNS_TX
//#define DEBUG_ESP_MDNS_RX
#endif
#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serialx
#endif
#ifdef DEBUG_ESP_MDNS_INFO
#define DEBUG_EX_INFO(A) A
#define DEBUG_EX_INFO_IF(C,A...) do if (C) { A; } while (0)
#else
#define DEBUG_EX_INFO(A)
#define DEBUG_EX_INFO_IF(C,A...)
#endif
#ifdef DEBUG_ESP_MDNS_INFO2
#define DEBUG_EX_INFO2(A) A
#define DEBUG_EX_INFO2_IF(C,A...) do if (C) { A; } while (0)
#else
#define DEBUG_EX_INFO2(A)
#define DEBUG_EX_INFO2_IF(C,A...)
#endif
#ifdef DEBUG_ESP_MDNS_ERR
#define DEBUG_EX_ERR(A) A
#define DEBUG_EX_ERR_IF(C,A...) do if (C) { A; } while (0)
#else
#define DEBUG_EX_ERR(A)
#define DEBUG_EX_ERR_IF(C,A...)
#endif
#ifdef DEBUG_ESP_MDNS_TX
#define DEBUG_EX_TX(A) do { A; } while (0)
#else
#define DEBUG_EX_TX(A)
#endif
#ifdef DEBUG_ESP_MDNS_RX
#define DEBUG_EX_RX(A) do { A; } while (0)
#else
#define DEBUG_EX_RX(A)
#endif
/*
Enable/disable the usage of the F() macro in debug trace printf calls.
There needs to be an PGM comptible printf function to use this.
USE_PGM_PRINTF and F
*/
#define USE_PGM_PRINTF
#ifdef USE_PGM_PRINTF
#else
#ifdef F
#undef F
#endif
#define F(A) A
#endif
#endif // MDNS2_PRIV_H

View File

@ -0,0 +1,31 @@
/*
LEAmDNS2_lwIPdefs.h
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef LEAMDNS2_LWIPDEFS_H
#define LEAMDNS2_LWIPDEFS_H
#include <lwip/init.h>
#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT
#endif // LEAMDNS2_LWIPDEFS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,808 @@
/*
LEAmDNS_Helpers.cpp
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <lwip/igmp.h>
#include <stdlib_noniso.h> // strrstr()
#include "ESP8266mDNS.h"
#include "LEAmDNS_lwIPdefs.h"
#include "LEAmDNS_Priv.h"
namespace esp8266
{
/*
LEAmDNS
*/
namespace MDNSImplementation
{
/**
HELPERS
*/
/*
MDNSResponder::indexDomain (static)
Updates the given domain 'p_rpcHostname' by appending a delimiter and an index number.
If the given domain already hasa numeric index (after the given delimiter), this index
incremented. If not, the delimiter and index '2' is added.
If 'p_rpcHostname' is empty (==0), the given default name 'p_pcDefaultHostname' is used,
if no default is given, 'esp8266' is used.
*/
/*static*/ bool MDNSResponder::indexDomain(char*& p_rpcDomain,
const char* p_pcDivider /*= "-"*/,
const char* p_pcDefaultDomain /*= 0*/)
{
bool bResult = false;
// Ensure a divider exists; use '-' as default
const char* pcDivider = (p_pcDivider ? : "-");
if (p_rpcDomain)
{
const char* pFoundDivider = strrstr(p_rpcDomain, pcDivider);
if (pFoundDivider) // maybe already extended
{
char* pEnd = 0;
unsigned long ulIndex = strtoul((pFoundDivider + strlen(pcDivider)), &pEnd, 10);
if ((ulIndex) &&
((pEnd - p_rpcDomain) == (ptrdiff_t)strlen(p_rpcDomain)) &&
(!*pEnd)) // Valid (old) index found
{
char acIndexBuffer[16];
sprintf(acIndexBuffer, "%lu", (++ulIndex));
size_t stLength = ((pFoundDivider - p_rpcDomain + strlen(pcDivider)) + strlen(acIndexBuffer) + 1);
char* pNewHostname = new char[stLength];
if (pNewHostname)
{
memcpy(pNewHostname, p_rpcDomain, (pFoundDivider - p_rpcDomain + strlen(pcDivider)));
pNewHostname[pFoundDivider - p_rpcDomain + strlen(pcDivider)] = 0;
strcat(pNewHostname, acIndexBuffer);
delete[] p_rpcDomain;
p_rpcDomain = pNewHostname;
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!")););
}
}
else
{
pFoundDivider = 0; // Flag the need to (base) extend the hostname
}
}
if (!pFoundDivider) // not yet extended (or failed to increment extension) -> start indexing
{
size_t stLength = strlen(p_rpcDomain) + (strlen(pcDivider) + 1 + 1); // Name + Divider + '2' + '\0'
char* pNewHostname = new char[stLength];
if (pNewHostname)
{
sprintf(pNewHostname, "%s%s2", p_rpcDomain, pcDivider);
delete[] p_rpcDomain;
p_rpcDomain = pNewHostname;
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!")););
}
}
}
else
{
// No given host domain, use base or default
const char* cpcDefaultName = (p_pcDefaultDomain ? : "esp8266");
size_t stLength = strlen(cpcDefaultName) + 1; // '\0'
p_rpcDomain = new char[stLength];
if (p_rpcDomain)
{
strncpy(p_rpcDomain, cpcDefaultName, stLength);
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.println(F("[MDNSResponder] indexDomain: FAILED to alloc new hostname!")););
}
}
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] indexDomain: %s\n"), p_rpcDomain););
return bResult;
}
/*
UDP CONTEXT
*/
bool MDNSResponder::_callProcess(void)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.printf("[MDNSResponder] _callProcess (%lu, triggered by: %s)\n", millis(), IPAddress(m_pUDPContext->getRemoteAddress()).toString().c_str()););
return _process(false);
}
/*
MDNSResponder::_allocUDPContext
(Re-)Creates the one-and-only UDP context for the MDNS responder.
The context is added to the 'multicast'-group and listens to the MDNS port (5353).
The travel-distance for multicast messages is set to 1 (local, via MDNS_MULTICAST_TTL).
Messages are received via the MDNSResponder '_update' function. CAUTION: This function
is called from the WiFi stack side of the ESP stack system.
*/
bool MDNSResponder::_allocUDPContext(void)
{
DEBUG_EX_INFO(DEBUG_OUTPUT.println("[MDNSResponder] _allocUDPContext"););
bool bResult = false;
_releaseUDPContext();
#ifdef MDNS_IP4_SUPPORT
ip_addr_t multicast_addr = DNS_MQUERY_IPV4_GROUP_INIT;
#endif
#ifdef MDNS_IP6_SUPPORT
//TODO: set multicast address (lwip_joingroup() is IPv4 only at the time of writing)
multicast_addr.addr = DNS_MQUERY_IPV6_GROUP_INIT;
#endif
if (ERR_OK == igmp_joingroup(ip_2_ip4(&m_netif->ip_addr), ip_2_ip4(&multicast_addr)))
{
m_pUDPContext = new UdpContext;
m_pUDPContext->ref();
if (m_pUDPContext->listen(IP4_ADDR_ANY, DNS_MQUERY_PORT))
{
m_pUDPContext->setMulticastTTL(MDNS_MULTICAST_TTL);
m_pUDPContext->onRx(std::bind(&MDNSResponder::_callProcess, this));
bResult = m_pUDPContext->connect(&multicast_addr, DNS_MQUERY_PORT);
}
}
return bResult;
}
/*
MDNSResponder::_releaseUDPContext
*/
bool MDNSResponder::_releaseUDPContext(void)
{
if (m_pUDPContext)
{
m_pUDPContext->unref();
m_pUDPContext = 0;
}
return true;
}
/*
SERVICE QUERY
*/
/*
MDNSResponder::_allocServiceQuery
*/
MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_allocServiceQuery(void)
{
stcMDNSServiceQuery* pServiceQuery = new stcMDNSServiceQuery;
if (pServiceQuery)
{
// Link to query list
pServiceQuery->m_pNext = m_pServiceQueries;
m_pServiceQueries = pServiceQuery;
}
return m_pServiceQueries;
}
/*
MDNSResponder::_removeServiceQuery
*/
bool MDNSResponder::_removeServiceQuery(MDNSResponder::stcMDNSServiceQuery* p_pServiceQuery)
{
bool bResult = false;
if (p_pServiceQuery)
{
stcMDNSServiceQuery* pPred = m_pServiceQueries;
while ((pPred) &&
(pPred->m_pNext != p_pServiceQuery))
{
pPred = pPred->m_pNext;
}
if (pPred)
{
pPred->m_pNext = p_pServiceQuery->m_pNext;
delete p_pServiceQuery;
bResult = true;
}
else // No predecesor
{
if (m_pServiceQueries == p_pServiceQuery)
{
m_pServiceQueries = p_pServiceQuery->m_pNext;
delete p_pServiceQuery;
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseServiceQuery: INVALID service query!"););
}
}
}
return bResult;
}
/*
MDNSResponder::_removeLegacyServiceQuery
*/
bool MDNSResponder::_removeLegacyServiceQuery(void)
{
stcMDNSServiceQuery* pLegacyServiceQuery = _findLegacyServiceQuery();
return (pLegacyServiceQuery ? _removeServiceQuery(pLegacyServiceQuery) : true);
}
/*
MDNSResponder::_findServiceQuery
'Convert' hMDNSServiceQuery to stcMDNSServiceQuery* (ensure existance)
*/
MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findServiceQuery(MDNSResponder::hMDNSServiceQuery p_hServiceQuery)
{
stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries;
while (pServiceQuery)
{
if ((hMDNSServiceQuery)pServiceQuery == p_hServiceQuery)
{
break;
}
pServiceQuery = pServiceQuery->m_pNext;
}
return pServiceQuery;
}
/*
MDNSResponder::_findLegacyServiceQuery
*/
MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findLegacyServiceQuery(void)
{
stcMDNSServiceQuery* pServiceQuery = m_pServiceQueries;
while (pServiceQuery)
{
if (pServiceQuery->m_bLegacyQuery)
{
break;
}
pServiceQuery = pServiceQuery->m_pNext;
}
return pServiceQuery;
}
/*
MDNSResponder::_releaseServiceQueries
*/
bool MDNSResponder::_releaseServiceQueries(void)
{
while (m_pServiceQueries)
{
stcMDNSServiceQuery* pNext = m_pServiceQueries->m_pNext;
delete m_pServiceQueries;
m_pServiceQueries = pNext;
}
return true;
}
/*
MDNSResponder::_findNextServiceQueryByServiceType
*/
MDNSResponder::stcMDNSServiceQuery* MDNSResponder::_findNextServiceQueryByServiceType(const stcMDNS_RRDomain& p_ServiceTypeDomain,
const stcMDNSServiceQuery* p_pPrevServiceQuery)
{
stcMDNSServiceQuery* pMatchingServiceQuery = 0;
stcMDNSServiceQuery* pServiceQuery = (p_pPrevServiceQuery ? p_pPrevServiceQuery->m_pNext : m_pServiceQueries);
while (pServiceQuery)
{
if (p_ServiceTypeDomain == pServiceQuery->m_ServiceTypeDomain)
{
pMatchingServiceQuery = pServiceQuery;
break;
}
pServiceQuery = pServiceQuery->m_pNext;
}
return pMatchingServiceQuery;
}
/*
HOSTNAME
*/
/*
MDNSResponder::_setHostname
*/
bool MDNSResponder::_setHostname(const char* p_pcHostname)
{
//DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _allocHostname (%s)\n"), p_pcHostname););
bool bResult = false;
_releaseHostname();
size_t stLength = 0;
if ((p_pcHostname) &&
(MDNS_DOMAIN_LABEL_MAXLENGTH >= (stLength = strlen(p_pcHostname)))) // char max size for a single label
{
// Copy in hostname characters as lowercase
if ((bResult = (0 != (m_pcHostname = new char[stLength + 1]))))
{
#ifdef MDNS_FORCE_LOWERCASE_HOSTNAME
size_t i = 0;
for (; i < stLength; ++i)
{
m_pcHostname[i] = (isupper(p_pcHostname[i]) ? tolower(p_pcHostname[i]) : p_pcHostname[i]);
}
m_pcHostname[i] = 0;
#else
strncpy(m_pcHostname, p_pcHostname, (stLength + 1));
#endif
}
}
return bResult;
}
/*
MDNSResponder::_releaseHostname
*/
bool MDNSResponder::_releaseHostname(void)
{
if (m_pcHostname)
{
delete[] m_pcHostname;
m_pcHostname = 0;
}
return true;
}
/*
SERVICE
*/
/*
MDNSResponder::_allocService
*/
MDNSResponder::stcMDNSService* MDNSResponder::_allocService(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol,
uint16_t p_u16Port)
{
stcMDNSService* pService = 0;
if (((!p_pcName) ||
(MDNS_DOMAIN_LABEL_MAXLENGTH >= strlen(p_pcName))) &&
(p_pcService) &&
(MDNS_SERVICE_NAME_LENGTH >= strlen(p_pcService)) &&
(p_pcProtocol) &&
(MDNS_SERVICE_PROTOCOL_LENGTH >= strlen(p_pcProtocol)) &&
(p_u16Port) &&
(0 != (pService = new stcMDNSService)) &&
(pService->setName(p_pcName ? : m_pcHostname)) &&
(pService->setService(p_pcService)) &&
(pService->setProtocol(p_pcProtocol)))
{
pService->m_bAutoName = (0 == p_pcName);
pService->m_u16Port = p_u16Port;
// Add to list (or start list)
pService->m_pNext = m_pServices;
m_pServices = pService;
}
return pService;
}
/*
MDNSResponder::_releaseService
*/
bool MDNSResponder::_releaseService(MDNSResponder::stcMDNSService* p_pService)
{
bool bResult = false;
if (p_pService)
{
stcMDNSService* pPred = m_pServices;
while ((pPred) &&
(pPred->m_pNext != p_pService))
{
pPred = pPred->m_pNext;
}
if (pPred)
{
pPred->m_pNext = p_pService->m_pNext;
delete p_pService;
bResult = true;
}
else // No predecesor
{
if (m_pServices == p_pService)
{
m_pServices = p_pService->m_pNext;
delete p_pService;
bResult = true;
}
else
{
DEBUG_EX_ERR(DEBUG_OUTPUT.println("[MDNSResponder] _releaseService: INVALID service!"););
}
}
}
return bResult;
}
/*
MDNSResponder::_releaseServices
*/
bool MDNSResponder::_releaseServices(void)
{
stcMDNSService* pService = m_pServices;
while (pService)
{
_releaseService(pService);
pService = m_pServices;
}
return true;
}
/*
MDNSResponder::_findService
*/
MDNSResponder::stcMDNSService* MDNSResponder::_findService(const char* p_pcName,
const char* p_pcService,
const char* p_pcProtocol)
{
stcMDNSService* pService = m_pServices;
while (pService)
{
if ((0 == strcmp(pService->m_pcName, p_pcName)) &&
(0 == strcmp(pService->m_pcService, p_pcService)) &&
(0 == strcmp(pService->m_pcProtocol, p_pcProtocol)))
{
break;
}
pService = pService->m_pNext;
}
return pService;
}
/*
MDNSResponder::_findService
*/
MDNSResponder::stcMDNSService* MDNSResponder::_findService(const MDNSResponder::hMDNSService p_hService)
{
stcMDNSService* pService = m_pServices;
while (pService)
{
if (p_hService == (hMDNSService)pService)
{
break;
}
pService = pService->m_pNext;
}
return pService;
}
/*
SERVICE TXT
*/
/*
MDNSResponder::_allocServiceTxt
*/
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_allocServiceTxt(MDNSResponder::stcMDNSService* p_pService,
const char* p_pcKey,
const char* p_pcValue,
bool p_bTemp)
{
stcMDNSServiceTxt* pTxt = 0;
if ((p_pService) &&
(p_pcKey) &&
(MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() +
1 + // Length byte
(p_pcKey ? strlen(p_pcKey) : 0) +
1 + // '='
(p_pcValue ? strlen(p_pcValue) : 0))))
{
pTxt = new stcMDNSServiceTxt;
if (pTxt)
{
size_t stLength = (p_pcKey ? strlen(p_pcKey) : 0);
pTxt->m_pcKey = new char[stLength + 1];
if (pTxt->m_pcKey)
{
strncpy(pTxt->m_pcKey, p_pcKey, stLength); pTxt->m_pcKey[stLength] = 0;
}
if (p_pcValue)
{
stLength = (p_pcValue ? strlen(p_pcValue) : 0);
pTxt->m_pcValue = new char[stLength + 1];
if (pTxt->m_pcValue)
{
strncpy(pTxt->m_pcValue, p_pcValue, stLength); pTxt->m_pcValue[stLength] = 0;
}
}
pTxt->m_bTemp = p_bTemp;
// Add to list (or start list)
p_pService->m_Txts.add(pTxt);
}
}
return pTxt;
}
/*
MDNSResponder::_releaseServiceTxt
*/
bool MDNSResponder::_releaseServiceTxt(MDNSResponder::stcMDNSService* p_pService,
MDNSResponder::stcMDNSServiceTxt* p_pTxt)
{
return ((p_pService) &&
(p_pTxt) &&
(p_pService->m_Txts.remove(p_pTxt)));
}
/*
MDNSResponder::_updateServiceTxt
*/
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_updateServiceTxt(MDNSResponder::stcMDNSService* p_pService,
MDNSResponder::stcMDNSServiceTxt* p_pTxt,
const char* p_pcValue,
bool p_bTemp)
{
if ((p_pService) &&
(p_pTxt) &&
(MDNS_SERVICE_TXT_MAXLENGTH > (p_pService->m_Txts.length() -
(p_pTxt->m_pcValue ? strlen(p_pTxt->m_pcValue) : 0) +
(p_pcValue ? strlen(p_pcValue) : 0))))
{
p_pTxt->update(p_pcValue);
p_pTxt->m_bTemp = p_bTemp;
}
return p_pTxt;
}
/*
MDNSResponder::_findServiceTxt
*/
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService,
const char* p_pcKey)
{
return (p_pService ? p_pService->m_Txts.find(p_pcKey) : 0);
}
/*
MDNSResponder::_findServiceTxt
*/
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_findServiceTxt(MDNSResponder::stcMDNSService* p_pService,
const hMDNSTxt p_hTxt)
{
return (((p_pService) && (p_hTxt)) ? p_pService->m_Txts.find((stcMDNSServiceTxt*)p_hTxt) : 0);
}
/*
MDNSResponder::_addServiceTxt
*/
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_addServiceTxt(MDNSResponder::stcMDNSService* p_pService,
const char* p_pcKey,
const char* p_pcValue,
bool p_bTemp)
{
stcMDNSServiceTxt* pResult = 0;
if ((p_pService) &&
(p_pcKey) &&
(strlen(p_pcKey)))
{
stcMDNSServiceTxt* pTxt = p_pService->m_Txts.find(p_pcKey);
if (pTxt)
{
pResult = _updateServiceTxt(p_pService, pTxt, p_pcValue, p_bTemp);
}
else
{
pResult = _allocServiceTxt(p_pService, p_pcKey, p_pcValue, p_bTemp);
}
}
return pResult;
}
MDNSResponder::stcMDNSServiceTxt* MDNSResponder::_answerKeyValue(const hMDNSServiceQuery p_hServiceQuery,
const uint32_t p_u32AnswerIndex)
{
stcMDNSServiceQuery* pServiceQuery = _findServiceQuery(p_hServiceQuery);
stcMDNSServiceQuery::stcAnswer* pSQAnswer = (pServiceQuery ? pServiceQuery->answerAtIndex(p_u32AnswerIndex) : 0);
// Fill m_pcTxts (if not already done)
return (pSQAnswer) ? pSQAnswer->m_Txts.m_pTxts : 0;
}
/*
MDNSResponder::_collectServiceTxts
*/
bool MDNSResponder::_collectServiceTxts(MDNSResponder::stcMDNSService& p_rService)
{
// Call Dynamic service callbacks
if (m_fnServiceTxtCallback)
{
m_fnServiceTxtCallback((hMDNSService)&p_rService);
}
if (p_rService.m_fnTxtCallback)
{
p_rService.m_fnTxtCallback((hMDNSService)&p_rService);
}
return true;
}
/*
MDNSResponder::_releaseTempServiceTxts
*/
bool MDNSResponder::_releaseTempServiceTxts(MDNSResponder::stcMDNSService& p_rService)
{
return (p_rService.m_Txts.removeTempTxts());
}
/*
MISC
*/
#ifdef DEBUG_ESP_MDNS_RESPONDER
/*
MDNSResponder::_printRRDomain
*/
bool MDNSResponder::_printRRDomain(const MDNSResponder::stcMDNS_RRDomain& p_RRDomain) const
{
//DEBUG_OUTPUT.printf_P(PSTR("Domain: "));
const char* pCursor = p_RRDomain.m_acName;
uint8_t u8Length = *pCursor++;
if (u8Length)
{
while (u8Length)
{
for (uint8_t u = 0; u < u8Length; ++u)
{
DEBUG_OUTPUT.printf_P(PSTR("%c"), *(pCursor++));
}
u8Length = *pCursor++;
if (u8Length)
{
DEBUG_OUTPUT.printf_P(PSTR("."));
}
}
}
else // empty domain
{
DEBUG_OUTPUT.printf_P(PSTR("-empty-"));
}
//DEBUG_OUTPUT.printf_P(PSTR("\n"));
return true;
}
/*
MDNSResponder::_printRRAnswer
*/
bool MDNSResponder::_printRRAnswer(const MDNSResponder::stcMDNS_RRAnswer& p_RRAnswer) const
{
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] RRAnswer: "));
_printRRDomain(p_RRAnswer.m_Header.m_Domain);
DEBUG_OUTPUT.printf_P(PSTR(" Type:0x%04X Class:0x%04X TTL:%u, "), p_RRAnswer.m_Header.m_Attributes.m_u16Type, p_RRAnswer.m_Header.m_Attributes.m_u16Class, p_RRAnswer.m_u32TTL);
switch (p_RRAnswer.m_Header.m_Attributes.m_u16Type & (~0x8000)) // Topmost bit might carry 'cache flush' flag
{
#ifdef MDNS_IP4_SUPPORT
case DNS_RRTYPE_A:
DEBUG_OUTPUT.printf_P(PSTR("A IP:%s"), ((const stcMDNS_RRAnswerA*)&p_RRAnswer)->m_IPAddress.toString().c_str());
break;
#endif
case DNS_RRTYPE_PTR:
DEBUG_OUTPUT.printf_P(PSTR("PTR "));
_printRRDomain(((const stcMDNS_RRAnswerPTR*)&p_RRAnswer)->m_PTRDomain);
break;
case DNS_RRTYPE_TXT:
{
size_t stTxtLength = ((const stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_strLength();
char* pTxts = new char[stTxtLength];
if (pTxts)
{
((/*const c_str()!!*/stcMDNS_RRAnswerTXT*)&p_RRAnswer)->m_Txts.c_str(pTxts);
DEBUG_OUTPUT.printf_P(PSTR("TXT(%u) %s"), stTxtLength, pTxts);
delete[] pTxts;
}
break;
}
#ifdef MDNS_IP6_SUPPORT
case DNS_RRTYPE_AAAA:
DEBUG_OUTPUT.printf_P(PSTR("AAAA IP:%s"), ((stcMDNS_RRAnswerA*&)p_rpRRAnswer)->m_IPAddress.toString().c_str());
break;
#endif
case DNS_RRTYPE_SRV:
DEBUG_OUTPUT.printf_P(PSTR("SRV Port:%u "), ((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_u16Port);
_printRRDomain(((const stcMDNS_RRAnswerSRV*)&p_RRAnswer)->m_SRVDomain);
break;
default:
DEBUG_OUTPUT.printf_P(PSTR("generic "));
break;
}
DEBUG_OUTPUT.printf_P(PSTR("\n"));
return true;
}
#endif
} // namespace MDNSImplementation
} // namespace esp8266

View File

@ -0,0 +1,182 @@
/*
LEAmDNS_Priv.h
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef MDNS_PRIV_H
#define MDNS_PRIV_H
namespace esp8266
{
/*
LEAmDNS
*/
namespace MDNSImplementation
{
// Enable class debug functions
#define ESP_8266_MDNS_INCLUDE
//#define DEBUG_ESP_MDNS_RESPONDER
#if !defined(DEBUG_ESP_MDNS_RESPONDER) && defined(DEBUG_ESP_MDNS)
#define DEBUG_ESP_MDNS_RESPONDER
#endif
#ifndef LWIP_OPEN_SRC
#define LWIP_OPEN_SRC
#endif
//
// If ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE is defined, the mDNS responder ignores a successful probing
// This allows to drive the responder in a environment, where 'update()' isn't called in the loop
//#define ENABLE_ESP_MDNS_RESPONDER_PASSIV_MODE
// Enable/disable debug trace macros
#if defined(DEBUG_ESP_PORT) && defined(DEBUG_ESP_MDNS_RESPONDER)
#define DEBUG_ESP_MDNS_INFO
#define DEBUG_ESP_MDNS_ERR
#define DEBUG_ESP_MDNS_TX
#define DEBUG_ESP_MDNS_RX
#endif
#ifdef DEBUG_ESP_MDNS_RESPONDER
#ifdef DEBUG_ESP_MDNS_INFO
#define DEBUG_EX_INFO(A) A
#else
#define DEBUG_EX_INFO(A)
#endif
#ifdef DEBUG_ESP_MDNS_ERR
#define DEBUG_EX_ERR(A) A
#else
#define DEBUG_EX_ERR(A)
#endif
#ifdef DEBUG_ESP_MDNS_TX
#define DEBUG_EX_TX(A) A
#else
#define DEBUG_EX_TX(A)
#endif
#ifdef DEBUG_ESP_MDNS_RX
#define DEBUG_EX_RX(A) A
#else
#define DEBUG_EX_RX(A)
#endif
#ifdef DEBUG_ESP_PORT
#define DEBUG_OUTPUT DEBUG_ESP_PORT
#else
#define DEBUG_OUTPUT Serial
#endif
#else
#define DEBUG_EX_INFO(A) do { (void)0; } while (0)
#define DEBUG_EX_ERR(A) do { (void)0; } while (0)
#define DEBUG_EX_TX(A) do { (void)0; } while (0)
#define DEBUG_EX_RX(A) do { (void)0; } while (0)
#endif
/* Replaced by 'lwip/prot/dns.h' definitions
#ifdef MDNS_IP4_SUPPORT
#define MDNS_MULTICAST_ADDR_IP4 (IPAddress(224, 0, 0, 251)) // ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT
#endif
#ifdef MDNS_IP6_SUPPORT
#define MDNS_MULTICAST_ADDR_IP6 (IPAddress("FF02::FB")) // ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT
#endif*/
//#define MDNS_MULTICAST_PORT 5353
/*
This is NOT the TTL (Time-To-Live) for MDNS records, but the
subnet level distance MDNS records should travel.
1 sets the subnet distance to 'local', which is default for MDNS.
(Btw.: 255 would set it to 'as far as possible' -> internet)
However, RFC 3171 seems to force 255 instead
*/
#define MDNS_MULTICAST_TTL 255/*1*/
/*
This is the MDNS record TTL
Host level records are set to 2min (120s)
service level records are set to 75min (4500s)
*/
#define MDNS_HOST_TTL 120
#define MDNS_SERVICE_TTL 4500
/*
Compressed labels are flaged by the two topmost bits of the length byte being set
*/
#define MDNS_DOMAIN_COMPRESS_MARK 0xC0
/*
Avoid endless recursion because of malformed compressed labels
*/
#define MDNS_DOMAIN_MAX_REDIRCTION 6
/*
Default service priority and weight in SRV answers
*/
#define MDNS_SRV_PRIORITY 0
#define MDNS_SRV_WEIGHT 0
/*
Delay between and number of probes for host and service domains
Delay between and number of announces for host and service domains
Delay between and number of service queries; the delay is multiplied by the resent number in '_checkServiceQueryCache'
*/
#define MDNS_PROBE_DELAY 250
#define MDNS_PROBE_COUNT 3
#define MDNS_ANNOUNCE_DELAY 1000
#define MDNS_ANNOUNCE_COUNT 8
#define MDNS_DYNAMIC_QUERY_RESEND_COUNT 5
#define MDNS_DYNAMIC_QUERY_RESEND_DELAY 5000
/*
Force host domain to use only lowercase letters
*/
//#define MDNS_FORCE_LOWERCASE_HOSTNAME
/*
Enable/disable the usage of the F() macro in debug trace printf calls.
There needs to be an PGM comptible printf function to use this.
USE_PGM_PRINTF and F
*/
#define USE_PGM_PRINTF
#ifdef USE_PGM_PRINTF
#else
#ifdef F
#undef F
#endif
#define F(A) A
#endif
} // namespace MDNSImplementation
} // namespace esp8266
// Include the main header, so the submodlues only need to include this header
#include "LEAmDNS.h"
#endif // MDNS_PRIV_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
/*
LEAmDNS_Priv.h
License (MIT license):
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef MDNS_LWIPDEFS_H
#define MDNS_LWIPDEFS_H
#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT
#endif // MDNS_LWIPDEFS_H