Skip to content

Commit a5f980e

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

File tree

7 files changed

+312
-0
lines changed

7 files changed

+312
-0
lines changed

app/include/lwip/app/ping.h

+1
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

+1
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

+1
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

+1
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

+228
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
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+
return nip;
65+
}
66+
67+
void ping_received(void *arg, void *data) {
68+
NODE_DBG("[ping_received] ");
69+
// struct ping_option *pingopt = (struct ping_option*)arg;
70+
ping_t nip = (ping_t)arg;
71+
struct ping_resp *pingresp = (struct ping_resp*)data;
72+
73+
char ipaddrstr[16];
74+
ip_addr_t source_ip;
75+
76+
source_ip.addr = nip->ping_opt.ip;
77+
ipaddr_ntoa_r(&source_ip, ipaddrstr, sizeof(ipaddrstr));
78+
79+
if (nip->ping_callback_ref != LUA_NOREF) {
80+
lua_State *L = lua_getstate();
81+
lua_rawgeti(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
82+
lua_pushinteger(L, pingresp->bytes);
83+
lua_pushstring(L, ipaddrstr);
84+
lua_pushinteger(L, pingresp->seqno);
85+
lua_pushinteger(L, pingresp->ttl);
86+
lua_pushinteger(L, pingresp->resp_time);
87+
lua_call(L, 5, 0);
88+
}
89+
}
90+
91+
// static void ping_by_hostname(const char *name, ip_addr_t *ipaddr, void *arg) {
92+
// if (!ping_opt) {
93+
// ping_opt = (struct ping_option *)os_zalloc(sizeof(struct ping_option));
94+
// } else {
95+
// os_memset (ping_opt, 0, sizeof(struct ping_option));
96+
// }
97+
98+
// if (ipaddr == NULL) {
99+
// lua_State *L = lua_getstate();
100+
// luaL_error(L, "SEVERE problem resolving hostname - network and DNS accessible?\n");
101+
// return;
102+
// }
103+
// if (ipaddr->addr == IPADDR_NONE) {
104+
// lua_State *L = lua_getstate();
105+
// luaL_error(L, "problem resolving hostname - maybe nonexistent host?\n");
106+
// return;
107+
// }
108+
109+
// ping_opt->count = ping_host_count;
110+
// ping_opt->ip = ipaddr->addr;
111+
// ping_opt->coarse_time = 0;
112+
// ping_opt->recv_function = &ping_received;
113+
114+
// ping_start(ping_opt);
115+
// }
116+
117+
// struct ping_option{
118+
// uint32 count;
119+
// uint32 ip;
120+
// uint32 coarse_time;
121+
// ping_recv_function recv_function;
122+
// ping_sent_function sent_function;
123+
// void* reverse;
124+
// struct ping_msg *parent_msg;
125+
// };
126+
127+
static int net_info_ping(lua_State *L)
128+
{
129+
NODE_DBG("[net_info_ping]");
130+
ping_t nip = nip_get(L, 1);
131+
132+
if (nip->self_ref != LUA_REFNIL) {
133+
luaL_unref(L, LUA_REGISTRYINDEX, nip->self_ref);
134+
nip->self_ref = LUA_NOREF;
135+
}
136+
137+
const char *ping_target;
138+
unsigned count = 4;
139+
140+
// retrieve address arg (mandatory)
141+
if (lua_isstring(L, 2)) {
142+
ping_target = luaL_checkstring(L, 1);
143+
} else {
144+
return luaL_error(L, "no address specified");
145+
}
146+
147+
// retrieve count arg (optional)
148+
if (lua_isnumber(L, 3)) {
149+
count = luaL_checkinteger(L, 2);
150+
}
151+
152+
// retrieve callback arg (optional)
153+
if (nip->ping_callback_ref != LUA_NOREF)
154+
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
155+
nip->ping_callback_ref = LUA_NOREF;
156+
157+
if (lua_type(L, 4) == LUA_TFUNCTION || lua_type(L, 4) == LUA_TLIGHTFUNCTION)
158+
nip->ping_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
159+
160+
// attempt to parse ping target as IP
161+
uint32 ip = ipaddr_addr(ping_target);
162+
163+
if (ip != IPADDR_NONE) {
164+
nip->ping_opt.count = count;
165+
nip->ping_opt.ip = ip;
166+
nip->ping_opt.coarse_time = 0;
167+
nip->ping_opt.recv_function = &ping_received;
168+
169+
NODE_DBG("[net_info_ping] calling ping_start");
170+
ping_start(&(nip->ping_opt));
171+
} else {
172+
// ping_host_count = count;
173+
174+
// struct espconn *ping_dns_lookup;
175+
// espconn_create(ping_dns_lookup);
176+
// espconn_gethostbyname(ping_dns_lookup, ping_target, &ping_host_ip, ping_by_hostname);
177+
}
178+
179+
return 0;
180+
}
181+
182+
183+
static int net_info_create( lua_State *L ) {
184+
NODE_DBG("[net_info_create]");
185+
ping_t nip = (ping_t)lua_newuserdata(L, sizeof(net_info_ping_t));
186+
if (!nip) return luaL_error(L, "not enough memory");
187+
luaL_getmetatable(L, "net_info.ping");
188+
lua_setmetatable(L, -2);
189+
nip->ping_callback_ref = LUA_NOREF;
190+
nip->self_ref = LUA_NOREF;
191+
return 1;
192+
}
193+
194+
static int net_info_unregister(lua_State* L){
195+
NODE_DBG("[net_info_unregister]");
196+
ping_t nip = nip_get(L, 1);
197+
198+
if (nip->self_ref != LUA_REFNIL) {
199+
luaL_unref(L, LUA_REGISTRYINDEX, nip->self_ref);
200+
nip->self_ref = LUA_NOREF;
201+
}
202+
203+
if(nip->ping_callback_ref != LUA_NOREF)
204+
luaL_unref(L, LUA_REGISTRYINDEX, nip->ping_callback_ref);
205+
nip->ping_callback_ref = LUA_NOREF;
206+
return 0;
207+
}
208+
209+
210+
// Module function map
211+
LROT_BEGIN(net_info_dyn)
212+
LROT_FUNCENTRY( ping, net_info_ping )
213+
LROT_FUNCENTRY( __gc, net_info_unregister )
214+
LROT_TABENTRY( __index, net_info_dyn )
215+
LROT_END( net_info_dyn, net_info_dyn, LROT_MASK_GC_INDEX )
216+
217+
218+
LROT_BEGIN(net_info)
219+
LROT_FUNCENTRY( create, net_info_create )
220+
LROT_END( net_ifo, NULL, 0 )
221+
222+
int luaopen_net_info( lua_State *L ){
223+
NODE_DBG("[luaopen_net_info]");
224+
luaL_rometatable(L, "net_info.ping", LROT_TABLEREF(net_info));
225+
return 0;
226+
}
227+
228+
NODEMCU_MODULE(NET_INFO, "net_info", net_info, NULL);

docs/modules/net_info.md

+79
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

+1
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': 'en/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)