1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string.h>
16 #include "esp_ping.h"
17 
18 #include "lwip/ip_addr.h"
19 typedef struct _ping_option {
20     ip_addr_t ping_target;
21     uint32_t ping_count;
22     uint32_t ping_rcv_timeout;
23     uint32_t ping_delay;
24     uint32_t interface;
25     size_t ping_data_len;
26     uint16_t ping_id;
27     u8_t ping_tos;
28     esp_ping_found_fn ping_res_fn;
29     esp_ping_found    ping_res;
30     void    *ping_reserve;
31 } ping_option;
32 
33 static ping_option ping_option_info[1];
34 
esp_ping_set_target(ping_target_id_t opt_id,void * opt_val,uint32_t opt_len)35 esp_err_t esp_ping_set_target(ping_target_id_t opt_id, void *opt_val, uint32_t opt_len)
36 {
37     esp_err_t ret = ESP_OK;
38 
39     if (opt_val == NULL) {
40         return ESP_ERR_PING_INVALID_PARAMS;
41     }
42 
43     switch (opt_id) {
44     case PING_TARGET_IP_ADDRESS:
45         ipaddr_aton(opt_val, &(ping_option_info->ping_target));
46         break;
47     case PING_TARGET_IP_ADDRESS_COUNT:
48         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
49         ping_option_info->ping_count = *(uint32_t *)opt_val;
50         break;
51     case PING_TARGET_IF_INDEX:
52         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
53         ping_option_info->interface = *(uint32_t *)opt_val;
54         break;
55     case PING_TARGET_RCV_TIMEO:
56         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
57         ping_option_info->ping_rcv_timeout = (*(uint32_t *)opt_val);
58         break;
59     case PING_TARGET_DELAY_TIME:
60         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
61         ping_option_info->ping_delay = (*(uint32_t *)opt_val);
62         break;
63     case PING_TARGET_DATA_LEN:
64         ESP_PING_CHECK_OPTLEN(opt_len, size_t);
65         ping_option_info->ping_data_len = (*(size_t *)opt_val);
66         break;
67     case PING_TARGET_ID:
68         ESP_PING_CHECK_OPTLEN(opt_len, uint16_t);
69         ping_option_info->ping_id = *(uint16_t *)opt_val;
70         break;
71     case PING_TARGET_IP_TOS:
72         ESP_PING_CHECK_OPTLEN(opt_len, u8_t);
73         ping_option_info->ping_tos = *(u8_t *)opt_val;
74         break;
75     case PING_TARGET_RES_FN:
76         ping_option_info->ping_res_fn = opt_val;
77         break;
78     case PING_TARGET_RES_RESET:
79         memset(&ping_option_info->ping_res, 0, sizeof(ping_option_info->ping_res));
80         break;
81     default:
82         ret = ESP_ERR_PING_INVALID_PARAMS;
83         break;
84     }
85 
86     return ret;
87 }
88 
esp_ping_get_target(ping_target_id_t opt_id,void * opt_val,uint32_t opt_len)89 esp_err_t esp_ping_get_target(ping_target_id_t opt_id, void *opt_val, uint32_t opt_len)
90 {
91     esp_err_t ret = ESP_OK;
92 
93     if (opt_val == NULL) {
94         return ESP_ERR_PING_INVALID_PARAMS;
95     }
96 
97     switch (opt_id) {
98     case PING_TARGET_IP_ADDRESS:
99         ip_addr_copy(*(ip_addr_t*)opt_val, ping_option_info->ping_target);
100         break;
101     case PING_TARGET_IP_ADDRESS_COUNT:
102         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
103         *(uint32_t *)opt_val = ping_option_info->ping_count;
104         break;
105     case PING_TARGET_IF_INDEX:
106         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
107         *(uint32_t *)opt_val = ping_option_info->interface;
108         break;
109     case PING_TARGET_RCV_TIMEO:
110         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
111         *(uint32_t *)opt_val = ping_option_info->ping_rcv_timeout;
112         break;
113     case PING_TARGET_DELAY_TIME:
114         ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
115         *(uint32_t *)opt_val = ping_option_info->ping_delay;
116         break;
117     case PING_TARGET_DATA_LEN:
118         ESP_PING_CHECK_OPTLEN(opt_len, size_t);
119         *(size_t *)opt_val = ping_option_info->ping_data_len;
120         break;
121     case PING_TARGET_ID:
122         ESP_PING_CHECK_OPTLEN(opt_len, uint16_t);
123         *(uint16_t *)opt_val = ping_option_info->ping_id;
124         break;
125     case PING_TARGET_IP_TOS:
126         ESP_PING_CHECK_OPTLEN(opt_len, uint16_t);
127         *(uint16_t *)opt_val = ping_option_info->ping_tos;
128         break;
129     default:
130         ret = ESP_ERR_PING_INVALID_PARAMS;
131         break;
132     }
133 
134     return ret;
135 }
136 
esp_ping_result(uint8_t res_val,uint16_t ping_len,uint32_t ping_time)137 esp_err_t esp_ping_result(uint8_t res_val, uint16_t ping_len, uint32_t ping_time)
138 {
139     esp_err_t ret = ESP_OK;
140 
141     ping_option_info->ping_res.ping_err = res_val;
142 
143     if (res_val != PING_RES_FINISH) {
144         ping_option_info->ping_res.bytes = ping_len;
145         ping_option_info->ping_res.resp_time = ping_time;
146         ping_option_info->ping_res.total_bytes += ping_len;
147         ping_option_info->ping_res.send_count ++;
148 
149         if (res_val == PING_RES_TIMEOUT) {
150             ping_option_info->ping_res.timeout_count ++;
151         } else {
152             if (!ping_option_info->ping_res.min_time || (ping_time < ping_option_info->ping_res.min_time)) {
153                 ping_option_info->ping_res.min_time = ping_time;
154             }
155 
156             if (ping_time > ping_option_info->ping_res.max_time) {
157                 ping_option_info->ping_res.max_time = ping_time;
158             }
159 
160 
161             ping_option_info->ping_res.total_time += ping_time;
162             ping_option_info->ping_res.recv_count ++;
163         }
164     }
165 
166     if (ping_option_info->ping_res_fn) {
167         ping_option_info->ping_res_fn(PING_TARGET_RES_FN, &ping_option_info->ping_res);
168         if (res_val == PING_RES_FINISH) {
169             memset(&ping_option_info->ping_res, 0, sizeof(esp_ping_found));
170         }
171     }
172 
173     return ret;
174 }
175