-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Net_info module exposing ping function initial commit
- Loading branch information
vsky
committed
Sep 13, 2019
1 parent
32ad759
commit 9395449
Showing
4 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// *************************************************************************** | ||
// net_info module for ESP8266 with nodeMCU | ||
// | ||
// adopted jan 2017 for commit to nodeMCU by Wolfgang Rosner | ||
// re-worked by Lukas Voborsky, @voborsky | ||
// *************************************************************************** | ||
|
||
/** | ||
* test.ping() | ||
* Description: | ||
* Send ICMP ping request to address, optionally call callback when response received | ||
* | ||
* Syntax: | ||
* wifi.sta.getconfig(ssid, password) --Set STATION configuration, Auto-connect by default, Connects to any BSSID | ||
* test.ping(address) -- send 4 ping requests to target address | ||
* test.ping(address, n) -- send n ping requests to target address | ||
* test.ping(address, n, callback) -- send n ping requests to target address | ||
* Parameters: | ||
* address: string | ||
* n: number of requests to send | ||
* callback: | ||
* Returns: | ||
* Nothing. | ||
* | ||
* Example: | ||
* test.ping("192.168.0.1") -- send 4 pings to 192.168.0.1 | ||
* test.ping("192.168.0.1", 10) -- send 10 pings to 192.168.0.1 | ||
* test.ping("192.168.0.1", 10, got_ping) -- send 10 pings to 192.168.0.1, call got_ping() with the | ||
* -- ping results | ||
*/ | ||
|
||
#define NODE_DEBUG | ||
|
||
#include "module.h" | ||
#include "lauxlib.h" | ||
#include "platform.h" | ||
#include "mem.h" | ||
#include "task/task.h" | ||
|
||
#include "lwip/ip_addr.h" | ||
#include "espconn.h" | ||
#include "lwip/dns.h" | ||
#include "lwip/app/ping.h" | ||
#include "lwip/raw.h" | ||
|
||
typedef struct { | ||
struct ping_option ping_opt; // ping_opt needs to be the first element of the structure | ||
sint32_t ping_callback_ref; | ||
sint32_t self_ref; /* Reference to this structure as userdata */ | ||
uint8_t ping_host_count; | ||
ip_addr_t ping_host_ip; | ||
} net_info_ping_t; | ||
typedef net_info_ping_t* ping_t; | ||
|
||
static ping_t nip_get( lua_State *L, int stack ) { | ||
ping_t nip = (ping_t)luaL_checkudata(L, stack, "net_info.ping"); | ||
if (nip == NULL) { | ||
return (ping_t)luaL_error(L, "ping object expected"); | ||
} | ||
return nip; | ||
} | ||
|
||
void ping_received(void *arg, void *data) { | ||
NODE_DBG("[ping_received] \n"); | ||
// struct ping_option *pingopt = (struct ping_option*)arg; | ||
ping_t nip = (ping_t)arg; | ||
struct ping_resp *pingresp = (struct ping_resp*)data; | ||
|
||
char ipaddrstr[16]; | ||
ip_addr_t source_ip; | ||
|
||
source_ip.addr = nip->ping_opt.ip; | ||
ipaddr_ntoa_r(&source_ip, ipaddrstr, sizeof(ipaddrstr)); | ||
|
||
if (nip->ping_callback_ref != LUA_NOREF) { | ||
lua_State *L = lua_getstate(); | ||
lua_rawgeti(L, LUA_REGISTRYINDEX, nip->ping_callback_ref); | ||
lua_pushinteger(L, pingresp->bytes); | ||
lua_pushstring(L, ipaddrstr); | ||
lua_pushinteger(L, pingresp->seqno); | ||
lua_pushinteger(L, pingresp->resp_time); | ||
lua_call(L, 4, 0); | ||
} | ||
} | ||
|
||
static int net_info_ping(lua_State *L) | ||
{ | ||
NODE_DBG("[net_info_ping]\n"); | ||
ping_t nip = nip_get(L, 1); | ||
|
||
if (nip->self_ref == LUA_NOREF) { | ||
lua_pushvalue(L, 1); | ||
nip->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
} | ||
|
||
const char *ping_target; | ||
unsigned count = 4; | ||
|
||
// retrieve address arg (mandatory) | ||
if (lua_isstring(L, 2)) { | ||
ping_target = luaL_checkstring(L, 2); | ||
} else { | ||
return luaL_error(L, "no address specified"); | ||
} | ||
|
||
// retrieve count arg (optional) | ||
if (lua_isnumber(L, 3)) { | ||
count = luaL_checkinteger(L, 3); | ||
} | ||
|
||
// retrieve callback arg (optional) | ||
if (nip->ping_callback_ref != LUA_NOREF) { | ||
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref); | ||
} | ||
nip->ping_callback_ref = LUA_NOREF; | ||
|
||
if (lua_type(L, 4) == LUA_TFUNCTION || lua_type(L, 4) == LUA_TLIGHTFUNCTION) { | ||
nip->ping_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); | ||
} | ||
|
||
// attempt to parse ping target as IP | ||
uint32 ip = ipaddr_addr(ping_target); | ||
|
||
if (ip != IPADDR_NONE) { | ||
nip->ping_opt.count = count; | ||
nip->ping_opt.ip = ip; | ||
nip->ping_opt.coarse_time = 0; | ||
nip->ping_opt.recv_function = &ping_received; | ||
|
||
NODE_DBG("[net_info_ping] calling ping_start\n"); | ||
ping_start(&(nip->ping_opt)); | ||
} else { | ||
return luaL_error(L, "wrong IP address"); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int net_info_create( lua_State *L ) { | ||
NODE_DBG("[net_info_create]\n"); | ||
ping_t nip = (ping_t)lua_newuserdata(L, sizeof(net_info_ping_t)); | ||
if (!nip) return luaL_error(L, "not enough memory"); | ||
luaL_getmetatable(L, "net_info.ping"); | ||
lua_setmetatable(L, -2); | ||
nip->ping_callback_ref = LUA_NOREF; | ||
nip->self_ref = LUA_NOREF; | ||
return 1; | ||
} | ||
|
||
static int net_info_unregister(lua_State* L){ | ||
NODE_DBG("[net_info_unregister]\n"); | ||
ping_t nip = nip_get(L, 1); | ||
|
||
if (nip->self_ref != LUA_REFNIL) { | ||
luaL_unref(L, LUA_REGISTRYINDEX, nip->self_ref); | ||
nip->self_ref = LUA_NOREF; | ||
} | ||
|
||
if(nip->ping_callback_ref != LUA_NOREF) { | ||
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref); | ||
} | ||
nip->ping_callback_ref = LUA_NOREF; | ||
return 0; | ||
} | ||
|
||
// Module function map | ||
LROT_BEGIN(net_info_dyn) | ||
LROT_FUNCENTRY( ping, net_info_ping ) | ||
LROT_FUNCENTRY( __gc, net_info_unregister ) | ||
LROT_TABENTRY( __index, net_info_dyn ) | ||
LROT_END( net_info_dyn, net_info_dyn, LROT_MASK_GC_INDEX ) | ||
|
||
|
||
LROT_BEGIN(net_info) | ||
LROT_FUNCENTRY( create, net_info_create ) | ||
LROT_END( net_ifo, NULL, 0 ) | ||
|
||
int luaopen_net_info( lua_State *L ){ | ||
NODE_DBG("[luaopen_net_info]\n"); | ||
luaL_rometatable(L, "net_info.ping", LROT_TABLEREF(net_info_dyn)); | ||
return 0; | ||
} | ||
|
||
NODEMCU_MODULE(NET_INFO, "net_info", net_info, luaopen_net_info); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# net_info Module | ||
| Since | Origin / Contributor | Maintainer | Source | | ||
| :----- | :-------------------- | :---------- | :------ | | ||
| 2017-01-21 | [smcl](http://blog.mclemon.io/esp8266-contributing-to-the-nodemcu-ecosystem) | [wolfgangr](https://github.com/wolfgangr/nodemcu-firmware) | [net_info.c](../../../app/modules/net_info.c) | ||
|
||
|
||
This module is a stub to collect common network diagnostic and analysis tools. | ||
|
||
##net_info.ping() | ||
send ICMP ECHO_REQUEST to network hosts | ||
|
||
**Synopsis:**: | ||
``` | ||
net_info.ping(host [, count [, callback]]) | ||
``` | ||
|
||
**Usage example:** | ||
``` | ||
=net_info.ping("www.google.de",2) | ||
> 32 bytes from 172.217.20.195, icmp_seq=25 ttl=53 time=37ms | ||
32 bytes from 172.217.20.195, icmp_seq=26 ttl=53 time=38ms | ||
ping 2, timeout 0, total payload 64 bytes, 1946 ms | ||
``` | ||
|
||
|
||
**Description:** (from *linux man 8 ping*) | ||
|
||
> `ping` uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway. ECHO_REQUEST datagrams (''pings'') have an IP and ICMP header, followed by a struct timeval and then an arbitrary number of ''pad'' bytes used to fill out the packet. | ||
|
||
**Usage variants** | ||
|
||
ping host **by IP-Adress:** | ||
``` | ||
net_info.ping("1.2.3.4") | ||
``` | ||
Enter IP-Adress in commonly known dotted quad-decimal notation, enclosed in string quotes. | ||
|
||
!!! Note | ||
There is only limited error checking on the validity of IP adresses in lwIP. Check twice! | ||
|
||
|
||
Use **DNS resolver** to get IP adress for ping: | ||
``` | ||
net_info.ping("hostname") | ||
``` | ||
|
||
!!! Note | ||
This only works with Network access and DNS resolution properly configured. | ||
|
||
|
||
Custom **ping count**: | ||
``` | ||
net_info.ping(host, count) | ||
``` | ||
* `host` can be given by IP or hostname as above. | ||
* `count` number of repetitive pings - default is 4 if omitted. | ||
|
||
|
||
Ping **callback function**: | ||
``` | ||
net_info.ping(host, count, callback) | ||
``` | ||
Instead of printing ping results on the console, the given callback function ist called each time a ECHO_RESPONSE is received. | ||
|
||
The callback receives the following arguments: | ||
``` | ||
function ping_recv(bytes, ipaddr, seqno, ttl, ping) | ||
``` | ||
* length of message | ||
* ip-address of pinged host | ||
* icmp_seq number | ||
* time-to-live-value | ||
* ping time in ms | ||
|
||
!!! Caution | ||
The callback functionality is still untested. Use at even more your own risk! | ||
|
||
For further reference to callback functionality, see smcl origin link provided on top of this page. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters