Skip to content

Commit

Permalink
add check type of pop3 and imap, tag v0.19
Browse files Browse the repository at this point in the history
  • Loading branch information
yaoweibin committed Apr 6, 2010
1 parent 4f3868e commit df22ece
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 3 deletions.
11 changes: 8 additions & 3 deletions README
Expand Up @@ -58,7 +58,7 @@ Description
upstream server health check, status monitor. upstream server health check, status monitor.


The motivation of writing these modules is Nginx's high performance and The motivation of writing these modules is Nginx's high performance and
robustness. It's more scalable in the SMP system when compared with HAProxy. robustness.




Directives Directives
Expand Down Expand Up @@ -144,7 +144,7 @@ Directives


==check== ==check==
syntax: check interval=milliseconds [fall=count] [rise=count] syntax: check interval=milliseconds [fall=count] [rise=count]
[timeout=milliseconds] [type=tcp|ssl_hello|smtp|mysql] [timeout=milliseconds] [type=tcp|ssl_hello|smtp|mysql|pop3|imap]
default: none, if parameters omitted, default parameters are 'interval=30000 default: none, if parameters omitted, default parameters are 'interval=30000
fall=5 rise=2 timeout=1000' fall=5 rise=2 timeout=1000'
context: upstream context: upstream
Expand All @@ -165,9 +165,14 @@ Directives
response to diagnose if the upstream server is alive. response to diagnose if the upstream server is alive.
'smtp' sends a smtp requst packet, recvives and parses the smtp 'smtp' sends a smtp requst packet, recvives and parses the smtp
response to diagnose if the upstream server is alive. The response response to diagnose if the upstream server is alive. The response
begins with '2' will be judged to be a OK response. begins with '2' should be an OK response.
'mysql' connects to the mysql server, recvives the greeting response 'mysql' connects to the mysql server, recvives the greeting response
to diagnose if the upstream server is alive. to diagnose if the upstream server is alive.
'pop3' recvives and parses the pop3 response to diagnose if the
upstream server is alive. The response begins with '+' should be an
OK response.
'imap' connects to the imap server, recvives the greeting response
to diagnose if the upstream server is alive.


==check_http_send= ==check_http_send=
syntax: check_http_send http_packet syntax: check_http_send http_packet
Expand Down
174 changes: 174 additions & 0 deletions ngx_tcp_upstream_check.c
Expand Up @@ -32,6 +32,14 @@ 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 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 void ngx_tcp_check_mysql_reinit(ngx_tcp_check_peer_conf_t *peer_conf);


static ngx_int_t ngx_tcp_check_pop3_init(ngx_tcp_check_peer_conf_t *peer_conf);
static ngx_int_t ngx_tcp_check_pop3_parse(ngx_tcp_check_peer_conf_t *peer_conf);
static void ngx_tcp_check_pop3_reinit(ngx_tcp_check_peer_conf_t *peer_conf);

static ngx_int_t ngx_tcp_check_imap_init(ngx_tcp_check_peer_conf_t *peer_conf);
static ngx_int_t ngx_tcp_check_imap_parse(ngx_tcp_check_peer_conf_t *peer_conf);
static void ngx_tcp_check_imap_reinit(ngx_tcp_check_peer_conf_t *peer_conf);

static char * ngx_tcp_upstream_check_status_set_status(ngx_conf_t *cf, static char * ngx_tcp_upstream_check_status_set_status(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf); ngx_command_t *cmd, void *conf);


Expand Down Expand Up @@ -134,6 +142,31 @@ static check_conf_t ngx_check_types[] = {
ngx_tcp_check_mysql_reinit, ngx_tcp_check_mysql_reinit,
1 1
}, },
{
NGX_TCP_CHECK_POP3,
"pop3",
ngx_null_string,
0,
ngx_tcp_check_send_handler,
ngx_tcp_check_recv_handler,
ngx_tcp_check_pop3_init,
ngx_tcp_check_pop3_parse,
ngx_tcp_check_pop3_reinit,
1
},
{
NGX_TCP_CHECK_IMAP,
"imap",
ngx_null_string,
0,
ngx_tcp_check_send_handler,
ngx_tcp_check_recv_handler,
ngx_tcp_check_imap_init,
ngx_tcp_check_imap_parse,
ngx_tcp_check_imap_reinit,
1
},



{0, "", ngx_null_string, 0, NULL, NULL, NULL, NULL, NULL, 0} {0, "", ngx_null_string, 0, NULL, NULL, NULL, NULL, NULL, 0}
}; };
Expand Down Expand Up @@ -915,6 +948,12 @@ ngx_tcp_check_smtp_parse(ngx_tcp_check_peer_conf_t *peer_conf) {
ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
"smtp parse error with peer: %V, recv data: %s", "smtp parse error with peer: %V, recv data: %s",
&peer_conf->peer->name, ctx->recv.pos); &peer_conf->peer->name, ctx->recv.pos);

