summaryrefslogtreecommitdiff
path: root/src/HTTP_Message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/HTTP_Message.c')
-rw-r--r--src/HTTP_Message.c1098
1 files changed, 1098 insertions, 0 deletions
diff --git a/src/HTTP_Message.c b/src/HTTP_Message.c
new file mode 100644
index 0000000..c03fa36
--- /dev/null
+++ b/src/HTTP_Message.c
@@ -0,0 +1,1098 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <dlfcn.h>
+#include <math.h>
+
+#include "HTTP_Message.h"
+#include "HTTP_Analyze.h"
+#include "HTTP_Common.h"
+#include "HTTP_Message_Region.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include "MESA_htable.h"
+#include "field_stat.h"
+
+extern int g_iThreadNum;
+extern http_prog_runtime_parameter_t g_http_prog_para;
+extern string_map_t g_http_regions[];
+extern const char* g_http_method[];
+
+const char* http_get_method(uchar method)
+{
+ if(method>0&&method<=HTTP_METHOD_TRACE)
+ {
+ return g_http_method[method];
+ }
+ return NULL;
+}
+
+char http_is_hexChar(char c)
+{
+ return c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F'? c - 'A' + 10 : c - 'a' + 10; /* accept small letters just in case */
+}
+
+int http_line2region(const char *line, uint32 line_len, char** region, uint32* region_len)
+{
+ /*line����ҵ��㣬��append,����lineǰ��Ŀո��Ѿ�ɾ����ֻ��Ҫɾ��: ֮��Ŀո�*/
+ uint32 del_data_len=0;
+ char* colon_pos = (char*)memchr(line, ':', line_len);
+ if(NULL==colon_pos) return -1;
+ http_deleteSPHTCRLFAtLast(&del_data_len, (char*)line, colon_pos - line);
+ *region = (char*)line;
+ *region_len = del_data_len;
+ return 0;
+}
+
+/* old platform
+char* http_url_decode(char *data, int* data_len)
+{
+ if (!data) return NULL;
+ char *str = (char *)malloc(*data_len + 1);
+ strncpy(str, data, *data_len);
+ str[*data_len] = '\0';
+ char *p = str;
+ char *q = str;
+
+ while(*p)
+ {
+ if (*p == '%')
+ {
+ p++;
+ if (*p) *q = http_is_hexChar(*p++) * 16;
+ if (*p) *q = (*q + http_is_hexChar(*p)), ++p;
+ q++;
+ }
+ else
+ {
+ *q++ = *p++;
+ }
+ }
+ *q++ = 0;
+ *data_len = strlen(str);
+ strncpy(data, str, *data_len);
+ free(str);
+ return data;
+}
+*/
+
+char* http_url_decode(char *data, int* data_len)
+{
+ if (!data) return NULL;
+ char *str = (char *)malloc(*data_len);
+ strncpy(str, data, *data_len);
+ char *p = str;
+ char *q = str;
+ char *str_end = str+*data_len;
+
+ while(p<str_end)
+ {
+ if (*p == '%')
+ {
+ p++;
+ if (*p) *q = http_is_hexChar(*p++) * 16;
+ if (*p) *q = (*q + http_is_hexChar(*p)), ++p;
+ q++;
+ }
+ else
+ {
+ *q++ = *p++;
+ }
+ }
+ *data_len = (int)(q - str);
+ memcpy(data, str, *data_len);
+ free(str);
+ return data;
+}
+
+
+const char* http_proto_flag2region(int64 proto_flag)
+{
+ //int region_id = get_bitnum(prot_flag);
+ int region_id = (int) (log(proto_flag)/log(2));
+ if(region_id>=(int)g_http_prog_para.http_region_cnt) return NULL;
+ return (const char*)g_http_prog_para.http_conf_regionname[region_id];
+}
+
+/*standard region: support Server(in pcap) or HTTP_SERVER*/
+long long http_region2proto_flag(const char *region, uint32 region_len)
+{
+ uint32* region_id = NULL;
+ char reg[REGION_NAME_LEN] = {0};
+
+ memcpy(reg, region, region_len);
+ stringA_to_stringa(reg, region_len);
+ region_id = (uint32*)MESA_htable_search_cb(g_http_prog_para.region_hash, (const uchar*)reg, region_len, NULL, NULL, NULL);
+ if(region_id!=NULL)
+ {
+ return (long long)(((long long)1)<<(*region_id));
+ }
+ /*http content......*/
+ else
+ {
+ for(int i=0;i<g_http_prog_para.http_region_cnt;i++)
+ {
+ if(0==strcasecmp(g_http_prog_para.http_conf_regionname[i], region))
+ {
+ return (long long)(((long long)1)<<(i));;
+ }
+ }
+ }
+ return -1;
+}
+
+MESA_htable_handle http_initRegionHash()
+{
+ MESA_htable_create_args_t hash_args;
+ memset(&hash_args,0,sizeof(MESA_htable_create_args_t));
+ hash_args.thread_safe = 0;
+ hash_args.recursive = 0;
+ hash_args.hash_slot_size = 1024;
+ hash_args.max_elem_num = 1024;
+ hash_args.eliminate_type = 0;
+ hash_args.expire_time = 0;
+ hash_args.key_comp = NULL;
+ hash_args.key2index = NULL;
+ hash_args.data_free = NULL;
+ hash_args.data_expire_with_condition = NULL;
+ MESA_htable_handle hash_handler = MESA_htable_create(&hash_args, sizeof(hash_args));
+ if(NULL==hash_handler)
+ {
+ MESA_htable_destroy(hash_handler, NULL);
+ return NULL;
+ }
+
+ /*init header hash: standard*/
+ int i=0;
+ for(i=0;i<HTTP_REGION_NUM;i++)
+ {
+ if(g_http_regions[i].string[0]=='\0') continue;
+ if(-1==(MESA_htable_add(hash_handler, (const uchar*)g_http_regions[i].string, strlen(g_http_regions[i].string), &g_http_regions[i].stringid)))
+ {
+ MESA_htable_destroy(hash_handler, NULL);
+ return NULL;
+ }
+ }
+ /*init header hash: expand*/
+ int* m = NULL;
+ for(i=HTTP_REGION_NUM;i<g_http_prog_para.http_region_cnt;i++)
+ {
+ m = (int*)malloc(sizeof(int));
+ *m = i;
+ stringA_to_stringa(g_http_prog_para.http_conf_regionname[i], strlen(g_http_prog_para.http_conf_regionname[i]));
+ if(-1==(MESA_htable_add(hash_handler, (const uchar*)g_http_prog_para.http_conf_regionname[i], strlen(g_http_prog_para.http_conf_regionname[i]), m)))
+ {
+ MESA_htable_destroy(hash_handler, NULL);
+ return NULL;
+ }
+ }
+ return hash_handler;
+}
+
+int http_readHttpConf(const char* filename)
+{
+ FILE* fp = NULL;
+ char buf[2048] = {0};
+ int region_id = 0;
+ int temp = 0;
+ char region_name[REGION_NAME_LEN] = {0};
+
+ g_http_prog_para.http_region_cnt++;
+ if(((fp = fopen(filename, "r"))!=NULL))
+ {
+ while( fgets(buf, sizeof(buf), fp))
+ {
+ if(buf[0]=='#' || buf[0]==' ' || buf[0]=='\r' || buf[0]=='\n') continue;
+ temp = sscanf(buf, "%d\t%s", &region_id, region_name);
+ if(2 > temp)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http.conf read %s error!", buf);
+ return -1;
+ }
+ if(region_id > MAX_REGION_NUM)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http.conf bigger than %d", MAX_REGION_NUM);
+ return -1;
+ }
+ strncpy(g_http_prog_para.http_conf_regionname[region_id], region_name, strlen(region_name));
+ g_http_prog_para.http_region_cnt++;
+ memset(region_name, 0, sizeof(region_name));
+ }
+ fclose(fp);
+ }
+ else
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http.conf open error!");
+ return -1;
+ }
+ /*init region hash*/
+ g_http_prog_para.region_hash = http_initRegionHash();
+ if(NULL==g_http_prog_para.region_hash)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int http_readMainConf(const char* filename)
+{
+ char http_log_filename[256];
+
+ MESA_load_profile_short_def(filename, "LOG", "log_level", (short*)&g_http_prog_para.http_log_level, 30);
+ MESA_load_profile_string_def(filename, "LOG", "log_path", http_log_filename, sizeof(http_log_filename),"./log/http/runtime");
+
+ g_http_prog_para.http_log_handle = MESA_create_runtime_log_handle(http_log_filename, g_http_prog_para.http_log_level);
+ if(NULL==g_http_prog_para.http_log_handle)
+ {
+ printf("%s get log handle error!\n", HTTP_PLUGIN_NAME);
+ return -1;
+ }
+ MESA_load_profile_short_def(filename, "FUNCTION", "switch_no_biz", (short*)&g_http_prog_para.http_switch_no_biz,0);
+ MESA_load_profile_short_def(filename, "FUNCTION", "ungzip_switch", (short*)&g_http_prog_para.ungzip_switch,1);
+ MESA_load_profile_short_def(filename, "FUNCTION", "proxy_switch", (short*)&g_http_prog_para.proxy_switch,1);
+ MESA_load_profile_int_def(filename, "FUNCTION", "stat_screen_print", &g_http_prog_para.http_stat_screen_print_trigger,0);
+ MESA_load_profile_int_def(filename, "FUNCTION", "stat_cycle", &g_http_prog_para.http_stat_cycle,0);
+ MESA_load_profile_uint_def(filename, "FUNCTION", "singleway_maxseq", &g_http_prog_para.singleway_seq,0);
+ MESA_load_profile_short_def(filename, "FUNCTION", "callback_mode", (short*)&g_http_prog_para.callback_mode,0);
+ MESA_load_profile_short_def(filename, "FUNCTION", "batch_field_maxnum", (short*)&g_http_prog_para.batch_field_maxnum,64);
+ MESA_load_profile_string_def(filename, "FUNCTION", "stat_file", g_http_prog_para.http_stat_filename, sizeof(g_http_prog_para.http_stat_filename),"./log/http/http_stat.log");
+
+ return 0;
+}
+
+int HTTP_INIT(void)
+{
+ memset(&g_http_prog_para,0,sizeof(http_prog_runtime_parameter_t));
+ if(0!=http_readMainConf("./conf/http/http_main.conf"))
+ {
+ printf("%s http_main.conf read error!", HTTP_PLUGIN_NAME);
+ return -1;
+ }
+ if(0!=http_readHttpConf("./conf/http/http.conf"))
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http.conf read error!");
+ return -1;
+ }
+
+ /*ungzip init*/
+ g_http_prog_para.docanly_handler = docanalyze_initialize(g_iThreadNum);
+ if(NULL==g_http_prog_para.docanly_handler)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "docanalyze_initialize error!");
+ return -1;
+ }
+
+#if HTTP_PROXY_CAPFILE
+ g_http_prog_para.capfile_project_id = project_producer_register("MESA_CAPFILE", "char", NULL);
+#endif
+
+#if DEBUG_TEST_DEAL_TIME
+ pthread_mutex_init(&g_http_prog_para.stat_lock, NULL);
+#endif
+
+ /*http stat*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ if(g_http_prog_para.http_stat_screen_print_trigger==0)
+ {
+ g_http_prog_para.stat_handler = init_screen_stat(stdout,g_http_prog_para.http_stat_cycle, 1);
+ }
+ else if(g_http_prog_para.http_stat_screen_print_trigger==1&&(g_http_prog_para.http_stat_file = fopen(g_http_prog_para.http_stat_filename, "a"))!=NULL)
+ {
+ g_http_prog_para.stat_handler = init_screen_stat(g_http_prog_para.http_stat_file ,g_http_prog_para.http_stat_cycle, 1);
+ }
+ else
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat file open error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_PKTS] = stat_field_register(g_http_prog_para.stat_handler,"http_pkts")) ==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_pkts register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_BITS] = stat_field_register(g_http_prog_para.stat_handler,"http_bytes")) ==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_bits register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_REQ] = stat_field_register(g_http_prog_para.stat_handler,"req_counts")) ==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_req_counts register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_RES] = stat_field_register(g_http_prog_para.stat_handler,"res_counts")) ==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_res_counts register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CREATE] = stat_field_register(g_http_prog_para.stat_handler,"http_create_N")) ==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_create register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_RELEASE] = stat_field_register(g_http_prog_para.stat_handler,"http_release_N"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_release register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_C2S] = stat_field_register(g_http_prog_para.stat_handler,"single_c2s_N"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_single_c2s register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_S2C] = stat_field_register(g_http_prog_para.stat_handler,"single_s2c_N"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_single_s2c register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_HEADER_C2S] = stat_field_register(g_http_prog_para.stat_handler,"header_c2s_B"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat header_c2s register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_HEADER_S2C] = stat_field_register(g_http_prog_para.stat_handler,"header_s2c_B"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat header_s2c register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CONTENT_C2S] = stat_field_register(g_http_prog_para.stat_handler,"content_c2s_B"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat content_c2s register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CONTENT_S2C] = stat_field_register(g_http_prog_para.stat_handler,"content_s2c_B"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat content_s2c register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_LOST] = stat_field_register(g_http_prog_para.stat_handler,"tcplost_cnt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_tcplost_cnt register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_RESET] = stat_field_register(g_http_prog_para.stat_handler,"reset_cnt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat http_reset_cnt register error!");
+ return -1;
+ }
+#if HTTP_STATIC
+ if((g_http_prog_para.stat_field[HTTP_STAT_REGION_TIME_STR] = stat_field_register(g_http_prog_para.stat_handler,"region_str"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat region_str register error!");
+ return -1;
+ }
+#if HTTP_REGION_HASH
+ if((g_http_prog_para.stat_field[HTTP_STAT_REGION_TIME_HASH] = stat_field_register(g_http_prog_para.stat_handler,"region_hash"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat region_hash register error!");
+ return -1;
+ }
+#endif
+ if((g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_CALLBACK] = stat_field_register(g_http_prog_para.stat_handler,"tcppkt_cb_N"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat tcppkt_cb_N register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_PROC_TIME] = stat_field_register(g_http_prog_para.stat_handler,"tcppkt_proc_T"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat tcppkt_proc_T register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_PROC_MAXTIME] = stat_field_register(g_http_prog_para.stat_handler,"tcppkt_proc_MT"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat tcppkt_proc_MT register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN] = stat_field_register(g_http_prog_para.stat_handler,"plugin_cb_N"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat tcppkt_proc_T register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN_PROC_TIME] = stat_field_register(g_http_prog_para.stat_handler,"plugin_cb_T"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat tcppkt_proc_MT register error!");
+ return -1;
+ }
+#endif
+ if((g_http_prog_para.stat_field[HTTP_STAT_CLIENT_PKT] = stat_field_register(g_http_prog_para.stat_handler,"client_pkt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat client_pkt register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_CLIENT_BYTE] = stat_field_register(g_http_prog_para.stat_handler,"client_byte"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat client_byte register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_SERVER_PKT] = stat_field_register(g_http_prog_para.stat_handler,"server_pkt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat server_pkt register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_SERVER_BYTE] = stat_field_register(g_http_prog_para.stat_handler,"server_byte"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat server_byte register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_CNT] = stat_field_register(g_http_prog_para.stat_handler,"header_span_cnt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat header_span_cnt register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_PKT] = stat_field_register(g_http_prog_para.stat_handler,"header_span_pkt"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat header_span_pkt register error!");
+ return -1;
+ }
+ if((g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_BYTE] = stat_field_register(g_http_prog_para.stat_handler,"header_span_byte"))==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_stat header_span_byte register error!");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void HTTP_DESTROY(void)
+{
+ MESA_htable_destroy(g_http_prog_para.region_hash, NULL);
+ /*http stat*/
+ if(NULL!=g_http_prog_para.http_stat_file)
+ {
+ fclose(g_http_prog_para.http_stat_file);
+ }
+
+ /*runtimelog*/
+ MESA_destroy_runtime_log_handle(g_http_prog_para.http_log_handle);
+
+ /*ungzip*/
+ docanalyze_destroy(g_http_prog_para.docanly_handler);
+}
+
+void HTTP_PROT_FUNSTAT(unsigned long long protflag)
+{
+ g_http_prog_para.http_interested_region_flag = protflag;
+ if((protflag&HTTP_STATE) || (protflag&HTTP_ALL))
+ {
+ g_http_prog_para.need_http_state = 1;
+ }
+ /*no bizplugin need*/
+ if(g_http_prog_para.http_interested_region_flag < HTTP_KEY)
+ {
+ g_http_prog_para.not_proc = 1;
+ }
+ /*switch set proc*/
+ if(g_http_prog_para.http_switch_no_biz)
+ {
+ g_http_prog_para.not_proc = 0;
+ }
+ /*protflag cnt*/
+ if(!(protflag & HTTP_OTHER_REGIONS))
+ {
+ unsigned long long protflag_temp = protflag;
+ int region_cnt = 0;
+ while(protflag_temp)
+ {
+ protflag_temp = protflag_temp & (protflag_temp-1);
+ region_cnt++;
+ }
+ g_http_prog_para.batch_field_maxnum = region_cnt;
+ }
+}
+
+void HTTP_GETPLUGID(unsigned short plugid)
+{
+ g_http_prog_para.http_plugid = plugid;
+}
+
+/*for HTTP_FLAG_CHANGE, only use when http.so init*/
+int http_region2id(const char *region, uint32 region_len)
+{
+ int i=0;
+ for(i=0;i<(int)g_http_prog_para.http_region_cnt;i++)
+ {
+ if(0==strcasecmp(g_http_prog_para.http_conf_regionname[i], region))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+long long HTTP_FLAG_CHANGE(char* flag_str)
+{
+ if(flag_str==NULL) return -1;
+
+ int64 protflag = 0;
+ int region_id = 0;
+ short region_cnt = 0;
+ char* start_token = flag_str;
+ char* end_token = flag_str;
+ char* end_pos = flag_str+strlen(flag_str);
+ char region_name[REGION_NAME_LEN] = {0};
+
+ /*all regions*/
+ if(0==(strncasecmp(flag_str, "all" , sizeof("all")))||(0==strncasecmp(flag_str, "http_all" , sizeof("http_all"))))
+ {
+ long long i=0;
+ for( i=0;i<(long long)g_http_prog_para.http_region_cnt;i++)
+ {
+ protflag |= ((long long)1)<<i;
+ }
+ return protflag;
+ }
+
+ while (end_token < end_pos)
+ {
+ end_token = (char*)memchr(start_token, ',', end_pos-start_token);
+ if(end_token!=NULL)
+ {
+ memcpy(region_name, start_token, end_token-start_token);
+ start_token = end_token+1;
+ end_token += 1;
+ }
+ else
+ {
+ memcpy(region_name, start_token, end_pos-start_token);
+ end_token = end_pos;
+ }
+ region_id = http_region2id(region_name, strlen(region_name));
+ if(-1==region_id)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "FLAG_CHANGE %s:%s error!", flag_str, region_name);
+ return -1;
+ }
+ region_cnt++;
+ protflag |= ((long long)1)<<region_id;
+ memset(region_name, 0, REGION_NAME_LEN);
+ }
+ return protflag;
+}
+
+/**********************************************************
+ * ���ܣ��ж���Ϣͷ�Ƿ������
+ * buffer:��洢��������
+ * data����ǰ���ݡ�
+ * data_len:��ǰ���ݵij��ȡ�
+ * proc_offset:��ǰ�����Ѵ������ݵ�ƫ������
+ return : GO_BACK OK ERROR
+***********************************************************/
+uchar http_judgeHeaderOver(http_parser_t *a_http, char *data, uint32 data_len, int thread_seq)
+{
+ /*at least two char*/
+ if(data_len+a_http->buflen<=a_http->processed_offset+1)
+ {
+ a_http->pbuf = (char*)dictator_realloc(thread_seq, a_http->pbuf, data_len-a_http->processed_offset);
+ memcpy(a_http->pbuf+a_http->buflen,data+a_http->processed_offset, data_len-a_http->processed_offset);
+ a_http->buflen += data_len-a_http->processed_offset;
+ a_http->processed_offset += data_len-a_http->processed_offset;
+ return GO_BACK;
+ }
+ if(a_http->pbuf!=NULL)
+ {
+ switch(a_http->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ if('\n'==*(a_http->pbuf))
+ {
+ return OK;
+ }
+ break;
+ case LINE_FLAG_CR:
+ if('\r'==*(a_http->pbuf))
+ {
+ return OK;
+ }
+ break;
+ case LINE_FLAG_CRLF:
+ /*only one situation*/
+ if('\r'==*(a_http->pbuf) && '\n'==*(data+a_http->processed_offset))
+ {
+ (a_http->processed_offset) ++;
+ return OK;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch(a_http->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ if('\n'==*(data+a_http->processed_offset))
+ {
+ (a_http->processed_offset)++;
+ return OK;
+ }
+ break;
+ case LINE_FLAG_CR:
+ if('\r'==*(data+a_http->processed_offset))
+ {
+ (a_http->processed_offset)++;
+ return OK;
+ }
+ break;
+ case LINE_FLAG_CRLF:
+ if('\r'==*(data+a_http->processed_offset) && '\n'==*(data+a_http->processed_offset+1))
+ {
+ (a_http->processed_offset) += 2;
+ return OK;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return ERROR;
+}
+
+void http_updateBefore(char* pos_n_1, const char**p, uint32* l_p, const char** q, uint32* l_q)
+{
+ if(pos_n_1>=*p&&pos_n_1<*p+*l_p)//pos_n_1 in before
+ {
+ *l_p = *l_p-(pos_n_1-*p);
+ *p = pos_n_1;
+ }
+ else// means pos_r>=q&&pos_r<q+l_q //pos_n_1 in this_data
+ {
+ *p = NULL;
+ *l_p = 0;
+ *l_q = *l_q-(pos_n_1-*q);
+ *q = pos_n_1;
+ }
+}
+
+/* \r or \r\n*/
+char* http_findLineEnd_CR(char* end_flag, char* fold_flag, const char*before, uint32 before_len,const char* this_data,uint32 this_len)
+{
+ char* pos_r=NULL;
+ char* pos_r_1=NULL;
+ char* pos_r_2=NULL;
+ const char* p=before;
+ const char* q=this_data;
+ uint32 l_p=before_len,l_q=this_len;
+ char search_rp_flag = 0;
+
+ /*\r\n \r as complete line*/
+ do
+ {
+ switch(*end_flag)
+ {
+ case LINE_FLAG_LF:
+ return NULL;
+ break;
+
+ case LINE_FLAG_CR:
+ if(l_p>0 && !search_rp_flag)
+ {
+ pos_r = double_memchr(p,l_p,q,l_q,'\r');
+ search_rp_flag = 1;
+ }
+ else
+ {
+ pos_r = double_memchr(NULL,0,q,l_q,'\r');
+ }
+ if(pos_r!=NULL)
+ {
+ pos_r_1=double_memread(p,l_p,q,l_q,pos_r,1);
+ if(pos_r_1==NULL)
+ {
+ return NULL;
+ }
+ if(*pos_r_1!='\t'&&*pos_r_1!=' ')
+ {
+ //\r complete line, return \r
+ return pos_r;
+ }
+ else //fold line
+ {
+ *fold_flag = 1;
+ http_updateBefore(pos_r_1, &p ,&l_p, &q, &l_q);
+ }
+ }
+ break;
+
+ /*same with default*/
+ case LINE_FLAG_CRLF:
+ /* \r\n : search p only first time,*/
+ if(l_p>0 && !search_rp_flag)
+ {
+ pos_r = double_memchr(p,l_p,q,l_q,'\r');
+ search_rp_flag = 1;
+ }
+ else
+ {
+ pos_r = double_memchr(NULL,0,q,l_q,'\r');
+ }
+ if(pos_r!=NULL)
+ {
+ pos_r_1=double_memread(p,l_p,q,l_q,pos_r,1);
+ pos_r_2=double_memread(p,l_p,q,l_q,pos_r,2);
+ if(pos_r_1==NULL)
+ {
+ return NULL;
+ }
+ if(*pos_r_1=='\n'&&pos_r_2==NULL) //\r\n over
+ {
+ return NULL;
+ }
+ if(*pos_r_1=='\n'&&pos_r_2!=NULL&&*pos_r_2!='\t'&&*pos_r_2!=' ')
+ {
+ //\r\n complete line, return \r
+ return pos_r;
+ }
+ else //fold line
+ {
+ *fold_flag = 1;
+ http_updateBefore(pos_r_1, &p ,&l_p, &q, &l_q);
+ }
+ }
+ break;
+ //do not know line end flag
+ default:
+ /*\r or \r\n : search p only first time,*/
+ if(l_p>0 && !search_rp_flag)
+ {
+ pos_r = double_memchr(p,l_p,q,l_q,'\r');
+ search_rp_flag = 1;
+ }
+ else
+ {
+ pos_r = double_memchr(NULL,0,q,l_q,'\r');
+ }
+ if(pos_r!=NULL)
+ {
+ pos_r_1=double_memread(p,l_p,q,l_q,pos_r,1);
+ pos_r_2=double_memread(p,l_p,q,l_q,pos_r,2);
+ if(pos_r_1==NULL)
+ {
+ return NULL;
+ }
+ if(*pos_r_1=='\n'&&pos_r_2==NULL) //\r\n over
+ {
+ return NULL;
+ }
+ if(*pos_r_1=='\n'&&pos_r_2!=NULL&&*pos_r_2!='\t'&&*pos_r_2!=' ')
+ {
+ //\r\n complete line, return \r
+ *end_flag = LINE_FLAG_CRLF;
+ return pos_r;
+ }
+ else if(*pos_r_1!='\n'&&*pos_r_1!='\t'&&*pos_r_1!=' ')
+ {
+ //\r complete line, return \r
+ *end_flag = LINE_FLAG_CR;
+ return pos_r;
+ }
+ else //fold line
+ {
+ *fold_flag = 1;
+ http_updateBefore(pos_r_1, &p ,&l_p, &q, &l_q);
+ }
+ }
+ break;
+ }
+ }while(pos_r!=NULL);
+ return NULL;
+}
+
+/*\n*/
+char* http_findLineEnd_LF(char* end_flag, char* fold_flag, const char*before, uint32 before_len,const char* this_data,uint32 this_len)
+{
+ char* pos_n=NULL;
+ char* pos_n_1=NULL;
+ const char *p=before;
+ const char *q=this_data;
+ uint32 l_p=before_len,l_q=this_len;
+ char search_np_flag = 0;
+
+ /*\r\n \r as complete line*/
+ do
+ {
+ switch(*end_flag)
+ {
+ case LINE_FLAG_CR:
+ case LINE_FLAG_CRLF:
+ return NULL;
+ break;
+
+ /*same with*/
+ case LINE_FLAG_LF:
+ //do not know line end flag
+ default:
+ /*\r or \r\n : search p only first time,*/
+ if(l_p>0 && !search_np_flag)
+ {
+ pos_n = double_memchr(p,l_p,q,l_q,'\n');
+ search_np_flag = 1;
+ }
+ else
+ {
+ pos_n = double_memchr(NULL,0,q,l_q,'\n');
+ }
+ if(pos_n!=NULL)
+ {
+ pos_n_1=double_memread(p,l_p,q,l_q,pos_n,1);
+ if(pos_n_1==NULL)
+ {
+ return NULL;
+ }
+ if(*pos_n_1!='\t'&&*pos_n_1!=' ')
+ {
+ //\n complete line, return \n
+ *end_flag = LINE_FLAG_LF;
+ return pos_n;
+ }
+ else //fold line
+ {
+ *fold_flag = 1;
+ http_updateBefore(pos_n_1, &p ,&l_p, &q, &l_q);
+ }
+ }
+ break;
+ }
+ }while(pos_n!=NULL);
+ return NULL;
+}
+
+
+/*\r\n or \r or \n*/
+char* http_findLineEnd(char* end_flag, char* fold, const char*before, uint32 before_len,const char* this_data,uint32 this_len)
+{
+ char* p_end = http_findLineEnd_CR(end_flag, fold, before, before_len, this_data, this_len);
+ if(NULL!=p_end)
+ {
+ return p_end;
+ }
+ return http_findLineEnd_LF(end_flag, fold, before, before_len, this_data, this_len);
+}
+
+void http_saveToBuf(const char* curdata,uint32 cur_datalen,const char* p_end, char fold_flag, char del_space, http_parser_t *cur_http_node, int thread_seq)
+{
+ /*not include end flag \r\n,\r,\n*/
+ uint32 append_line_len = 0;
+ uint32 i=0,j=0;
+ char* c = NULL;
+
+ if(NULL==p_end)
+ {
+ /*null, delete fold flag to save*/
+ append_line_len = cur_datalen;
+ }
+ else
+ {
+ /*p_end must in curdata*/
+ append_line_len = p_end - curdata;
+ }
+
+ /*need proc fold line*/
+ if(fold_flag)
+ {
+ char* newdata = (char*)dictator_malloc(thread_seq, append_line_len);;
+ for(i=0;i<append_line_len;i++)
+ {
+ c = (char*)(curdata+i);
+ if(*c!=HTTP_SP && *c!=HTTP_HT && *c!=HTTP_CR && *c!=HTTP_LF)
+ {
+ newdata[j] = *c;
+ j++;
+ }
+ /*may not delate sapce because in start_line*/
+ if(*c==HTTP_SP && !del_space)
+ {
+ newdata[j] = *c;
+ j++;
+ }
+ }
+ cur_http_node->pbuf = (char*)dictator_realloc(thread_seq, cur_http_node->pbuf, cur_http_node->buflen + j);
+ memcpy(cur_http_node->pbuf+cur_http_node->buflen, newdata, j);
+ cur_http_node->buflen += j;
+ dictator_free(thread_seq, newdata);
+ }
+ else
+ {
+ cur_http_node->pbuf = (char*)dictator_realloc(thread_seq, cur_http_node->pbuf, cur_http_node->buflen + append_line_len);
+ memcpy(cur_http_node->pbuf+cur_http_node->buflen, curdata, append_line_len);
+ cur_http_node->buflen += append_line_len;
+ }
+
+ if(NULL==p_end)
+ {
+ /*update process*/
+ cur_http_node->processed_offset += cur_datalen;
+ }
+ else
+ {
+ cur_http_node->poneline_data = cur_http_node->pbuf;
+ cur_http_node->poneline_datalen = cur_http_node->buflen;
+
+ /*update process*/
+ cur_http_node->processed_offset += p_end-curdata;
+ /*add endline flag*/
+ switch(cur_http_node->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ case LINE_FLAG_CR:
+ cur_http_node->processed_offset += 1;
+ break;
+ case LINE_FLAG_CRLF:
+ cur_http_node->processed_offset += 2;
+ break;
+ default:
+ break;
+ }
+ }
+}
+/**********************************************************
+ * buffer:���ݴ洢��������
+ * processed_offset����ǰ�����У��Ѵ������ݵ�ƫ����.
+ * cur_data����ǰ���ݡ�
+ * cur_data_len����ǰ���ݵij��ȡ�
+***********************************************************/
+uchar http_positioningACompleteLine(char del_space, http_parser_t *cur_http_node, struct streaminfo *a_tcp, int thread_seq)
+{
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ char* curdata = (char*)(tcp_detail->pdata)+cur_http_node->processed_offset;
+ uint32 curdata_len = tcp_detail->datalen-cur_http_node->processed_offset;
+ char* before = cur_http_node->pbuf;
+ uint32 before_len = cur_http_node->buflen;
+ char* p_end=NULL;
+ char fold_flag = 0;
+
+ p_end = http_findLineEnd(&cur_http_node->endline_flag, &fold_flag, before, before_len, curdata, curdata_len);
+ if(p_end==NULL)
+ {
+ if(COMPLETE_BUFLEN<cur_http_node->buflen)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_RESET;
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_positioningACompleteLine error, comleteline is too long, %u>%u",
+ cur_http_node->buflen, COMPLETE_BUFLEN);
+ return ERROR;
+ }
+ /*to keep buf no fold flag, to avoid search fold flag next time*/
+ if(fold_flag)
+ {
+ http_saveToBuf(curdata,curdata_len,NULL,fold_flag,1,cur_http_node,thread_seq);
+ }
+ else
+ {
+ cur_http_node->pbuf = (char*)dictator_realloc(thread_seq, cur_http_node->pbuf, before_len+curdata_len);
+ memcpy(cur_http_node->pbuf+before_len,curdata,curdata_len);
+ cur_http_node->buflen += curdata_len;
+ cur_http_node->processed_offset += curdata_len;
+ }
+ return GO_BACK;
+ }
+ else
+ {
+ if(NULL==cur_http_node->pbuf)
+ {
+ /*need copy and delete fold flag*/
+ if(fold_flag)
+ {
+ http_saveToBuf(curdata,curdata_len,p_end,fold_flag,del_space,cur_http_node,thread_seq);
+ }
+ else
+ {
+ switch(cur_http_node->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ case LINE_FLAG_CR:
+ cur_http_node->poneline_data = curdata;
+ cur_http_node->poneline_datalen = p_end-curdata;
+ cur_http_node->processed_offset += p_end-curdata+1;
+ break;
+
+ case LINE_FLAG_CRLF:
+ cur_http_node->poneline_data = curdata;
+ cur_http_node->poneline_datalen = p_end-curdata;
+ cur_http_node->processed_offset += p_end-curdata+2;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*free pbuf outside*/
+ if(p_end>=before&&p_end<=before+before_len-1)//\r or \n endline flag in before
+ {
+ cur_http_node->poneline_data = before;
+ cur_http_node->poneline_datalen = p_end-before;
+ /*in before, can not be fold flag*/
+ switch(cur_http_node->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ case LINE_FLAG_CR:
+ cur_http_node->processed_offset += 0;
+ break;
+ case LINE_FLAG_CRLF:
+ if(p_end==before+before_len-1)// \n in curdata
+ {
+ cur_http_node->processed_offset += 1;
+ }
+ else
+ {
+ cur_http_node->processed_offset += 0;
+ }
+ break;
+ }
+ }
+ else //\r or \n endline flag in curdata
+ {
+ if(p_end==curdata)//\r , \n, \r in \r\n in curdata
+ {
+ cur_http_node->poneline_data = before;
+ cur_http_node->poneline_datalen = before_len;
+ switch(cur_http_node->endline_flag)
+ {
+ case LINE_FLAG_LF:
+ case LINE_FLAG_CR:
+ cur_http_node->processed_offset += 1;
+ break;
+ case LINE_FLAG_CRLF:
+ cur_http_node->processed_offset += 2;
+ break;
+ default:
+ break;
+ }
+
+ }
+ else
+ {
+ http_saveToBuf(curdata,curdata_len,p_end,fold_flag,del_space,cur_http_node,thread_seq);
+ }
+ }
+ }
+ }
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ if(DIR_C2S==cur_http_node->parser.curdir)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_HEADER_C2S], FS_OP_TYPE_ADD,cur_http_node->poneline_datalen);
+ }
+ else
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_HEADER_S2C], FS_OP_TYPE_ADD,cur_http_node->poneline_datalen);
+ }
+ }
+ return OK;
+}
+
+void http_updatePktOffset(http_parser_t *a_http, http_stream* a_http_stream, struct streaminfo *a_tcp)
+{
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ if(tcp_detail->datalen>a_http->processed_offset)
+ {
+ /*because pbuf, a_http->processed_offset maybe 0 ,but need proc continue*/
+ a_http_stream->packet_offset = a_http->processed_offset;
+ a_http_stream->proc_pkt_continue = 1;
+ }
+ else
+ {
+ a_http_stream->packet_offset = 0;
+ }
+}