• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

SMTP压力测试工具:客户端程序smtp-client.c

发布: 2007-7-02 21:50 | 作者: admin | 来源: | 查看: 63次 | 进入软件测试论坛讨论

领测软件测试网
SMTP压力测试工具:客户端程序smtp-client.c

/*++ /* NAME /* smtp-sink 8 /* SUMMARY /* multi-threaded SMTP/LMTP test server /* SYNOPSIS /* smtp-sink [-cLpv] [-w delay] [host]:port backlog /* DESCRIPTION /* \\\\fIsmtp-sink\\\\fR listens on the named host (or address) and port. /* It takes SMTP messages from the network and throws them away. /* The purpose is to measure SMTP client performance, not protocol /* compliance. /* This program is the complement of the \\\\fIsmtp-source\\\\fR program. /* .IP -c /* Display a running counter that is updated whenever an SMTP /* QUIT command is executed. /* .IP -L /* Speak LMTP rather than SMTP. /* .IP -p /* Disable ESMTP command pipelining. /* .IP -v /* Show the SMTP conversations. /* .IP \\\"-w delay\\\" /* Wait \\\\fIdelay\\\\fR seconds before responding to a DATA command. /* SEE ALSO /* smtp-source, SMTP/LMTP test message generator /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include #include #include #include #include #include #ifdef STRCASECMP_IN_STRINGS_H #include #endif /* Utility library. */ #include #include #include #include #include #include #include #include #include #include /* Global library. */ #include /* Application-specific. */ typedef struct SINK_STATE { VSTREAM *stream; int data_state; int (*read) (struct SINK_STATE *); int rcpts; } SINK_STATE; #define ST_ANY 0 #define ST_CR 1 #define ST_CR_LF 2 #define ST_CR_LF_DOT 3 #define ST_CR_LF_DOT_CR 4 #define ST_CR_LF_DOT_CR_LF 5 static int var_tmout; static int var_max_line_length; static char *var_myhostname; static VSTRING *buffer; static int command_read(SINK_STATE *); static int data_read(SINK_STATE *); static void disconnect(SINK_STATE *); static int count; static int counter; static int disable_pipelining; static int fixed_delay; static int enable_lmtp; /* ehlo_response - respond to EHLO command */ static void ehlo_response(SINK_STATE *state) { smtp_printf(state->stream, \\\"250-%s\\\", var_myhostname); if (!disable_pipelining) smtp_printf(state->stream, \\\"250-PIPELINING\\\"); smtp_printf(state->stream, \\\"250 8BITMIME\\\"); } /* ok_response - send 250 OK */ static void ok_response(SINK_STATE *state) { smtp_printf(state->stream, \\\"250 Ok\\\"); } /* mail_response - reset recipient count, send 250 OK */ static void mail_response(SINK_STATE *state) { state->rcpts = 0; ok_response(state); } /* rcpt_response - bump recipient count, send 250 OK */ static void rcpt_response(SINK_STATE *state) { state->rcpts++; ok_response(state); } /* data_response - respond to DATA command */ static void data_response(SINK_STATE *state) { state->data_state = ST_CR_LF; smtp_printf(state->stream, \\\"354 End data with .\\\"); state->read = data_read; } /* data_event - delayed response to DATA command */ static void data_event(int unused_event, char *context) { SINK_STATE *state = (SINK_STATE *) context; data_response(state); } /* dot_response - response to . command */ static void dot_response(SINK_STATE *state) { if (enable_lmtp) { while (state->rcpts-- > 0) /* XXX this could block */ ok_response(state); } else { ok_response(state); } } /* quit_response - respond to QUIT command */ static void quit_response(SINK_STATE *state) { smtp_printf(state->stream, \\\"221 Bye\\\"); if (count) { counter++; vstream_printf(\\\"%d\\\\r\\\", counter); vstream_fflush(VSTREAM_OUT); } } /* data_read - read data from socket */ static int data_read(SINK_STATE *state) { int ch; struct data_trans { int state; int want; int next_state; }; static struct data_trans data_trans[] = { ST_ANY, \\\@#\\\\r\\\@#, ST_CR, ST_CR, \\\@#\\\\n\\\@#, ST_CR_LF, ST_CR_LF, \\\@#.\\\@#, ST_CR_LF_DOT, ST_CR_LF_DOT, \\\@#\\\\r\\\@#, ST_CR_LF_DOT_CR, ST_CR_LF_DOT_CR, \\\@#\\\\n\\\@#, ST_CR_LF_DOT_CR_LF, }; struct data_trans *dp; /* * We must avoid blocking I/O, so get out of here as soon as both the * VSTREAM and kernel read buffers dry up. */ while (vstream_peek(state->stream) > 0 || peekfd(vstream_fileno(state->stream)) > 0) { if ((ch = VSTREAM_GETC(state->stream)) == VSTREAM_EOF) return (-1); for (dp = data_trans; dp->state != state->data_state; dp++) /* void */ ; /* * Try to match the current character desired by the state machine. * If that fails, try to restart the machine with a match for its * first state. This covers the case of a CR/LF/CR/LF sequence * (empty line) right before the end of the message data. */ if (ch == dp->want) state->data_state = dp->next_state; else if (ch == data_trans[0].want) state->data_state = data_trans[0].next_state; else state->data_state = ST_ANY; if (state->data_state == ST_CR_LF_DOT_CR_LF) { if (msg_verbose) msg_info(\\\".\\\"); dot_response(state); state->read = command_read; break; } } return (0); } /* * The table of all SMTP commands that we can handle. */ typedef struct SINK_COMMAND { char *name; void (*response) (SINK_STATE *); } SINK_COMMAND; static SINK_COMMAND command_table[] = { \\\"helo\\\", ok_response, \\\"ehlo\\\", ehlo_response, \\\"lhlo\\\", ehlo_response, \\\"mail\\\", mail_response, \\\"rcpt\\\", rcpt_response, \\\"data\\\", data_response, \\\"rset\\\", ok_response, \\\"noop\\\", ok_response, \\\"vrfy\\\", ok_response, \\\"quit\\\", quit_response, 0, }; /* command_read - talk the SMTP protocol, server side */ static int command_read(SINK_STATE *state) { char *command; SINK_COMMAND *cmdp; smtp_get(buffer, state->stream, var_max_line_length); if ((command = strtok(vstring_str(buffer), \\\" \\\\t\\\")) == 0) { smtp_printf(state->stream, \\\"500 Error: unknown command\\\"); return (0); } if (msg_verbose) msg_info(\\\"%s\\\", command); for (cmdp = command_table; cmdp->name != 0; cmdp++) if (strcasecmp(command, cmdp->name) == 0) break; if (cmdp->name == 0) { smtp_printf(state->stream, \\\"500 Error: unknown command\\\"); return (0); } if (cmdp->response == data_response && fixed_delay > 0) { event_request_timer(data_event, (char *) state, fixed_delay); } else { cmdp->response(state); if (cmdp->response == quit_response) return (-1); } return (0); } /* read_event - handle command or data read events */ static void read_event(int unused_event, char *context) { SINK_STATE *state = (SINK_STATE *) context; do { switch (vstream_setjmp(state->stream)) { default: msg_panic(\\\"unknown error reading input\\\"); case SMTP_ERR_TIME: msg_panic(\\\"attempt to read non-readable socket\\\"); /* NOTREACHED */ case SMTP_ERR_EOF: msg_warn(\\\"lost connection\\\"); disconnect(state); return; case 0: if (state->read(state) < 0) { if (msg_verbose) msg_info(\\\"disconnect\\\"); disconnect(state); return; } } } while (vstream_peek(state->stream) > 0); } /* disconnect - handle disconnection events */ static void disconnect(SINK_STATE *state) { event_disable_readwrite(vstream_fileno(state->stream)); vstream_fclose(state->stream); myfree((char *) state); } /* connect_event - handle connection events */ static void connect_event(int unused_event, char *context) { int sock = (int) context; SINK_STATE *state; int fd; if ((fd = accept(sock, (struct sockaddr *) 0, (SOCKADDR_SIZE *) 0)) >= 0) { if (msg_verbose) msg_info(\\\"connect\\\"); non_blocking(fd, NON_BLOCKING); state = (SINK_STATE *) mymalloc(sizeof(*state)); state->stream = vstream_fdopen(fd, O_RDWR); state->read = command_read; state->data_state = 0; smtp_timeout_setup(state->stream, var_tmout); smtp_printf(state->stream, \\\"220 %s ESMTP\\\", var_myhostname); event_enable_read(fd, read_event, (char *) state); } } /* usage - explain */ static void usage(char *myname) { msg_fatal(\\\"usage: %s [-cLpv] [host]:port backlog\\\", myname); } int main(int argc, char **argv) { int sock; int backlog; int ch; /* * Initialize diagnostics. */ msg_vstream_init(argv[0], VSTREAM_ERR); /* * Parse JCL. */ while ((ch = GETOPT(argc, argv, \\\"cLpvw:\\\")) > 0) { switch (ch) { case \\\@#c\\\@#: count++; break; case \\\@#L\\\@#: enable_lmtp = 1; break; case \\\@#p\\\@#: disable_pipelining = 1; break; case \\\@#v\\\@#: msg_verbose++; break; case \\\@#w\\\@#: if ((fixed_delay = atoi(optarg)) <= 0) usage(argv[0]); break; default: usage(argv[0]); } } if (argc - optind != 2) usage(argv[0]); if ((backlog = atoi(argv[optind + 1])) <= 0) usage(argv[0]); /* * Initialize. */ buffer = vstring_alloc(1024); var_myhostname = \\\"smtp-sink\\\"; sock = inet_listen(argv[optind], backlog, BLOCKING); /* * Start the event handler. */ event_enable_read(sock, connect_event, (char *) sock); for (;;) event_loop(-1); }

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备10010545号-5
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网