Skip to content

Commit d81729c

Browse files
author
vsky
committed
Net_info module exposing ping function initial commit
1 parent 32ad759 commit d81729c

File tree

7 files changed

+316
-0
lines changed

7 files changed

+316
-0
lines changed

app/include/lwip/app/ping.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct ping_resp{
7575
uint32 bytes;
7676
uint32 total_bytes;
7777
uint32 total_time;
78+
uint8 ttl;
7879
sint8 ping_err;
7980
};
8081

app/include/user_modules.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
//#define LUA_USE_MODULES_MDNS
3939
#define LUA_USE_MODULES_MQTT
4040
#define LUA_USE_MODULES_NET
41+
#define LUA_USE_MODULES_NET_INFO
4142
#define LUA_USE_MODULES_NODE
4243
#define LUA_USE_MODULES_OW
4344
//#define LUA_USE_MODULES_PCM

app/lwip/app/ping.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
165165
pingresp.seqno = ntohs(iecho->seqno);
166166
pingresp.ping_err = 0;
167167
pingmsg->ping_opt->recv_function(pingmsg->ping_opt,(void*) &pingresp);
168+
pingresp.ttl = iphdr->_ttl;
168169
}
169170
}
170171
seqno = iecho->seqno;

app/modules/hx711.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdlib.h>
99
#include <string.h>
1010
#include "user_interface.h"
11+
#include "task/task.h"
1112
static uint8_t data_pin;
1213
static uint8_t clk_pin;
1314
// The fields below are after the pin_num conversion

