diff --git a/lib_fiber/samples/ping/main.c b/lib_fiber/samples/ping/main.c index fd1d982c5..5b672f8d9 100644 --- a/lib_fiber/samples/ping/main.c +++ b/lib_fiber/samples/ping/main.c @@ -9,6 +9,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) { @@ -58,18 +62,90 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg) acl_fiber_schedule_stop(); } +static void reply_callback(ICMP_PKT_STATUS *status acl_unused, void *arg) +{ + if (__show_reply) { + ICMP_HOST *host = (ICMP_HOST *) arg; + printf("%s\r\n", host->dest_ip); + } +} + +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 fiber_pine_one(ACL_FIBER *fiber acl_unused, void *arg) +{ + char *ip = (char*) arg; + ICMP_CHAT *chat = icmp_chat_create(NULL, 1); + ICMP_HOST *host = icmp_host_new(chat, ip, ip, __npkt, 64, + __delay, __timeout); + + icmp_host_set(host, host, reply_callback, timeout_callback, + unreach_callback, finish_callback); + + icmp_chat(host); + + icmp_host_free(host); + icmp_chat_free(chat); + + 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]\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, "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) { @@ -80,11 +156,14 @@ 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 记录的信息输出至屏幕 */ - while ((ch = getopt(argc, argv, "hn:d:z:b:t:")) > 0) { + iplist[0] = 0; + + while ((ch = getopt(argc, argv, "hn:d:z:b:t:f:s:")) > 0) { switch (ch) { case 'n': __npkt = atoi(optarg); @@ -104,6 +183,12 @@ int main(int argc, char* argv[]) case 'b': __benchmark = atoi(optarg); break; + case 'f': + ACL_SAFE_STRNCPY(iplist, optarg, sizeof(iplist)); + break; + case 's': + show_list(optarg); + break; default: break; } @@ -119,6 +204,32 @@ int main(int argc, char* argv[]) 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]); diff --git a/lib_protocol/include/icmp/lib_icmp_type.h b/lib_protocol/include/icmp/lib_icmp_type.h index 80d5c2458..884d0a25c 100644 --- a/lib_protocol/include/icmp/lib_icmp_type.h +++ b/lib_protocol/include/icmp/lib_icmp_type.h @@ -21,12 +21,12 @@ struct ICMP_STAT { /**< ICMP 所发送的每个 PING 包之后的主机状态应答 */ struct ICMP_PKT_STATUS { size_t reply_len; /**< 包回复的数据长度 */ - char frome_ip[32]; /**< 源地址 */ + char from_ip[32]; /**< 源地址 */ - double rtt; /**< 往返时间(毫秒)(Round Trip Time) */ + double rtt; /**< 往返时间(毫秒)(Round Trip Time) */ unsigned short seq; /**< 序列号(seq no) */ - unsigned char ttl; /**< 生存时间(time to live) */ - char status; + unsigned char ttl; /**< 生存时间(time to live) */ + char status; #define ICMP_STATUS_OK 0 #define ICMP_STATUS_UNREACH 1 #define ICMP_STATUS_TIMEOUT 2 @@ -47,8 +47,8 @@ struct ICMP_HOST { size_t nsent; /**< 已经发送给该目的主机包的个数 */ char enable_log; /**< 是否将响应包的信息记日志 */ - ACL_RING host_ring; /**< 由此链入 ICMP_CHAT->host_head 链中 */ - ACL_RING pkt_head; /**< 发送给目的主机数据包的链的链头 */ + ACL_RING host_ring; /**< 由此链入 ICMP_CHAT->host_head 链中 */ + ACL_RING pkt_head; /**< 发送给目的主机数据包的链的链头 */ ICMP_CHAT *chat; /**< 所属的通信对象 */ /**< 汇报发送包的响应包状态 */ diff --git a/lib_protocol/src/icmp/icmp_pkt.c b/lib_protocol/src/icmp/icmp_pkt.c index 461f6ebad..1ad820867 100644 --- a/lib_protocol/src/icmp/icmp_pkt.c +++ b/lib_protocol/src/icmp/icmp_pkt.c @@ -98,13 +98,14 @@ void icmp_pkt_save(ICMP_PKT* to, const ICMP_PKT* from) to->pkt_status.reply_len = from->pkt_status.reply_len; to->pkt_status.rtt = stamp_sub(&from->stamp, &to->stamp); to->pkt_status.ttl = from->pkt_status.ttl; - snprintf(to->pkt_status.frome_ip, sizeof(to->pkt_status.frome_ip), - "%s", from->pkt_status.frome_ip); + snprintf(to->pkt_status.from_ip, sizeof(to->pkt_status.from_ip), + "%s", from->pkt_status.from_ip); to->pkt_status.status = ICMP_STATUS_OK; } -int icmp_pkt_unpack(const ICMP_CHAT *chat, const char *buf, int bytes, ICMP_PKT *pkt) +int icmp_pkt_unpack(const ICMP_CHAT *chat, const char *buf, + int bytes, ICMP_PKT *pkt) { const IP_HDR *iphdr; const ICMP_HDR *icmphdr; @@ -115,7 +116,8 @@ int icmp_pkt_unpack(const ICMP_CHAT *chat, const char *buf, int bytes, ICMP_PKT iphdrlen = iphdr->h_len * 4 ; /* number of 32-bit words *4 = bytes */ if (bytes < iphdrlen + ICMP_MIN) { - acl_msg_error("Too few bytes from %s", inet_ntoa(chat->is->from.sin_addr)); + acl_msg_error("Too few bytes from %s", + inet_ntoa(chat->is->from.sin_addr)); return (-1); } @@ -145,7 +147,7 @@ int icmp_pkt_unpack(const ICMP_CHAT *chat, const char *buf, int bytes, ICMP_PKT pkt->pkt_status.status = ICMP_STATUS_OK; pkt->pkt_status.seq = icmphdr->seq; pkt->pkt_status.ttl = iphdr->ttl; - snprintf(pkt->pkt_status.frome_ip, sizeof(pkt->pkt_status.frome_ip), + snprintf(pkt->pkt_status.from_ip, sizeof(pkt->pkt_status.from_ip), "%s", inet_ntoa(chat->is->from.sin_addr)); return (0); } diff --git a/lib_protocol/src/icmp/icmp_stat.c b/lib_protocol/src/icmp/icmp_stat.c index 5a5682ac7..d15980d06 100644 --- a/lib_protocol/src/icmp/icmp_stat.c +++ b/lib_protocol/src/icmp/icmp_stat.c @@ -27,7 +27,7 @@ void icmp_stat_report(ICMP_PKT *pkt) pkt->pkt_status.status = ICMP_STATUS_OK; if (pkt->icmp_host->enable_log) acl_msg_info("Reply from %s: bytes=%d time=%.3fms TTL=%d icmp_seq=%d status=%d", - pkt->pkt_status.frome_ip, (int) pkt->pkt_status.reply_len, + pkt->pkt_status.from_ip, (int) pkt->pkt_status.reply_len, pkt->pkt_status.rtt, pkt->pkt_status.ttl, pkt->pkt_status.seq, pkt->pkt_status.status);