Files
OpenMQTT-Gateway/lib/esp8266_mdns/mdns.h
T

245 lines
8.9 KiB
C++

#ifndef MDNS_H
#define MDNS_H
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#define DEBUG_STATISTICS // Record how many incoming packets fitted into data_buffer.
//#define DEBUG_OUTPUT // Send packet summaries to Serial.
//#define DEBUG_RAW // Send HEX ans ASCII encoded raw packet to Serial.
#define MDNS_TYPE_A 0x0001
#define MDNS_TYPE_PTR 0x000C
#define MDNS_TYPE_HINFO 0x000D
#define MDNS_TYPE_TXT 0x0010
#define MDNS_TYPE_AAAA 0x001C
#define MDNS_TYPE_SRV 0x0021
#define MDNS_TARGET_PORT 5353
#define MDNS_SOURCE_PORT 5353
#define MDNS_TTL 255
// Make this as big as memory limitations allow.
// This default value can be overridden using the max_packet_size_ parameter of
// MDns().
#define MAX_PACKET_SIZE 1024
// The mDNS spec says this should never be more than 256 (including trailing '\0').
#define MAX_MDNS_NAME_LEN 256
namespace mdns{
// A single mDNS Query.
typedef struct Query{
#ifdef DEBUG_OUTPUT
unsigned int buffer_pointer; // Position of Answer in packet. (Used for debugging only.)
#endif
char qname_buffer[MAX_MDNS_NAME_LEN]; // Question Name: Contains the object, domain or zone name.
unsigned int qtype; // Question Type: Type of question being asked by client.
unsigned int qclass; // Question Class: Normally the value 1 for Internet (“IN”)
bool unicast_response; //
bool valid; // False if problems were encountered decoding packet.
void Display() const; // Display a summary of this Answer on Serial port.
} Query;
// A single mDNS Answer.
typedef struct Answer{
#ifdef DEBUG_OUTPUT
unsigned int buffer_pointer; // Position of Answer in packet. (Used for debugging only.)
#endif
char name_buffer[MAX_MDNS_NAME_LEN]; // object, domain or zone name.
char rdata_buffer[MAX_MDNS_NAME_LEN]; // The data portion of the resource record.
unsigned int rrtype; // ResourceRecord Type.
unsigned int rrclass; // ResourceRecord Class: Normally the value 1 for Internet (“IN”)
unsigned long int rrttl; // ResourceRecord Time To Live: Number of seconds ths should be remembered.
bool rrset; // Flush cache of records matching this name.
bool valid; // False if problems were encountered decoding packet.
void Display() const ; // Display a summary of this Answer on Serial port.
} Answer;
class MDns {
private:
public:
// Simple constructor does not fire any callbacks on incoming data.
// Default incoming data_buffer size is used.
MDns() : MDns(NULL, NULL, NULL, MAX_PACKET_SIZE) {}
// Simple constructor does not fire any callbacks on incoming data.
// Args:
// max_packet_size_ : Set the data_buffer size allocated to store incoming packets.
MDns(int max_packet_size_) : MDns(NULL, NULL, NULL, max_packet_size_) {}
// Constructor takes callbacks which fire when mDNS data arrives.
// Args:
// p_packet_function : Callback fires for every mDNS packet that arrives.
// p_query_function : Callback fires for every mDNS Query that arrives as part of a packet.
// p_answer_function : Callback fires for every mDNS Answer that arrives as part of a packet.
MDns(std::function<void(const MDns*)> p_packet_function,
std::function<void(const Query*)> p_query_function,
std::function<void(const Answer*)> p_answer_function) :
MDns(p_packet_function, p_query_function, p_answer_function, MAX_PACKET_SIZE) { }
// Constructor takes callbacks which fire when mDNS data arrives.
// Args:
// p_packet_function : Callback fires for every mDNS packet that arrives.
// p_query_function : Callback fires for every mDNS Query that arrives as part of a packet.
// p_answer_function : Callback fires for every mDNS Answer that arrives as part of a packet.
// max_packet_size_ : Set the data_buffer size allocated to store incoming packets.
MDns(std::function<void(const MDns*)> p_packet_function,
std::function<void(const Query*)> p_query_function,
std::function<void(const Answer*)> p_answer_function,
int max_packet_size_) :
#ifdef DEBUG_STATISTICS
buffer_size_fail(0),
largest_packet_seen(0),
packet_count(0),
#endif
p_packet_function_(p_packet_function),
p_query_function_(p_query_function),
p_answer_function_(p_answer_function),
buffer_pointer(0),
data_buffer(new byte[max_packet_size_]),
max_packet_size(max_packet_size_)
{
this->startUdpMulticast();
};
// Constructor can be passed the buffer to hold the mDNS data.
// This way the potentially large buffer can be shared with other processes.
// Args:
// p_packet_function : Callback fires for every mDNS packet that arrives.
// p_query_function : Callback fires for every mDNS Query that arrives as part of a packet.
// p_answer_function : Callback fires for every mDNS Answer that arrives as part of a packet.
// max_packet_size_ : Set the data_buffer size allocated to store incoming packets.
MDns(std::function<void(const MDns*)> p_packet_function,
std::function<void(const Query*)> p_query_function,
std::function<void(const Answer*)> p_answer_function,
byte* data_buffer_,
int max_packet_size_) :
#ifdef DEBUG_STATISTICS
buffer_size_fail(0),
largest_packet_seen(0),
packet_count(0),
#endif
p_packet_function_(p_packet_function),
p_query_function_(p_query_function),
p_answer_function_(p_answer_function),
buffer_pointer(0),
data_buffer(data_buffer_),
max_packet_size(max_packet_size_)
{
this->startUdpMulticast();
};
~MDns();
// Call this regularly to check for an incoming packet.
bool loop();
// Deprecated. Use loop() instead.
bool Check(){
return loop();
}
// Send this MDns packet.
void Send() const;
// Resets everything to represent an empty packet.
// Do this before building a packet for sending.
void Clear();
// Add a query to packet prior to sending.
// May only be done before any Answers have been added.
bool AddQuery(const Query& query);
// Add an answer to packet prior to sending.
bool AddAnswer(const Answer& answer);
// Display a summary of the packet on Serial port.
void Display() const;
// Display the raw packet in HEX and ASCII.
void DisplayRawPacket() const;
#ifdef DEBUG_STATISTICS
// Counter gets increased every time an incoming mDNS packet arrives that does
// not fit in the data_buffer.
unsigned int buffer_size_fail;
// Track the largest mDNS packet that has arrived.
// Useful for knowing what size to make data_buffer.
unsigned int largest_packet_seen;
// How many mDNS packets have arrived so far.
unsigned int packet_count;
#endif
private:
// Initializes udp multicast
void startUdpMulticast();
void Parse_Query(Query& query);
void Parse_Answer(Answer& answer);
unsigned int PopulateName(const char* name_buffer);
void PopulateAnswerResult(Answer* answer);
// Pointer to function that gets called for every incoming mDNS packet.
std::function<void(const MDns*)> p_packet_function_;
// Pointer to function that gets called for every incoming query.
std::function<void(const Query*)> p_query_function_;
// Pointer to function that gets called for every incoming answer.
std::function<void(const Answer*)> p_answer_function_;
// Position in data_buffer while processing packet.
unsigned int buffer_pointer;
// Buffer containing mDNS packet.
byte* data_buffer;
// Buffer size for incoming MDns packet.
unsigned int max_packet_size;
// Size of mDNS packet.
unsigned int data_size;
// Query or Answer
bool type;
// Whether more follows in another packet.
bool truncated;
// Number of Qeries in the packet.
unsigned int query_count;
// Number of Answers in the packet.
unsigned int answer_count;
unsigned int ns_count;
unsigned int ar_count;
};
// Display a byte on serial console in hexadecimal notation,
// padding with leading zero if necisary to provide evenly tabulated display data.
void PrintHex(unsigned char data);
// Extract Name from DNS data. Will follow pointers used by Message Compression.
// TODO Check for exceeding packet size.
int nameFromDnsPointer(char* p_name_buffer, int name_buffer_pos, const int name_buffer_len,
const byte* p_packet_buffer, int packet_buffer_pos);
int nameFromDnsPointer(char* p_name_buffer, int name_buffer_pos, const int name_buffer_len,
const byte* p_packet_buffer, int packet_buffer_pos, const bool recurse);
bool writeToBuffer(const byte value, char* p_name_buffer, int* p_name_buffer_pos, const int name_buffer_len);
int parseText(char* data_buffer, const int data_buffer_len, int const data_len,
const byte* p_packet_buffer, int packet_buffer_pos);
} // namespace mdns
#endif // MDNS_H