From 3c9ef2862374c4c500d47a1dc4a461c15446b116 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Mon, 24 Feb 2025 16:32:17 +0100 Subject: [PATCH 1/6] lwIpWrapper: rebuild lwip library to enable LWIP_RAW --- extras/net/lwipopts.h | 4 ++-- .../lwIpWrapper/src/cortex-m33/liblwIP.a | Bin 274428 -> 278314 bytes libraries/lwIpWrapper/src/lwipopts.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extras/net/lwipopts.h b/extras/net/lwipopts.h index 87d0d9a5c..3d8022920 100644 --- a/extras/net/lwipopts.h +++ b/extras/net/lwipopts.h @@ -277,7 +277,7 @@ * (requires the LWIP_RAW option) */ #ifndef MEMP_NUM_RAW_PCB -#define MEMP_NUM_RAW_PCB 0 +#define MEMP_NUM_RAW_PCB 1 #endif /** @@ -642,7 +642,7 @@ * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. */ #ifndef LWIP_RAW -#define LWIP_RAW 0 +#define LWIP_RAW 1 #endif /* diff --git a/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a b/libraries/lwIpWrapper/src/cortex-m33/liblwIP.a index adaabfb1cd45db2e25e5800f1377a10dcf103d47..687e03a87e792d87c96efb5d6cfc284b98329b2b 100644 GIT binary patch delta 9761 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 delta 8838 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 Date: Mon, 24 Feb 2025 16:33:12 +0100 Subject: [PATCH 2/6] lwIpWrapper: CNetIf add ping command --- libraries/Ethernet/src/Ethernet.cpp | 23 ++++++ libraries/Ethernet/src/EthernetC33.h | 6 ++ libraries/WiFi/src/WiFi.cpp | 25 ++++++- libraries/WiFi/src/WiFiC3.h | 7 +- libraries/lwIpWrapper/src/CNetIf.cpp | 105 +++++++++++++++++++++++++++ libraries/lwIpWrapper/src/CNetIf.h | 10 +++ 6 files changed, 173 insertions(+), 3 deletions(-) diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp index 993ea2372..c2570d13f 100644 --- a/libraries/Ethernet/src/Ethernet.cpp +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -223,4 +223,27 @@ IPAddress CEthernet::dnsServerIP() { return CLwipIf::getInstance().getDns(); } +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(IPAddress ip, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().ping(ip, ttl); +} + +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(const String &hostname, uint8_t ttl) +/* -------------------------------------------------------------------------- */ +{ + return ping(hostname.c_str(), ttl); +} + +/* -------------------------------------------------------------------------- */ +int CEthernet::ping(const char* host, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + IPAddress ip; + if(CLwipIf::getInstance().getHostByName(host,ip)) { + return CLwipIf::getInstance().ping(ip, ttl); + } + return -1; +} + CEthernet Ethernet; diff --git a/libraries/Ethernet/src/EthernetC33.h b/libraries/Ethernet/src/EthernetC33.h index 5c684fe63..5147d0464 100644 --- a/libraries/Ethernet/src/EthernetC33.h +++ b/libraries/Ethernet/src/EthernetC33.h @@ -69,6 +69,12 @@ class CEthernet { IPAddress gatewayIP(); IPAddress dnsServerIP(); + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); + int ping(const String &hostname, uint8_t ttl = 128); + int ping(const char* host, uint8_t ttl = 128); friend class EthernetClient; friend class EthernetServer; diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index ba19f311c..db773d457 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -321,12 +321,33 @@ unsigned long CWifi::getTime() { return 0; } - - void CWifi::setTimeout(unsigned long timeout) { (void)(timeout); } +/* -------------------------------------------------------------------------- */ +int CWifi::ping(IPAddress ip, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + return CLwipIf::getInstance().ping(ip, ttl); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const String &hostname, uint8_t ttl) +/* -------------------------------------------------------------------------- */ +{ + return ping(hostname.c_str(), ttl); +} + +/* -------------------------------------------------------------------------- */ +int CWifi::ping(const char* host, uint8_t ttl) { +/* -------------------------------------------------------------------------- */ + IPAddress ip; + if(hostByName(host,ip)) { + return CLwipIf::getInstance().ping(ip, ttl); + } + return -1; +} + CWifi WiFi; diff --git a/libraries/WiFi/src/WiFiC3.h b/libraries/WiFi/src/WiFiC3.h index 2995cdcf9..2ff804d42 100644 --- a/libraries/WiFi/src/WiFiC3.h +++ b/libraries/WiFi/src/WiFiC3.h @@ -254,7 +254,12 @@ class CWifi { void setTimeout(unsigned long timeout); - + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); + int ping(const String &hostname, uint8_t ttl = 128); + int ping(const char* host, uint8_t ttl = 128); }; diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 810b14075..94aa7eb11 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -1,5 +1,9 @@ #include "CNetIf.h" #include +#include "lwip/include/lwip/raw.h" +#include "lwip/include/lwip/icmp.h" +#include "lwip/include/lwip/ip_addr.h" +#include "lwip/include/lwip/inet_chksum.h" IPAddress CNetIf::default_ip("192.168.0.10"); IPAddress CNetIf::default_nm("255.255.255.0"); @@ -14,6 +18,32 @@ bool CLwipIf::pending_eth_rx = false; FspTimer CLwipIf::timer; +u8_t icmp_receive_callback(void* arg, struct raw_pcb* pcb, struct pbuf* p, const ip_addr_t* addr) +{ + struct ping_data *d = (struct ping_data*)arg; + struct __attribute__((__packed__)) { + struct ip_hdr ipHeader; + struct icmp_echo_hdr header; + } response; + + if(d->s == pcb) { + if(p->len < sizeof(response)) { + pbuf_free(p); + return 1; + } + + pbuf_copy_partial(p, &response, sizeof(response), 0); + + if(response.header.id == d->echo_req.id && response.header.seqno == d->echo_req.seqno) { + d->endMillis = millis(); + } + pbuf_free(p); + return 1; + } + + return 0; +} + ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) { IP_ADDR4(ipaddr, ipu8[0], ipu8[1], ipu8[2], ipu8[3]); @@ -120,6 +150,81 @@ void CLwipIf::lwip_task() } } +int CLwipIf::ping(IPAddress ip, uint8_t ttl) +{ + uint32_t result = -1; + uint32_t timeout = 5000; + uint32_t sendTime = 0; + uint32_t startWait = 0; + struct pbuf *p; + struct raw_pcb* s; + struct ping_data *d = new ping_data; + if (!d){ + goto exit; + } + + //Create a raw socket + s = raw_new(IP_PROTO_ICMP); + if(!s) { + goto exit; + } + + struct __attribute__((__packed__)) { + struct icmp_echo_hdr header; + uint8_t data[32]; + } request; + + ICMPH_TYPE_SET(&request.header, ICMP_ECHO); + ICMPH_CODE_SET(&request.header, 0); + request.header.chksum = 0; + request.header.id = 0xAFAF; + request.header.seqno = random(0xffff); + + d->echo_req = request.header; + + for (size_t i = 0; i < sizeof(request.data); i++) { + request.data[i] = i; + } + + request.header.chksum = inet_chksum(&request, sizeof(request)); + + ip_addr_t addr; + addr.addr = ip; + + d->endMillis = 0; + + raw_recv(s, icmp_receive_callback, d); + + // Build the packet + p = pbuf_alloc(PBUF_IP, sizeof(request), PBUF_RAM); + if (!p) { + goto exit; + } + + //Load payload into buffer + pbuf_take(p, &request, sizeof(request)); + + // Send the echo request + sendTime = millis(); + raw_sendto(s, p, &addr); + + // Wait for response + startWait = millis(); + do { + lwip_task(); + } while (d->endMillis == 0 && (millis() - startWait) < timeout); + + if (d->endMillis != 0) { + result = d->endMillis - sendTime; + } + +exit: + pbuf_free(p); + delete d; + raw_remove(s); + return result; +} + /* -------------------------------------------------------------------------- */ /* GET INSTANCE SINGLETONE FUNCTION */ /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 407501b72..7606d6993 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -131,6 +131,12 @@ ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr); uint32_t ip_addr_to_u32(ip_addr_t* ipaddr); +struct ping_data{ + uint32_t endMillis; + icmp_echo_hdr echo_req; + struct raw_pcb* s; +}; + /* Base class implements DHCP, derived class will switch it on or off */ /* -------------------------------------------------------------------------- */ class CNetIf { @@ -436,6 +442,10 @@ class CLwipIf { int setWifiMode(WifiMode_t mode); void lwip_task(); + /* + * PING + */ + int ping(IPAddress ip, uint8_t ttl = 128); }; #endif From f5374059b08a3e0d76b98d58b5eb34b505e04a6c Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 19 Feb 2025 14:15:42 +0100 Subject: [PATCH 3/6] lwIpWrapper: CNetIf fix ping command --- libraries/lwIpWrapper/src/CNetIf.cpp | 139 ++++++++++++--------------- libraries/lwIpWrapper/src/CNetIf.h | 8 +- 2 files changed, 68 insertions(+), 79 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 94aa7eb11..e80065459 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -18,30 +18,30 @@ bool CLwipIf::pending_eth_rx = false; FspTimer CLwipIf::timer; -u8_t icmp_receive_callback(void* arg, struct raw_pcb* pcb, struct pbuf* p, const ip_addr_t* addr) +static u8_t icmp_receive_callback(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) { - struct ping_data *d = (struct ping_data*)arg; - struct __attribute__((__packed__)) { - struct ip_hdr ipHeader; - struct icmp_echo_hdr header; - } response; + struct icmp_echo_hdr *iecho; + (void)(pcb); + (void)(addr); + LWIP_ASSERT("p != NULL", p != NULL); - if(d->s == pcb) { - if(p->len < sizeof(response)) { - pbuf_free(p); - return 1; - } + recv_callback_data* request = (recv_callback_data*)arg; - pbuf_copy_partial(p, &response, sizeof(response), 0); + if ((p->tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) && + pbuf_remove_header(p, PBUF_IP_HLEN) == 0) { + iecho = (struct icmp_echo_hdr *)p->payload; - if(response.header.id == d->echo_req.id && response.header.seqno == d->echo_req.seqno) { - d->endMillis = millis(); + if ((iecho->id == 0xAFAF) && (iecho->seqno == lwip_htons(request->seqNum))) { + /* do some ping result processing */ + request->endMillis = millis(); + pbuf_free(p); + return 1; /* eat the packet */ } - pbuf_free(p); - return 1; + /* not eaten, restore original packet */ + pbuf_add_header(p, PBUF_IP_HLEN); } - return 0; + return 0; /* don't eat the packet */ } ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) @@ -150,79 +150,68 @@ void CLwipIf::lwip_task() } } + int CLwipIf::ping(IPAddress ip, uint8_t ttl) { - uint32_t result = -1; - uint32_t timeout = 5000; - uint32_t sendTime = 0; - uint32_t startWait = 0; - struct pbuf *p; - struct raw_pcb* s; - struct ping_data *d = new ping_data; - if (!d){ - goto exit; - } + /* ttl is not supported. Default value used is 255 */ + (void)ttl; + ip_addr_t addr; + addr.addr = ip; + recv_callback_data requestCbkData = { 0, 0, (uint16_t)random(0xffff) }; //Create a raw socket - s = raw_new(IP_PROTO_ICMP); - if(!s) { - goto exit; - } - - struct __attribute__((__packed__)) { - struct icmp_echo_hdr header; - uint8_t data[32]; - } request; - - ICMPH_TYPE_SET(&request.header, ICMP_ECHO); - ICMPH_CODE_SET(&request.header, 0); - request.header.chksum = 0; - request.header.id = 0xAFAF; - request.header.seqno = random(0xffff); - - d->echo_req = request.header; - - for (size_t i = 0; i < sizeof(request.data); i++) { - request.data[i] = i; + struct raw_pcb* s = raw_new(IP_PROTO_ICMP); + if (!s) { + return -1; } - request.header.chksum = inet_chksum(&request, sizeof(request)); - - ip_addr_t addr; - addr.addr = ip; - - d->endMillis = 0; + raw_recv(s, icmp_receive_callback, (void*)&requestCbkData); + raw_bind(s, IP_ADDR_ANY); - raw_recv(s, icmp_receive_callback, d); + struct pbuf *p; + struct icmp_echo_hdr *iecho; + size_t ping_size = sizeof(struct icmp_echo_hdr) + 32; - // Build the packet - p = pbuf_alloc(PBUF_IP, sizeof(request), PBUF_RAM); + p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM); if (!p) { - goto exit; + raw_remove(s); + return -1; } - //Load payload into buffer - pbuf_take(p, &request, sizeof(request)); + if ((p->len == p->tot_len) && (p->next == NULL)) { + iecho = (struct icmp_echo_hdr *)p->payload; - // Send the echo request - sendTime = millis(); - raw_sendto(s, p, &addr); + size_t i; + size_t data_len = ping_size - sizeof(struct icmp_echo_hdr); - // Wait for response - startWait = millis(); - do { - lwip_task(); - } while (d->endMillis == 0 && (millis() - startWait) < timeout); - - if (d->endMillis != 0) { - result = d->endMillis - sendTime; + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = 0xAFAF; + iecho->seqno = lwip_htons(requestCbkData.seqNum); + + /* fill the additional data buffer with some data */ + for(i = 0; i < data_len; i++) { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, ping_size); + requestCbkData.startMillis = millis(); + raw_sendto(s, p, &addr); + + } + pbuf_free(p); + + bool timeout = false; + while (!requestCbkData.endMillis && !timeout) { + timeout = (millis() - requestCbkData.startMillis) > 5000; + } + + if (timeout) { + return -1; } -exit: - pbuf_free(p); - delete d; - raw_remove(s); - return result; + return requestCbkData.endMillis - requestCbkData.startMillis; } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.h b/libraries/lwIpWrapper/src/CNetIf.h index 7606d6993..21a1ebaf9 100644 --- a/libraries/lwIpWrapper/src/CNetIf.h +++ b/libraries/lwIpWrapper/src/CNetIf.h @@ -131,10 +131,10 @@ ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr); uint32_t ip_addr_to_u32(ip_addr_t* ipaddr); -struct ping_data{ - uint32_t endMillis; - icmp_echo_hdr echo_req; - struct raw_pcb* s; +struct recv_callback_data{ + u32_t startMillis; + u32_t endMillis; + u16_t seqNum; }; /* Base class implements DHCP, derived class will switch it on or off */ From 489d637270f671878a780fb26a052d82dd87241a Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 27 Feb 2025 16:33:05 +0100 Subject: [PATCH 4/6] lwIpWrapper: CNetIf refactor ping functions --- libraries/Ethernet/src/Ethernet.cpp | 14 +++++------ libraries/WiFi/src/WiFi.cpp | 2 +- libraries/lwIpWrapper/src/CNetIf.cpp | 35 +++++++++++++++++----------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/libraries/Ethernet/src/Ethernet.cpp b/libraries/Ethernet/src/Ethernet.cpp index c2570d13f..35bbd4fd3 100644 --- a/libraries/Ethernet/src/Ethernet.cpp +++ b/libraries/Ethernet/src/Ethernet.cpp @@ -226,24 +226,24 @@ IPAddress CEthernet::dnsServerIP() { /* -------------------------------------------------------------------------- */ int CEthernet::ping(IPAddress ip, uint8_t ttl) { /* -------------------------------------------------------------------------- */ - return CLwipIf::getInstance().ping(ip, ttl); + return CLwipIf::getInstance().ping(ip, ttl); } /* -------------------------------------------------------------------------- */ int CEthernet::ping(const String &hostname, uint8_t ttl) /* -------------------------------------------------------------------------- */ { - return ping(hostname.c_str(), ttl); + return ping(hostname.c_str(), ttl); } /* -------------------------------------------------------------------------- */ int CEthernet::ping(const char* host, uint8_t ttl) { /* -------------------------------------------------------------------------- */ - IPAddress ip; - if(CLwipIf::getInstance().getHostByName(host,ip)) { - return CLwipIf::getInstance().ping(ip, ttl); - } - return -1; + IPAddress ip; + if(CLwipIf::getInstance().getHostByName(host,ip)) { + return CLwipIf::getInstance().ping(ip, ttl); + } + return -1; } CEthernet Ethernet; diff --git a/libraries/WiFi/src/WiFi.cpp b/libraries/WiFi/src/WiFi.cpp index db773d457..fe4a7e7b1 100644 --- a/libraries/WiFi/src/WiFi.cpp +++ b/libraries/WiFi/src/WiFi.cpp @@ -335,7 +335,7 @@ int CWifi::ping(IPAddress ip, uint8_t ttl) { int CWifi::ping(const String &hostname, uint8_t ttl) /* -------------------------------------------------------------------------- */ { - return ping(hostname.c_str(), ttl); + return ping(hostname.c_str(), ttl); } /* -------------------------------------------------------------------------- */ diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index e80065459..01a2c169d 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -26,22 +26,24 @@ static u8_t icmp_receive_callback(void *arg, struct raw_pcb *pcb, struct pbuf *p LWIP_ASSERT("p != NULL", p != NULL); recv_callback_data* request = (recv_callback_data*)arg; + if ((p->tot_len < (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) || + pbuf_remove_header(p, PBUF_IP_HLEN) != 0) { + return 0; /* don't consume the packet */ + } - if ((p->tot_len >= (PBUF_IP_HLEN + sizeof(struct icmp_echo_hdr))) && - pbuf_remove_header(p, PBUF_IP_HLEN) == 0) { - iecho = (struct icmp_echo_hdr *)p->payload; + iecho = (struct icmp_echo_hdr *)p->payload; - if ((iecho->id == 0xAFAF) && (iecho->seqno == lwip_htons(request->seqNum))) { - /* do some ping result processing */ - request->endMillis = millis(); - pbuf_free(p); - return 1; /* eat the packet */ - } + if(iecho->id != 0xAFAF || iecho->seqno != lwip_htons(request->seqNum)) { /* not eaten, restore original packet */ pbuf_add_header(p, PBUF_IP_HLEN); + return 0; } - return 0; /* don't eat the packet */ + /* do some ping result processing */ + request->endMillis = millis(); + pbuf_free(p); + return 1; /* consume the packet */ + } ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) @@ -202,12 +204,17 @@ int CLwipIf::ping(IPAddress ip, uint8_t ttl) } pbuf_free(p); - bool timeout = false; - while (!requestCbkData.endMillis && !timeout) { - timeout = (millis() - requestCbkData.startMillis) > 5000; + CLwipIf::getInstance().startSyncRequest(); + + while (!requestCbkData.endMillis && (millis() - requestCbkData.startMillis) <= 5000) { + CLwipIf::getInstance().lwip_task(); } - if (timeout) { + CLwipIf::getInstance().restartAsyncRequest(); + + raw_remove(s); + + if (!requestCbkData.endMillis) { return -1; } From 7f6ad1ea9b24b4e7cad0c67d62d7272c17a6fbe3 Mon Sep 17 00:00:00 2001 From: fabik111 Date: Thu, 27 Feb 2025 16:33:35 +0100 Subject: [PATCH 5/6] add ping examples --- .../examples/EthernetPing/EthernetPing.ino | 83 ++++++++++++ libraries/WiFi/examples/WiFiPing/WiFiPing.ino | 120 ++++++++++++++++++ .../WiFi/examples/WiFiPing/arduino_secrets.h | 2 + 3 files changed, 205 insertions(+) create mode 100644 libraries/Ethernet/examples/EthernetPing/EthernetPing.ino create mode 100644 libraries/WiFi/examples/WiFiPing/WiFiPing.ino create mode 100644 libraries/WiFi/examples/WiFiPing/arduino_secrets.h diff --git a/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino b/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino new file mode 100644 index 000000000..2baadaadd --- /dev/null +++ b/libraries/Ethernet/examples/EthernetPing/EthernetPing.ino @@ -0,0 +1,83 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the Ethernet module. + + created 14 February 2024 + by paulvha + + updated 27 February 2025 + by Fabik111 + + */ + +#include "EthernetC33.h" + +int status = WL_IDLE_STATUS; + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(10, 130, 22, 84); + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // start the Ethernet connection: + if (Ethernet.begin() == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // try to configure using IP address instead of DHCP: + // IN THAT CASE YOU SHOULD CONFIGURE manually THE DNS or USE the IPAddress Server variable above + // that is what is automatically done here... + Ethernet.begin(ip); + } + // give the Ethernet shield a second to initialize: + delay(2000); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = Ethernet.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + // setting ttl to 128 and ping count to 10 + int res1 = Ethernet.ping(remote_host); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + } + + Serial.println(); + delay(1000); +} diff --git a/libraries/WiFi/examples/WiFiPing/WiFiPing.ino b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino new file mode 100644 index 000000000..a8f9ee979 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/WiFiPing.ino @@ -0,0 +1,120 @@ +/* + Web ICMP Ping + + This sketch pings a device based on the IP address or the hostname + using the WiFi module. By default the attempt is performed 5 times, but can + be changed to max. 255 + + It requires at least version 0.5.0 of USB Wifi bridge firmware and WiFiS3 library. + + This example is written for a network using WPA encryption. For + WEP or WPA, change the WiFi.begin() call accordingly. + + created 14 February 2024 + by paulvha + + updated 27 February 2025 + by Fabik111 + + */ + +#include "WiFiC3.h" +#include "arduino_secrets.h" + +///////please enter your sensitive data in the Secret tab/arduino_secrets.h +char ssid[] = SECRET_SSID; // your network SSID (name) +char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) +int keyIndex = 0; // your network key index number (needed only for WEP) + +int status = WL_IDLE_STATUS; + +/* -------------------------------------------------------------------------- */ +void setup() { +/* -------------------------------------------------------------------------- */ + //Initialize serial and wait for port to open: + Serial.begin(115200); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // check for the WiFi module: + if (WiFi.status() == WL_NO_MODULE) { + Serial.println("Communication with WiFi module failed."); + // don't continue + while (true); + } + + // attempt to connect to WiFi network: + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + // Connect to WPA/WPA2 network. Change this line if using open or WEP network: + status = WiFi.begin(ssid, pass); + + // wait 10 seconds for connection: + delay(10000); + } + + printWifiStatus(); +} + +/* -------------------------------------------------------------------------- */ +void loop() { +/* -------------------------------------------------------------------------- */ + + // Ping IP + const IPAddress remote_ip(140,82,121,4); + Serial.print("Trying to ping github.com on IP: "); + Serial.println(remote_ip); + + // using default ping count of 1 + int res = WiFi.ping(remote_ip); + + if (res > 0) { + Serial.print("Ping response time: "); + Serial.print(res); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on IP!"); + } + + // Ping Host + const char* remote_host = "www.google.com"; + Serial.print("Trying to ping host: "); + Serial.println(remote_host); + + // setting ttl to 128 and ping count to 10 + int res1 = WiFi.ping(remote_host); + + if (res1 > 0) { + Serial.print("Ping average response time: "); + Serial.print(res1); + Serial.println(" ms"); + } + else { + Serial.println("Timeout on host!"); + } + + Serial.println(); + delay(1000); +} + +/* -------------------------------------------------------------------------- */ +void printWifiStatus() { +/* -------------------------------------------------------------------------- */ + // print the SSID of the network you're attached to: + Serial.print("SSID: "); + Serial.println(WiFi.SSID()); + + // print your board's IP address: + IPAddress ip = WiFi.localIP(); + Serial.print("IP Address: "); + Serial.println(ip); + + // print the received signal strength: + long rssi = WiFi.RSSI(); + Serial.print("signal strength (RSSI):"); + Serial.print(rssi); + Serial.println(" dBm"); +} diff --git a/libraries/WiFi/examples/WiFiPing/arduino_secrets.h b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h new file mode 100644 index 000000000..0c9fdd556 --- /dev/null +++ b/libraries/WiFi/examples/WiFiPing/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" From 8094f719bf74c5327438902b9883e8abcef73c9e Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 3 Mar 2025 09:05:20 +0100 Subject: [PATCH 6/6] lwIpWrapper: CNetIf make recv_callback_data a static data structure This ensure access to existing data if icmp callback is fired after ping timeout --- libraries/lwIpWrapper/src/CNetIf.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/lwIpWrapper/src/CNetIf.cpp b/libraries/lwIpWrapper/src/CNetIf.cpp index 01a2c169d..ca1495f50 100644 --- a/libraries/lwIpWrapper/src/CNetIf.cpp +++ b/libraries/lwIpWrapper/src/CNetIf.cpp @@ -43,7 +43,6 @@ static u8_t icmp_receive_callback(void *arg, struct raw_pcb *pcb, struct pbuf *p request->endMillis = millis(); pbuf_free(p); return 1; /* consume the packet */ - } ip_addr_t* u8_to_ip_addr(uint8_t* ipu8, ip_addr_t* ipaddr) @@ -159,9 +158,15 @@ int CLwipIf::ping(IPAddress ip, uint8_t ttl) (void)ttl; ip_addr_t addr; addr.addr = ip; - recv_callback_data requestCbkData = { 0, 0, (uint16_t)random(0xffff) }; - //Create a raw socket + /* ICMP ping callback data structure */ + static recv_callback_data requestCbkData; + + /* initialize callback data for a new request */ + memset(&requestCbkData, 0, sizeof(recv_callback_data)); + requestCbkData.seqNum = (uint16_t)random(0xffff); + + /* Create a raw socket */ struct raw_pcb* s = raw_new(IP_PROTO_ICMP); if (!s) { return -1;