mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-03 07:02:28 +03:00
Add mDNS library for esp8266
This commit is contained in:
parent
c28a63c9d5
commit
31c7b384b2
210
libraries/ESP8266mDNS/ESP8266mDNS.cpp
Normal file
210
libraries/ESP8266mDNS/ESP8266mDNS.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
|
||||
ESP8266 Multicast DNS (port of CC3000 Multicast DNS library)
|
||||
Version 1.1
|
||||
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
||||
ESP8266 port (c) 2015 Ivan Grokhotkov (igrokhotkov@gmail.com)
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// Important RFC's for reference:
|
||||
// - DNS request and response: http://www.ietf.org/rfc/rfc1035.txt
|
||||
// - Multicast DNS: http://www.ietf.org/rfc/rfc6762.txt
|
||||
|
||||
#include "ESP8266mDNS.h"
|
||||
|
||||
|
||||
// #define MDNS_DEBUG
|
||||
|
||||
#define HEADER_SIZE 12
|
||||
#define QDCOUNT_OFFSET 4
|
||||
#define A_RECORD_SIZE 14
|
||||
#define NSEC_RECORD_SIZE 20
|
||||
#define TTL_OFFSET 4
|
||||
#define IP_OFFSET 10
|
||||
|
||||
|
||||
MDNSResponder::MDNSResponder()
|
||||
: _expected(NULL)
|
||||
, _expectedLen(0)
|
||||
, _response(NULL)
|
||||
, _responseLen(0)
|
||||
, _index(0)
|
||||
{ }
|
||||
|
||||
MDNSResponder::~MDNSResponder() {
|
||||
if (_expected) {
|
||||
delete[] _expected;
|
||||
}
|
||||
if (_response) {
|
||||
delete[] _response;
|
||||
}
|
||||
}
|
||||
|
||||
bool MDNSResponder::begin(const char* domain, IPAddress addr, uint32_t ttlSeconds)
|
||||
{
|
||||
// Construct DNS request/response fully qualified domain name of form:
|
||||
// <domain length>, <domain characters>, 5, "local"
|
||||
size_t n = strlen(domain);
|
||||
if (n > 255) {
|
||||
// Can only handle domains that are 255 chars in length.
|
||||
return false;
|
||||
}
|
||||
_expectedLen = 12 + n;
|
||||
if (_expected) {
|
||||
delete[] _expected;
|
||||
}
|
||||
_expected = new uint8_t[_expectedLen];
|
||||
_expected[0] = (uint8_t)n;
|
||||
|
||||
// Copy in domain characters as lowercase
|
||||
for (int i = 0; i < n; ++i) {
|
||||
_expected[1+i] = tolower(domain[i]);
|
||||
}
|
||||
|
||||
// Values for:
|
||||
// - 5 (length)
|
||||
// - "local"
|
||||
// - 0x00 (end of domain)
|
||||
// - 0x00 0x01 (A record query)
|
||||
// - 0x00 0x01 (Class IN)
|
||||
const uint8_t local[] = { 0x05, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0x00, 0x01, 0x00, 0x01 };
|
||||
memcpy(&_expected[1+n], local, 11);
|
||||
|
||||
// Construct DNS query response
|
||||
// TODO: Move these to flash or just construct in code.
|
||||
const uint8_t respHeader[] = { 0x00, 0x00, // ID = 0
|
||||
0x84, 0x00, // Flags = response + authoritative answer
|
||||
0x00, 0x00, // Question count = 0
|
||||
0x00, 0x01, // Answer count = 1
|
||||
0x00, 0x00, // Name server records = 0
|
||||
0x00, 0x01 // Additional records = 1
|
||||
};
|
||||
// Generate positive response for IPV4 address
|
||||
const uint8_t aRecord[] = { 0x00, 0x01, // Type = 1, A record/IPV4 address
|
||||
0x80, 0x01, // Class = Internet, with cache flush bit
|
||||
0x00, 0x00, 0x00, 0x00, // TTL in seconds, to be filled in later
|
||||
0x00, 0x04, // Length of record
|
||||
0x00, 0x00, 0x00, 0x00 // IP address, to be filled in later
|
||||
};
|
||||
// Generate negative response for IPV6 address (CC3000 doesn't support IPV6)
|
||||
const uint8_t nsecRecord[] = { 0xC0, 0x0C, // Name offset
|
||||
0x00, 0x2F, // Type = 47, NSEC (overloaded by MDNS)
|
||||
0x80, 0x01, // Class = Internet, with cache flush bit
|
||||
0x00, 0x00, 0x00, 0x00, // TTL in seconds, to be filled in later
|
||||
0x00, 0x08, // Length of record
|
||||
0xC0, 0x0C, // Next domain = offset to FQDN
|
||||
0x00, // Block number = 0
|
||||
0x04, // Length of bitmap = 4 bytes
|
||||
0x40, 0x00, 0x00, 0x00 // Bitmap value = Only first bit (A record/IPV4) is set
|
||||
};
|
||||
|
||||
// Allocate memory for response.
|
||||
int queryFQDNLen = _expectedLen - 4;
|
||||
_responseLen = HEADER_SIZE + queryFQDNLen + A_RECORD_SIZE + NSEC_RECORD_SIZE;
|
||||
if (_response) {
|
||||
delete[] _response;
|
||||
}
|
||||
_response = new uint8_t[_responseLen];
|
||||
|
||||
// Copy data into response.
|
||||
memcpy(_response, respHeader, HEADER_SIZE);
|
||||
memcpy(_response + HEADER_SIZE, _expected, queryFQDNLen);
|
||||
uint8_t* records = _response + HEADER_SIZE + queryFQDNLen;
|
||||
memcpy(records, aRecord, A_RECORD_SIZE);
|
||||
memcpy(records + A_RECORD_SIZE, nsecRecord, NSEC_RECORD_SIZE);
|
||||
|
||||
// Add TTL to records.
|
||||
uint8_t ttl[4] = { (uint8_t)(ttlSeconds >> 24), (uint8_t)(ttlSeconds >> 16), (uint8_t)(ttlSeconds >> 8), (uint8_t)ttlSeconds };
|
||||
memcpy(records + TTL_OFFSET, ttl, 4);
|
||||
memcpy(records + A_RECORD_SIZE + 2 + TTL_OFFSET, ttl, 4);
|
||||
|
||||
// Add IP address to response
|
||||
|
||||
uint32_t ipAddress = (uint32_t) addr;
|
||||
|
||||
records[IP_OFFSET + 3] = (uint8_t)(ipAddress >> 24);
|
||||
records[IP_OFFSET + 2] = (uint8_t)(ipAddress >> 16);
|
||||
records[IP_OFFSET + 1] = (uint8_t)(ipAddress >> 8);
|
||||
records[IP_OFFSET + 0] = (uint8_t) ipAddress;
|
||||
|
||||
// Open the MDNS socket if it isn't already open.
|
||||
if (!_mdnsConn) {
|
||||
if (!_mdnsConn.beginMulticast(IPAddress(224, 0, 0, 251), 5353)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MDNSResponder::update() {
|
||||
if (!_mdnsConn.parsePacket())
|
||||
return;
|
||||
|
||||
// Read available data.
|
||||
int n = _mdnsConn.available();
|
||||
|
||||
_index = 0;
|
||||
|
||||
#ifdef MDNS_DEBUG
|
||||
Serial.println("{");
|
||||
#endif
|
||||
// Look for domain name in request and respond with canned response if found.
|
||||
for (int i = 0; i < n; ++i) {
|
||||
uint8_t ch = tolower(_mdnsConn.read());
|
||||
|
||||
#ifdef MDNS_DEBUG
|
||||
String str(ch, 16);
|
||||
Serial.print("0x");
|
||||
Serial.print(str);
|
||||
Serial.print(", ");
|
||||
#endif
|
||||
// Check character matches expected.
|
||||
if (ch == _expected[_index])
|
||||
{
|
||||
_index++;
|
||||
// Check if domain name was found and send a response.
|
||||
if (_index == _expectedLen) {
|
||||
// Send response to multicast address.
|
||||
#ifdef MDNS_DEBUG
|
||||
Serial.print("responding, i=");
|
||||
Serial.println(i);
|
||||
#endif
|
||||
_mdnsConn.write(_response, _responseLen);
|
||||
_mdnsConn.endPacketMulticast(IPAddress(224, 0, 0, 251), 5353);
|
||||
_index = 0;
|
||||
}
|
||||
}
|
||||
else if (ch == _expected[0]) {
|
||||
// Found a character that doesn't match, but does match the start of the domain.
|
||||
_index = 1;
|
||||
}
|
||||
else {
|
||||
// Found a character that doesn't match the expected character or start of domain.
|
||||
_index = 0;
|
||||
}
|
||||
}
|
||||
#ifdef MDNS_DEBUG
|
||||
Serial.println("}");
|
||||
#endif
|
||||
}
|
69
libraries/ESP8266mDNS/ESP8266mDNS.h
Normal file
69
libraries/ESP8266mDNS/ESP8266mDNS.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
ESP8266 Multicast DNS (port of CC3000 Multicast DNS library)
|
||||
Version 1.1
|
||||
Copyright (c) 2013 Tony DiCola (tony@tonydicola.com)
|
||||
ESP8266 port (c) 2015 Ivan Grokhotkov (igrokhotkov@gmail.com)
|
||||
|
||||
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
|
||||
|
||||
Usage:
|
||||
- Include the ESP8266 Multicast DNS library in the sketch.
|
||||
- Create an instance of the MDNSResponder class.
|
||||
- Call the 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'), and the
|
||||
Adafruit CC3000 class instance. Optionally provide a time to live (in seconds)
|
||||
for the DNS record--the default is 1 hour.
|
||||
- Call the update method in each iteration of the sketch's loop function.
|
||||
|
||||
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 ESP8266MDNS_H
|
||||
#define ESP8266MDNS_H
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiUdp.h"
|
||||
|
||||
class MDNSResponder {
|
||||
public:
|
||||
MDNSResponder();
|
||||
~MDNSResponder();
|
||||
bool begin(const char* domain, IPAddress addr, uint32_t ttlSeconds = 3600);
|
||||
void update();
|
||||
|
||||
private:
|
||||
// Expected query values
|
||||
uint8_t* _expected;
|
||||
int _expectedLen;
|
||||
// Current parsing state
|
||||
int _index;
|
||||
// Response data
|
||||
uint8_t* _response;
|
||||
int _responseLen;
|
||||
// Socket for MDNS communication
|
||||
WiFiUDP _mdnsConn;
|
||||
};
|
||||
|
||||
#endif //ESP8266MDNS_H
|
52
libraries/ESP8266mDNS/README.md
Normal file
52
libraries/ESP8266mDNS/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
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. Create an instance of the MDNSResponder class.
|
||||
4. Call the 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'), and the
|
||||
IP address to advertise. Optionally provide a time to live (in seconds)
|
||||
for the DNS record--the default is 1 hour.
|
||||
5. Call the update method in each iteration of the sketch's loop function.
|
||||
|
||||
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 (igrokhotkov@gmail.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.
|
@ -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>
|
||||
|
||||
const char* ssid = "............";
|
||||
const char* password = "..............";
|
||||
|
||||
// multicast DNS responder
|
||||
MDNSResponder mdns;
|
||||
|
||||
// TCP server at port 80 will respond to HTTP requests
|
||||
WiFiServer server(80);
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
// Connect to WiFi network
|
||||
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
|
||||
// Note: for AP mode we would use WiFi.softAPIP()!
|
||||
if (!mdns.begin("esp8266", WiFi.localIP())) {
|
||||
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");
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// Check for any mDNS queries and send responses
|
||||
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");
|
||||
}
|
||||
|
21
libraries/ESP8266mDNS/keywords.txt
Normal file
21
libraries/ESP8266mDNS/keywords.txt
Normal file
@ -0,0 +1,21 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Ultrasound
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
MDNSResponder KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
update KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
Loading…
x
Reference in New Issue
Block a user