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-2021 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 
36 namespace fabgl {
37 
38 
39 ICMP::ICMP()
40  : m_queue(xQueueCreate(1, sizeof(uint8_t))), m_waitingID(rand() & 0xFFFF), m_waitingSeq(-1)
41 {
42 }
43 
44 
45 ICMP::~ICMP()
46 {
47  vQueueDelete(m_queue);
48 }
49 
50 
51 // -1 = timeout
52 // -2 = cannot resolve name
53 int 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
63 int 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 
107 uint8_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.
Definition: canvas.cpp:36