app/modules/net_info.c

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// ***************************************************************************
2+
// net_info module for ESP8266 with nodeMCU
3+
//
4+
// adopted jan 2017 for commit to nodeMCU by Wolfgang Rosner
5+
// re-worked by Lukas Voborsky, @voborsky
6+
// ***************************************************************************
7+
8+
/**
9+
* test.ping()
10+
* Description:
11+
* Send ICMP ping request to address, optionally call callback when response received
12+
*
13+
* Syntax:
14+
* wifi.sta.getconfig(ssid, password) --Set STATION configuration, Auto-connect by default, Connects to any BSSID
15+
* test.ping(address) -- send 4 ping requests to target address
16+
* test.ping(address, n) -- send n ping requests to target address
17+
* test.ping(address, n, callback) -- send n ping requests to target address
18+
* Parameters:
19+
* address: string
20+
* n: number of requests to send
21+
* callback:
22+
* Returns:
23+
* Nothing.
24+
*
25+
* Example:
26+
* test.ping("192.168.0.1") -- send 4 pings to 192.168.0.1
27+
* test.ping("192.168.0.1", 10) -- send 10 pings to 192.168.0.1
28+
* test.ping("192.168.0.1", 10, got_ping) -- send 10 pings to 192.168.0.1, call got_ping() with the
29+
* -- ping results
30+
*/
31+
32+
#define NODE_DEBUG
33+
34+
#include "module.h"
35+
#include "lauxlib.h"
36+
#include "platform.h"
37+
38+
// #include <string.h>
39+
// #include <strings.h>
40+
// #include <stddef.h>
41+
// #include <stdint.h>
42+
#include "mem.h"
43+
#include "task/task.h"
44+
45+
#include "lwip/ip_addr.h"
46+
#include "espconn.h"
47+
#include "lwip/dns.h"
48+
#include "lwip/app/ping.h"
49+
#include "lwip/raw.h"
50+
51+
typedef struct {
52+
struct ping_option ping_opt; // ping_opt needs to be the first element of the structure
53+
sint32_t ping_callback_ref;
54+
sint32_t self_ref; /* Reference to this structure as userdata */
55+
uint8_t ping_host_count;
56+
ip_addr_t ping_host_ip;
57+
} net_info_ping_t;
58+
typedef net_info_ping_t* ping_t;
59+
60+
static ping_t nip_get( lua_State *L, int stack ) {
61+
ping_t nip = (ping_t)luaL_checkudata(L, stack, "net_info.ping");
62+
if (nip == NULL) {
63+
return (ping_t)luaL_error(L, "ping object expected");
64+
}
65+
return nip;
66+
}
67+
68+
void ping_received(void *arg, void *data) {
69+
NODE_DBG("[ping_received] \n");
70+
// struct ping_option *pingopt = (struct ping_option*)arg;
71+
ping_t nip = (ping_t)arg;
72+
struct ping_resp *pingresp = (struct ping_resp*)data;
73+
74+
char ipaddrstr[16];
75+
ip_addr_t source_ip;
76+
77+
source_ip.addr = nip->ping_opt.ip;
78+
ipaddr_ntoa_r(&source_ip, ipaddrstr, sizeof(ipaddrstr));
79+
80+
if (nip->ping_callback_ref != LUA_NOREF) {
81+
lua_State *L = lua_getstate();
82+
lua_rawgeti(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
83+
lua_pushinteger(L, pingresp->bytes);
84+
lua_pushstring(L, ipaddrstr);
85+
lua_pushinteger(L, pingresp->seqno);
86+
lua_pushinteger(L, pingresp->ttl);
87+
lua_pushinteger(L, pingresp->resp_time);
88+
lua_call(L, 5, 0);
89+
}
90+
}
91+
92+
// static void ping_by_hostname(const char *name, ip_addr_t *ipaddr, void *arg) {
93+
// if (!ping_opt) {
94+
// ping_opt = (struct ping_option *)os_zalloc(sizeof(struct ping_option));
95+
// } else {
96+
// os_memset (ping_opt, 0, sizeof(struct ping_option));
97+
// }
98+
99+
// if (ipaddr == NULL) {
100+
// lua_State *L = lua_getstate();
101+
// luaL_error(L, "SEVERE problem resolving hostname - network and DNS accessible?\n");
102+
// return;
103+
// }
104+
// if (ipaddr->addr == IPADDR_NONE) {
105+
// lua_State *L = lua_getstate();
106+
// luaL_error(L, "problem resolving hostname - maybe nonexistent host?\n");
107+
// return;
108+
// }
109+
110+
// ping_opt->count = ping_host_count;
111+
// ping_opt->ip = ipaddr->addr;
112+
// ping_opt->coarse_time = 0;
113+
// ping_opt->recv_function = &ping_received;
114+
115+
// ping_start(ping_opt);
116+
// }
117+
118+
// struct ping_option{
119+
// uint32 count;
120+
// uint32 ip;
121+
// uint32 coarse_time;
122+
// ping_recv_function recv_function;
123+
// ping_sent_function sent_function;
124+
// void* reverse;
125+
// struct ping_msg *parent_msg;
126+
// };
127+
128+
static int net_info_ping(lua_State *L)
129+
{
130+
NODE_DBG("[net_info_ping]\n");
131+
ping_t nip = nip_get(L, 1);
132+
133+
if (nip->self_ref != LUA_REFNIL) {
134+
luaL_unref(L, LUA_REGISTRYINDEX, nip->self_ref);
135+
nip->self_ref = LUA_NOREF;
136+
}
137+
138+
const char *ping_target;
139+
unsigned count = 4;
140+
141+
// retrieve address arg (mandatory)
142+
if (lua_isstring(L, 2)) {
143+
ping_target = luaL_checkstring(L, 1);
144+
} else {
145+
return luaL_error(L, "no address specified");
146+
}
147+
148+
// retrieve count arg (optional)
149+
if (lua_isnumber(L, 3)) {
150+
count = luaL_checkinteger(L, 2);
151+
}
152+
153+
// retrieve callback arg (optional)
154+
if (nip->ping_callback_ref != LUA_NOREF) {
155+
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
156+
}
157+
nip->ping_callback_ref = LUA_NOREF;
158+
159+
if (lua_type(L, 4) == LUA_TFUNCTION || lua_type(L, 4) == LUA_TLIGHTFUNCTION) {
160+
nip->ping_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
161+
}
162+
163+
// attempt to parse ping target as IP
164+
uint32 ip = ipaddr_addr(ping_target);
165+
166+
if (ip != IPADDR_NONE) {
167+
nip->ping_opt.count = count;
168+
nip->ping_opt.ip = ip;
169+
nip->ping_opt.coarse_time = 0;
170+
nip->ping_opt.recv_function = &ping_received;
171+
172+
NODE_DBG("[net_info_ping] calling ping_start\n");
173+
ping_start(&(nip->ping_opt));
174+
} else {
175+
// ping_host_count = count;
176+
177+
// struct espconn *ping_dns_lookup;
178+
// espconn_create(ping_dns_lookup);
179+
// espconn_gethostbyname(ping_dns_lookup, ping_target, &ping_host_ip, ping_by_hostname);
180+
}
181+
182+
return 0;
183+
}
184+
185+
186+
static int net_info_create( lua_State *L ) {
187+
NODE_DBG("[net_info_create]\n");
188+
ping_t nip = (ping_t)lua_newuserdata(L, sizeof(net_info_ping_t));
189+
if (!nip) return luaL_error(L, "not enough memory");
190+
luaL_getmetatable(L, "net_info.ping");
191+
lua_setmetatable(L, -2);
192+
nip->ping_callback_ref = LUA_NOREF;
193+
nip->self_ref = LUA_NOREF;
194+
return 1;
195+
}
196+
197+
static int net_info_unregister(lua_State* L){
198+
NODE_DBG("[net_info_unregister]\n");
199+
ping_t nip = nip_get(L, 1);
200+
201+
if (nip->self_ref != LUA_REFNIL) {
202+
luaL_unref(L, LUA_REGISTRYINDEX, nip->self_ref);
203+
nip->self_ref = LUA_NOREF;
204+
}
205+
206+
if(nip->ping_callback_ref != LUA_NOREF) {
207+
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
208+
}
209+
nip->ping_callback_ref = LUA_NOREF;
210+
return 0;
211+
}
212+
213+
214+
// Module function map
215+
LROT_BEGIN(net_info_dyn)
216+
LROT_FUNCENTRY( ping, net_info_ping )
217+
LROT_FUNCENTRY( __gc, net_info_unregister )
218+
LROT_TABENTRY( __index, net_info_dyn )
219+
LROT_END( net_info_dyn, net_info_dyn, LROT_MASK_GC_INDEX )
220+
221+
222+
LROT_BEGIN(net_info)
223+
LROT_FUNCENTRY( create, net_info_create )
224+
LROT_END( net_ifo, NULL, 0 )
225+
226+
int luaopen_net_info( lua_State *L ){
227+
NODE_DBG("[luaopen_net_info]\n");
228+
luaL_rometatable(L, "net_info.ping", LROT_TABLEREF(net_info));
229+
return 0;
230+
}
231+
232+
NODEMCU_MODULE(NET_INFO, "net_info", net_info, luaopen_net_info);

docs/modules/net_info.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# net_info Module
2+
| Since | Origin / Contributor | Maintainer | Source |
3+
| :----- | :-------------------- | :---------- | :------ |
4+
| 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)
5+
6+
7+
This module is a stub to collect common network diagnostic and analysis tools.
8+
9+
##net_info.ping()
10+
send ICMP ECHO_REQUEST to network hosts
11+
12+
**Synopsis:**:
13+
```
14+
net_info.ping(host [, count [, callback]])
15+
```
16+
17+
**Usage example:**
18+
```
19+
=net_info.ping("www.google.de",2)
20+
> 32 bytes from 172.217.20.195, icmp_seq=25 ttl=53 time=37ms
21+
32 bytes from 172.217.20.195, icmp_seq=26 ttl=53 time=38ms
22+
ping 2, timeout 0, total payload 64 bytes, 1946 ms
23+
```
24+
25+
26+
**Description:** (from *linux man 8 ping*)
27+
28+
> `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.
29+
30+
31+
**Usage variants**
32+
33+
ping host **by IP-Adress:**
34+
```
35+
net_info.ping("1.2.3.4")
36+
```
37+
Enter IP-Adress in commonly known dotted quad-decimal notation, enclosed in string quotes.
38+
39+
!!! Note
40+
There is only limited error checking on the validity of IP adresses in lwIP. Check twice!
41+
42+
43+
Use **DNS resolver** to get IP adress for ping:
44+
```
45+
net_info.ping("hostname")
46+
```
47+
48+
!!! Note
49+
This only works with Network access and DNS resolution properly configured.
50+
51+
52+
Custom **ping count**:
53+
```
54+
net_info.ping(host, count)
55+
```
56+
* `host` can be given by IP or hostname as above.
57+
* `count` number of repetitive pings - default is 4 if omitted.
58+
59+
60+
Ping **callback function**:
61+
```
62+
net_info.ping(host, count, callback)
63+
```
64+
Instead of printing ping results on the console, the given callback function ist called each time a ECHO_RESPONSE is received.
65+
66+
The callback receives the following arguments:
67+
```
68+
function ping_recv(bytes, ipaddr, seqno, ttl, ping)
69+
```
70+
* length of message
71+
* ip-address of pinged host
72+
* icmp_seq number
73+
* time-to-live-value
74+
* ping time in ms
75+
76+
!!! Caution
77+
The callback functionality is still untested. Use at even more your own risk!
78+
79+
For further reference to callback functionality, see smcl origin link provided on top of this page.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pages:
8383
- 'mdns': 'modules/mdns.md'
8484
- 'mqtt': 'modules/mqtt.md'
8585
- 'net': 'modules/net.md'
86+
- 'net_info': 'modules/net_info.md'
8687
- 'node': 'modules/node.md'
8788
- 'ow (1-Wire)': 'modules/ow.md'
8889
- 'pcm' : 'modules/pcm.md'

0 commit comments

Comments
 (0)