Started adding in standalone mdns implementation

pull/72/head
Benjamin Runnels 9 years ago
parent b7ae39ae8d
commit 5935a30f03
  1. 2
      esp-link.vcxproj
  2. 22
      esp-link/cgiwifi.c
  3. 335
      esp-link/mdns.c
  4. 52
      esp-link/mdns.h
  5. 1
      include/user_config.h

@ -23,6 +23,7 @@
<ClCompile Include="esp-link\config.c" />
<ClCompile Include="esp-link\log.c" />
<ClCompile Include="esp-link\main.c" />
<ClCompile Include="esp-link\mdns.c" />
<ClCompile Include="esp-link\mqtt_client.c" />
<ClCompile Include="esp-link\status.c" />
<ClCompile Include="espfs\espfs.c" />
@ -57,6 +58,7 @@
<ClInclude Include="esp-link\cgiwifi.h" />
<ClInclude Include="esp-link\config.h" />
<ClInclude Include="esp-link\log.h" />
<ClInclude Include="esp-link\mdns.h" />
<ClInclude Include="esp-link\mqtt_client.h" />
<ClInclude Include="esp-link\status.h" />
<ClInclude Include="esp-link\stk500.h" />

@ -20,6 +20,7 @@ Cgi/template routines for the /wifi url.
#include "status.h"
#include "config.h"
#include "log.h"
#include "mdns.h"
#ifdef CGIWIFI_DBG
#define DBG(format, ...) os_printf(format, ## __VA_ARGS__)
@ -114,19 +115,24 @@ wifiAddStateChangeCb(WifiStateChangeCb cb) {
}
static bool mdns_started = false;
static struct mdns_info mdns_info;
//static struct mdns_info mdns_info;
// cannot allocate the info struct on the stack, it crashes!
static ICACHE_FLASH_ATTR
void wifiStartMDNS(struct ip_addr ip) {
if (!mdns_started) {
os_memset(&mdns_info, 0, sizeof(struct mdns_info));
mdns_info.host_name = flashConfig.hostname,
mdns_info.server_name = "http", // service name
mdns_info.server_port = 80, // service port
mdns_info.ipAddr = ip.addr,
mdns_info.txt_data[0] = (char *) "version = now",
espconn_mdns_init(&mdns_info);
// struct mdns_info *ard_mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
// ard_mdns_info->host_name = flashConfig.hostname;
// ard_mdns_info->server_name = "arduino"; // service name
// ard_mdns_info->server_port = 2323; // service port
// ard_mdns_info->ipAddr = ip.addr;
// ard_mdns_info->txt_data[0] = (char *) "version = now";
// espconn_mdns_init(ard_mdns_info);
// espconn_mdns_server_register();
mdns_init(60, 3600);
mdns_addhost(flashConfig.hostname, &ip);
//mdns_addhost("arduino", &ip);
mdns_started = true;
}
}

@ -0,0 +1,335 @@
/*
* mdns.h
*
* Simple mDNS responder.
* It replys to mDNS IP (IPv4/A) queries and optionally broadcasts ip advertisements
* using the mDNS protocol
* Created on: Apr 10, 2015
* Author: Kevin Uhlir (n0bel)
*
*/
#include <esp8266.h>
#include "mdns.h"
#ifdef MDNS_DBG
#define DBG(format, ...) os_printf(format, ## __VA_ARGS__)
#else
#define DBG(format, ...) do { } while(0)
#endif
static int mdns_initialized = 0;
static int ttl = 0;
static os_timer_t bc_timer;
static struct espconn mdns_conn;
#define MAX_HOSTS 5
static struct _host {
char *hostname;
unsigned char *mdns;
struct ip_addr ip;
int len;
} hosts[MAX_HOSTS] = { { NULL } };
int nhosts = 0;
struct ip_addr mdns_multicast;
struct ip_addr ipaddr_any;
#ifdef MDNS_DBG
void ICACHE_FLASH_ATTR hexdump(char *desc, void *addr, int len) {
int i;
unsigned char buff[17];
unsigned char *pc = (unsigned char*)addr;
// Output description if given.
if (desc != NULL)
DBG("%s:\n", desc);
// Process every byte in the data.
for (i = 0; i < len; i++) {
// Multiple of 16 means new line (with line offset).
if ((i % 16) == 0) {
// Just don't print ASCII for the zeroth line.
if (i != 0)
DBG(" %s\n", buff);
// Output the offset.
DBG(" %04x ", i);
}
// Now the hex code for the specific character.
DBG(" %02x", pc[i]);
// And store a printable ASCII character for later.
if ((pc[i] < 0x20) || (pc[i] > 0x7e))
buff[i % 16] = '.';
else
buff[i % 16] = pc[i];
buff[(i % 16) + 1] = '\0';
}
// Pad out last line if not exactly 16 characters.
while ((i % 16) != 0) {
DBG(" ");
i++;
}
// And print the final ASCII bit.
DBG(" %s\n", buff);
}
#endif
unsigned ICACHE_FLASH_ATTR char * encodeResp(struct ip_addr * addr, char *name, int *len)
{
*len = 12 + strlen(name) + 16;
unsigned char *data = (unsigned char *)os_zalloc(*len);
data[2] = 0x84;
data[7] = 1;
unsigned char *p = data + 12;
char *np = name;
char *i;
while ((i = strchr(np, '.')))
{
*p = i - np;
p++;
memcpy(p, np, i - np);
p += i - np;
np = i + 1;
}
*p = strlen(np);
p++;
memcpy(p, np, strlen(np));
p += strlen(np);
*p++ = 0; // terminate string sequence
*p++ = 0; *p++ = 1; // type 0001 (A)
*p++ = 0x80; *p++ = 1; // class code (IPV4)
*p++ = ttl >> 24;
*p++ = ttl >> 16;
*p++ = ttl >> 8;
*p++ = ttl;
*p++ = 0; *p++ = 4; // length (of ip)
memcpy(p, addr, 4);
return data;
}
char ICACHE_FLASH_ATTR *decode_name_strings(unsigned char *p, int *len)
{
unsigned char *s = p;
int c;
*len = 0;
while ((c = *s++))
{
*len += c + 1;
s += c;
}
char *name = (char *)os_zalloc(*len + 1);
char *np = name;
s = p;
while ((c = *s++))
{
memcpy(np, s, c);
np += c;
*np++ = '.';
s += c;
}
np--; *np = 0;
return name;
}
void ICACHE_FLASH_ATTR sendOne(struct _host *h)
{
mdns_conn.proto.udp->remote_ip[0] = 224;
mdns_conn.proto.udp->remote_ip[1] = 0;
mdns_conn.proto.udp->remote_ip[2] = 0;
mdns_conn.proto.udp->remote_ip[3] = 251;
mdns_conn.proto.udp->remote_port = 5353;
mdns_conn.proto.udp->local_port = 5353;
#ifdef MDNS_DBG
hexdump("sending", h->mdns, h->len);
#endif
espconn_sent(&mdns_conn, h->mdns, h->len);
}
void ICACHE_FLASH_ATTR decodeQuery(unsigned char *data)
{
if (data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 0) return; // only queries
int qcount = data[5]; // purposely ignore qcount > 255
unsigned char *p = data + 12;
char *name;
int len;
while (qcount-- > 0)
{
if (*p == 0xc0) // pointer
{
name = decode_name_strings(data + p[1], &len);
p += 2;
}
else
{
name = decode_name_strings(p, &len);
p += len + 1;
}
int qtype = p[0] * 256 + p[1];
int qclass = p[2] * 256 + p[3];
p += 4;
DBG("decoded name %s qtype=%d qclass=%d\n", name, qtype, qclass);
if (qtype == 1 && (qclass & 0x7fff) == 1)
{
struct _host *h;
int i;
for (h = hosts, i = 0; i < nhosts; i++, h++)
{
if (h->hostname && strcmp(name, h->hostname) == 0)
{
DBG("its %s!\n", h->hostname);
sendOne(h);
}
}
os_free(name);
}
}
return;
}
static void ICACHE_FLASH_ATTR broadcast(void *arg)
{
struct _host *h;
int i;
for (h = hosts, i = 0; i < nhosts; i++, h++)
{
DBG("broadcast for %s\n", h->hostname);
sendOne(h);
}
}
static void ICACHE_FLASH_ATTR mdns_udp_recv(void *arg, char *pusrdata, unsigned short length) {
unsigned char *data = (unsigned char *)pusrdata;
DBG("remote port=%d remoteip=%d.%d.%d.%d\n", mdns_conn.proto.udp->remote_port,
mdns_conn.proto.udp->remote_ip[0],
mdns_conn.proto.udp->remote_ip[1],
mdns_conn.proto.udp->remote_ip[2],
mdns_conn.proto.udp->remote_ip[3]
);
#ifdef MDNS_DBG
// hexdump("rec mNDS:", data, length);
#endif
decodeQuery(data);
}
int ICACHE_FLASH_ATTR mdns_addhost(char *hn, struct ip_addr* ip)
{
struct _host *h = &hosts[nhosts];
if (nhosts >= MAX_HOSTS)
{
int i;
for (h = hosts, i = 0; i < MAX_HOSTS; i++, h++)
{
if (!h->hostname) break;
}
if (i >= MAX_HOSTS) return -1;
}
else
{
nhosts++;
}
h->hostname = (char *)os_zalloc(os_strlen(hn) + 1);
os_strcpy(h->hostname, hn);
h->ip.addr = ip->addr;
h->mdns = encodeResp(ip, hn, &(h->len));
#ifdef MDNS_DBG
hexdump("addhost", hosts, sizeof(hosts));
#endif
return(0);
}
int ICACHE_FLASH_ATTR mdns_delhost(char *hn, struct ip_addr* ip)
{
if (nhosts < 1) return -1;
struct _host *h;
int i;
for (h = hosts, i = 0; i < MAX_HOSTS; i++, h++)
{
if ((hn && strcmp(hn, h->hostname) == 0)
|| (ip && h->ip.addr == ip->addr))
{
if (h->hostname) os_free(h->hostname);
if (h->mdns) os_free(h->mdns);
h->hostname = NULL;
h->mdns = NULL;
h->ip.addr = 0;
}
}
#ifdef MDNS_DBG
// hexdump("delhost", hosts, sizeof(hosts));
#endif
return(0);
}
int ICACHE_FLASH_ATTR mdns_init(int bctime, int sttl)
{
if (mdns_initialized) mdns_stop();
mdns_initialized = 1;
ttl = sttl;
IP4_ADDR(&mdns_multicast, 224, 0, 0, 251);
ipaddr_any.addr = IPADDR_ANY;
espconn_igmp_join(&ipaddr_any, &mdns_multicast);
static esp_udp mdns_udp;
mdns_conn.type = ESPCONN_UDP;
mdns_conn.state = ESPCONN_NONE;
mdns_conn.proto.udp = &mdns_udp;
mdns_udp.local_port = 5353;
mdns_conn.reverse = NULL;
espconn_regist_recvcb(&mdns_conn, mdns_udp_recv);
espconn_create(&mdns_conn);
os_timer_disarm(&bc_timer);
if (bctime > 0)
{
os_timer_setfn(&bc_timer, (os_timer_func_t *)broadcast, (void *)0);
os_timer_arm(&bc_timer, bctime * 1000, 1);
}
return 0;
}
int ICACHE_FLASH_ATTR mdns_stop()
{
if (!mdns_initialized) return(0);
os_timer_disarm(&bc_timer);
espconn_disconnect(&mdns_conn);
espconn_delete(&mdns_conn);
espconn_igmp_leave(&ipaddr_any, &mdns_multicast);
mdns_initialized = 0;
struct _host *h;
int i;
for (h = hosts, i = 0; i < MAX_HOSTS; i++, h++)
{
if (h->hostname) os_free(h->hostname);
if (h->mdns) os_free(h->mdns);
h->hostname = NULL;
h->mdns = NULL;
h->ip.addr = 0;
}
nhosts = 0;
return(0);
}

