FabGL
ESP32 Display Controller and Graphics Library
ICMP.cpp
1/*
2 Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
3 Copyright (c) 2019-2022 Fabrizio Di Vittorio.
4 All rights reserved.
5
6
7* Please contact fdivitto2013@gmail.com if you need a commercial license.
8
9
10* This library and related software is available under GPL v3.
11
12 FabGL is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 FabGL is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with FabGL. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27#ifdef ARDUINO
28
29
30#include "ICMP.h"
31
32#include "Arduino.h"
33#include "WiFiGeneric.h"
34
35
36namespace fabgl {
37
38
39ICMP::ICMP()
40 : m_queue(xQueueCreate(1, sizeof(uint8_t))), m_waitingID(rand() & 0xFFFF), m_waitingSeq(-1)
41{
42}
43
44
45ICMP::~ICMP()
46{
47 vQueueDelete(m_queue);
48}
49
50
51// -1 = timeout
52// -2 = cannot resolve name
53int ICMP::ping(char const * host)
54{
55 IPAddress hostIP((uint32_t)0);
56 if (!WiFiGenericClass::hostByName(host, hostIP))
57 return -2;
58 return ping(hostIP);
59}
60
61
62// -1 = timeout
63int ICMP::ping(IPAddress const &dest)
64{
65 static int32_t const TIMEOUT = 1000;
66 static int32_t const TIMEOUT_RESULT = -1;
67
68 m_destIP = dest;
69
70 int result = TIMEOUT_RESULT;
71
72 // generate seq
73 ++m_waitingSeq;
74
75 // prepare packet to send
76 pbuf * hdrbuf = pbuf_alloc(PBUF_IP, sizeof(icmp_echo_hdr), PBUF_RAM);
77 icmp_echo_hdr * hdr = (icmp_echo_hdr *) hdrbuf->payload;
78 hdr->type = ICMP_ECHO;
79 hdr->code = 0;
80 hdr->chksum = 0;
81 hdr->id = htons(m_waitingID);
82 hdr->seqno = htons(m_waitingSeq);
83 hdr->chksum = inet_chksum((uint16_t *) hdr, sizeof(icmp_echo_hdr));
84
85 // send Echo request
86 raw_pcb * pcb = raw_new(IP_PROTO_ICMP);
87 raw_recv(pcb, ICMP::raw_recv_fn, this);
88 raw_bind(pcb, IP_ADDR_ANY);
89
90 ip_addr_t addr;
91 addr.type = IPADDR_TYPE_V4;
92 addr.u_addr.ip4.addr = dest;
93 raw_sendto(pcb, hdrbuf, &addr);
94 pbuf_free(hdrbuf);
95
96 result = -1;
97 int32_t t1 = micros();
98 uint8_t c;
99 if (xQueueReceive(m_queue, &c, pdMS_TO_TICKS(TIMEOUT)))
100 result = micros() - t1;
101 raw_remove(pcb);
102
103 return result;
104}
105
106
107uint8_t ICMP::raw_recv_fn(void * arg, raw_pcb * pcb, pbuf * p, const ip_addr_t * addr)
108{
109 ICMP * this_ = (ICMP *)arg;
110
111 ip_hdr * iphdr = (ip_hdr *)p->payload;
112
113 int ttl = IPH_TTL(iphdr);
114
115 if (p->tot_len >= sizeof(ip_hdr) + sizeof(icmp_echo_hdr) && pbuf_header(p, -(s16_t)sizeof(ip_hdr)) == 0) {
116 icmp_echo_hdr * hdr = (icmp_echo_hdr *) p->payload;
117 if (ntohs(hdr->id) == this_->m_waitingID && ntohs(hdr->seqno) == this_->m_waitingSeq) {
118 this_->m_receivedBytes = p->tot_len;
119 this_->m_receivedTTL = ttl;
120 uint8_t c = 0;
121 xQueueSendToBack(this_->m_queue, &c, portMAX_DELAY);
122 }
123 pbuf_free(p);
124 return 1;
125 }
126
127 return 0;
128}
129
130
131
132}
133
134
135
136#endif // #ifdef ARDUINO
This file contains ICMP (ping) class.