Simple mdns implementation using the Espressif code
This commit is contained in:
parent
1697126a15
commit
76b28c1f74
|
@ -27,6 +27,7 @@
|
||||||
#define LUA_USE_MODULES_HTTP
|
#define LUA_USE_MODULES_HTTP
|
||||||
//#define LUA_USE_MODULES_HX711
|
//#define LUA_USE_MODULES_HX711
|
||||||
#define LUA_USE_MODULES_I2C
|
#define LUA_USE_MODULES_I2C
|
||||||
|
//#define LUA_USE_MODULES_MDNS
|
||||||
#define LUA_USE_MODULES_MQTT
|
#define LUA_USE_MODULES_MQTT
|
||||||
#define LUA_USE_MODULES_NET
|
#define LUA_USE_MODULES_NET
|
||||||
#define LUA_USE_MODULES_NODE
|
#define LUA_USE_MODULES_NODE
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
// Module for access to the espconn_mdns functions
|
||||||
|
|
||||||
|
#include "module.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
|
||||||
|
#include "c_string.h"
|
||||||
|
#include "c_stdlib.h"
|
||||||
|
|
||||||
|
#include "c_types.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
#include "user_interface.h"
|
||||||
|
|
||||||
|
typedef struct wrapper {
|
||||||
|
struct mdns_info mdns_info;
|
||||||
|
char data;
|
||||||
|
} wrapper_t;
|
||||||
|
|
||||||
|
static wrapper_t *info;
|
||||||
|
|
||||||
|
typedef enum phase {
|
||||||
|
PHASE_CALCULATE_LENGTH,
|
||||||
|
PHASE_COPY_DATA
|
||||||
|
} phase_t;
|
||||||
|
|
||||||
|
static char *advance_over_string(char *s)
|
||||||
|
{
|
||||||
|
while (*s++) {
|
||||||
|
}
|
||||||
|
// s now points after the null
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// mdns.close()
|
||||||
|
//
|
||||||
|
static int mdns_close(lua_State *L)
|
||||||
|
{
|
||||||
|
if (info) {
|
||||||
|
espconn_mdns_close();
|
||||||
|
c_free(info);
|
||||||
|
info = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// this handles all the arguments. Two passes are necessary --
|
||||||
|
// one to calculate the size of the block, and the other to
|
||||||
|
// copy the data. It is vitally important that these two
|
||||||
|
// passes are kept in step.
|
||||||
|
//
|
||||||
|
static wrapper_t *process_args(lua_State *L, phase_t phase, size_t *sizep)
|
||||||
|
{
|
||||||
|
wrapper_t *result = NULL;
|
||||||
|
char *p = NULL;
|
||||||
|
|
||||||
|
if (phase == PHASE_COPY_DATA) {
|
||||||
|
result = (wrapper_t *) c_zalloc(sizeof(wrapper_t) + *sizep);
|
||||||
|
if (!result) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p = &result->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phase == PHASE_CALCULATE_LENGTH) {
|
||||||
|
luaL_checktype(L, 1, LUA_TSTRING);
|
||||||
|
luaL_checktype(L, 2, LUA_TSTRING);
|
||||||
|
(void) luaL_checkinteger(L, 3);
|
||||||
|
*sizep += c_strlen(luaL_checkstring(L, 1)) + 1;
|
||||||
|
*sizep += c_strlen(luaL_checkstring(L, 2)) + 1;
|
||||||
|
} else {
|
||||||
|
c_strcpy(p, luaL_checkstring(L, 1));
|
||||||
|
result->mdns_info.host_name = p;
|
||||||
|
p = advance_over_string(p);
|
||||||
|
|
||||||
|
c_strcpy(p, luaL_checkstring(L, 2));
|
||||||
|
result->mdns_info.server_name = p;
|
||||||
|
p = advance_over_string(p);
|
||||||
|
|
||||||
|
result->mdns_info.server_port = luaL_checkinteger(L, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lua_gettop(L) >= 4) {
|
||||||
|
luaL_checktype(L, 4, LUA_TTABLE);
|
||||||
|
lua_pushnil(L); // first key
|
||||||
|
int slot = 0;
|
||||||
|
while (lua_next(L, 4) != 0 && slot < sizeof(result->mdns_info.txt_data) / sizeof(result->mdns_info.txt_data[0])) {
|
||||||
|
if (phase == PHASE_CALCULATE_LENGTH) {
|
||||||
|
luaL_checktype(L, -2, LUA_TSTRING);
|
||||||
|
*sizep += c_strlen(luaL_checkstring(L, -2)) + 1;
|
||||||
|
*sizep += c_strlen(luaL_checkstring(L, -1)) + 1;
|
||||||
|
} else {
|
||||||
|
// put in the key
|
||||||
|
c_strcpy(p, luaL_checkstring(L, -2));
|
||||||
|
result->mdns_info.txt_data[slot] = p;
|
||||||
|
p = advance_over_string(p);
|
||||||
|
|
||||||
|
// now smash in the value
|
||||||
|
const char *value = luaL_checkstring(L, -1);
|
||||||
|
p[-1] = '=';
|
||||||
|
c_strcpy(p, value);
|
||||||
|
p = advance_over_string(p);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// mdns.register(hostname, servicename, port [, attributes])
|
||||||
|
//
|
||||||
|
static int mdns_register(lua_State *L)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
(void) process_args(L, PHASE_CALCULATE_LENGTH, &len);
|
||||||
|
|
||||||
|
struct ip_info ipconfig;
|
||||||
|
|
||||||
|
uint8_t mode = wifi_get_opmode();
|
||||||
|
|
||||||
|
if (!wifi_get_ip_info((mode == 2) ? SOFTAP_IF : STATION_IF, &ipconfig) || !ipconfig.ip.addr) {
|
||||||
|
return luaL_error(L, "No network connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper_t *result = process_args(L, PHASE_COPY_DATA, &len);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return luaL_error( L, "failed to allocate info block" );
|
||||||
|
}
|
||||||
|
|
||||||
|
result->mdns_info.ipAddr = ipconfig.ip.addr;
|
||||||
|
|
||||||
|
// Close up the old session (if any). This cannot fail
|
||||||
|
// so no chance of losing the memory in 'result'
|
||||||
|
|
||||||
|
mdns_close(L);
|
||||||
|
|
||||||
|
// Save the result as it appears that espconn_mdns_init needs
|
||||||
|
// to have the data valid while it is running.
|
||||||
|
|
||||||
|
info = result;
|
||||||
|
|
||||||
|
espconn_mdns_init(&(info->mdns_info));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Module function map
|
||||||
|
static const LUA_REG_TYPE mdns_map[] = {
|
||||||
|
{ LSTRKEY("register"), LFUNCVAL(mdns_register) },
|
||||||
|
{ LSTRKEY("close"), LFUNCVAL(mdns_close) },
|
||||||
|
{ LNILKEY, LNILVAL }
|
||||||
|
};
|
||||||
|
|
||||||
|
NODEMCU_MODULE(MDNS, "mdns", mdns_map, NULL);
|
|
@ -0,0 +1,38 @@
|
||||||
|
# mdns Module
|
||||||
|
|
||||||
|
Multicast DNS is used as part of Bonjour / Zeroconf. This allows system to identify themselves and the services that they provide on a local area network. Clients are then
|
||||||
|
able to discover these systems and connect to them.
|
||||||
|
|
||||||
|
## mdns.register()
|
||||||
|
Register a hostname and start the mDns service. If the service is already running, then it
|
||||||
|
will be restarted with the new parameters.
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
`mdns.register(hostname, servicename, port [, attributes])`
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
- `hostname` The hostname for this device. Alphanumeric characters are best.
|
||||||
|
- `servicename` The servicename for this device. Alphanumeric characters are best. This will get prefixed with '_' and suffixed with ._tcp
|
||||||
|
- `port` The port number for the primary service.
|
||||||
|
- `attributes` A optional table of up to 10 attributes to be exposed. The keys must all be strings.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
Nothing.
|
||||||
|
|
||||||
|
#### Errors
|
||||||
|
Various errors can be generated during argument validation. The nodemcu must have an IP address at the time of the call, otherwise an error is thrown.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
mdns.register("fishtank", "http", 80, { hardware='NodeMCU'})
|
||||||
|
|
||||||
|
Using dns-sd on OSX, you can see fishtank.local as providing the _http._tcp service. You can also browse directly to fishtank.local. In safari you can get all the mdns web pages as part of your bookmarks menu.
|
||||||
|
|
||||||
|
## mdns.close()
|
||||||
|
Shut down the mDns service. This is not normally needed.
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
`mdns.close()`
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
Nothing.
|
|
@ -44,6 +44,7 @@ pages:
|
||||||
- 'http': 'en/modules/http.md'
|
- 'http': 'en/modules/http.md'
|
||||||
- 'hx711' : 'en/modules/hx711.md'
|
- 'hx711' : 'en/modules/hx711.md'
|
||||||
- 'i2c' : 'en/modules/i2c.md'
|
- 'i2c' : 'en/modules/i2c.md'
|
||||||
|
- 'mdns': 'en/modules/mdns.md'
|
||||||
- 'mqtt': 'en/modules/mqtt.md'
|
- 'mqtt': 'en/modules/mqtt.md'
|
||||||
- 'net': 'en/modules/net.md'
|
- 'net': 'en/modules/net.md'
|
||||||
- 'node': 'en/modules/node.md'
|
- 'node': 'en/modules/node.md'
|
||||||
|
|
Loading…
Reference in New Issue