mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-30 19:07:35 +08:00
267 lines
5.7 KiB
C
267 lines
5.7 KiB
C
#include "lib_acl.h"
|
|
#include "lib_protocol.h"
|
|
#include "fiber/lib_fiber.h"
|
|
#include <signal.h>
|
|
|
|
static int __nfibers = 0;
|
|
static int __npkt = 10;
|
|
static int __delay = 10;
|
|
static int __timeout = 1000;
|
|
static int __benchmark = 0;
|
|
|
|
static int __show_reply = 0;
|
|
static int __show_timeout = 0;
|
|
static int __show_unreach = 0;
|
|
|
|
static void display_res(ICMP_CHAT *chat)
|
|
{
|
|
if (chat) {
|
|
/* 显示 PING 的结果总结 */
|
|
icmp_stat(chat);
|
|
printf(">>>max pkts: %d\r\n", icmp_chat_seqno(chat));
|
|
}
|
|
}
|
|
|
|
static void reply_callback(ICMP_PKT_STATUS *status, void *arg)
|
|
{
|
|
if (__show_reply) {
|
|
ICMP_HOST *host = (ICMP_HOST *) arg;
|
|
const ICMP_PKT *pkt_reply = icmp_pkt_peer(status->pkt);
|
|
const ICMP_PKT_STATUS *status_reply;
|
|
char buf[ICMP_MAX_PACKET];
|
|
size_t dlen;
|
|
|
|
assert(pkt_reply);
|
|
status_reply = icmp_pkt_status(pkt_reply);
|
|
dlen = icmp_pkt_payload(pkt_reply, buf, sizeof(buf));
|
|
|
|
printf("%d bytes reply from %s: seq=%d ttl=%d time=%.2f ms"
|
|
" code=%d type=%d dlen=%d data=%s\r\n",
|
|
(int) status_reply->reply_len, host->dest_ip,
|
|
status->seq, status->ttl, status->rtt,
|
|
icmp_pkt_code(pkt_reply), icmp_pkt_type(pkt_reply),
|
|
(int) dlen, buf);
|
|
}
|
|
}
|
|
|
|
static void timeout_callback(ICMP_PKT_STATUS *status, void *arg)
|
|
{
|
|
if (__show_timeout) {
|
|
ICMP_HOST *host = (ICMP_HOST *) arg;
|
|
printf("timeout: from %s, %.2f ms\r\n", host->dest_ip, status->rtt);
|
|
}
|
|
}
|
|
|
|
static void unreach_callback(ICMP_PKT_STATUS *status acl_unused, void *arg)
|
|
{
|
|
if (__show_unreach) {
|
|
ICMP_HOST *host = (ICMP_HOST *) arg;
|
|
printf("unreach: from %st\r\n", host->dest_ip);
|
|
}
|
|
}
|
|
|
|
static void finish_callback(ICMP_HOST *host, void *arg acl_unused)
|
|
{
|
|
icmp_stat_host(host, 0);
|
|
}
|
|
|
|
static void ping_one(const char *ip)
|
|
{
|
|
ICMP_CHAT *chat = icmp_chat_create(NULL, 1); /* 创建 ICMP 对象 */
|
|
ICMP_HOST *host = icmp_host_alloc(chat, ip, ip);
|
|
|
|
icmp_host_init(host, ICMP_TYPE_ECHO, ICMP_CODE_EXTRA, __npkt, 64,
|
|
__delay, __timeout);
|
|
icmp_host_set(host, host, reply_callback, timeout_callback,
|
|
unreach_callback, finish_callback);
|
|
|
|
icmp_chat(host); /* 开始 PING */
|
|
display_res(chat); /* 显示 PING 结果 */
|
|
|
|
icmp_host_free(host);
|
|
icmp_chat_free(chat); /* 释放 ICMP 对象 */
|
|
}
|
|
|
|
/* PING 协程入口 */
|
|
static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
|
|
{
|
|
const char *dest = (const char *) arg;
|
|
ACL_DNS_DB* dns_db;
|
|
const char *ip;
|
|
|
|
/* 通过域名解析出IP地址 */
|
|
dns_db = acl_gethostbyname(dest, NULL);
|
|
if (dns_db == NULL) {
|
|
acl_msg_warn("Can't find domain %s", dest);
|
|
return;
|
|
}
|
|
|
|
/* 只取出域名第一个 IP 地址 PING */
|
|
ip = acl_netdb_index_ip(dns_db, 0);
|
|
if (ip == NULL || *ip == 0) {
|
|
acl_msg_error("ip invalid");
|
|
acl_netdb_free(dns_db);
|
|
return;
|
|
}
|
|
|
|
ping_one(ip);
|
|
|
|
acl_netdb_free(dns_db); /* 释放域名解析对象 */
|
|
|
|
if (--__nfibers == 0)
|
|
acl_fiber_schedule_stop();
|
|
}
|
|
|
|
static void fiber_pine_one(ACL_FIBER *fiber acl_unused, void *arg)
|
|
{
|
|
char *ip = (char*) arg;
|
|
|
|
ping_one(ip);
|
|
|
|
acl_myfree(ip);
|
|
|
|
if (--__nfibers == 0)
|
|
acl_fiber_schedule_stop();
|
|
}
|
|
|
|
static void usage(const char* progname)
|
|
{
|
|
printf("usage: %s -h help\r\n"
|
|
" -d delay[milliseconds]\r\n"
|
|
" -t timout[milliseconds]\r\n"
|
|
" -z stack_size\r\n"
|
|
" -f ip_list_file\r\n"
|
|
" -s show_result_list[timeout,reply,unreach,all]\r\n"
|
|
" -b benchmark [if > 0 dest will be ignored]\r\n"
|
|
" -n npkt dest1 dest2...\r\n", progname);
|
|
|
|
printf("example: %s -n 10 www.sina.com.cn www.qq.com\r\n", progname);
|
|
}
|
|
|
|
static void show_list(const char *s)
|
|
{
|
|
ACL_ITER iter;
|
|
ACL_ARGV *tokens = acl_argv_split(s, ",;: \t\r\n");
|
|
|
|
#define EQ !strcasecmp
|
|
|
|
acl_foreach(iter, tokens) {
|
|
const char *ptr = (const char *) iter.data;
|
|
|
|
if (EQ(ptr, "all")) {
|
|
__show_timeout = 1;
|
|
__show_reply = 1;
|
|
__show_unreach = 1;
|
|
} else if (EQ(ptr, "timeout"))
|
|
__show_timeout = 1;
|
|
else if (EQ(ptr, "reply"))
|
|
__show_reply = 1;
|
|
else if (EQ(ptr, "unreach"))
|
|
__show_unreach = 1;
|
|
}
|
|
|
|
acl_argv_free(tokens);
|
|
}
|
|
|
|
/* 当收到 SIGINT 信号(即在 PING 过程中用户按下 ctrl + c)时的信号处理函数 */
|
|
static void on_sigint(int signo acl_unused)
|
|
{
|
|
exit(0);
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
char ch;
|
|
int i, stack_size = 16000;
|
|
char iplist[256];
|
|
|
|
signal(SIGINT, on_sigint); /* 用户按下 ctr + c 时中断 PING 程序 */
|
|
acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */
|
|
|
|
iplist[0] = 0;
|
|
|
|
while ((ch = getopt(argc, argv, "hn:d:z:b:t:f:s:")) > 0) {
|
|
switch (ch) {
|
|
case 'n':
|
|
__npkt = atoi(optarg);
|
|
break;
|
|
case 'h':
|
|
usage(argv[0]);
|
|
return 0;
|
|
case 'z':
|
|
stack_size = atoi(optarg);
|
|
break;
|
|
case 'd':
|
|
__delay = atoi(optarg);
|
|
break;
|
|
case 't':
|
|
__timeout = atoi(optarg);
|
|
break;
|
|
case 'b':
|
|
__benchmark = atoi(optarg);
|
|
break;
|
|
case 'f':
|
|
ACL_SAFE_STRNCPY(iplist, optarg, sizeof(iplist));
|
|
break;
|
|
case 's':
|
|
show_list(optarg);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (__npkt <= 0)
|
|
__npkt = 10;
|
|
|
|
if (__benchmark > 0) {
|
|
static char *localhost = "127.0.0.1";
|
|
|
|
__nfibers = __benchmark;
|
|
|
|
for (i = 0; i < __benchmark; i++)
|
|
acl_fiber_create(fiber_ping, localhost, stack_size);
|
|
} else if (iplist[0]) {
|
|
ACL_ARGV *ips = acl_argv_alloc(10240);
|
|
ACL_FILE *fp = acl_fopen(iplist, "r");
|
|
ACL_ITER iter;
|
|
|
|
if (fp == NULL) {
|
|
printf("open file %s error %s\r\n",
|
|
iplist, acl_last_serror());
|
|
acl_argv_free(ips);
|
|
return 1;
|
|
}
|
|
while (!acl_feof(fp)) {
|
|
char line[256];
|
|
if (acl_fgets_nonl(line, sizeof(line), fp) == NULL)
|
|
break;
|
|
acl_argv_add(ips, line, NULL);
|
|
}
|
|
acl_fclose(fp);
|
|
|
|
acl_foreach(iter, ips) {
|
|
char *ip = acl_mystrdup((char*) iter.data);
|
|
acl_fiber_create(fiber_pine_one, ip, stack_size);
|
|
}
|
|
|
|
__nfibers = acl_argv_size(ips);
|
|
acl_argv_free(ips);
|
|
} else {
|
|
if (optind == argc) {
|
|
usage(argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
/* 记录要启动的协程的总数 */
|
|
__nfibers = argc - optind;
|
|
|
|
for (i = optind; i < argc; i++)
|
|
acl_fiber_create(fiber_ping, argv[i], stack_size);
|
|
}
|
|
|
|
acl_fiber_schedule();
|
|
|
|
return 0;
|
|
}
|