2013-08-18 17:42:25 +08:00
|
|
|
|
#include "lib_acl.h"
|
|
|
|
|
#include "lib_protocol.h"
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "probe.h"
|
|
|
|
|
|
|
|
|
|
ACL_ARRAY *var_probe_server_link = NULL;
|
|
|
|
|
const char *var_probe_logfile = NULL;
|
|
|
|
|
int var_probe_loglevel = 0;
|
|
|
|
|
int var_probe_statlen = 1024;
|
|
|
|
|
int var_probe_fork_sleep = 1;
|
|
|
|
|
ACL_VSTREAM *var_probe_debug_fp = NULL;
|
|
|
|
|
|
|
|
|
|
static ACL_XINETD_CFG_PARSER *__cfg_parser = NULL;
|
|
|
|
|
|
|
|
|
|
static char request_format[] = "\
|
|
|
|
|
GET %s HTTP/1.1\r\n\
|
|
|
|
|
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n\
|
|
|
|
|
Accept-Language: zh-cn\r\n\
|
|
|
|
|
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)\r\n\
|
|
|
|
|
Accept-Encoding: gzip, deflate\r\n\
|
|
|
|
|
Host: %s:%d\r\n\r\n";
|
|
|
|
|
|
2013-10-20 18:12:47 +08:00
|
|
|
|
static int __parse_url(const char *url, char *host_buf, int hlen,
|
|
|
|
|
int *http_port, char *url_buf, int ulen)
|
2013-08-18 17:42:25 +08:00
|
|
|
|
{
|
|
|
|
|
/* url format: http://www.hexun.com[:80]/index.html */
|
|
|
|
|
char *ptr, *url_begin;
|
|
|
|
|
char buf[1024];
|
|
|
|
|
size_t n;
|
|
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf) - 1, "%s", url);
|
|
|
|
|
ptr = buf;
|
|
|
|
|
while (*ptr == ' ' || *ptr == '\t')
|
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
|
|
n = strlen("http://");
|
|
|
|
|
|
2013-10-20 18:12:47 +08:00
|
|
|
|
/* <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><D7BC> http Э<><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ */
|
|
|
|
|
if (strncasecmp(ptr, "http://", n) == 0)
|
2013-08-18 17:42:25 +08:00
|
|
|
|
ptr += n;
|
|
|
|
|
|
|
|
|
|
if (*ptr == 0)
|
2013-10-20 18:12:47 +08:00
|
|
|
|
return -1;
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
url_begin = ptr;
|
|
|
|
|
ptr = strchr(url_begin, '/');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
if (*ptr == 0)
|
|
|
|
|
strcpy(url_buf, "/");
|
|
|
|
|
else
|
|
|
|
|
snprintf(url_buf, ulen, "/%s", ptr);
|
2013-10-20 18:12:47 +08:00
|
|
|
|
} else
|
2013-08-18 17:42:25 +08:00
|
|
|
|
strcpy(url_buf, "/");
|
|
|
|
|
|
|
|
|
|
/* <20><><EFBFBD><EFBFBD> http Э<><D0AD><EFBFBD>˿ں<CBBF> */
|
|
|
|
|
if (http_port) {
|
|
|
|
|
ptr = strchr(url_begin, ':');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
n = atoi(ptr);
|
|
|
|
|
if (n <= 0)
|
|
|
|
|
*http_port = 80;
|
|
|
|
|
else
|
|
|
|
|
*http_port = (int) n;
|
|
|
|
|
} else
|
|
|
|
|
*http_port = 80;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
snprintf(host_buf, hlen, "%s", url_begin);
|
2013-10-20 18:12:47 +08:00
|
|
|
|
return 0;
|
2013-08-18 17:42:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __build_http_request(PROBE_SERVER *server)
|
|
|
|
|
{
|
2013-10-20 18:12:47 +08:00
|
|
|
|
const char *myname = "__build_http_request";
|
2013-08-18 17:42:25 +08:00
|
|
|
|
char host_refer[256], url_request[256];
|
|
|
|
|
int port_refer = 80;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
memset(host_refer, 0, sizeof(host_refer));
|
|
|
|
|
memset(url_request, 0, sizeof(url_request));
|
|
|
|
|
|
2013-10-20 18:12:47 +08:00
|
|
|
|
ret = __parse_url(server->url, host_refer, sizeof(host_refer),
|
|
|
|
|
&port_refer, url_request, sizeof(url_request));
|
2013-08-18 17:42:25 +08:00
|
|
|
|
if (ret < 0)
|
2013-10-20 18:12:47 +08:00
|
|
|
|
acl_msg_fatal("%s(%d), %s: invalid url=[%s]",
|
|
|
|
|
__FILE__, __LINE__, myname, server->url);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
snprintf(server->http_request_header,
|
2013-10-20 18:12:47 +08:00
|
|
|
|
sizeof(server->http_request_header) - 1, request_format,
|
|
|
|
|
url_request, host_refer, port_refer);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
server->http_request_len = (int) strlen(server->http_request_header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __set_name_value(char *data, PROBE_SERVER *server)
|
|
|
|
|
{
|
2013-10-20 18:12:47 +08:00
|
|
|
|
/* data: name=value */
|
|
|
|
|
const char *myname = "__set_name_value";
|
2013-08-18 17:42:25 +08:00
|
|
|
|
char *pname, *pvalue, *ptr;
|
|
|
|
|
|
|
|
|
|
pname = data;
|
|
|
|
|
/* skip ' ' and '\t' */
|
|
|
|
|
while (*pname == ' ' || *pname == '\t')
|
|
|
|
|
pname++;
|
|
|
|
|
if (pname == 0) {
|
2013-10-20 18:12:47 +08:00
|
|
|
|
acl_msg_error("%s(%d), %s: invalid data=[%s]",
|
|
|
|
|
__FILE__, __LINE__, myname, data);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pvalue = pname;
|
|
|
|
|
/* find '=' */
|
|
|
|
|
while (*pvalue) {
|
|
|
|
|
if (*pvalue == '=') {
|
|
|
|
|
*pvalue++ = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pvalue++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* skip ' ' and '\t' */
|
|
|
|
|
while (*pvalue == ' ' || *pvalue == '\t')
|
|
|
|
|
pvalue++;
|
|
|
|
|
if (pvalue == 0) {
|
|
|
|
|
acl_msg_error("%s(%d)->%s: invalid data=[%s]",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname, data);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ptr = pvalue;
|
|
|
|
|
while (*ptr) {
|
|
|
|
|
if (*ptr == ' ' || *ptr == '\t' || *ptr == ',') {
|
|
|
|
|
*ptr = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ptr++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcasecmp(pname, VAR_CFG_SERVER_NAME) == 0)
|
|
|
|
|
server->name = acl_mystrdup(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_ADDR) == 0)
|
|
|
|
|
server->addr = acl_mystrdup(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_URL) == 0)
|
|
|
|
|
server->url = acl_mystrdup(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_CONNECT_TIMEOUT) == 0)
|
|
|
|
|
server->connect_timeout = atoi(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_RW_TIMEOUT) == 0)
|
|
|
|
|
server->rw_timeout = atoi(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_RETRY_INTER) == 0)
|
|
|
|
|
server->retry_inter = atoi(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_PROBE_INTER) == 0)
|
|
|
|
|
server->probe_inter = atoi(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_HTTP_ERRORS) == 0)
|
|
|
|
|
server->http_status_errors = acl_mystrdup(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_LOG) == 0)
|
|
|
|
|
server->logfile = acl_mystrdup(pvalue);
|
|
|
|
|
else if (strcasecmp(pname, VAR_CFG_SERVER_WARN_TIME) == 0)
|
|
|
|
|
server->warn_time = atoi(pvalue);
|
|
|
|
|
|
|
|
|
|
/* only for test */
|
2013-10-20 18:12:47 +08:00
|
|
|
|
printf("name(%s)=value(%s), probe_inter=%d\n",
|
|
|
|
|
pname, pvalue, server->probe_inter);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static PROBE_SERVER *__cfg_server_new(char *data)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* data: server_name="<EFBFBD><EFBFBD><EFBFBD><EFBFBD>2", addr=10.0.90.246:80, url=http://blog.hexun.com/index.aspx, connect_timeout=60, rw_timeout=60, retry_inter=5, probe_inter=5
|
|
|
|
|
*/
|
2013-10-20 18:12:47 +08:00
|
|
|
|
const char *myname = "__cfg_server_new";
|
2013-08-18 17:42:25 +08:00
|
|
|
|
PROBE_SERVER *server = NULL;
|
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
|
|
if (data == NULL || *data == 0) {
|
|
|
|
|
acl_msg_error("%s: invalid data input", myname);
|
2013-10-20 18:12:47 +08:00
|
|
|
|
return NULL;
|
2013-08-18 17:42:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server = (PROBE_SERVER *) acl_mycalloc(1, sizeof(PROBE_SERVER));
|
|
|
|
|
if (server == NULL)
|
2013-10-20 18:12:47 +08:00
|
|
|
|
acl_msg_fatal("%s: can't calloc, serr=%s",
|
|
|
|
|
myname, strerror(errno));
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
ptr = acl_mystrtok(&data, ",");
|
|
|
|
|
if (ptr == NULL)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
__set_name_value(ptr, server);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__build_http_request(server);
|
|
|
|
|
if (server->logfile != NULL) {
|
|
|
|
|
server->logfp = acl_vstream_fopen(server->logfile,
|
2013-10-20 18:12:47 +08:00
|
|
|
|
O_WRONLY | O_CREAT | O_APPEND, 0600, 4096);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
if (server->logfp == NULL)
|
2013-10-20 18:12:47 +08:00
|
|
|
|
acl_msg_fatal("%s: open logfile(%s) error %s ",
|
|
|
|
|
myname, server->logfile, strerror(errno));
|
2013-08-18 17:42:25 +08:00
|
|
|
|
} else
|
|
|
|
|
server->logfp = NULL;
|
|
|
|
|
|
2013-10-20 18:12:47 +08:00
|
|
|
|
return server;
|
2013-08-18 17:42:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __cfg_parse_one_server(const char *server_data)
|
|
|
|
|
{
|
2013-10-20 18:12:47 +08:00
|
|
|
|
const char *myname = "__cfg_parse_one_server";
|
2013-08-18 17:42:25 +08:00
|
|
|
|
char *buf = NULL;
|
|
|
|
|
char *begin, *end;
|
|
|
|
|
PROBE_SERVER *server;
|
|
|
|
|
|
|
|
|
|
#undef RETURN
|
|
|
|
|
#define RETURN do { \
|
|
|
|
|
if (buf) \
|
|
|
|
|
acl_myfree(buf); \
|
|
|
|
|
return; \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
if (server_data == NULL || *server_data == 0)
|
|
|
|
|
acl_msg_fatal("%s(%d)->%s: input invalid",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
buf = acl_mystrdup(server_data);
|
|
|
|
|
|
|
|
|
|
begin = buf;
|
|
|
|
|
while (*begin) {
|
|
|
|
|
if (*begin == '<') {
|
|
|
|
|
*begin++ = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
begin++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*begin == 0)
|
|
|
|
|
RETURN;
|
|
|
|
|
end = begin;
|
|
|
|
|
while (*end) {
|
|
|
|
|
if (*end == '>') {
|
|
|
|
|
*end = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
end++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server = __cfg_server_new(begin);
|
2013-10-20 18:12:47 +08:00
|
|
|
|
if (server == NULL)
|
2013-08-18 17:42:25 +08:00
|
|
|
|
acl_msg_fatal("%s(%d)->%s: invalid data=[%s]",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname, server_data);
|
|
|
|
|
else
|
|
|
|
|
acl_array_append(var_probe_server_link, (void *) server);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
acl_msg_info("%s(%d)->%s: name=%s, addr=%s, url=%s, connect_timeout=%d,"
|
2013-10-20 18:12:47 +08:00
|
|
|
|
" rw_timeout=%d, retry_inter=%d, probe_inter=%d\n",
|
|
|
|
|
__FILE__, __LINE__, myname, server->name, server->addr,
|
|
|
|
|
server->url, server->connect_timeout, server->rw_timeout,
|
|
|
|
|
server->retry_inter, server->probe_inter);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
RETURN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __cfg_server_parse(const ACL_ARRAY *a)
|
|
|
|
|
{
|
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
|
|
if (a == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
n = acl_array_size(a);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
acl_msg_info("%s: %s", VAR_CFG_SERVER, (const char *) acl_array_index(a, i));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
__cfg_parse_one_server((const char *) acl_array_index(a, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void probe_cfg_load(void)
|
|
|
|
|
{
|
2013-10-20 18:12:47 +08:00
|
|
|
|
const char *myname = "probe_cfg_load";
|
2013-08-18 17:42:25 +08:00
|
|
|
|
ACL_XINETD_CFG_PARSER *xcp;
|
|
|
|
|
const ACL_ARRAY *servers_array;
|
|
|
|
|
const char *ptr;
|
|
|
|
|
|
|
|
|
|
if (var_cfg_file == NULL || *var_cfg_file == 0)
|
|
|
|
|
acl_msg_fatal("%s(%d)->%s: __cfg_file null",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
xcp = acl_xinetd_cfg_load(var_cfg_file);
|
|
|
|
|
if (xcp == NULL) {
|
|
|
|
|
acl_msg_error("%s(%d)->%s: xinetd_cfg_load return null, file=%s",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname, var_cfg_file);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
exit (1);
|
|
|
|
|
}
|
|
|
|
|
__cfg_parser = xcp;
|
|
|
|
|
|
|
|
|
|
var_probe_server_link = acl_array_create(50);
|
|
|
|
|
if (var_probe_server_link == NULL)
|
|
|
|
|
acl_msg_fatal("%s(%d)->%s: acl_array_create error, serr=%s",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname, strerror(errno));
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
servers_array = acl_xinetd_cfg_get_ex(xcp, VAR_CFG_SERVER);
|
|
|
|
|
if (servers_array == NULL)
|
|
|
|
|
acl_msg_fatal("%s(%d)->%s: not fine %s line",
|
2013-10-20 18:12:47 +08:00
|
|
|
|
__FILE__, __LINE__, myname, VAR_CFG_SERVER);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
|
|
|
|
|
__cfg_server_parse(servers_array);
|
|
|
|
|
|
|
|
|
|
var_probe_logfile = acl_xinetd_cfg_get(xcp, VAR_CFG_LOGFILE);
|
|
|
|
|
if (var_probe_logfile == NULL || *var_probe_logfile == 0)
|
|
|
|
|
acl_msg_warn("%s(%d)->%s: null var_probe_logfile",
|
|
|
|
|
__FILE__, __LINE__, myname);
|
|
|
|
|
ptr = acl_xinetd_cfg_get(xcp, VAR_CFG_LOGLEVEL);
|
|
|
|
|
if (ptr && *ptr)
|
|
|
|
|
var_probe_loglevel = atoi(ptr);
|
|
|
|
|
if (var_probe_loglevel < 0)
|
|
|
|
|
var_probe_loglevel = 0;
|
|
|
|
|
ptr = acl_xinetd_cfg_get(xcp, VAR_CFG_STATLEN);
|
|
|
|
|
if (ptr && *ptr)
|
|
|
|
|
var_probe_statlen = atoi(ptr);
|
|
|
|
|
if (var_probe_statlen <= 0)
|
|
|
|
|
var_probe_statlen = 1024;
|
|
|
|
|
|
|
|
|
|
ptr = acl_xinetd_cfg_get(xcp, VAR_CFG_FORK_SLEEP);
|
|
|
|
|
if (ptr && *ptr)
|
|
|
|
|
var_probe_fork_sleep = atoi(ptr);
|
|
|
|
|
if (var_probe_fork_sleep < 0)
|
|
|
|
|
var_probe_fork_sleep = 1;
|
|
|
|
|
|
|
|
|
|
ptr = acl_xinetd_cfg_get(xcp, VAR_CFG_DEBUG_FILE);
|
|
|
|
|
if (ptr && *ptr)
|
|
|
|
|
var_probe_debug_fp = acl_vstream_fopen(ptr,
|
2013-10-20 18:12:47 +08:00
|
|
|
|
O_WRONLY | O_CREAT | O_APPEND, 0600, 4096);
|
2013-08-18 17:42:25 +08:00
|
|
|
|
else
|
|
|
|
|
var_probe_debug_fp = NULL;
|
|
|
|
|
}
|