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