@ -0,0 +1,52 @@
/*
* mdns.h
*
* Simple mDNS responder.
* It replys to mDNS IP (IPv4/A) queries and optionally broadcasts ip advertisements
* using the mDNS protocol
* Created on: Apr 10, 2015
* Author: Kevin Uhlir (n0bel)
*
*/
#ifndef MDNS_H
#define MDNS_H
/******************************************************************************
* FunctionName : mdns_init
* Description : Initialize the module
* done once after the system is up and ready to run
* Parameters : bctime -- broadcast timer (seconds) can be 0 for no broadcasting
* ttl -- Time To Live must be > 0, should be a reasonable DNS ttl
* Returns : 0 success, -1 failed
*******************************************************************************/
int mdns_init(int bctime, int ttl);
/******************************************************************************
* FunctionName : mdns_stop
* Description : Stop the module.
* Parameters : None
* Returns : 0 success, -1 failed
*******************************************************************************/
int mdns_stop(void);
/******************************************************************************
* FunctionName : mdns_addhost
* Description : Add a host to be resolved by mDNS
* Parameters : hostname -- the hostname to add (must end in .local)
* for most clients to function
* ip -- the ip address of the host
* Returns : 0 success, -1 failed
*******************************************************************************/
int mdns_addhost(char *hostname, struct ip_addr* ip);
/******************************************************************************
* FunctionName : mdns_delhost
* Description : Delete a host to be resolved by mDNS
* Parameters : hostname -- the hostname to delete
* if NULL, hostname won't be used
* ip -- the ip address of the host to delete
* if NULL, ip won't be used
* Returns : 0 success, -1 failed
*******************************************************************************/
int mdns_delhost(char *hostname, struct ip_addr* ip);
#endif /* MDNS_H */

@ -29,6 +29,7 @@
#define SERLED_DBG
#undef SLIP_DBG
#define UART_DBG
#define MDNS_DBG
// If defined, the default hostname for DHCP will include the chip ID to make it unique
#undef CHIP_IN_HOSTNAME

Loading…
Cancel
Save