Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add mysql check, modify the smtp parser.

  • Loading branch information...
commit 4f3868e9a0b0e1db370498ff24a6305853261e1c 1 parent dd222ae
@yaoweibin authored
View
24 README
@@ -144,7 +144,7 @@ Directives
==check==
syntax: check interval=milliseconds [fall=count] [rise=count]
- [timeout=milliseconds] [type=tcp|ssl_hello]
+ [timeout=milliseconds] [type=tcp|ssl_hello|smtp|mysql]
default: none, if parameters omitted, default parameters are 'interval=30000
fall=5 rise=2 timeout=1000'
context: upstream
@@ -161,8 +161,13 @@ Directives
'tcp' is a simple tcp socket connect and peek one byte.
'ssl_hello' sends a client ssl hello packet and receives the server
ssl hello packet.
- 'http' sends a http requst packet and recvives and parses the http
+ 'http' sends a http requst packet, recvives and parses the http
response to diagnose if the upstream server is alive.
+ 'smtp' sends a smtp requst packet, recvives and parses the smtp
+ response to diagnose if the upstream server is alive. The response
+ begins with '2' will be judged to be a OK response.
+ 'mysql' connects to the mysql server, recvives the greeting response
+ to diagnose if the upstream server is alive.
==check_http_send=
syntax: check_http_send http_packet
@@ -178,6 +183,21 @@ Directives
description: These status codes indicate the upstream server's http response
is ok, the backend is alive.
+ ==check_smtp_send=
+ syntax: check_smtp_send smtp_packet
+ default: "HELO smtp.localdomain\r\n"
+ context: upstream
+ description: If you set the check type is smtp, then the check function will
+ sends this smtp packet to check the upstream server.
+
+ ==check_smtp_expect_alive=
+ syntax: check_smtp_expect_alive [smtp_2xx | smtp_3xx | smtp_4xx | smtp_5xx]
+ default: check_smtp_expect_alive smtp_2xx;
+ context: upstream
+ description: These status codes indicate the upstream server's smtp response
+ is ok, the backend is alive.
+
+
==check_shm_size==
syntax: check_shm_size size
default: (number_of_checked_upstream_blocks + 1) * pagesize
View
2  config
@@ -4,7 +4,7 @@ ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path="$ngx_addon_dir/modules $ngx_addon_dir"
ngx_feature_deps="$ngx_addon_dir/ngx_tcp.h $ngx_addon_dir/ngx_tcp_session.h $ngx_addon_dir/ngx_tcp_upstream.h $ngx_addon_dir/ngx_tcp_upstream_check.h $ngx_addon_dir/ngx_tcp_upstream_round_robin.h"
-ngx_tcp_src="$ngx_addon_dir/ngx_tcp.c $ngx_addon_dir/ngx_tcp_core_module.c $ngx_addon_dir/ngx_tcp_session.c $ngx_addon_dir/ngx_tcp_upstream.c $ngx_addon_dir/ngx_tcp_upstream_round_robin.c $ngx_addon_dir/modules/ngx_tcp_proxy_module.c $ngx_addon_dir/modules/ngx_tcp_upstream_ip_hash_module.c $ngx_addon_dir/ngx_tcp_upstream_check.c $ngx_addon_dir/http_response_parse.c"
+ngx_tcp_src="$ngx_addon_dir/ngx_tcp.c $ngx_addon_dir/ngx_tcp_core_module.c $ngx_addon_dir/ngx_tcp_session.c $ngx_addon_dir/ngx_tcp_upstream.c $ngx_addon_dir/ngx_tcp_upstream_round_robin.c $ngx_addon_dir/modules/ngx_tcp_proxy_module.c $ngx_addon_dir/modules/ngx_tcp_upstream_ip_hash_module.c $ngx_addon_dir/ngx_tcp_upstream_check.c $ngx_addon_dir/http_response_parse.c $ngx_addon_dir/smtp_response_parse.c"
ngx_feature_test="int a;"
. auto/feature
View
16 ngx_tcp_upstream.c
@@ -29,6 +29,14 @@ static ngx_conf_bitmask_t ngx_check_http_expect_alive_masks[] = {
{ ngx_null_string, 0 }
};
+static ngx_conf_bitmask_t ngx_check_smtp_expect_alive_masks[] = {
+ { ngx_string("smtp_2xx"), NGX_CHECK_SMTP_2XX },
+ { ngx_string("smtp_3xx"), NGX_CHECK_SMTP_3XX },
+ { ngx_string("smtp_4xx"), NGX_CHECK_SMTP_4XX },
+ { ngx_string("smtp_5xx"), NGX_CHECK_SMTP_5XX },
+ { ngx_null_string, 0 }
+};
+
static ngx_command_t ngx_tcp_upstream_commands[] = {
{ ngx_string("upstream"),
@@ -73,6 +81,13 @@ static ngx_command_t ngx_tcp_upstream_commands[] = {
offsetof(ngx_tcp_upstream_srv_conf_t, status_alive),
&ngx_check_http_expect_alive_masks },
+ { ngx_string("check_smtp_expect_alive"),
+ NGX_TCP_UPS_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_TCP_SRV_CONF_OFFSET,
+ offsetof(ngx_tcp_upstream_srv_conf_t, status_alive),
+ &ngx_check_smtp_expect_alive_masks },
+
{ ngx_string("check_shm_size"),
NGX_TCP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
@@ -647,6 +662,7 @@ ngx_tcp_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) {
uscf->line = cf->conf_file->line;
uscf->port = u->port;
uscf->default_port = u->default_port;
+ uscf->status_alive = 0;
if (u->naddrs == 1) {
uscf->servers = ngx_array_create(cf->pool, 1,
View
238 ngx_tcp_upstream_check.c
@@ -28,6 +28,10 @@ static ngx_int_t ngx_tcp_check_smtp_init(ngx_tcp_check_peer_conf_t *peer_conf);
static ngx_int_t ngx_tcp_check_smtp_parse(ngx_tcp_check_peer_conf_t *peer_conf);
static void ngx_tcp_check_smtp_reinit(ngx_tcp_check_peer_conf_t *peer_conf);
+static ngx_int_t ngx_tcp_check_mysql_init(ngx_tcp_check_peer_conf_t *peer_conf);
+static ngx_int_t ngx_tcp_check_mysql_parse(ngx_tcp_check_peer_conf_t *peer_conf);
+static void ngx_tcp_check_mysql_reinit(ngx_tcp_check_peer_conf_t *peer_conf);
+
static char * ngx_tcp_upstream_check_status_set_status(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
@@ -109,8 +113,8 @@ static check_conf_t ngx_check_types[] = {
{
NGX_TCP_CHECK_SMTP,
"smtp",
- ngx_string("HELO localhost\r\n"),
- 0,
+ ngx_string("HELO smtp.localdomain\r\n"),
+ NGX_CONF_BITMASK_SET | NGX_CHECK_SMTP_2XX,
ngx_tcp_check_send_handler,
ngx_tcp_check_recv_handler,
ngx_tcp_check_smtp_init,
@@ -118,6 +122,18 @@ static check_conf_t ngx_check_types[] = {
ngx_tcp_check_smtp_reinit,
1
},
+ {
+ NGX_TCP_CHECK_MYSQL,
+ "mysql",
+ ngx_null_string,
+ 0,
+ ngx_tcp_check_send_handler,
+ ngx_tcp_check_recv_handler,
+ ngx_tcp_check_mysql_init,
+ ngx_tcp_check_mysql_parse,
+ ngx_tcp_check_mysql_reinit,
+ 1
+ },
{0, "", ngx_null_string, 0, NULL, NULL, NULL, NULL, NULL, 0}
};
@@ -588,7 +604,7 @@ void header_done(void *data, const char *at, size_t length)
}
-static void parser_init(http_parser *hp, void *data)
+static void check_http_parser_init(http_parser *hp, void *data)
{
hp->data = data;
hp->http_field = http_field;
@@ -619,10 +635,10 @@ ngx_tcp_check_http_init(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->parser = ngx_pcalloc(peer_conf->pool, sizeof(http_parser));
if (ctx->parser == NULL) {
- return NGX_OK;
+ return NGX_ERROR;
}
- parser_init(ctx->parser, peer_conf);
+ check_http_parser_init(ctx->parser, peer_conf);
return NGX_OK;
}
@@ -687,7 +703,7 @@ ngx_tcp_check_http_reinit(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->recv.pos = ctx->recv.last = ctx->recv.start;
- parser_init(ctx->parser, peer_conf);
+ check_http_parser_init(ctx->parser, peer_conf);
}
@@ -758,6 +774,93 @@ ngx_tcp_check_ssl_hello_reinit(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->recv.pos = ctx->recv.last = ctx->recv.start;
}
+static void domain(void *data, const char *at, size_t length)
+{
+ ngx_str_t str;
+
+ str.data = (u_char *) at;
+ str.len = length;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "DOMAIN: \"%V\"", &str);
+}
+
+static void greeting_text(void *data, const char *at, size_t length)
+{
+ ngx_str_t str;
+
+ str.data = (u_char *) at;
+ str.len = length;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "GREETING_TEXT: \"%V\"", &str);
+}
+
+static void reply_code(void *data, const char *at, size_t length)
+{
+ ngx_tcp_check_peer_conf_t *peer_conf = data;
+ ngx_tcp_check_ctx *ctx;
+ smtp_parser *sp;
+ ngx_str_t str;
+ int code;
+
+ str.data = (u_char *) at;
+ str.len = length;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "REPLY_CODE: \"%V\"", &str);
+
+ ctx = peer_conf->check_data;
+ sp = ctx->parser;
+
+ code = ngx_atoi((u_char*)at, length);
+
+ if (code >= 200 && code < 300) {
+ sp->hello_reply_code = NGX_CHECK_SMTP_2XX;
+ }
+ else if (code >= 300 && code < 400) {
+ sp->hello_reply_code = NGX_CHECK_SMTP_3XX;
+ }
+ else if (code >= 400 && code < 500) {
+ sp->hello_reply_code = NGX_CHECK_SMTP_4XX;
+ }
+ else if (code >= 500 && code < 600) {
+ sp->hello_reply_code = NGX_CHECK_SMTP_5XX;
+ }
+ else {
+ sp->hello_reply_code = NGX_CHECK_SMTP_ERR;
+ }
+}
+
+static void reply_text(void *data, const char *at, size_t length)
+{
+ ngx_str_t str;
+
+ str.data = (u_char *) at;
+ str.len = length;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "REPLY_TEXT: \"%V\"", &str);
+}
+
+static void smtp_done(void *data, const char *at, size_t length)
+{
+}
+
+static void check_smtp_parser_init(smtp_parser *sp, void *data)
+{
+ sp->data = data;
+ sp->hello_reply_code = 0;
+
+ sp->domain = domain;
+ sp->greeting_text = greeting_text;
+ sp->reply_code = reply_code;
+ sp->reply_text = reply_text;
+ sp->smtp_done = smtp_done;
+
+ smtp_parser_init(sp);
+}
+
static ngx_int_t
ngx_tcp_check_smtp_init(ngx_tcp_check_peer_conf_t *peer_conf) {
@@ -770,11 +873,18 @@ ngx_tcp_check_smtp_init(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->send.start = ctx->send.pos = (u_char *)uscf->send.data;
ctx->send.end = ctx->send.last = ctx->send.start + uscf->send.len;
+ ctx->recv.start = ctx->recv.pos = NULL;
+ ctx->recv.end = ctx->recv.last = NULL;
+
ngx_log_debug1(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
"smtp_init: send:%V", &uscf->send);
- ctx->recv.start = ctx->recv.pos = NULL;
- ctx->recv.end = ctx->recv.last = NULL;
+ ctx->parser = ngx_pcalloc(peer_conf->pool, sizeof(smtp_parser));
+ if (ctx->parser == NULL) {
+ return NGX_ERROR;
+ }
+
+ check_smtp_parser_init(ctx->parser, peer_conf);
return NGX_OK;
}
@@ -782,21 +892,43 @@ ngx_tcp_check_smtp_init(ngx_tcp_check_peer_conf_t *peer_conf) {
static ngx_int_t
ngx_tcp_check_smtp_parse(ngx_tcp_check_peer_conf_t *peer_conf) {
- u_char ch;
+ ssize_t n, offset, length;
+ smtp_parser *sp;
ngx_tcp_check_ctx *ctx;
+ ngx_tcp_upstream_srv_conf_t *uscf;
+ uscf = peer_conf->conf;
ctx = peer_conf->check_data;
+ sp = ctx->parser;
if (ctx->recv.last - ctx->recv.pos <= 0 ) {
return NGX_AGAIN;
}
- ngx_log_debug1(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
- "smtp_parse: recv:%s", ctx->recv.pos);
+ offset = ctx->recv.pos - ctx->recv.start;
+ length = ctx->recv.last - ctx->recv.start;
- ch = (u_char) *(ctx->recv.pos);
+ n = smtp_parser_execute(sp, (char *)ctx->recv.start, length, offset);
+ ctx->recv.pos += n;
- if (ch != '2') {
+ if (smtp_parser_finish(sp) == -1) {
+ ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
+ "smtp parse error with peer: %V, recv data: %s",
+ &peer_conf->peer->name, ctx->recv.pos);
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "smtp_parse: sp->hello_reply_code: %d, conf: %d",
+ sp->hello_reply_code, uscf->status_alive);
+
+ if (sp->hello_reply_code == 0) {
+ return NGX_AGAIN;
+ }
+ else if (sp->hello_reply_code & uscf->status_alive) {
+ return NGX_OK;
+ }
+ else {
return NGX_ERROR;
}
@@ -814,8 +946,69 @@ ngx_tcp_check_smtp_reinit(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->send.last = ctx->send.end;
ctx->recv.pos = ctx->recv.last = ctx->recv.start;
+
+ check_smtp_parser_init(ctx->parser, peer_conf);
}
+static ngx_int_t
+ngx_tcp_check_mysql_init(ngx_tcp_check_peer_conf_t *peer_conf) {
+
+ ngx_tcp_check_ctx *ctx;
+ ngx_tcp_upstream_srv_conf_t *uscf;
+
+ ctx = peer_conf->check_data;
+ uscf = peer_conf->conf;
+
+ ctx->send.start = ctx->send.pos = (u_char *)uscf->send.data;
+ ctx->send.end = ctx->send.last = ctx->send.start + uscf->send.len;
+
+ ctx->recv.start = ctx->recv.pos = NULL;
+ ctx->recv.end = ctx->recv.last = NULL;
+
+ return NGX_OK;
+}
+
+static ngx_int_t
+ngx_tcp_check_mysql_parse(ngx_tcp_check_peer_conf_t *peer_conf) {
+
+ ngx_tcp_check_ctx *ctx;
+ mysql_handshake_init_t *handshake;
+
+ ctx = peer_conf->check_data;
+
+ if (ctx->recv.last - ctx->recv.pos <= 0 ) {
+ return NGX_AGAIN;
+ }
+
+ handshake = (mysql_handshake_init_t *) ctx->recv.pos;
+
+ ngx_log_debug3(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+ "mysql_parse: packet_number=%d, protocol=%d, server=%s",
+ handshake->packet_number,
+ handshake->protocol_version,
+ handshake->others);
+
+ /* The mysql greeting packet's serial number always begin with 0. */
+ if (handshake->packet_number != 0x00) {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+static void
+ngx_tcp_check_mysql_reinit(ngx_tcp_check_peer_conf_t *peer_conf) {
+
+ ngx_tcp_check_ctx *ctx;
+
+ ctx = peer_conf->check_data;
+
+ ctx->send.pos = ctx->send.start;
+ ctx->send.last = ctx->send.end;
+
+ ctx->recv.pos = ctx->recv.last = ctx->recv.start;
+}
+
static void
ngx_tcp_check_send_handler(ngx_event_t *event) {
@@ -842,6 +1035,10 @@ ngx_tcp_check_send_handler(ngx_event_t *event) {
}
if (peer_conf->state != NGX_TCP_CHECK_CONNECT_DONE) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
+ goto check_send_fail;
+ }
+
return;
}
@@ -883,6 +1080,7 @@ ngx_tcp_check_send_handler(ngx_event_t *event) {
}
if (ctx->send.pos == ctx->send.last) {
+ ngx_log_debug(NGX_LOG_DEBUG_TCP, c->log, 0, "tcp check send done.");
peer_conf->state = NGX_TCP_CHECK_SEND_DONE;
}
@@ -912,6 +1110,11 @@ ngx_tcp_check_recv_handler(ngx_event_t *event) {
peer_conf = c->data;
if (peer_conf->state != NGX_TCP_CHECK_SEND_DONE) {
+
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
+ goto check_recv_fail;
+ }
+
return;
}
@@ -1095,13 +1298,8 @@ ngx_tcp_upstream_init_check_conf(ngx_tcp_upstream_srv_conf_t *uscf) {
uscf->send.len = cf->default_send.len;
}
- if (cf->type & NGX_TCP_CHECK_HTTP) {
-
- if ((uscf->status_alive < NGX_CHECK_HTTP_2XX) ||
- (uscf->status_alive >= NGX_CHECK_HTTP_6XX)) {
-
- uscf->status_alive = cf->default_status_alive;
- }
+ if (uscf->status_alive == 0) {
+ uscf->status_alive = cf->default_status_alive;
}
}
View
43 ngx_tcp_upstream_check.h
@@ -31,6 +31,15 @@ typedef struct {
} __attribute__((packed)) server_ssl_hello_t;
typedef struct {
+
+ u_char packet_length[3];
+ u_char packet_number;
+
+ u_char protocol_version;
+ u_char others[0];
+} __attribute__((packed)) mysql_handshake_init_t;
+
+typedef struct {
ngx_buf_t send;
ngx_buf_t recv;
@@ -76,6 +85,7 @@ typedef void (*ngx_tcp_check_packet_clean_pt)(ngx_tcp_check_peer_conf_t *peer_co
#define NGX_TCP_CHECK_HTTP 0x0002
#define NGX_TCP_CHECK_SSL_HELLO 0x0004
#define NGX_TCP_CHECK_SMTP 0x0008
+#define NGX_TCP_CHECK_MYSQL 0x0010
#define NGX_CHECK_HTTP_2XX 0x0002
@@ -85,6 +95,13 @@ typedef void (*ngx_tcp_check_packet_clean_pt)(ngx_tcp_check_peer_conf_t *peer_co
#define NGX_CHECK_HTTP_6XX 0x0020
#define NGX_CHECK_HTTP_ERR 0x8000
+#define NGX_CHECK_SMTP_2XX 0x0002
+#define NGX_CHECK_SMTP_3XX 0x0004
+#define NGX_CHECK_SMTP_4XX 0x0008
+#define NGX_CHECK_SMTP_5XX 0x0010
+#define NGX_CHECK_SMTP_6XX 0x0020
+#define NGX_CHECK_SMTP_ERR 0x8000
+
struct check_conf_s {
ngx_uint_t type;
@@ -169,6 +186,32 @@ int http_parser_is_finished(http_parser *parser);
#define http_parser_nread(parser) (parser)->nread
+typedef struct smtp_parser {
+
+ int cs;
+ size_t nread;
+ size_t mark;
+
+ int hello_reply_code;
+
+ void *data;
+
+ element_cb domain;
+ element_cb greeting_text;
+ element_cb reply_code;
+ element_cb reply_text;
+ element_cb smtp_done;
+
+} smtp_parser;
+
+int smtp_parser_init(smtp_parser *parser);
+int smtp_parser_finish(smtp_parser *parser);
+size_t smtp_parser_execute(smtp_parser *parser, const char *data, size_t len, size_t off);
+int smtp_parser_has_error(smtp_parser *parser);
+int smtp_parser_is_finished(smtp_parser *parser);
+
+#define http_parser_nread(parser) (parser)->nread
+
ngx_int_t ngx_tcp_upstream_init_main_check_conf(ngx_conf_t *cf, void*conf);
View
6,546 smtp_response_parse.c
6,546 additions, 0 deletions not shown
View
162 smtp_response_parse.rl
@@ -0,0 +1,162 @@
+
+#include "ngx_tcp_upstream_check.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define LEN(AT, FPC) (FPC - buffer - parser->AT)
+#define MARK(M,FPC) (parser->M = (FPC) - buffer)
+#define PTR_TO(F) (buffer + parser->F)
+
+/** Machine **/
+
+%%{
+
+ machine smtp_parser;
+
+ action mark {MARK(mark, fpc);}
+
+ action domain {
+ if(parser->domain != NULL) {
+ parser->domain(parser->data, PTR_TO(mark), LEN(mark, fpc));
+ }
+ }
+
+ action greeting_text {
+ if(parser->greeting_text != NULL)
+ parser->greeting_text(parser->data, PTR_TO(mark), LEN(mark, fpc));
+ }
+
+ action reply_code {
+ if(parser->reply_code != NULL)
+ parser->reply_code(parser->data, PTR_TO(mark), LEN(mark,fpc));
+ }
+
+ action reply_text {
+ if(parser->reply_text != NULL)
+ parser->reply_text(parser->data, PTR_TO(mark), LEN(mark,fpc));
+ }
+
+ action done {
+ if(parser->smtp_done != NULL)
+ parser->smtp_done(parser->data, fpc + 1, pe - fpc - 1);
+ fbreak;
+ }
+
+#### SMTP PROTOCOL GRAMMAR
+ CRLF = "\r\n";
+ SP = " ";
+
+ Let_dig = alnum;
+ Ldh_str = ( alnum | "-" )* alnum;
+ Snum = digit{1,3};
+#Standardized_tag = Ldh_str;
+#Not supported yet
+#General_address_literal = Standardized_tag ":" content{1,d};
+
+ IPv4_address_literal = Snum ("." Snum){3};
+
+ IPv6_hex = xdigit{1,4};
+ IPv6_full = IPv6_hex ( ":" IPv6_hex ){7};
+ IPv6_comp = (IPv6_hex (":" IPv6_hex){0,5})? "::" (IPv6_hex (":" IPv6_hex){0,5})?;
+ IPv6v4_full = IPv6_hex (":" IPv6_hex){5} ":" IPv4_address_literal;
+ IPv6v4_comp = (IPv6_hex (":" IPv6_hex){0,3})? "::" (IPv6_hex (":" IPv6_hex){0,3} ":")? IPv4_address_literal;
+
+ IPv6_addr = ( IPv6_full | IPv6_comp | IPv6v4_full | IPv6v4_comp );
+
+ IPv6_address_literal = "IPv6:" IPv6_addr;
+
+ Sub_domain = Let_dig Ldh_str?;
+#Address_literal = "[" ( Pv4_address_literal | IPv6_address_literal | General_address_literal ) "]";
+ Address_literal = "[" ( IPv4_address_literal | IPv6_address_literal ) "]";
+
+#It should be '+', but smtp.163.com is sucks.
+#Domain = (( Sub_domain ( '.' Sub_domain )+ ) | Address_literal ) >mark %domain;
+ Domain = (( Sub_domain ( '.' Sub_domain )? ) | Address_literal ) >mark %domain;
+
+ Greeting_text = ( ascii -- ("\r" | "\n") )+ >mark %greeting_text;
+
+ Greeting_line = "220 " Domain ( SP Greeting_text )? CRLF;
+
+
+
+ Reply_code = ( digit+ ) >mark %reply_code;
+
+ Ehlo_keyword = Let_dig ( Let_dig | "-" )*;
+ Ehlo_param = ( ascii -- ( cntrl | SP ) )+;
+
+#the "=" is not in the RFC, the reason see also: http://www.linuxquestions.org/questions/linux-networking-3/qmail-auth-login-auth%3Dlogin-arghhhhhhhh-226524/
+ Ehlo_line = ( Ehlo_keyword ( ( SP | "=" ) Ehlo_param )* ) >mark %reply_text;
+
+Ehlo_reply_ok = ( ( "250" Domain ( SP Greeting_text )? CRLF )
+ | ("250-" Domain ( SP Greeting_text)? CRLF ( "250-" Ehlo_line CRLF )* Reply_code SP Ehlo_line CRLF) );
+
+ Reply_text = ( ascii -- ("\r" | "\n") )+ >mark %reply_text;
+
+ General_reply_line = Reply_code ( SP Reply_text )? CRLF;
+
+ Reply_line = ( General_reply_line | Ehlo_reply_ok );
+
+
+ Response = Greeting_line Reply_line @done;
+
+main := Response;
+
+}%%
+
+/** Data **/
+%% write data;
+
+int smtp_parser_init(smtp_parser *parser) {
+
+ int cs = 0;
+ %% write init;
+ parser->cs = cs;
+ parser->mark = 0;
+ parser->nread = 0;
+
+ return(1);
+}
+
+
+/** exec **/
+size_t smtp_parser_execute(smtp_parser *parser, const char *buffer, size_t len, size_t off) {
+
+ const char *p, *pe;
+ int cs = parser->cs;
+
+ assert(off <= len && "offset past end of buffer");
+
+ p = buffer + off;
+ pe = buffer + len;
+
+ %% write exec;
+
+ if (!smtp_parser_has_error(parser))
+ parser->cs = cs;
+ parser->nread += p - (buffer + off);
+
+ return(parser->nread);
+}
+
+int smtp_parser_finish(smtp_parser *parser)
+{
+ if (smtp_parser_has_error(parser) ) {
+ return -1;
+ } else if (smtp_parser_is_finished(parser) ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int smtp_parser_has_error(smtp_parser *parser) {
+ return parser->cs == smtp_parser_error;
+}
+
+int smtp_parser_is_finished(smtp_parser *parser) {
+ return parser->cs >= smtp_parser_first_final;
+}
View
48 test/t/mysql_check.t
@@ -0,0 +1,48 @@
+#
+#===============================================================================
+#
+# FILE: mysql_check.t
+#
+# DESCRIPTION: test
+#
+# FILES: ---
+# BUGS: ---
+# NOTES: ---
+# AUTHOR: Weibin Yao (http://yaoweibin.cn/), yaoweibin@gmail.com
+# COMPANY:
+# VERSION: 1.0
+# CREATED: 03/02/2010 03:18:28 PM
+# REVISION: ---
+#===============================================================================
+
+
+# vi:filetype=perl
+
+use lib 'lib';
+use Test::Nginx::LWP;
+
+plan tests => repeat_each() * 2 * blocks();
+
+#no_diff;
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: the mysql_check
+--- config
+ upstream test{
+ server 127.0.0.1:3306;
+
+ #ip_hash;
+ check interval=3000 rise=2 fall=5 timeout=1000 type=mysql;
+ }
+
+ server {
+ listen 1982;
+
+ proxy_pass test;
+ }
+--- request
+GET /
+--- response_body_like: ^(.*)$
Please sign in to comment.
Something went wrong with that request. Please try again.