XFusion API v1.3.0
载入中...
搜索中...
未找到
xf_ping.c
浏览该文件的文档.
1
12/* ==================== [Includes] ========================================== */
13
14#include <stdlib.h>
15#include <stdbool.h>
16
17#include "lwip/opt.h"
18#include "lwip/init.h"
19#include "lwip/mem.h"
20#include "lwip/icmp.h"
21#include "lwip/netif.h"
22#include "lwip/sys.h"
23#include "lwip/timeouts.h"
24#include "lwip/inet.h"
25#include "lwip/inet_chksum.h"
26#include "lwip/ip.h"
27#include "lwip/netdb.h"
28#include "lwip/sockets.h"
29
30#include "xf_sys.h"
31#include "xf_ping.h"
32
33/* ==================== [Defines] =========================================== */
34
35#define PING_TIME_DIFF_MS(_end, _start) \
36 ((uint32_t)((_end - _start) / 1000))
37
38#define PING_CHECK_START_TIMEOUT_MS (100)
39
40#define PING_FLAGS_INIT (1 << 0)
41#define PING_FLAGS_RUN (1 << 1)
42
43#define THREAD_NOTIFY_BIT 0x01
44
45/* ==================== [Typedefs] ========================================== */
46
47/* ==================== [Static Prototypes] ================================= */
48
51static void xf_ping_thread(void *args);
52
53/* ==================== [Static Variables] ================================== */
54
55static const char *TAG = "xf_ping";
56
57/* ==================== [Macros] ============================================ */
58
59#define XF_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format, ...) \
60 do { \
61 if (unlikely(!(a))) { \
62 XF_LOGE(log_tag, format, ##__VA_ARGS__); \
63 ret = err_code; \
64 goto goto_tag; \
65 } \
66 } while (0)
67
68/* ==================== [Global Functions] ================================== */
69
71 const xf_ping_cfg_t *p_cfg, xf_ping_cb_t cb_func, void *user_args,
72 xf_ping_t *hdl_out)
73{
74 xf_err_t ret = XF_FAIL;
75 xf_ping_ctx_t *ctx = NULL;
76
80 TAG, "hdl_out-%s", xf_err_to_name(XF_ERR_INVALID_ARG));
81
82 ctx = xf_malloc(sizeof(xf_ping_ctx_t));
84 TAG, "ping_ctx-%s", xf_err_to_name(XF_ERR_NO_MEM));
85 xf_memset(ctx, 0x00, sizeof(xf_ping_ctx_t));
86
87 /* 防止 ping 任务退出 */
89
90 ctx->task_exit_flag = false;
91 xf_osal_thread_attr_t thread_attr = {
93 .priority = p_cfg->task_prio,
94 .stack_size = p_cfg->task_stack_size,
95 };
96 ctx->task_hdl = xf_osal_thread_create(xf_ping_thread, ctx, &thread_attr);
97 XF_GOTO_ON_FALSE(ctx->task_hdl != NULL, XF_ERR_NO_MEM, l_err,
98 TAG, "ping_task-%s", xf_err_to_name(XF_ERR_NO_MEM));
99
100 if (cb_func) {
101 ctx->cb_func = cb_func;
102 ctx->user_args = user_args;
103 }
104 ctx->auto_delete_flag = p_cfg->auto_delete_flag;
105 ctx->recv_addr = p_cfg->target_addr;
106 ctx->target_addr_type = p_cfg->target_addr.type;
107 ctx->count = p_cfg->count;
108 ctx->interval_ms = p_cfg->interval_ms;
109 ctx->tos = p_cfg->tos;
110 ctx->ttl = p_cfg->ttl;
111 ctx->icmp_pkt_size = sizeof(struct icmp_echo_hdr) + p_cfg->data_size;
112 ctx->packet_hdr = xf_malloc(ctx->icmp_pkt_size);
113 XF_GOTO_ON_FALSE(ctx->packet_hdr, XF_ERR_NO_MEM, l_err,
114 TAG, "icmp_pkt-%s", xf_err_to_name(XF_ERR_NO_MEM));
115 xf_memset(ctx->packet_hdr, 0x00, ctx->icmp_pkt_size);
116
117 ctx->packet_hdr->code = 0;
118 ctx->packet_hdr->id = ((uint32_t)ctx->task_hdl) & 0xFFFF;
120 char *d = (char *)(ctx->packet_hdr) + sizeof(struct icmp_echo_hdr);
121 for (uint32_t i = 0; i < p_cfg->data_size; i++) {
122 d[i] = 'A' + i;
123 }
124
125 /* 创建 socket */
126 if (IP_IS_V4(&p_cfg->target_addr)
127#if CONFIG_XF_NET_APPS_ENABLE_IPV6
128 || ip6_addr_isipv4mappedipv6(ip_2_ip6(&p_cfg->target_addr))
129#endif
130 ) {
131 ctx->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
132 }
133#if CONFIG_XF_NET_APPS_ENABLE_IPV6
134 else {
135 ctx->sock = socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6);
136 }
137#endif
138 XF_GOTO_ON_FALSE(ctx->sock >= 0, XF_FAIL, l_err,
139 TAG, "create socket failed: %d", ctx->sock);
140
141 if (p_cfg->interface) {
142 struct ifreq iface;
143 if (netif_index_to_name(p_cfg->interface, iface.ifr_name) == NULL) {
144 XF_LOGE(TAG, "fail to find interface name with netif index %d",
145 p_cfg->interface);
146 goto l_err;
147 }
148 if (setsockopt(ctx->sock, SOL_SOCKET, SO_BINDTODEVICE, &iface, sizeof(iface)) != 0) {
149 XF_LOGE(TAG, "fail to setsockopt SO_BINDTODEVICE");
150 goto l_err;
151 }
152 }
153
154 struct timeval timeout;
155 timeout.tv_sec = p_cfg->timeout_ms / 1000;
156 timeout.tv_usec = (p_cfg->timeout_ms % 1000) * 1000;
157 setsockopt(ctx->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
158 setsockopt(ctx->sock, IPPROTO_IP, IP_TOS, &ctx->tos, sizeof(ctx->tos));
159 setsockopt(ctx->sock, IPPROTO_IP, IP_TTL, &ctx->ttl, sizeof(ctx->ttl));
160
161 if (IP_IS_V4(&p_cfg->target_addr)) {
162 struct sockaddr_in *to4 = (struct sockaddr_in *)&ctx->target_addr;
163 to4->sin_family = AF_INET;
164 inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(&p_cfg->target_addr));
165 ctx->packet_hdr->type = ICMP_ECHO;
166 }
167#if CONFIG_XF_NET_APPS_ENABLE_IPV6
168 if (IP_IS_V6(&p_cfg->target_addr)) {
169 struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ctx->target_addr;
170 to6->sin6_family = AF_INET6;
171 inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(&p_cfg->target_addr));
172 ctx->packet_hdr->type = ICMP6_TYPE_EREQ;
173 }
174#endif
175
176 *hdl_out = (xf_ping_t)ctx;
177
178 return XF_OK;
179
180l_err:
181 if (ctx) {
182 if (ctx->sock > 0) {
183 closesocket(ctx->sock);
184 }
185 if (ctx->packet_hdr) {
186 xf_free(ctx->packet_hdr);
187 }
188 if (ctx->task_hdl) {
189 xf_osal_thread_delete(ctx->task_hdl);
190 }
191 xf_free(ctx);
192 }
193 return ret;
194}
195
197{
198 xf_err_t ret = XF_OK;
202
204
205 size_t wait_cnt = 0;
206#define WAIT_CNT_MAX 1000
207 while (ctx->task_exit_flag != true) {
209 wait_cnt++;
210 if (wait_cnt >= WAIT_CNT_MAX) {
211 xf_osal_thread_delete(ctx->task_hdl);
213 break;
214 }
215 }
216
217 xf_free(ctx);
218
219 return XF_OK;
220l_err:
221 return ret;
222}
223
225{
226 xf_err_t ret = XF_OK;
230
233
234 return XF_OK;
235l_err:
236 return ret;
237}
238
240 xf_ping_t hdl, const xf_ping_cfg_t *p_cfg, xf_ping_cfg_update_flags_t *p_flags)
241{
242 xf_err_t ret = XF_OK;
246
247 bool b_running = false;
248 b_running = xf_ping_is_running(hdl);
249 XF_GOTO_ON_FALSE(false == b_running, XF_ERR_BUSY, l_err,
250 TAG, "hdl-%s", xf_err_to_name(XF_ERR_BUSY));
251
252 if ((NULL == p_cfg) || (NULL == p_flags)) {
253 goto l_skip_recfg;
254 }
255
256 if (p_flags->b_count) {
257 ctx->count = p_cfg->count;
258 }
259 if (p_flags->b_interval_ms) {
260 ctx->interval_ms = p_cfg->interval_ms;
261 }
262 if (p_flags->b_timeout_ms) {
263 struct timeval timeout;
264 timeout.tv_sec = p_cfg->timeout_ms / 1000;
265 timeout.tv_usec = (p_cfg->timeout_ms % 1000) * 1000;
266 setsockopt(ctx->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
267 }
268 if (p_flags->b_tos) {
269 ctx->tos = p_cfg->tos;
270 setsockopt(ctx->sock, IPPROTO_IP, IP_TOS, &ctx->tos, sizeof(ctx->tos));
271 }
272 if (p_flags->b_ttl) {
273 ctx->ttl = p_cfg->ttl;
274 setsockopt(ctx->sock, IPPROTO_IP, IP_TTL, &ctx->ttl, sizeof(ctx->ttl));
275 }
276 if (p_flags->b_target_addr) {
277 ctx->recv_addr = p_cfg->target_addr;
278 ctx->target_addr_type = p_cfg->target_addr.type;
279 if (IP_IS_V4(&p_cfg->target_addr)) {
280 struct sockaddr_in *to4 = (struct sockaddr_in *)&ctx->target_addr;
281 to4->sin_family = AF_INET;
282 inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(&p_cfg->target_addr));
283 ctx->packet_hdr->type = ICMP_ECHO;
284 }
285#if CONFIG_XF_NET_APPS_ENABLE_IPV6
286 if (IP_IS_V6(&p_cfg->target_addr)) {
287 struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ctx->target_addr;
288 to6->sin6_family = AF_INET6;
289 inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(&p_cfg->target_addr));
290 ctx->packet_hdr->type = ICMP6_TYPE_EREQ;
291 }
292#endif
293 }
294 if (p_flags->b_interface) {
295 struct ifreq iface;
296 if (netif_index_to_name(p_cfg->interface, iface.ifr_name) == NULL) {
297 XF_LOGE(TAG, "fail to find interface name with netif index %d",
298 p_cfg->interface);
299 goto l_err;
300 }
301 if (setsockopt(ctx->sock, SOL_SOCKET, SO_BINDTODEVICE, &iface, sizeof(iface)) != 0) {
302 XF_LOGE(TAG, "fail to setsockopt SO_BINDTODEVICE");
303 goto l_err;
304 }
305 }
306 if (p_flags->b_auto_delete_flag) {
307 ctx->auto_delete_flag = p_cfg->auto_delete_flag;
308 }
309
310l_skip_recfg:;
311
314
315 return XF_OK;
316l_err:
317 return ret;
318}
319
321{
322 bool ret = false;
324 XF_GOTO_ON_FALSE(ctx, false, l_err,
326 return ctx->ping_running_flag;
327l_err:
328 return ret;
329}
330
332{
333 xf_err_t ret = XF_OK;
337
339
340 return XF_OK;
341l_err:
342 return ret;
343}
344
345/* ==================== [Static Functions] ================================== */
346
348{
349 xf_err_t ret = XF_OK;
350
351 ctx->packet_hdr->seqno++;
352 /* seqno 已更改,重新计算校验和 */
353 ctx->packet_hdr->chksum = 0;
354 if (ctx->packet_hdr->type == ICMP_ECHO) {
355 ctx->packet_hdr->chksum = inet_chksum(ctx->packet_hdr, ctx->icmp_pkt_size);
356 }
357
358 socklen_t socklen = (ctx->target_addr_type == IPADDR_TYPE_V4)
359 ? sizeof(struct sockaddr_in)
360 : sizeof(struct sockaddr_in6);
361 ssize_t sent = sendto(ctx->sock, ctx->packet_hdr, ctx->icmp_pkt_size, 0,
362 (struct sockaddr *)&ctx->target_addr, socklen);
363
364 if (sent != (ssize_t)ctx->icmp_pkt_size) {
365 int opt_val;
366 socklen_t opt_len = sizeof(opt_val);
367 getsockopt(ctx->sock, SOL_SOCKET, SO_ERROR, &opt_val, &opt_len);
368 XF_LOGE(TAG, "send error=%d", opt_val);
369 ret = XF_FAIL;
370 } else {
371 ctx->transmitted++;
372 }
373 return ret;
374}
375
377{
378 char buf[64];
379 int len = 0;
380 struct sockaddr_storage from;
381
382 int fromlen = (ctx->target_addr_type == IPADDR_TYPE_V4)
383 ? sizeof(struct sockaddr_in)
384 : sizeof(struct sockaddr_in6);
385 uint16_t data_head = 0;
386
387 while ((len = recvfrom(ctx->sock, buf, sizeof(buf), 0,
388 (struct sockaddr *)&from, (socklen_t *)&fromlen)) > 0) {
389 if (from.ss_family == AF_INET) {
390 // IPv4
391 struct sockaddr_in *from4 = (struct sockaddr_in *)&from;
392 inet_addr_to_ip4addr(ip_2_ip4(&ctx->recv_addr), &from4->sin_addr);
393 IP_SET_TYPE_VAL(ctx->recv_addr, IPADDR_TYPE_V4);
394 data_head = (uint16_t)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr));
395 }
396#if CONFIG_XF_NET_APPS_ENABLE_IPV6
397 else {
398 // IPv6
399 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from;
400 inet6_addr_to_ip6addr(ip_2_ip6(&ctx->recv_addr), &from6->sin6_addr);
401 IP_SET_TYPE_VAL(ctx->recv_addr, IPADDR_TYPE_V6);
402 data_head = (uint16_t)(sizeof(struct ip6_hdr) + sizeof(struct icmp6_echo_hdr));
403 }
404#endif
405 if (len >= data_head) {
406 if (IP_IS_V4_VAL(ctx->recv_addr)) {
407 struct ip_hdr *iphdr = (struct ip_hdr *)buf;
408 struct icmp_echo_hdr *iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
409 if ((iecho->id == ctx->packet_hdr->id) && (iecho->seqno == ctx->packet_hdr->seqno)) {
410 ctx->received++;
411 ctx->ttl = iphdr->_ttl;
412 ctx->tos = iphdr->_tos;
413 ctx->recv_len = lwip_ntohs(IPH_LEN(iphdr)) - data_head;
414 return len;
415 }
416 }
417#if CONFIG_XF_NET_APPS_ENABLE_IPV6
418 else if (IP_IS_V6_VAL(ctx->recv_addr)) {
419 struct ip6_hdr *iphdr = (struct ip6_hdr *)buf;
420 struct icmp6_echo_hdr *iecho6 = (struct icmp6_echo_hdr *)(buf + sizeof(struct ip6_hdr));
421 if ((iecho6->id == ctx->packet_hdr->id) && (iecho6->seqno == ctx->packet_hdr->seqno)) {
422 ctx->received++;
423 ctx->recv_len = IP6H_PLEN(iphdr) - sizeof(struct icmp6_echo_hdr);
424 return len;
425 }
426 }
427#endif
428 }
429 fromlen = (ctx->target_addr_type == IPADDR_TYPE_V4)
430 ? sizeof(struct sockaddr_in)
431 : sizeof(struct sockaddr_in6);
432 }
433 /* 如果超时,len 将为 -1 */
434 return len;
435}
436
437static void xf_ping_thread(void *args)
438{
439 xf_ping_ctx_t *ctx = (xf_ping_ctx_t *)(args);
440 int recv_ret;
441 xf_err_t xf_ret = XF_OK;
443 uint32_t interval_ticks;
444 uint32_t last_wake;
445 xf_us_t start_time, end_time;
446
447 for (;;) {
448 if (!(ctx->flags & PING_FLAGS_INIT)) {
449 break;
450 }
451 /* 此处 PING_FLAGS_RUN 避免长时间等待通知 */
452 if (!(ctx->flags & PING_FLAGS_RUN)) {
454 continue;
455 }
457 if (xf_ret != XF_OK) {
458 continue;
459 }
462
463 ctx->packet_hdr->seqno = 0;
464 ctx->transmitted = 0;
465 ctx->received = 0;
466 ctx->total_time_ms = 0;
467
468 /* 此处 PING_FLAGS_RUN 用于在运行时暂停 */
469 while ((ctx->flags & PING_FLAGS_RUN)
470 && ((ctx->count == 0xFFFFFFFF) || (ctx->packet_hdr->seqno < ctx->count))) {
471 last_wake = xf_osal_kernel_get_tick_count();
472
473 /*
474 ctx->flags 告诉 xf_ping_thread ping 能否运行;
475 ctx->ping_running_flag 指示 ping 是否正在运行。
476 */
477 ctx->ping_running_flag = true;
478
480
481 start_time = xf_sys_time_get_us();
482 recv_ret = xf_ping_receive(ctx);
483 end_time = xf_sys_time_get_us();
484
485 ctx->elapsed_time_ms = PING_TIME_DIFF_MS(end_time, start_time);
486 ctx->total_time_ms += ctx->elapsed_time_ms;
487
488 if (ctx->cb_func) {
489 xf_ping_event_id_t event_id = (recv_ret >= 0) ? (XF_PING_EVENT_SUCC) : (XF_PING_EVENT_TIMEOUT);
490 ctx->cb_func(event_id, (void *)ctx, ctx->user_args);
491 }
492
493 interval_ticks = xf_osal_kernel_ms_to_ticks(ctx->interval_ms);
494 if (interval_ticks) {
495 xf_osal_delay_until(last_wake + interval_ticks);
496 }
497 } /* while */
498
500 ctx->ping_running_flag = false;
501
502 if (ctx->cb_func) {
503 ctx->cb_func(XF_PING_EVENT_END, (void *)ctx, ctx->user_args);
504 }
505
506 if (ctx->auto_delete_flag) {
507 break;
508 }
509 } /* for */
510
511 if (ctx->packet_hdr) {
512 xf_free(ctx->packet_hdr);
513 }
514 if (ctx->sock >= 0) {
515 closesocket(ctx->sock);
516 }
517 ctx->task_exit_flag = true;
518
519 if (ctx->cb_func) {
520 ctx->cb_func(XF_PING_EVENT_DELETE, (void *)ctx, ctx->user_args);
521 }
522
523 if (ctx->auto_delete_flag) {
524 xf_free(ctx);
525 }
526
527 /* 如果未设置自动释放,则 ctx 需手动调用 xf_ping_delete_session() 释放 */
529}
uint32_t xf_osal_kernel_ms_to_ticks(uint32_t ms)
将 ms 数转为滴答数.
uint32_t xf_osal_kernel_get_tick_count(void)
获取 RTOS 内核滴答计数。
xf_err_t xf_osal_thread_delete(xf_osal_thread_t thread)
终止线程的执行。
xf_osal_thread_t xf_osal_thread_create(xf_osal_thread_func_t func, void *argument, const xf_osal_thread_attr_t *attr)
创建一个线程并将其添加到活动线程中。
xf_err_t xf_osal_delay_until(uint32_t ticks)
(睡眠)等到指定时间刻度。
uint32_t xf_osal_thread_notify_get(void)
获取当前正在运行的线程的当前线程标志。
xf_err_t xf_osal_delay_ms(uint32_t ms)
(睡眠)等待超时,以 ms 为单位。
xf_err_t xf_osal_thread_notify_clear(uint32_t notify)
清除当前运行线程的指定线程标志。
xf_err_t xf_osal_thread_notify_wait(uint32_t notify, uint32_t options, uint32_t timeout)
当前运行线程等待一个或多个线程标志变为有信号状态。
xf_err_t xf_osal_thread_notify_set(xf_osal_thread_t thread, uint32_t notify)
设置线程的指定线程标志。
#define XF_OSAL_WAIT_ANY
标志选项。 xf_osal_event_wait() 或 xf_osal_thread_notify_wait().
Definition xf_osal_def.h:35
xf_err_t xf_ping_new_session(const xf_ping_cfg_t *p_cfg, xf_ping_cb_t cb_func, void *user_args, xf_ping_t *hdl_out)
创建 ping 会话。
Definition xf_ping.c:70
xf_err_t xf_ping_restart(xf_ping_t hdl, const xf_ping_cfg_t *p_cfg, xf_ping_cfg_update_flags_t *p_flags)
重新启动 ping 会话。
Definition xf_ping.c:239
struct _xf_ping_ctx_t * xf_ping_t
ping 会话句柄。
Definition xf_ping.h:56
xf_err_t xf_ping_stop(xf_ping_t hdl)
停止 ping 会话。
Definition xf_ping.c:331
#define XF_PING_THREAD_NAME
Definition xf_ping.h:44
xf_err_t xf_ping_start(xf_ping_t hdl)
启动 ping 会话。
Definition xf_ping.c:224
bool xf_ping_is_running(xf_ping_t hdl)
检查 ping 是否正在运行。
Definition xf_ping.c:320
int32_t xf_ping_event_id_t
ping 事件 id。见 xf_ping_event_code_t.
Definition xf_ping.h:134
void(* xf_ping_cb_t)(xf_ping_event_id_t event_id, xf_ping_t hdl, void *user_args)
ping 回调函数原型。
Definition xf_ping.h:143
xf_err_t xf_ping_delete_session(xf_ping_t hdl)
删除 ping 会话。
Definition xf_ping.c:196
@ XF_PING_EVENT_DELETE
Definition xf_ping.h:126
@ XF_PING_EVENT_TIMEOUT
Definition xf_ping.h:124
@ XF_PING_EVENT_END
Definition xf_ping.h:125
@ XF_PING_EVENT_SUCC
Definition xf_ping.h:123
xf_us_t xf_sys_time_get_us(void)
获取系统时间的时间戳,单位微秒(us)
#define BITS_SET0(var, bits_mask)
设置 32 位变量 var 的对应位掩码 bits_mask 为 1 的地方为 0。
#define BITS_SET1(var, bits_mask)
设置 32 位变量 var 的对应位掩码 bits_mask 为 1 的地方为 1。
int32_t xf_err_t
整形错误类型。 错误码具体值见 xf_err_code_t.
Definition xf_err.h:69
const char * xf_err_to_name(xf_err_t code)
返回 xf_err_code_t 错误代码对应的错误信息字符串。
@ XF_FAIL
Definition xf_err.h:42
@ XF_ERR_INVALID_ARG
Definition xf_err.h:46
@ XF_OK
Definition xf_err.h:43
@ XF_ERR_BUSY
Definition xf_err.h:52
@ XF_ERR_NO_MEM
Definition xf_err.h:45
#define xf_malloc(x)
Definition xf_stdlib.h:38
#define xf_free(x)
Definition xf_stdlib.h:39
#define xf_memset(ptr, value, size)
Definition xf_string.h:42
线程的属性结构。
ping 配置类型。
Definition xf_ping.h:61
uint32_t task_prio
Definition xf_ping.h:70
uint8_t tos
Definition xf_ping.h:66
uint8_t ttl
Definition xf_ping.h:67
uint32_t interface
Definition xf_ping.h:71
uint8_t auto_delete_flag
Definition xf_ping.h:72
uint32_t count
Definition xf_ping.h:62
uint32_t interval_ms
Definition xf_ping.h:63
uint32_t data_size
Definition xf_ping.h:65
uint32_t timeout_ms
Definition xf_ping.h:64
uint32_t task_stack_size
Definition xf_ping.h:69
ip_addr_t target_addr
Definition xf_ping.h:68
ping 更新配置标志。
Definition xf_ping.h:78
ping 会话的上下文。
Definition xf_ping.h:151
static ex_scan_ctx_t ctx
Definition xf_main.c:69
#define XF_LOGE(tag, format,...)
static xf_err_t xf_ping_send(xf_ping_ctx_t *ctx)
Definition xf_ping.c:347
#define THREAD_NOTIFY_BIT
Definition xf_ping.c:43
static const char * TAG
Definition xf_ping.c:55
#define PING_FLAGS_INIT
Definition xf_ping.c:40
#define PING_FLAGS_RUN
Definition xf_ping.c:41
#define XF_GOTO_ON_FALSE(a, err_code, goto_tag, log_tag, format,...)
Definition xf_ping.c:59
#define PING_TIME_DIFF_MS(_end, _start)
Definition xf_ping.c:35
static void xf_ping_thread(void *args)
Definition xf_ping.c:437
static int xf_ping_receive(xf_ping_ctx_t *ctx)
Definition xf_ping.c:376
#define WAIT_CNT_MAX
#define PING_CHECK_START_TIMEOUT_MS
Definition xf_ping.c:38
XF_US_TYPE xf_us_t
#define UNUSED(_x)