/*Some SMTP servers are not strictly designed with the RFC2821, but it does work*/
if (*ctx->recv.start == '2') {
return NGX_OK;
}

return NGX_ERROR; return NGX_ERROR;
} }


Expand Down Expand Up @@ -1009,6 +1048,138 @@ ngx_tcp_check_mysql_reinit(ngx_tcp_check_peer_conf_t *peer_conf) {
ctx->recv.pos = ctx->recv.last = ctx->recv.start; ctx->recv.pos = ctx->recv.last = ctx->recv.start;
} }



static ngx_int_t
ngx_tcp_check_pop3_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_pop3_parse(ngx_tcp_check_peer_conf_t *peer_conf) {

u_char ch;
ngx_tcp_check_ctx *ctx;

ctx = peer_conf->check_data;

if (ctx->recv.last - ctx->recv.pos <= 0 ) {
return NGX_AGAIN;
}

ch = *(ctx->recv.start);

ngx_log_debug1(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
"pop3_parse: packet_greeting \"%s\"", ctx->recv.start);

/* RFC 1939
There are currently two status indicators: positive ("+OK") and
negative ("-ERR"). Servers MUST send the "+OK" and "-ERR" in upper case.
*/
if (ch != '+') {
return NGX_ERROR;
}

return NGX_OK;
}

static void
ngx_tcp_check_pop3_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 ngx_int_t
ngx_tcp_check_imap_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_imap_parse(ngx_tcp_check_peer_conf_t *peer_conf) {

u_char *p;
ngx_tcp_check_ctx *ctx;

ctx = peer_conf->check_data;

if (ctx->recv.last - ctx->recv.pos <= 0 ) {
return NGX_AGAIN;
}

ngx_log_debug1(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
"imap_parse: packet_greeting \"%s\"", ctx->recv.start);

/* RFC 3501
command = tag SP (command-any / command-auth / command-nonauth /
command-select) CRLF
*/

p = ctx->recv.start;
while (p < ctx->recv.last) {

if (*p == ' ') {
if ((p + 2) >= ctx->recv.last) {
return NGX_AGAIN;
}
else if (*(p + 1) == 'O' && *(p + 2) == 'K') {
return NGX_OK;
}
else {
return NGX_ERROR;
}
}

p++;
}

return NGX_AGAIN;
}

static void
ngx_tcp_check_imap_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 static void
ngx_tcp_check_send_handler(ngx_event_t *event) { ngx_tcp_check_send_handler(ngx_event_t *event) {


Expand Down Expand Up @@ -1177,6 +1348,9 @@ ngx_tcp_check_recv_handler(ngx_event_t *event) {
case NGX_AGAIN: case NGX_AGAIN:
return; return;
case NGX_ERROR: case NGX_ERROR:
ngx_log_error(NGX_LOG_ERR, event->log, 0,
"check protocol %s error with peer: %V ",
peer_conf->conf->check_type_conf->name, &peer_conf->peer->name);
ngx_tcp_check_status_update(peer_conf, 0); ngx_tcp_check_status_update(peer_conf, 0);
break; break;
case NGX_OK: case NGX_OK:
Expand Down
2 changes: 2 additions & 0 deletions ngx_tcp_upstream_check.h
Expand Up @@ -86,6 +86,8 @@ typedef void (*ngx_tcp_check_packet_clean_pt)(ngx_tcp_check_peer_conf_t *peer_co
#define NGX_TCP_CHECK_SSL_HELLO 0x0004 #define NGX_TCP_CHECK_SSL_HELLO 0x0004
#define NGX_TCP_CHECK_SMTP 0x0008 #define NGX_TCP_CHECK_SMTP 0x0008
#define NGX_TCP_CHECK_MYSQL 0x0010 #define NGX_TCP_CHECK_MYSQL 0x0010
#define NGX_TCP_CHECK_POP3 0x0020
#define NGX_TCP_CHECK_IMAP 0x0040




#define NGX_CHECK_HTTP_2XX 0x0002 #define NGX_CHECK_HTTP_2XX 0x0002
Expand Down
48 changes: 48 additions & 0 deletions test/t/imap_check.t
@@ -0,0 +1,48 @@
#
#===============================================================================
#
# FILE: imap_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 imap_check
--- config
upstream test{
server imap.163.com:143;
#ip_hash;
check interval=3000 rise=2 fall=5 timeout=1000 type=imap;
}
server {
listen 1982;
proxy_pass test;
}
--- request
GET /
--- response_body_like: ^(.*)$
48 changes: 48 additions & 0 deletions test/t/pop3_check.t
@@ -0,0 +1,48 @@
#
#===============================================================================
#
# FILE: pop3_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 pop3_check
--- config
upstream test{
server pop3.163.com:110;
#ip_hash;
check interval=3000 rise=2 fall=5 timeout=1000 type=pop3;
}
server {
listen 1982;
proxy_pass test;
}
--- request
GET /
--- response_body_like: ^(.*)$

0 comments on commit df22ece

Please sign in to comment.