summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/HTTP_Analyze.c1226
-rw-r--r--src/HTTP_Analyze.h60
-rw-r--r--src/HTTP_Common.c269
-rw-r--r--src/HTTP_Common.h31
-rw-r--r--src/HTTP_Message.c1098
-rw-r--r--src/HTTP_Message.h246
-rw-r--r--src/HTTP_Message_Entry.c607
-rw-r--r--src/HTTP_Message_Entry.h17
-rw-r--r--src/HTTP_Message_Header.c872
-rw-r--r--src/HTTP_Message_Header.h44
-rw-r--r--src/HTTP_Message_Region.c767
-rw-r--r--src/HTTP_Message_Region.h23
-rw-r--r--src/Makefile64
-rw-r--r--src/base64.c186
-rw-r--r--src/base64.d1
-rw-r--r--src/base64.h38
-rw-r--r--src/field_stat.cpp105
-rw-r--r--src/field_stat.h19
-rw-r--r--src/http.h235
-rw-r--r--src/http_global.map16
20 files changed, 5924 insertions, 0 deletions
diff --git a/src/HTTP_Analyze.c b/src/HTTP_Analyze.c
new file mode 100644
index 0000000..e652485
--- /dev/null
+++ b/src/HTTP_Analyze.c
@@ -0,0 +1,1226 @@
+/**********************************************************
+ *
+ * by lishu
+ **********************************************************/
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <math.h>
+#include "HTTP_Message.h"
+#include "HTTP_Analyze.h"
+#include "HTTP_Common.h"
+#include "HTTP_Message_Region.h"
+#include "HTTP_Message_Header.h"
+#include "HTTP_Message_Entry.h"
+#include "MESA_handle_logger.h"
+#include "field_stat.h"
+
+http_prog_runtime_parameter_t g_http_prog_para;
+
+int G_HTTP_H_VERSION_3_20150320 = 0;
+int G_HTTP_VERSION_4_20181113 = 0;
+void history()
+{
+ //2014-12-09 V3.0 new documentAnalyze lib ; http.h add and delete ;
+ //2015-01-05 V3.0 conf to ./conf/http/
+ //2015-01-14 V3.0 support http_method to string funcition
+ //2015-01-16 V3.0 change function name
+ //2015-01-26 V3.0 add url_decode; other_region(http.conf); session; http_proxy; DROPPKT to platform
+ //2015-02-02 V3.0 http_stream pbuf to free; ungzip session_buf not ==NULL because ungzip free; ungzip free_result; host memcheck; chunklen memcheck;thread_safe=0
+ //2015-03-18 V3.0 when tcp_lostlen>0
+ //2015-03-20 V3.0 entity proc end, http_infor maybe release, so can not use mgs_status
+ //2015-03-23 V3.0 content-length==-1
+ //2015-03-26 V3.0 not return APP_STATE_GIVEME and curdir
+ //2015-03-30 V3.0 if lost
+ //2015-04-03 V3.0 bug in
+ //2015-04-20 V3.0 http_tripleMatching dig[3] -> dig[4]
+ //2015-06-01 V3.0 1. add pending and close. 2. when lost ,pend!=close
+ //2015-06-02 V3.0 1. add fault log when chunk_len < 0
+ //2015-06-03 V3.0 1. get http header to service plugin.
+ //2015-06-09 V3.0 1. memcheck http_doWithGzipData 2. check session->buf=NULL
+ //2015-07-23 V3.0 1. lost proc
+ //2015-08-18 V3.0 1. http_url_decode error
+ //2015-09-17 V3.0 1. build http first node
+ //2015-11-03 V3.0 1. http_region2proto_flag A->a
+ //2016-01-22 V3.0 1. C2S lost bug, cur_http_node->parser.http_state = HTTP_DATA_END; when http_clearHttpInfor
+ //2016-01-28 V3.0 1. support deflate. 2. add COMPLETE_BUFLEN to limit the size of complete line
+ //2016-03-02 V3.0 1. relative URL and absolute URL
+ //2. not joint URL when proxy
+ //3. proc proxy
+ //4. add proxt capture
+ //2016-04-05 V3.0 http_free_proxy_stream free bug : free_tcp_proxy_stream free proxy
+ //2016-04-29 V4.0
+ //1. http batch : no do
+ //2. free http_infor when single-way
+ //3. http_seq_session=-1 when lost
+ //2016-05-26 V4.0
+ //1. curdir=0
+ //2. proxy loop
+ //3. tcpdata is GET+URI , but bizplug get content
+ //4. proxy add switch
+ //2016-06-01 V4.0
+ //http_findFristAndLastSPPos depend on spcae is wrong; http_judgeHttpMethod(method, (char*)tcp_detail->pdata, curdir), tcp_detail->pdata is wrong
+ //2016-06-12 V4.0
+ //\n as one complete line
+ //2016-06-17 V4.0
+ //expend head, >=HTTP_REGION_NUM
+ //add static
+
+ //2016-07-01 V4.0
+ //expand use hash
+ //2016-07-15 V4.0
+ //http proxy when reset
+ //g_http_prog_para.batch_field_maxnum bug
+ //2016-08-19 V4.0
+ //add static: header span cache byte
+ //2016-08-19 V4.0
+ //standard region : support append
+ //2016-09-22 V4.0
+ //malloc->dictator_malloc
+ //2016-11-21 V4.0
+ //support 101 Switching Protocols
+ //modify proxy, process same with websocket
+ //2016-12-12 V4.0 //region is NULL, not callback
+ //2016-12-13 V4.0 //dictator_malloc, http_saveToBuf
+ //2016-12-19 V4.0 //C2S method==0
+ //2016-12-24 V4.0 //http_url_decode
+ //2017-02-07 V4.0 //serverIP + URI = URL when without host ; purl not cache uri before set url
+ //2017-03-30 V4.0 //HTTP_MAX_UINT64_LEN 32->64
+ //2017-04-25 V4.0 //response_line \r\n span, but http_resetResponseSpace
+ //2017-09-18 V4.0 //batch info when callback, not to do
+ //2017-11-03 V4.0 //proc absolute URI without host
+ //2018-09-07 V4.0 //http_line2region:region name is raw pkt
+ //2018-11-13 V4.0 //special http pkt, proc span
+}
+
+/*
+int get_bitnum(int64 prot_flag)
+{
+ int i=-1;
+ while(prot_flag)
+ {
+ prot_flag>>=2;
+ i++;
+ }
+ return i;
+}
+*/
+
+/* not use because need plugin_manager support
+uchar http_getSessionState(http_parser_t *cur_http_node)
+{
+ uchar state = 0;
+ if(HTTP_FLASE==cur_http_node->session_flag)
+ {
+ if(HTTP_INTEREST_KEY_MASK!=cur_http_node->interested_reg_mask)
+ {
+ state = SESSION_STATE_DATA;
+ }
+ if(HTTP_TRUE==cur_http_node->over_flag)
+ {
+ state |= SESSION_STATE_PENDING | SESSION_STATE_CLOSE;
+ }
+ else
+ {
+ state |= SESSION_STATE_PENDING;
+ }
+ }
+ else
+ {
+ if(HTTP_INTEREST_KEY_MASK!=cur_http_node->interested_reg_mask)
+ {
+ state = SESSION_STATE_DATA;
+ }
+ if(HTTP_TRUE==cur_http_node->over_flag)
+ {
+ state |= SESSION_STATE_CLOSE;
+ }
+ }
+ cur_http_node->session_flag = HTTP_TRUE;
+ return state;
+}
+*/
+
+uchar http_getSessionState(http_parser_t *cur_http_node)
+{
+ uchar state = 0;
+ if(!FLAG_TEST(cur_http_node->flag, HTTP_FLAG_SESSION))
+ {
+ if(FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER))
+ state = SESSION_STATE_CLOSE | SESSION_STATE_PENDING;
+ else
+ state = SESSION_STATE_PENDING;
+ }
+ else
+ {
+ if(FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER))
+ state = SESSION_STATE_CLOSE;
+ else
+ state = SESSION_STATE_DATA;
+ }
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_SESSION);
+ return state;
+}
+
+void http_callPluginField(http_parser_t* cur_http_node,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int state = 0;
+ stSessionInfo session_info;
+
+ state = http_getSessionState(cur_http_node);
+ session_info.plugid = g_http_prog_para.http_plugid;
+ session_info.prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ session_info.session_state = state;
+ session_info._pad_ = 0;
+ session_info.app_info = (void*)(&(cur_http_node->parser));
+ session_info.buf = (void*)(cur_http_node->session.buf);
+ session_info.buflen = cur_http_node->session.buflen;
+ cur_http_node->business.return_value = PROT_PROCESS(&session_info,
+ &(cur_http_node->business.param),
+ thread_seq,a_tcp, a_packet);
+ if(cur_http_node->business.return_value&PROT_STATE_DROPPKT)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_DROPPKT;
+ }
+ if(cur_http_node->business.return_value&PROT_STATE_DROPME)
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_NO_UNGZIP);
+ }
+ return ;
+}
+
+void http_callPluginBatch(http_parser_t* cur_http_node,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int state = 0;
+ stSessionInfo session_info;
+
+ if(!(PROT_STATE_DROPME&cur_http_node->business.return_value))
+ {
+ state = http_getSessionState(cur_http_node);
+ session_info.plugid = g_http_prog_para.http_plugid;
+ session_info._pad_ = 1;
+ session_info.prot_flag = cur_http_node->batch_prot_flag;
+ session_info.session_state = state;
+ session_info.app_info = (void*)(&(cur_http_node->parser));
+ session_info.buf = NULL;
+ session_info.buflen = 0;
+ cur_http_node->business.return_value = PROT_PROCESS(&session_info,
+ &(cur_http_node->business.param),
+ thread_seq,a_tcp, a_packet);
+ if(cur_http_node->business.return_value&PROT_STATE_DROPPKT)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_DROPPKT;
+ }
+ if(cur_http_node->business.return_value&PROT_STATE_DROPME)
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_NO_UNGZIP);
+ }
+ }
+ /*clear*/
+ /*clear batch*/
+ for(int i=0;i<cur_http_node->parser.batch_infor->field_cnt;i++)
+ {
+ cur_http_node->parser.batch_infor->field[i].prot_flag = 0;
+ cur_http_node->parser.batch_infor->field[i].buf = NULL;
+ cur_http_node->parser.batch_infor->field[i].buflen = 0;
+ //cur_http_node->parser.batch_infor->field[i].src_buf = NULL;
+ //cur_http_node->parser.batch_infor->field[i].src_buflen = 0;
+ }
+ cur_http_node->parser.batch_infor->field_cnt = 0;
+ /*clear fold buf*/
+ if(NULL!=cur_http_node->pbuf_fold)
+ {
+ for(int j=0;j<cur_http_node->pbuf_fold->cnt;j++)
+ {
+ if(NULL!=cur_http_node->pbuf_fold->fold[j].buf)
+ {
+ dictator_free(thread_seq, cur_http_node->pbuf_fold->fold[j].buf);
+ cur_http_node->pbuf_fold->fold[j].buf = NULL;
+ cur_http_node->pbuf_fold->fold[j].buflen = 0;
+ }
+ }
+ cur_http_node->pbuf_fold->cnt = 0 ;
+ }
+ cur_http_node->batch_prot_flag = 0;
+ FLAG_CLEAR(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK);
+ FLAG_CLEAR(cur_http_node->flag, HTTP_FLAG_SPAN);
+ return ;
+}
+
+
+/*�ֶλص���ͬʱ��������ֵ*/
+void http_callPluginPreFieldBatch(http_parser_t* cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(HTTP_INTEREST_KEY_MASK!=cur_http_node->interested_reg_mask &&
+ HTTP_CONTENT_MASK!=cur_http_node->interested_reg_mask &&
+ HTTP_UNGZIP_CONTENT_MASK!=cur_http_node->interested_reg_mask &&
+ HTTP_STATE_MASK!=cur_http_node->interested_reg_mask)
+ {
+ /*excess, callback*/
+ if(cur_http_node->parser.batch_infor->field_cnt>=g_http_prog_para.batch_field_maxnum)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "batch field more than %d, callback.",g_http_prog_para.batch_field_maxnum);
+ return;
+ }
+ int j = cur_http_node->parser.batch_infor->field_cnt;
+ /*url need not copy because p_url*/
+ /*other not fold line*/
+ if(HTTP_MESSAGE_URL_MASK==cur_http_node->interested_reg_mask||
+ NULL==cur_http_node->pbuf)
+ {
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = cur_http_node->session.buf;
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = cur_http_node->parser.append_infor.content;
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+ }
+ else
+ {
+ /*malloc when first time*/
+ if(NULL==cur_http_node->pbuf_fold)
+ {
+ cur_http_node->pbuf_fold = (fold_buf_t*)dictator_malloc(thread_seq, sizeof(fold_buf_t));
+ cur_http_node->pbuf_fold->cnt = 0;
+ cur_http_node->pbuf_fold->fold = (fold_infor_t*)dictator_malloc(thread_seq, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ memset(cur_http_node->pbuf_fold->fold, 0, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ }
+ int i = cur_http_node->pbuf_fold->cnt;
+ /*copy to fold_buf*/
+ cur_http_node->pbuf_fold->fold[i].buf = (char*)dictator_malloc(thread_seq, cur_http_node->buflen);
+ memcpy(cur_http_node->pbuf_fold->fold[i].buf, cur_http_node->pbuf, cur_http_node->buflen);
+ cur_http_node->pbuf_fold->fold[i].buflen = cur_http_node->buflen;
+
+ /*set batch field*/
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->session.buf - cur_http_node->pbuf));
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->parser.append_infor.content - cur_http_node->pbuf));
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+ cur_http_node->pbuf_fold->cnt++;
+ }
+ }
+}
+
+/*�������ص�*/
+void http_callPluginPreBatch(http_parser_t* cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(HTTP_INTEREST_KEY_MASK!=cur_http_node->interested_reg_mask)
+ {
+ /*excess, callback*/
+ if(cur_http_node->parser.batch_infor->field_cnt>=g_http_prog_para.batch_field_maxnum)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "batch field more than %d, callback.",g_http_prog_para.batch_field_maxnum);
+ http_callPluginBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ int j = cur_http_node->parser.batch_infor->field_cnt;
+ /*url need not because p_url*/
+ /*content need not copy*/
+ /*other not fold line*/
+ if(HTTP_MESSAGE_URL_MASK==cur_http_node->interested_reg_mask||
+ HTTP_CONTENT_MASK==cur_http_node->interested_reg_mask ||
+ HTTP_UNGZIP_CONTENT_MASK==cur_http_node->interested_reg_mask ||
+ HTTP_STATE_MASK==cur_http_node->interested_reg_mask||
+ NULL==cur_http_node->pbuf)
+ {
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = cur_http_node->session.buf;
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = cur_http_node->parser.append_infor.content;
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+ }
+ else
+ {
+ /*malloc when first time*/
+ if(NULL==cur_http_node->pbuf_fold)
+ {
+ cur_http_node->pbuf_fold = (fold_buf_t*)dictator_malloc(thread_seq, sizeof(fold_buf_t));
+ cur_http_node->pbuf_fold->cnt = 0;
+ cur_http_node->pbuf_fold->fold = (fold_infor_t*)dictator_malloc(thread_seq, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ memset(cur_http_node->pbuf_fold->fold, 0, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ }
+ int i = cur_http_node->pbuf_fold->cnt;
+ /*copy to fold_buf*/
+ cur_http_node->pbuf_fold->fold[i].buf = (char*)dictator_malloc(thread_seq, cur_http_node->buflen);
+ memcpy(cur_http_node->pbuf_fold->fold[i].buf, cur_http_node->pbuf, cur_http_node->buflen);
+ cur_http_node->pbuf_fold->fold[i].buflen = cur_http_node->buflen;
+
+ /*set batch field*/
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->session.buf - cur_http_node->pbuf));
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->parser.append_infor.content - cur_http_node->pbuf));
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+ cur_http_node->pbuf_fold->cnt++;
+ }
+ /*set callback by parser*/
+ /*http session over callback*/
+ /*pkt span callback*/
+ if(FLAG_TEST(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK)||
+ FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER) ||
+ FLAG_TEST(cur_http_node->flag, HTTP_FLAG_SPAN))
+ {
+ if(cur_http_node->parser.batch_infor->field_cnt>0)
+ {
+ http_callPluginBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ }
+ }
+}
+
+/*�ֶλص���ͬʱ��������ֵ*/
+void http_callPlugin(http_parser_t* cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int64 prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ uint64 region_flag = g_http_prog_para.http_interested_region_flag&prot_flag;
+
+ if((!region_flag && !FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER)) || PROT_STATE_DROPME & cur_http_node->business.return_value)
+ {
+ /*clear*/
+ /*20150603 maybe memleak,because http_doWithGzipData:106*/
+ if(cur_http_node->interested_reg_mask!=HTTP_UNGZIP_CONTENT_MASK)
+ {
+ cur_http_node->session.buf = NULL;
+ cur_http_node->session.buflen = 0;
+ }
+ cur_http_node->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+ return;
+ }
+
+#if HTTP_STATIC
+ long long before = 0;
+ long long after = 0;
+ long long dealtime = 0;
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ before = rdtsc();
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN], FS_OP_TYPE_ADD, 1);
+ }
+#endif
+
+ if(HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode)
+ {
+ http_callPluginPreBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ else if(HTTP_CALLBACK_MODE_FIELD==g_http_prog_para.callback_mode && !(PROT_STATE_DROPME&cur_http_node->business.return_value))
+ {
+ http_callPluginField(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ else if(HTTP_CALLBACK_MODE_FIELD_BATCH==g_http_prog_para.callback_mode && !(PROT_STATE_DROPME&cur_http_node->business.return_value))
+ {
+ http_callPluginPreFieldBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ http_callPluginField(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+
+ /*clear*/
+ /*20150603 maybe memleak,because http_doWithGzipData:106*/
+ if(cur_http_node->interested_reg_mask!=HTTP_UNGZIP_CONTENT_MASK)
+ {
+ cur_http_node->session.buf = NULL;
+ cur_http_node->session.buflen = 0;
+ }
+ cur_http_node->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+
+#if HTTP_STATIC
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ after = rdtsc();
+ dealtime = after-before;
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN_PROC_TIME], FS_OP_TYPE_ADD, dealtime);
+ }
+#endif
+}
+
+/*�ֶλص����������ص��ֿ�������*/
+void http_callPlugin_field_or_batch(http_parser_t* cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int64 prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ uint64 region_flag = g_http_prog_para.http_interested_region_flag&prot_flag;
+
+ if((!region_flag && !FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER)) || PROT_STATE_DROPME & cur_http_node->business.return_value)
+ {
+ /*clear*/
+ /*20150603 maybe memleak,because http_doWithGzipData:106*/
+ if(cur_http_node->interested_reg_mask!=HTTP_UNGZIP_CONTENT_MASK)
+ {
+ cur_http_node->session.buf = NULL;
+ cur_http_node->session.buflen = 0;
+ }
+ cur_http_node->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+ return;
+ }
+
+#if HTTP_STATIC
+ long long before = 0;
+ long long after = 0;
+ long long dealtime = 0;
+
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ before = rdtsc();
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN], FS_OP_TYPE_ADD, 1);
+ }
+#endif
+
+ if(HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode)
+ {
+ if(HTTP_INTEREST_KEY_MASK!=cur_http_node->interested_reg_mask)
+ {
+ cur_http_node->batch_prot_flag |= region_flag;
+ /*excess, callback*/
+ if(cur_http_node->parser.batch_infor->field_cnt>=g_http_prog_para.batch_field_maxnum)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "batch field more than %d, callback.",g_http_prog_para.batch_field_maxnum);
+ http_callPluginBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ int j = cur_http_node->parser.batch_infor->field_cnt;
+ /*url need not because p_url*/
+ /*content need not copy*/
+ /*other not fold line*/
+ if(HTTP_MESSAGE_URL_MASK==cur_http_node->interested_reg_mask||
+ HTTP_CONTENT_MASK==cur_http_node->interested_reg_mask ||
+ HTTP_UNGZIP_CONTENT_MASK==cur_http_node->interested_reg_mask ||
+ HTTP_STATE_MASK==cur_http_node->interested_reg_mask||
+ NULL==cur_http_node->pbuf)
+ {
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = cur_http_node->session.buf;
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = cur_http_node->parser.append_infor.content;
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+ }
+ else
+ {
+ /*malloc when first time*/
+ if(NULL==cur_http_node->pbuf_fold)
+ {
+ cur_http_node->pbuf_fold = (fold_buf_t*)dictator_malloc(thread_seq, sizeof(fold_buf_t));
+ cur_http_node->pbuf_fold->cnt = 0;
+ cur_http_node->pbuf_fold->fold = (fold_infor_t*)dictator_malloc(thread_seq, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ memset(cur_http_node->pbuf_fold->fold, 0, g_http_prog_para.batch_field_maxnum*sizeof(fold_infor_t));
+ }
+ int i = cur_http_node->pbuf_fold->cnt;
+ /*copy to fold_buf*/
+ cur_http_node->pbuf_fold->fold[i].buf = (char*)dictator_malloc(thread_seq, cur_http_node->buflen);
+ memcpy(cur_http_node->pbuf_fold->fold[i].buf, cur_http_node->pbuf, cur_http_node->buflen);
+ cur_http_node->pbuf_fold->fold[i].buflen = cur_http_node->buflen;
+
+ /*set batch field*/
+ cur_http_node->parser.batch_infor->field[j].prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ cur_http_node->parser.batch_infor->field[j].buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->session.buf - cur_http_node->pbuf));
+ cur_http_node->parser.batch_infor->field[j].buflen = cur_http_node->session.buflen;
+ //cur_http_node->parser.batch_infor->field[j].src_buf = (void*)((char*)cur_http_node->pbuf_fold->fold[i].buf + (cur_http_node->parser.append_infor.content - cur_http_node->pbuf));
+ //cur_http_node->parser.batch_infor->field[j].src_buflen = cur_http_node->parser.append_infor.contlen;
+ cur_http_node->parser.batch_infor->field_cnt++;
+
+ cur_http_node->pbuf_fold->cnt++;
+ }
+ /*set callback by parser*/
+ /*http session over callback*/
+ /*pkt span callback*/
+ if(FLAG_TEST(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK)||
+ FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER) ||
+ FLAG_TEST(cur_http_node->flag, HTTP_FLAG_SPAN))
+ {
+ if(cur_http_node->parser.batch_infor->field_cnt>0)
+ {
+ http_callPluginBatch(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ }
+ }
+ }
+ else if(HTTP_CALLBACK_MODE_FIELD==g_http_prog_para.callback_mode && !(PROT_STATE_DROPME&cur_http_node->business.return_value))
+ {
+ http_callPluginField(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+
+ /*clear*/
+ /*20150603 maybe memleak,because http_doWithGzipData:106*/
+ if(cur_http_node->interested_reg_mask!=HTTP_UNGZIP_CONTENT_MASK)
+ {
+ cur_http_node->session.buf = NULL;
+ cur_http_node->session.buflen = 0;
+ }
+ cur_http_node->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+
+#if HTTP_STATIC
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ after = rdtsc();
+ dealtime = after-before;
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CBPLUGIN_PROC_TIME], FS_OP_TYPE_ADD, dealtime);
+ }
+#endif
+}
+
+/*
+* release and delete the first node from http_link, use when release http_stream
+*/
+void http_releaseHttpLinkNode(http_stream *a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ http_parser_t *cur_node = NULL;
+ cur_node = a_http_stream->first_link_node;
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s-close", printaddr(&a_tcp->addr,thread_seq));
+ }
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_RELEASE], FS_OP_TYPE_ADD, 1);
+ }
+ if(NULL!=a_http_stream->first_link_node->next)
+ {
+ a_http_stream->first_link_node->next->prev = NULL;
+ }
+ a_http_stream->first_link_node = a_http_stream->first_link_node->next;
+
+ /*call http business plugin*/
+ FLAG_SET(cur_node->flag, HTTP_FLAG_OVER);
+ cur_node->parser.http_state = HTTP_DATA_END;
+ cur_node->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+ if(g_http_prog_para.need_http_state)
+ {
+ cur_node->interested_reg_mask = HTTP_STATE_MASK;
+ }
+ /*may not call biz plugin*/
+ cur_node->session.buf = NULL;
+ cur_node->session.buflen = 0;
+
+ /*if not http, not callback , because startline maybe span pkt*/
+ if(a_http_stream->is_http_falgs && cur_node->parser.curdir!=0)
+ //if(a_http_stream->is_http_falgs)
+ {
+ http_callPlugin(cur_node, a_tcp, thread_seq, a_packet);
+ }
+
+ http_freeBuf(thread_seq,&cur_node->url_buf, &cur_node->url_buflen);
+ cur_node->parser.p_url = NULL;
+ cur_node->parser.url_len = 0;
+
+ http_freeBuf(thread_seq,&cur_node->pbuf, &cur_node->buflen);
+
+ /*batch free*/
+ if(HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode)
+ {
+ /*clear fold buf*/
+ if(NULL!=cur_node->pbuf_fold)
+ {
+ for(int j=0;j<cur_node->pbuf_fold->cnt;j++)
+ {
+ if(NULL!=cur_node->pbuf_fold->fold[j].buf)
+ {
+ dictator_free(thread_seq, cur_node->pbuf_fold->fold[j].buf);
+ }
+ }
+ if(NULL!=cur_node->pbuf_fold->fold)
+ {
+ dictator_free(thread_seq, cur_node->pbuf_fold->fold);
+ }
+ dictator_free(thread_seq, cur_node->pbuf_fold);
+ }
+ /*clear batch infor*/
+ if(NULL!=cur_node->parser.batch_infor)
+ {
+ if(NULL!=cur_node->parser.batch_infor->field)
+ {
+ dictator_free(thread_seq, cur_node->parser.batch_infor->field);
+ }
+ dictator_free(thread_seq, cur_node->parser.batch_infor);
+ }
+ }
+
+ if(cur_node->ungzip_handle!=NULL)
+ {
+ docanalyze_endstream(cur_node->ungzip_handle);
+ }
+ if(cur_node->parser.cont_range!=NULL)
+ {
+ dictator_free(thread_seq,cur_node->parser.cont_range);
+ cur_node->parser.cont_range = NULL;
+ }
+ dictator_free(thread_seq, cur_node);
+ cur_node = NULL;
+ a_http_stream->uncomplete_count--;
+ return ;
+}
+
+void http_free_proxy_stream(int thread_seq, struct streaminfo *pProxy)
+{
+ struct proxydetail *pProxydetail = NULL;
+ if(pProxy != NULL)
+ {
+ pProxydetail = (struct proxydetail*)pProxy->pdetail;
+ if(pProxydetail->pUser)
+ {
+ dictator_free(thread_seq,pProxydetail->pUser);
+ pProxydetail->pUser = NULL;
+ }
+ if(pProxydetail->pPwd)
+ {
+ dictator_free(thread_seq,pProxydetail->pPwd);
+ pProxydetail->pPwd = NULL;
+ }
+ if(pProxydetail->pIpv6)
+ {
+ dictator_free(thread_seq,pProxydetail->pIpv6);
+ pProxydetail->pIpv6 = NULL;
+ }
+ if(pProxydetail->append)
+ {
+ dictator_free(thread_seq,pProxydetail->append);
+ pProxydetail->append = NULL;
+ }
+ if(pProxy->pdetail != NULL)
+ {
+ dictator_free(thread_seq,pProxy->pdetail);
+ pProxy->pdetail=NULL;
+ }
+ dictator_free(thread_seq,pProxy);
+ pProxy = NULL;
+ }
+}
+
+/*
+* reset http_stream when lost packet
+*/
+void http_resetHttpStream(http_stream **ppa_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ http_stream *a_http_stream = *ppa_http_stream;
+ if(NULL==(a_http_stream)) return ;
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_RESET], FS_OP_TYPE_ADD, 1);
+ }
+ a_http_stream->reset_count ++;
+ while(NULL!=(a_http_stream)->first_link_node)
+ {
+ http_releaseHttpLinkNode(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ a_http_stream->res_req = 0;
+ a_http_stream->dir = 0;
+ a_http_stream->uncomplete_count = 0;
+ a_http_stream->first_link_node = NULL;
+ a_http_stream->last_link_node = NULL;
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ /*have set proxy and deal_tcp_in_proxy_stream , not free, otherwise free*/
+ if(NULL!=(a_http_stream)->p_stream_proxy && 0==a_http_stream->is_proxy)
+ {
+ free_tcp_proxy_stream(a_tcp,a_http_stream->p_stream_proxy);
+ a_http_stream->p_stream_proxy = NULL;
+ a_http_stream->is_proxy = 0;
+ /*log*/
+ if(g_http_prog_para.http_log_level<=RLOG_LV_INFO)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "FREE_HTTP_PROXY:%s",
+ printaddr(&a_tcp->addr,thread_seq));
+ }
+ }
+ }
+#endif
+ return;
+}
+/*
+* release http_link all infor, and release http_stream
+*/
+void http_releaseHttpStream(http_stream **a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(g_http_prog_para.http_stat_cycle && (*a_http_stream)->is_http_falgs)
+ {
+ struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CLIENT_PKT], FS_OP_TYPE_ADD, tcp_detail->clientpktnum);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CLIENT_BYTE], FS_OP_TYPE_ADD, tcp_detail->clientbytes);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_SERVER_PKT], FS_OP_TYPE_ADD, tcp_detail->serverpktnum);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_SERVER_BYTE], FS_OP_TYPE_ADD, tcp_detail->serverbytes);
+
+ }
+ if(NULL==(*a_http_stream)) return ;
+
+ while(NULL!=(*a_http_stream)->first_link_node)
+ {
+ http_releaseHttpLinkNode(*a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ (*a_http_stream)->first_link_node = NULL;
+ (*a_http_stream)->last_link_node = NULL;
+
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(NULL!=(*a_http_stream)->p_stream_proxy)
+ {
+ free_tcp_proxy_stream(a_tcp,(*a_http_stream)->p_stream_proxy);
+ /*log*/
+ if(g_http_prog_para.http_log_level<=RLOG_LV_INFO)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "FREE_HTTP_PROXY:%s",
+ printaddr(&a_tcp->addr,thread_seq));
+ }
+ }
+ }
+#endif
+ if(NULL!=(*a_http_stream)->pbuf)
+ {
+ dictator_free(thread_seq, (*a_http_stream)->pbuf);
+ }
+ dictator_free(thread_seq, *a_http_stream);
+ *a_http_stream = NULL;
+}
+
+void http_initHttpStream(http_stream**pme, int thread_seq)
+{
+ http_stream *a_http_stream = *pme;
+ if(NULL!=a_http_stream) return;
+ a_http_stream = (http_stream *)dictator_malloc(thread_seq, sizeof(http_stream));
+ memset(a_http_stream,0,sizeof(http_stream));
+ *pme = a_http_stream;
+ return;
+}
+
+/*two session in one pakcet*/
+void http_prevAnylse(http_parser_t* cur_node, uint32* packet_offset)
+{
+ cur_node->processed_offset = *packet_offset;
+ *packet_offset = 0;
+}
+
+uchar http_procLost(http_stream* a_http_stream, struct streaminfo* a_tcp, int thread_seq, void* a_packet)
+{
+ http_parser_t* cur_http_node = NULL;
+ struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ uchar res_req_temp = a_http_stream->res_req;
+
+ //20160526 get cur_http_node according to
+ a_http_stream->res_req = a_tcp->curdir;
+
+ //20150326 according a_tcp->curdir
+ //20150318 20150723
+ cur_http_node = (a_http_stream->res_req==DIR_C2S) ? a_http_stream->last_link_node:a_http_stream->first_link_node;
+ if( NULL!=cur_http_node &&
+ (cur_http_node->parser.http_state==HTTP_DATA_BEGIN || cur_http_node->parser.http_state==HTTP_DATA )&&
+ cur_http_node->packet_entity_len>=tcp_detail->lostlen)
+ {
+ (cur_http_node)->packet_entity_len -= tcp_detail->lostlen;
+ //20150330
+ if((cur_http_node)->packet_entity_len==0)
+ {
+ cur_http_node->parser.http_state = HTTP_DATA_END;
+ if(a_tcp->curdir==DIR_S2C)
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_OVER);
+ if(g_http_prog_para.need_http_state|| FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER))
+ {
+ cur_http_node->interested_reg_mask = HTTP_STATE_MASK;
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ http_reseaseHttpInfor(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ else
+ {
+ http_resetResponseSpace(cur_http_node, thread_seq);
+ /*20160122*/
+ cur_http_node->parser.http_state = HTTP_DATA_END;
+ }
+ }
+ }
+ else
+ {
+ //a_http_stream->http_session_num = -1;
+ http_resetHttpStream(&a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ a_http_stream->res_req = res_req_temp;
+ return OK;
+}
+
+/*
+1. return value
+ OK, is http
+ NO,is not http
+ GO_BACK, data is not enough
+*/
+uchar http_judgeHttpProtocol(http_stream *a_http_stream, uchar curdir, struct tcpdetail *tcp_detail, int thread_seq)
+{
+ uint32* buflen = &(a_http_stream->buflen);
+ uint32* offset = &(a_http_stream->packet_offset);
+ uchar method = HTTP_METHOD_UNKNOWN;
+
+ //��һ������ȥ�����У��ո��Ʊ�������HTTP_START_FLAGS_LEN�ֽ�
+ if(0==*buflen)
+ {
+ if(tcp_detail->datalen < HTTP_START_FLAGS_LEN+*offset)
+ {
+ if(tcp_detail->datalen-*offset > 0)
+ {
+ a_http_stream->pbuf = (char*)dictator_malloc(thread_seq, tcp_detail->datalen-*offset);
+ memcpy((void*)(a_http_stream->pbuf), (void*)((uchar*)tcp_detail->pdata+*offset), tcp_detail->datalen-*offset);
+ *buflen = tcp_detail->datalen-*offset;
+ }
+ return GO_BACK;
+ }
+ return http_judgeHttpMethod(&method, (char*)tcp_detail->pdata+*offset, curdir);
+ }
+
+ //һֱ�ȹ�HTTP_START_FLAGS_LEN�ֽ�
+ if(0<*buflen)
+ {
+ if(tcp_detail->datalen+*buflen < HTTP_START_FLAGS_LEN+*offset && tcp_detail->datalen-*offset>0)
+ {
+ if(tcp_detail->datalen-*offset > 0)
+ {
+ a_http_stream->pbuf = (char*)dictator_realloc(thread_seq,a_http_stream->pbuf, (*buflen)+ tcp_detail->datalen-*offset);
+ memcpy((void*)(a_http_stream->pbuf+(*buflen)), (void*)((uchar*)tcp_detail->pdata+*offset),tcp_detail->datalen-*offset);
+ *buflen += tcp_detail->datalen-*offset;
+ }
+ return GO_BACK;
+ }
+ //��־һ������buffer���棬һ������data����
+ a_http_stream->pbuf = (char*)dictator_realloc(thread_seq, a_http_stream->pbuf, HTTP_START_FLAGS_LEN);
+ memcpy((void*)(a_http_stream->pbuf+(*buflen)), (void*)((uchar*)tcp_detail->pdata+*offset),HTTP_START_FLAGS_LEN-*buflen);
+ *buflen = HTTP_START_FLAGS_LEN;
+ return http_judgeHttpMethod(&method, (char*)a_http_stream->pbuf, curdir);
+ }
+
+ return ERROR;
+}
+
+uchar http_analyseHttpConnection(http_stream* a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ struct tcpdetail* tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ http_parser_t* cur_http_node = NULL;
+ uchar rec = OK;
+ uchar return_value = APP_STATE_GIVEME;
+
+ assert(tcp_detail);
+ assert(a_http_stream);
+
+ if(0==tcp_detail->datalen||a_http_stream->uncomplete_count>=MAX_UNCOMPLETE_COUNT)
+ {
+ return APP_STATE_DROPME;
+ }
+
+ /*http identify : v3 judge is http stream or not firstly*/
+ if(HTTP_FLASE==a_http_stream->maybe_http_stream)
+ {
+ http_deleteEmptyRow(&(a_http_stream->packet_offset), (char*)(tcp_detail->pdata), tcp_detail->datalen);
+ uchar rec = http_judgeHttpProtocol(a_http_stream, a_tcp->curdir, tcp_detail, thread_seq);
+ if(rec==ERROR)
+ {
+ return APP_STATE_DROPME;
+ }
+ /*buf is not enough*/
+ if(rec==GO_BACK)
+ {
+ a_http_stream->packet_offset = 0;
+ return APP_STATE_GIVEME;
+ }
+ a_http_stream->maybe_http_stream = HTTP_TRUE;
+ http_freeBuf(thread_seq,&a_http_stream->pbuf, &a_http_stream->buflen);
+ }
+
+ /*http_stat : packet_offset=0 for the same pkt is not stated twice*/
+ if(g_http_prog_para.http_stat_cycle&&a_http_stream->maybe_http_stream==HTTP_TRUE&&a_http_stream->packet_offset==0)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_PKTS], FS_OP_TYPE_ADD, 1);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_BITS], FS_OP_TYPE_ADD,tcp_detail->datalen);
+ }
+
+ /*http proxy*/
+/*
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(a_http_stream->http_proxy!=0)
+ {
+ if((a_http_stream->http_proxy&DIR_C2S && a_tcp->curdir==DIR_C2S) ||
+ (a_http_stream->http_proxy&DIR_S2C && a_tcp->curdir==DIR_S2C))
+ {
+ return deal_tcp_in_proxy_stream(a_tcp,a_packet,a_http_stream->p_stream_proxy);
+ }
+ }
+ }
+#endif
+*/
+
+ /*http lost : lostlen must be proc befor http_initHttpConnection���൱��֮ǰ������*/
+ if(tcp_detail->lostlen>0)
+ {
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_LOST], FS_OP_TYPE_ADD, 1);
+ }
+ if(RLOG_LV_INFO>=g_http_prog_para.http_log_level)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "http lostlen : %s:%u",
+ printaddr(&a_tcp->addr,thread_seq), tcp_detail->lostlen);
+ }
+ http_procLost(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+
+ /*init http session*/
+ http_initHttpConnection(a_http_stream, thread_seq, a_tcp, a_packet);
+ /*packet process*/
+ cur_http_node = (a_http_stream->res_req==DIR_C2S)?a_http_stream->last_link_node:a_http_stream->first_link_node;
+ /*because maybe more \r\n...*/
+ if(cur_http_node==NULL || tcp_detail->datalen-a_http_stream->packet_offset<=0) return APP_STATE_GIVEME;
+ http_prevAnylse(cur_http_node, &(a_http_stream->packet_offset));
+
+ /*avoid keep HTTP_RETURN_DROPPKT*/
+ cur_http_node->phttp_begin = (char*)tcp_detail->pdata+cur_http_node->processed_offset;
+
+ //ͷ������
+ rec = http_analyseHttpReqResHeader(cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ switch(cur_http_node->mgs_status)
+ {
+ case HTTP_RETURN_RESET:
+ if(a_http_stream->is_http_falgs==HTTP_FLASE)//ȷ������httpЭ��
+ {
+ return APP_STATE_DROPME;
+ }
+ else
+ {
+ http_resetHttpStream(&a_http_stream, a_tcp, thread_seq, a_packet);
+ return APP_STATE_GIVEME;
+ }
+ break;
+
+ case HTTP_RETURN_DROPPKT:
+ cur_http_node->mgs_status = HTTP_RETURN_GIVEME;
+ return_value |= APP_STATE_DROPPKT;
+ break;
+
+ default:
+ break;
+ }
+
+ /*main : go back*/
+ if(rec!=OK&&a_http_stream->is_http_falgs==HTTP_TRUE)
+ {
+ /*span pkt*/
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_SPAN);
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ if(!cur_http_node->header_span_flag)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_CNT], FS_OP_TYPE_ADD, 1);
+ cur_http_node->header_span_flag = 1;
+ }
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_PKT], FS_OP_TYPE_ADD, 1);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_HEADER_SPAN_BYTE], FS_OP_TYPE_ADD, (char*)(tcp_detail->pdata)+cur_http_node->processed_offset-cur_http_node->phttp_begin);
+ }
+ if(g_http_prog_para.need_http_state)
+ {
+ cur_http_node->interested_reg_mask = HTTP_STATE_MASK;
+ /*http state only keep 2 state*/
+ if(cur_http_node->parser.http_state>=HTTP_REGION && cur_http_node->parser.http_state<HTTP_DATA_BEGIN)
+ {
+ cur_http_node->session.buf = cur_http_node->phttp_begin;
+ cur_http_node->session.buflen = (char*)(tcp_detail->pdata)+cur_http_node->processed_offset-cur_http_node->phttp_begin;
+ }
+ }
+ /*batch mode, callback, span pkt ,callback. cur_http_node->parser.curdir!=0 when start line*/
+ /*������ֻ����*/
+ //if(HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode || g_http_prog_para.need_http_state )
+ if((HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode || g_http_prog_para.need_http_state)&& cur_http_node->parser.curdir!=0 )
+ {
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ return return_value|APP_STATE_GIVEME;
+ }
+
+ /*more content in one pcaket*/
+/*
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(a_http_stream->is_proxy!=0)
+ {
+ http_updatePktOffset(cur_http_node, a_http_stream, a_tcp);
+ if(a_http_stream->proc_pkt_continue)
+ {
+ a_http_stream->proc_pkt_continue = 0;
+ return return_value|http_analyseHttpConnection(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ return return_value;
+ }
+ }
+#endif
+*/
+
+ //��Ϣ�����
+ /*set mgs_status because cur_http_node maybe release*/
+ uchar mgs_status = HTTP_RETURN_GIVEME;
+ rec = http_findAndDoWithEntity(&mgs_status, cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ switch(mgs_status)
+ {
+ case HTTP_RETURN_RESET:
+ http_resetHttpStream(&a_http_stream, a_tcp, thread_seq, a_packet);
+ return return_value|APP_STATE_GIVEME;
+ break;
+
+ case HTTP_RETURN_DROPPKT:
+ return return_value|APP_STATE_DROPPKT;
+
+ default:
+ break;
+ }
+ if(rec!=OK) return return_value|APP_STATE_GIVEME;
+
+ /*session over, analyze again*/
+ if(a_http_stream->proc_pkt_continue)
+ {
+ /*clear*/
+ a_http_stream->proc_pkt_continue = 0;
+ return return_value|http_analyseHttpConnection(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ return return_value|APP_STATE_GIVEME;
+}
+
+#if DEBUG_TEST_DEAL_TIME
+#define LEVEL_INTERVAL 20
+#define LEVEL_INTERVAL_NUM 11
+void http_stat_report(unsigned long long dealtime)
+{
+ pthread_mutex_lock(&g_http_prog_para.stat_lock);
+ struct timeval tv;
+ unsigned long level = 0;
+ gettimeofday(&tv, 0);
+
+ unsigned long long now_time = tv.tv_sec* 1000*1000 + tv.tv_usec;
+ static unsigned long long last_time = tv.tv_sec* 1000*1000 + tv.tv_usec;
+ //unsigned long pps = 0;
+ /*interval stat*/
+ level = dealtime/LEVEL_INTERVAL;
+ if(level<LEVEL_INTERVAL_NUM-1)
+ {
+ g_http_prog_para.dealtime_level[level]++;
+ }
+ else
+ {
+ g_http_prog_para.dealtime_level[MAX_DEALTIME_LEVEL-1]++;
+ }
+
+
+ if(now_time-last_time<1000*1000)
+ {
+ pthread_mutex_unlock(&g_http_prog_para.stat_lock);
+ return;
+ }
+
+ /*output*/
+ g_http_prog_para.pkt_dealtime_arv = g_http_prog_para.pkt_dealtime_total/g_http_prog_para.pkt_num;
+ fprintf(stdout,"------------------------------------------------------------------------\n");
+ fprintf(stdout,"%15s%15s%15s%15s%15s\n", "pkt_deaitime", "MAX", "TOTAL","PKT_NUM", "ARV");
+ fprintf(stdout,"%15s%15lu%15lu%15lu%15lu\n", "acc", g_http_prog_para.pkt_dealtime_max, g_http_prog_para.pkt_dealtime_total, g_http_prog_para.pkt_num, g_http_prog_para.pkt_dealtime_arv);
+
+ for(unsigned long i=0;i<LEVEL_INTERVAL_NUM-1;i++)
+ {
+ fprintf(stdout,"[%lu-%lu]:%lu %f \n", i*LEVEL_INTERVAL, (i+1)*LEVEL_INTERVAL,
+ g_http_prog_para.dealtime_level[i],
+ (float)((float)g_http_prog_para.dealtime_level[i]/(float)g_http_prog_para.pkt_num));
+ }
+ fprintf(stdout,"[%lu-]:%lu %f\n", (unsigned long)(LEVEL_INTERVAL_NUM-1)*LEVEL_INTERVAL,
+ g_http_prog_para.dealtime_level[MAX_DEALTIME_LEVEL-1],
+ (float)((float)g_http_prog_para.dealtime_level[MAX_DEALTIME_LEVEL-1]/(float)g_http_prog_para.pkt_num));
+ fprintf(stdout,"\n\n\n");
+ last_time = now_time;
+ pthread_mutex_unlock(&g_http_prog_para.stat_lock);
+}
+#endif
+
+char HTTP_ENTRY(struct streaminfo *a_tcp, void**pme, int thread_seq, void *a_packet)
+{
+#if DEBUG_TEST_DEAL_TIME
+ struct timeval tv;
+ unsigned long long bgn_time = 0;
+ unsigned long long end_time = 0;
+ unsigned long long pkt_dealtime = 0;
+ gettimeofday(&tv, 0);
+ bgn_time = tv.tv_sec* 1000*1000 + tv.tv_usec;
+ g_http_prog_para.pkt_num++;
+#endif
+
+ /*no biz*/
+ if(g_http_prog_para.not_proc) return APP_STATE_DROPME;
+
+#if HTTP_STATIC
+ long long before = 0;
+ long long after = 0;
+ long long dealtime = 0;
+
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ before = rdtsc();
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_CALLBACK], FS_OP_TYPE_ADD, 1);
+ }
+#endif
+
+ uchar rec = APP_STATE_GIVEME;
+ http_stream *a_http_stream = (http_stream *)*pme;
+
+ switch(a_tcp->opstate)
+ {
+ case OP_STATE_PENDING:
+ http_initHttpStream(&a_http_stream, thread_seq);
+ *pme = a_http_stream;
+ case OP_STATE_DATA:
+ case OP_STATE_CLOSE:
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(a_http_stream->p_stream_proxy!=NULL)
+ {
+ a_http_stream->p_stream_proxy->opstate = OP_STATE_CLOSE;
+ }
+ }
+#endif
+ rec = http_analyseHttpConnection(a_http_stream, a_tcp, thread_seq, a_packet);
+ a_http_stream->packet_offset = 0;
+ break;
+ default:
+ break;
+ }
+
+ if(OP_STATE_CLOSE==a_tcp->opstate||APP_STATE_DROPME&rec)
+ {
+ http_releaseHttpStream(&a_http_stream, a_tcp, thread_seq, a_packet);
+ *pme = NULL;
+ }
+
+#if HTTP_STATIC
+ /*static pkt dealtime*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ after = rdtsc();
+ dealtime = after-before;
+ g_http_prog_para.tcppkt_dealtime_max = MAX(dealtime, g_http_prog_para.tcppkt_dealtime_max);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_PROC_TIME], FS_OP_TYPE_ADD, dealtime);
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_TCP_PKT_PROC_MAXTIME], FS_OP_TYPE_SET, g_http_prog_para.tcppkt_dealtime_max);
+ }
+#endif
+
+#if DEBUG_TEST_DEAL_TIME
+ gettimeofday(&tv, 0);
+ end_time = tv.tv_sec*1000*1000 + tv.tv_usec;
+ pkt_dealtime = end_time-bgn_time;
+ g_http_prog_para.pkt_dealtime_total += pkt_dealtime;
+ g_http_prog_para.pkt_dealtime_max = MAX(pkt_dealtime, g_http_prog_para.pkt_dealtime_max);
+ http_stat_report(pkt_dealtime);
+#endif
+ return rec;
+}
diff --git a/src/HTTP_Analyze.h b/src/HTTP_Analyze.h
new file mode 100644
index 0000000..2f78ab1
--- /dev/null
+++ b/src/HTTP_Analyze.h
@@ -0,0 +1,60 @@
+#ifndef HTTP_ANALYZE_H_
+#define HTTP_ANALYZE_H_
+
+#include "HTTP_Message.h"
+
+#define MAX_UNCOMPLETE_COUNT 256
+
+typedef struct http_stream
+{
+ uint32 create_infor_num; //data for tcp create stream, not for syn
+ int http_session_num;
+
+ http_parser_t* first_link_node; //��Ҫ���ڴ�����ʽ����/��Ӧ�Ե���Ӧ��Ϣ
+ http_parser_t* last_link_node; //��Ҫ���ڴ�����ʽ����/��Ӧ�Ե�������Ϣ
+
+ uint32 uncomplete_count; //��¼��ǰ��Ҫ����������/��Ӧ������
+ uint32 packet_offset; //�Ѵ��������ڵ�ǰ����ƫ����,��������һ������Ҫ����
+
+ char* pbuf;
+ uint32 buflen;
+ uint32 reset_count;
+#if HTTP_PROXY
+ struct streaminfo* p_stream_proxy;
+ uchar is_proxy; //callback set_proxy_fstream
+#endif
+ uchar maybe_http_stream;
+ uchar res_req; //���账��������������Ӧ
+ uchar dir; //��˫����
+ uchar is_http_falgs;
+ uchar proc_pkt_continue;
+}http_stream;
+
+/*string map func*/
+typedef uchar (*STRING_MAP_FUNC)(http_parser_t* a_http, http_stream* a_http_stream, char* value, uint32 valuelen, struct streaminfo *a_tcp,int thread_seq, void *a_packet);
+typedef struct string_map_s
+{
+ const char* string;
+ uint32 stringid;
+ STRING_MAP_FUNC handler;
+}string_map_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void http_initHttpStream(http_stream**pme, int thread_seq);
+void http_releaseHttpStream(http_stream **a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+void http_resetHttpStream(http_stream **ppa_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+void http_callPlugin(http_parser_t* cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+int http_getLinkState(http_parser_t *cur_http_node);
+void http_resetHttpLinkNode(http_parser_t *cur_node,struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+void http_releaseHttpLinkNode(http_stream *a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+uchar http_analyseHttpConnection(http_stream* a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+void http_updatePktOffset(http_parser_t *a_http, http_stream* a_http_stream, struct streaminfo *a_tcp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/HTTP_Common.c b/src/HTTP_Common.c
new file mode 100644
index 0000000..e409477
--- /dev/null
+++ b/src/HTTP_Common.c
@@ -0,0 +1,269 @@
+#include <stdio.h>
+//#define _GNU_SOURCE
+#include <string.h>
+#include <ctype.h>
+#include "HTTP_Common.h"
+#include "HTTP_Message.h"
+
+
+void http_freeBuf(int thread_seq, char **buf, uint32 *buflen)
+{
+ if(*buf!=NULL)
+ {
+ dictator_free(thread_seq,*buf);
+ *buf = NULL;
+ *buflen = 0;
+ }
+ return;
+}
+
+char* double_memchr(const char* before, uint32 before_len, const char* this_data, uint32 this_len, char c)
+{
+ /*before only find last two char*/
+ if(before_len>=1)
+ {
+ if(*(before+(before_len-1))==c) return (char*)(before+(before_len-1));
+ }
+ if(before_len>=2)
+ {
+ if(*(before+(before_len-2))==c) return (char*)(before+(before_len-2));
+ }
+ return (char*)memchr(this_data,c,this_len);
+}
+
+/*
+char* double_memchr(const char* before, uint32 before_len, const char* this_data, uint32 this_len, char c)
+{
+ char*pos=(char*)memchr(before,c,before_len);
+ if(pos!=NULL)
+ {
+ return pos;
+ }
+ pos=(char*)memchr(this_data,c,this_len);
+ return pos;
+}
+*/
+char* double_memread(const char*before,uint32 before_len,const char* this_data,uint32 this_len,const char*pos,uint32 offset)
+{
+ const char* v_target=pos+offset;
+ if((pos>=before&&pos<before+before_len)||(pos>=this_data&&pos<this_data+this_len))
+ {
+ if(before<=v_target&&v_target<before+before_len)
+ {
+ return (char*)v_target;
+ }
+ if(this_data<=v_target&&v_target<this_data+this_len)
+ {
+ return (char*)v_target;
+ }
+ if(this_data<=(this_data+offset-(before+before_len-pos))&&(this_data+offset-(before+before_len-pos))<this_data+this_len)
+ {
+ return (char*)(this_data+offset-(before+before_len-pos));
+ }
+ }
+ return NULL;
+}
+
+uint32 double_mem_offset(const char*before,uint32 before_len,const char* this_data,uint32 this_len,const char* p)
+{
+ if(p>=this_data&&p<this_data+this_len)
+ {
+ return before_len+(p-this_data);
+ }
+ if(p>=before&&p<before+before_len)
+ {
+ return p-before;
+ }
+ return -1;
+}
+
+char A_to_a(char ch)
+{
+ if(ch>='A'&&ch<='Z') return ch+'a'-'A';
+ return ch;
+}
+
+/**********************************************************
+ * ���ܣ�ȥ��dataǰ��Ŀ��У��ո��Ʊ�����
+ * offset:����ֵ����һ�����ǿ��У��ո��Ʊ��������ڵ�ǰ���ݵ�ƫ������
+ * data����ǰ���ݡ�
+ * data_len:��ǰ���ݵij��ȡ�
+***********************************************************/
+void http_deleteEmptyRow(uint32 *offset, char* data, uint32 data_len)
+{
+ if(NULL==data||data_len==0) return;
+ while(*offset<data_len && *offset>=0)
+ {
+ if(HTTP_CR!=*(data+(*offset)) && HTTP_NULL!=*(data+(*offset)) && HTTP_LF!=*(data+(*offset)) && HTTP_SP!=*(data+(*offset)) && HTTP_HT!=*(data+(*offset)))
+ break;
+ if(HTTP_CR==*(data+(*offset)) || HTTP_NULL==*(data+(*offset)) || HTTP_LF==*(data+(*offset)) || HTTP_SP==*(data+(*offset)) || HTTP_HT==*(data+(*offset)))
+ (*offset)++;
+ }
+}
+
+void http_deleteEmptyRow_chunk(uint32 *offset, char* data, uint32 data_len)
+{
+ if(NULL==data||data_len==0) return;
+ while(*offset<data_len && *offset>=0)
+ {
+ if(HTTP_CR!=*(data+(*offset)) && HTTP_LF!=*(data+(*offset))&& HTTP_SP!=*(data+(*offset)) && HTTP_HT!=*(data+(*offset)) && 0!=*(data+(*offset)))
+ break;
+ if(HTTP_CR==*(data+(*offset)) || HTTP_LF==*(data+(*offset))|| HTTP_SP==*(data+(*offset)) || HTTP_HT==*(data+(*offset)) || 0==*(data+(*offset)))
+ (*offset)++;
+ }
+ return;
+}
+
+/**********************************************************
+ * ���ܣ�ɾ��dataǰ����۵�����
+ * offset:����ֵ����һ�����ǿ��У��ո��Ʊ��������ڵ�ǰ���ݵ�ƫ������
+ * data����ǰ���ݡ�
+ * data_len����ǰ���ݵij��ȡ�
+***********************************************************/
+void http_deleteSPHT(uint32 *offset, char* data, uint32 data_len)
+{
+ while(*offset<data_len && *offset>=0)
+ {
+ if(HTTP_SP!=*(data+(*offset)) && HTTP_HT!=*(data+(*offset)))
+ break;
+ (*offset)++;
+ }
+}/*http_deleteSPHTCRLFAtLast*/
+
+/**********************************************************
+ * ���ܣ�ɾ��data����Ŀո񣬿��У��Ʊ�����
+ * del_data_len��ɾ�������ݵij��ȡ�
+ * data����ǰ���ݡ�
+ * data_len����ǰ���ݵij��ȡ�
+***********************************************************/
+void http_deleteSPHTCRLFAtLast(uint32 *del_data_len, char* data, uint32 data_len)
+{
+ if(data==NULL||data_len==0) return ;
+ *del_data_len = data_len - 1;
+ if(0==*del_data_len)
+ {
+ if(HTTP_CR==*(data+*del_data_len) || HTTP_HT==*(data+*del_data_len) ||
+ HTTP_SP==*(data+*del_data_len) || HTTP_LF==*(data+*del_data_len))
+ return ;
+ }
+ while(*del_data_len>=0)
+ {
+ if(HTTP_CR!=*(data+*del_data_len) && HTTP_HT!=*(data+*del_data_len) &&
+ HTTP_SP!=*(data+*del_data_len) && HTTP_LF!=*(data+*del_data_len))
+ break;
+ if(HTTP_CR==*(data+*del_data_len) || HTTP_HT==*(data+*del_data_len) ||
+ HTTP_SP==*(data+*del_data_len) || HTTP_LF==*(data+*del_data_len))
+ (*del_data_len)--;
+
+ if((*del_data_len)<=0)
+ break;
+ }
+ (*del_data_len)++;
+}
+
+/**********************************************************
+ * ���ܣ�Ѱ��all_data������CRLF��λ�á�
+ * res:���ֵ��ͨ���ò����ж��Ƿ����\r\n
+ * all_data:�������ݻ�������
+ **********************************************************/
+char* http_findCRLF(char *all_data, uint32 len)
+{
+ if(NULL==all_data||0==len) return NULL;
+ char *s_cr=NULL;
+ s_cr=(char*)memchr(all_data,'\r',len);
+ /*����\r*/
+ if(NULL!=s_cr)
+ {
+ return s_cr;
+ }
+ /*û����\r*/
+ return NULL;
+}
+
+char* http_findCRLF_Chunk(char *all_data, uint32 len, uint32* end_flag_size)
+{
+ if(all_data==NULL || len==0) return NULL;
+
+ char *s_cr=NULL;
+ char *s_lf=NULL;
+ char *p_ret=NULL;
+ uint32 rf = 2;
+ s_cr=(char*)memchr(all_data, '\r',len);
+ s_lf=(char*)memmem(all_data, len, (void*)"\0\n", rf);
+ if(NULL!=s_cr && NULL!=s_lf)
+ {
+ p_ret = MIN(s_cr, s_lf);
+ *end_flag_size = (p_ret == s_cr)? 1:2;
+ }
+ else if(NULL == s_cr && NULL == s_lf)
+ {
+ }
+ else
+ {
+ p_ret = (s_lf != NULL)?s_lf:s_cr;
+ *end_flag_size = (s_lf != NULL)? 2:1;
+ }
+ return p_ret;
+}
+
+void stringA_to_stringa(char* str, uint32 l_str)
+{
+ uint16 m =0;
+ for(m=0;m<l_str;m++)
+ {
+ str[m] = A_to_a(str[m]);
+ }
+}
+
+/* this function is copy from other system. */
+char *memcasemem(const char *strsrc,int len1,const char *substr,int len2)
+{
+
+ char *p1,*p2,*pend;
+ char *p;
+ char *substrS;
+ int i,lenth;
+
+ if((strsrc==NULL)||substr==NULL)
+ return NULL;
+ if(len1<len2) return NULL;
+
+ lenth=len2;
+ substrS=(char *)malloc(sizeof(char)*(lenth+1));
+ if(substrS==NULL)
+ return NULL;
+ for(i=0;i<lenth;i++)
+ {
+ substrS[i]=tolower(*(substr+i));
+ }
+ substrS[lenth]=0;
+
+ lenth=len1;
+ pend =(char *)strsrc + lenth;
+ for(p1 =(char *) strsrc; p1 != pend;p1++)
+ {
+ for(p2 = p1,p = substrS;*p != '\0'&& p2 != pend;p++,p2++)
+ {
+ if(tolower(*p2) != *p)
+ break;
+ }
+ if(*p == '\0')
+ {
+ free(substrS);
+ return p1;
+ }
+ }
+
+ free(substrS);
+ return NULL;
+}
+
+long long rdtsc(void)
+{
+long long l;
+long long h;
+
+__asm__ volatile("rdtsc" : "=a"(l), "=d"(h));
+return (long long )l | ((long long )h<<32);
+}
+
diff --git a/src/HTTP_Common.h b/src/HTTP_Common.h
new file mode 100644
index 0000000..51eff75
--- /dev/null
+++ b/src/HTTP_Common.h
@@ -0,0 +1,31 @@
+#ifndef HTTP_COMMON_H_
+#define HTTP_COMMON_H_
+
+#include "HTTP_Message.h"
+
+#define MIN(a, b) ((a) <= (b) ? (a):(b))
+#define MAX(a, b) ((a) >= (b) ? (a):(b))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void http_freeBuf(int thread_seq, char **buf, uint32 *buflen);
+char* double_memchr(const char* before, uint32 before_len, const char* this_data, uint32 this_len, char c);
+char* double_memread(const char*before,uint32 before_len,const char* this_data,uint32 this_len,const char*pos,uint32 offset);
+uint32 double_mem_offset(const char*before,uint32 before_len,const char* this_data,uint32 this_len,const char* p);
+char A_to_a(char ch);
+void http_deleteEmptyRow(uint32 *offset, char* data, uint32 data_len);
+void http_deleteEmptyRow_chunk(uint32 *offset, char* data, uint32 data_len);
+void http_deleteSPHT(uint32 *offset, char* data, uint32 data_len);
+void http_deleteSPHTCRLFAtLast(uint32 *del_data_len, char* data, uint32 data_len);
+char* http_findCRLF(char *all_data, uint32 len);
+char* http_findCRLF_Chunk(char *all_data, uint32 len, uint32* end_flag_size);
+void stringA_to_stringa(char* str, uint32 l_str);
+char *memcasemem(const char *strsrc,int len1,const char *substr,int len2);
+long long rdtsc(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* HTTP_COMMON_H_ */
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;
+ }
+}
diff --git a/src/HTTP_Message.h b/src/HTTP_Message.h
new file mode 100644
index 0000000..e2d9a06
--- /dev/null
+++ b/src/HTTP_Message.h
@@ -0,0 +1,246 @@
+#ifndef HTTP_MESSAGE_H_
+#define HTTP_MESSAGE_H_
+
+#include <stdio.h>
+#include "http.h"
+#include "stream.h"
+#include "DocumentAnalyze.h"
+
+#define HTTP_PLUGIN_NAME "http.so"
+
+/*-------------------function switch---------------------------*/
+#define DEBUG_TEST_DEAL_TIME 0
+#define HTTP_PROXY 1
+#define HTTP_PROXY_CAPFILE 0
+/*-------------------function switch end---------------------------*/
+
+#define HTTP_REGION_HASH 0
+#define HTTP_STATIC 0 //close some test static 1. hash VS str 2. pkt proc time when HTTP_ENTRY
+
+#define PROXY_CONNECTION_SUCC "Connection established"
+#define PROXY_CONNECTION_FAIL_401 "unauthorized"
+#define PROXY_CONNECTION_FAIL_407 "proxy authentication required"
+
+#define HTTP_KEY 2
+#define HTTP_TRUE 1
+#define HTTP_FLASE 0
+
+#define MAX_REGION_NUM 64
+#define REGION_NAME_LEN 64
+
+#define HTTP_RETURN_GIVEME 0x00
+#define HTTP_RETURN_RESET 0x01
+#define HTTP_RETURN_DROPPKT 0x02
+
+#define HTTP_CR 13
+#define HTTP_LF 10
+#define HTTP_SP 32
+#define HTTP_HT 9
+#define HTTP_NULL 0x00
+
+#define MAX_DEALTIME_LEVEL 20
+
+/*http state*/
+#define HTTP_STAT_PKTS 0
+#define HTTP_STAT_BITS 1
+#define HTTP_STAT_REQ 2
+#define HTTP_STAT_RES 3
+#define HTTP_STAT_CREATE 4
+#define HTTP_STAT_RELEASE 5
+#define HTTP_STAT_C2S 6
+#define HTTP_STAT_S2C 7
+#define HTTP_STAT_HEADER_C2S 8
+#define HTTP_STAT_HEADER_S2C 9
+#define HTTP_STAT_CONTENT_C2S 10
+#define HTTP_STAT_CONTENT_S2C 11
+#define HTTP_STAT_LOST 12
+#define HTTP_STAT_RESET 13
+#define HTTP_STAT_REGION_TIME_STR 14
+#define HTTP_STAT_REGION_TIME_HASH 15
+#define HTTP_STAT_TCP_PKT_CALLBACK 16
+#define HTTP_STAT_TCP_PKT_PROC_TIME 17
+#define HTTP_STAT_TCP_PKT_PROC_MAXTIME 18
+#define HTTP_STAT_CBPLUGIN 19
+#define HTTP_STAT_CBPLUGIN_PROC_TIME 20
+#define HTTP_STAT_CLIENT_PKT 21
+#define HTTP_STAT_CLIENT_BYTE 22
+#define HTTP_STAT_SERVER_PKT 23
+#define HTTP_STAT_SERVER_BYTE 24
+#define HTTP_STAT_HEADER_SPAN_CNT 25
+#define HTTP_STAT_HEADER_SPAN_PKT 26
+#define HTTP_STAT_HEADER_SPAN_BYTE 27
+#define HTTP_MAX_STAT_FIELD 28
+
+/*������룬û��chunk��û��cont-length*/
+#define HTTP_TRANS_ENCOD_CNNTCLOSE 0X04//connection close
+
+#define HTTP_CHUNK_STATE_UNKONWN 0X00
+#define HTTP_CHUNK_STATE_LENGTH 0X01
+#define HTTP_CHUNK_STATE_DATA 0X02
+
+#define COMPLETE_BUFLEN 100*1024*1024
+
+#define FLAG_SET(x, flag) ((x) |= (flag))
+#define FLAG_CLEAR(x, flag) ((x) &= ~(flag))
+#define FLAG_TEST(x, flag) (0 != ((x) & (flag)))
+
+/*http flag in http_parser_t*/
+#define HTTP_FLAG_OVER 0x0001
+#define HTTP_FLAG_SESSION 0x0002
+#define HTTP_FLAG_TRANS_LEN 0x0004
+#define HTTP_FLAG_GET_URL 0x0008
+#define HTTP_FLAG_CONNECT_CLOSE 0x0010
+#define HTTP_FLAG_NO_UNGZIP 0x0020
+#define HTTP_FLAG_SPAN 0x0040
+#define HTTP_FLAG_BATCH_CALLBACK 0x0080
+#define HTTP_FLAG_CONNECT_WEBSOCKET 0x0100
+
+/*callback mode*/
+#define HTTP_CALLBACK_MODE_FIELD 0x00
+#define HTTP_CALLBACK_MODE_BATCH 0x01
+#define HTTP_CALLBACK_MODE_FIELD_BATCH 0x02
+
+#define LINE_FLAG_CR 0x01
+#define LINE_FLAG_LF 0x02
+#define LINE_FLAG_CRLF 0x03
+
+
+typedef enum
+{
+ GO_BACK=1,
+ OK=2,
+ ERROR=3,
+}rec_val;
+
+typedef struct _business_infor_t
+{
+ void* param;
+ uchar return_value;
+}business_infor_t;
+
+typedef struct _session_infor_t
+{
+ char* buf;
+ uint32 buflen;
+}session_infor_t;
+
+typedef struct _fold_infor_t
+{
+ void* buf; //�۵��л�����
+ int buflen; //�۵��л�������С
+}fold_infor_t;
+
+typedef struct _fold_buf_t
+{
+ int cnt;
+ fold_infor_t* fold;
+}fold_buf_t;
+
+typedef struct _http_parser_t
+{
+ http_infor parser;
+ business_infor_t business;
+ session_infor_t session;
+
+ struct _http_parser_t* prev;
+ struct _http_parser_t* next;
+
+ interested_region_mask interested_reg_mask;
+ uint32 buflen;
+
+ char* pbuf;
+ fold_buf_t* pbuf_fold;
+ char* poneline_data;
+ char* phttp_begin;
+
+ uint32 poneline_datalen;
+ uint32 processed_offset; //�Ѵ��������ڵ�ǰ����ƫ����,��������һ������Ҫ����
+
+ uint64 packet_entity_len; //δ������ʵ�峤��
+ docanalyze_streamparam_t ungzip_handle;
+ uint64 acc_cont_length;
+ int64 batch_prot_flag;
+ char* url_buf;
+ uint32 url_buflen;
+ uint16 flag; //see define
+
+ uint8 chunk_state; //chunk state : 3 state
+ char endline_flag; //complete line flag: \r\n, \r, \n.
+ uint8 mgs_status; //return state
+ uint8 header_span_flag; //see define
+
+#if HTTP_PROXY
+ uchar proxy_flag; //DIR_C2S, DIR_S2C,DIR_DOUBLE
+ uchar proxy_cb_flag;
+#endif
+}http_parser_t;
+
+typedef struct _http_prog_runtime_parameter_t
+{
+ uint64 http_interested_region_flag;
+ char http_stat_filename[256];
+ char http_conf_regionname[MAX_REGION_NUM][REGION_NAME_LEN];
+
+ FILE* http_stat_file;
+ void* http_log_handle;
+ void* region_hash; //��չ���ʶ��
+ void* stat_handler;
+ void* docanly_handler;
+
+ uint16 http_plugid;
+ uint16 http_log_level;
+ uint16 ungzip_switch;
+ uint16 http_switch_no_biz;
+
+ int http_stat_screen_print_trigger;
+ int http_stat_cycle;
+
+ long long stat_value[HTTP_MAX_STAT_FIELD];
+ int stat_field[HTTP_MAX_STAT_FIELD];
+ uint32 http_header_string_map_num;
+ uint32 singleway_seq;
+#if HTTP_STATIC
+ long long tcppkt_dealtime_max;
+#endif
+ int http_region_cnt;
+ uint16 callback_mode;
+ uint16 batch_field_maxnum;
+ uint16 proxy_switch;
+ uchar need_http_state;
+ uchar not_proc;
+
+#if DEBUG_TEST_DEAL_TIME
+ unsigned long pkt_dealtime;
+ unsigned long pkt_dealtime_total;
+ unsigned long pkt_dealtime_max;
+ unsigned long pkt_dealtime_arv;
+ unsigned long pkt_num;
+ unsigned long dealtime_level[MAX_DEALTIME_LEVEL];
+ pthread_mutex_t stat_lock;
+#endif
+
+#if HTTP_PROXY_CAPFILE
+ int capfile_project_id;
+#endif
+
+}http_prog_runtime_parameter_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int HTTP_INIT(void);
+char HTTP_ENTRY(struct streaminfo *a_tcp, void**pme, int thread_seq, void *a_pcaket);
+void HTTP_DESTROY(void);
+
+long long HTTP_FLAG_CHANGE(char* flag_str);
+void HTTP_PROT_FUNSTAT(unsigned long long protflag);
+void HTTP_GETPLUGID(unsigned short plugid);
+uchar http_judgeHeaderOver(http_parser_t *a_http, char *data, uint32 data_len, int thread_seq);
+uchar http_positioningACompleteLine(char del_space, http_parser_t *cur_http_node, struct streaminfo *a_tcp, int thread_seq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/HTTP_Message_Entry.c b/src/HTTP_Message_Entry.c
new file mode 100644
index 0000000..1365648
--- /dev/null
+++ b/src/HTTP_Message_Entry.c
@@ -0,0 +1,607 @@
+#include <stdio.h>
+#include <ctype.h>
+#include "HTTP_Message_Entry.h"
+#include "HTTP_Message_Header.h"
+#include "MESA_handle_logger.h"
+#include "HTTP_Common.h"
+#include "field_stat.h"
+
+extern http_prog_runtime_parameter_t g_http_prog_para;
+
+/**********************************************************
+ *entity is over
+ **********************************************************/
+static void http_clearSpace(http_stream *a_http_stream, struct streaminfo *a_tcp,
+ int thread_seq, void *a_packet)
+{
+ if(DIR_C2S == a_http_stream->res_req)
+ {
+ /*one-way traffic*/
+ if(DIR_C2S==a_http_stream->dir)
+ {
+ //http_reseaseHttpInfor(a_http_stream,a_tcp, thread_seq, a_packet);
+ while(NULL!=(a_http_stream)->first_link_node)
+ {
+ http_releaseHttpLinkNode(a_http_stream, a_tcp, thread_seq, a_packet);
+ a_http_stream->last_link_node = NULL;
+ }
+ }
+ else
+ {
+ http_resetResponseSpace(a_http_stream->last_link_node, thread_seq);
+ a_http_stream->last_link_node->parser.http_state = HTTP_DATA_END;
+ }
+ }
+ else
+ {
+ http_reseaseHttpInfor(a_http_stream,a_tcp, thread_seq, a_packet);
+ }
+ return;
+}
+
+void http_doWithGzipData(http_parser_t *cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int ret = 0;
+ result_array_t *result_array = (result_array_t*)dictator_malloc(thread_seq, sizeof(result_array_t));
+ memset(result_array, 0, sizeof(result_array_t));
+ if(cur_http_node->ungzip_handle==NULL)
+ {
+ //20160128
+ switch(cur_http_node->parser.cont_encoding)
+ {
+ case HTTP_CONT_ENCOD_GZIP:
+ cur_http_node->ungzip_handle=docanalyze_startstream(DOC_GZIP_TYPE, g_http_prog_para.docanly_handler, thread_seq);
+ break;
+
+ case HTTP_CONT_ENCOD_DEFLATE:
+ cur_http_node->ungzip_handle=docanalyze_startstream(DOC_DEFLATE_TYPE, g_http_prog_para.docanly_handler, thread_seq);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(cur_http_node->ungzip_handle==NULL)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "docanalyze_startstream error!");
+ dictator_free(thread_seq, result_array);
+ return ;
+ }
+ ret = docanalyze_parsestream(cur_http_node->ungzip_handle,
+ (const char*)cur_http_node->session.buf,
+ cur_http_node->session.buflen,
+ result_array);
+ if(ret==DOC_PRO_OK)
+ {
+ cur_http_node->parser.append_infor.content = cur_http_node->session.buf;
+ cur_http_node->parser.append_infor.contlen = cur_http_node->session.buflen;
+ cur_http_node->session.buf =NULL;
+ cur_http_node->session.buflen = 0;
+ for (int k=0; k < result_array->result_num; k++)
+ {
+ cur_http_node->session.buf = (char*)dictator_realloc(thread_seq, cur_http_node->session.buf,cur_http_node->session.buflen+result_array->result_buff->size);
+ memcpy(cur_http_node->session.buf+cur_http_node->session.buflen,
+ result_array->result_buff->presult,
+ result_array->result_buff->size);
+ cur_http_node->session.buflen += result_array->result_buff->size;
+ }
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK);
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ if(cur_http_node->session.buf!=NULL)
+ {
+ dictator_free(thread_seq, cur_http_node->session.buf);
+ cur_http_node->session.buf = NULL;
+ cur_http_node->session.buflen = 0;
+ }
+ cur_http_node->parser.append_infor.content = NULL;
+ cur_http_node->parser.append_infor.contlen = 0;
+ }
+ else if(ret==DOC_PRO_ERR)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "docanalyze_parsestream return DOC_PRO_ERR!");
+ }
+ docanalyze_freeresult(result_array);
+ dictator_free(thread_seq, result_array);
+ return ;
+}
+
+void http_judgeContentEncoding(http_parser_t *a_http, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ char* entity_data = a_http->session.buf;
+ uint32 entity_datalen = a_http->session.buflen;
+ unsigned long long region_flag_ungzip = g_http_prog_para.http_interested_region_flag;
+ unsigned long long region_flag = g_http_prog_para.http_interested_region_flag;
+ region_flag_ungzip &= HTTP_UNGZIP_CONTENT;
+ region_flag &= HTTP_CONTENT;
+
+ /*static*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ if(DIR_C2S==a_http->parser.curdir)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CONTENT_C2S], FS_OP_TYPE_ADD,entity_datalen);
+ }
+ else
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CONTENT_S2C], FS_OP_TYPE_ADD,entity_datalen);
+ }
+ }
+
+ if(region_flag_ungzip && g_http_prog_para.ungzip_switch && !FLAG_TEST(a_http->flag, HTTP_FLAG_NO_UNGZIP))
+ {
+ a_http->interested_reg_mask = HTTP_UNGZIP_CONTENT_MASK;
+ //20160128
+ if(HTTP_CONT_ENCOD_GZIP==a_http->parser.cont_encoding||HTTP_CONT_ENCOD_DEFLATE==a_http->parser.cont_encoding)
+ {
+ http_doWithGzipData(a_http, a_tcp, thread_seq, a_packet);
+ }
+ else
+ {
+ FLAG_SET(a_http->flag, HTTP_FLAG_BATCH_CALLBACK);
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+ }
+ if(region_flag)
+ {
+ a_http->session.buf = entity_data;
+ a_http->session.buflen = entity_datalen;
+ a_http->interested_reg_mask = HTTP_CONTENT_MASK;
+ FLAG_SET(a_http->flag, HTTP_FLAG_BATCH_CALLBACK);
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+
+ a_http->interested_reg_mask = HTTP_CONTENT_MASK;
+ /*may not call biz plugin*/
+ a_http->session.buf = NULL;
+ a_http->session.buflen = 0;
+ return ;
+}
+
+uchar http_doWithDefaultData(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ uint32* offset = &(a_http->processed_offset);
+ char* cur_data = (char*)(tcp_detail->pdata);
+ uint32 len = tcp_detail->datalen - *offset;
+
+ if(tcp_detail->datalen >= a_http->packet_entity_len + a_http->processed_offset)
+ {
+ a_http->parser.http_state = HTTP_DATA_END;
+ a_http->session.buflen = a_http->packet_entity_len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ *offset += a_http->packet_entity_len;
+ a_http->packet_entity_len = 0;
+ a_http->acc_cont_length += a_http->packet_entity_len;
+ }
+ else
+ {
+ a_http->session.buflen = len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ *offset += len;
+ a_http->packet_entity_len -= len;
+ a_http->acc_cont_length += len;
+ rec = GO_BACK;
+ }
+
+ http_judgeContentEncoding(a_http, a_tcp, thread_seq, a_packet);
+
+ return rec;
+}
+
+uchar http_doWithCnntcloseData(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ uint32 *offset = &(a_http->processed_offset);
+ char *cur_data = (char*)(tcp_detail->pdata);
+ uint32 len = tcp_detail->datalen - *offset;
+
+ if(a_tcp->opstate==OP_STATE_CLOSE)
+ {
+ a_http->parser.http_state = HTTP_DATA_END;
+ a_http->session.buflen = len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ a_http->acc_cont_length += len;
+ *offset += len;
+ a_http->parser.cont_length = a_http->acc_cont_length;
+ }
+ else
+ {
+ a_http->session.buflen = len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ a_http->acc_cont_length += len;
+ *offset += len;
+ rec = GO_BACK;
+ }
+
+ http_judgeContentEncoding(a_http, a_tcp, thread_seq, a_packet);
+
+ return rec;
+}
+
+uchar http_doWithProxyData(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ uint32 *offset = &(a_http->processed_offset);
+ uint32 len = tcp_detail->datalen - *offset;
+
+ if(a_tcp->opstate==OP_STATE_CLOSE)
+ {
+ a_http->parser.http_state = HTTP_DATA_END;
+ *offset += len;
+ }
+ else
+ {
+ *offset += len;
+ rec = GO_BACK;
+ }
+ /*����һ��pkt��ʼ�ص��������������������HTTP�����������ѭ��*/
+ if(len==0)
+ {
+ a_http->proxy_cb_flag = 1;
+ }
+ if(len>0 && a_http->proxy_cb_flag)
+ {
+ deal_tcp_in_proxy_stream(a_tcp,a_packet,a_http_stream->p_stream_proxy);
+ }
+ return rec;
+}
+
+
+/**********************************************************
+ * ���ܣ�Ѱ��chunked�����ݿ�ʼλ��.
+ * a_http_node:��Ϣ�ڵ�,�������������Ҳ�Ƿ��ز�����
+ * cur_half����ǰ���ݡ�
+ * ע��after_cr_data_len<1����û�ҵ���ʼλ��
+ * (*a_http_node)->crlf_offset<1����û�õ����ȡ�
+ **********************************************************/
+uchar http_findChunkedDataStartPos(http_parser_t *a_http_node, uchar *tcp_data, UINT32 tcp_data_len)
+{
+ uint32 *offset = &((a_http_node)->processed_offset);
+ if(*offset == tcp_data_len)
+ {
+ return GO_BACK;
+ }
+ if(*offset+1==tcp_data_len)
+ {
+ if('\n'==*(tcp_data+*offset))
+ {
+ *offset += 1;
+ a_http_node->chunk_state=HTTP_CHUNK_STATE_DATA;
+ return GO_BACK;
+ }
+ a_http_node->chunk_state=HTTP_CHUNK_STATE_DATA;
+ return OK;
+ }
+ if(tcp_data_len>=2+*offset)
+ {
+ if('\n'==*(tcp_data+*offset)) (*offset)++;
+ a_http_node->chunk_state=HTTP_CHUNK_STATE_DATA;
+ return OK;
+ }
+ return OK;
+}
+
+uchar http_readChunkedData(http_parser_t *a_http, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ uint32* offset = &a_http->processed_offset;
+ char* cur_data = (char*)(tcp_detail->pdata);
+ uint32 len = 0;
+ uchar rec = OK;
+
+ len = tcp_detail->datalen - *offset;
+
+ if(a_http->packet_entity_len+*offset <= tcp_detail->datalen)
+ {
+ a_http->session.buflen = a_http->packet_entity_len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ *offset += a_http->packet_entity_len;
+ a_http->packet_entity_len = 0;
+ a_http->chunk_state = HTTP_CHUNK_STATE_UNKONWN;
+ a_http->acc_cont_length += a_http->packet_entity_len;
+
+ }
+ else
+ {
+ a_http->session.buflen = len;
+ if(a_http->session.buflen > 0)
+ {
+ a_http->session.buf = cur_data+*offset;
+ }
+ *offset += len;
+ a_http->packet_entity_len -= len;
+ a_http->acc_cont_length += len;
+ rec = GO_BACK;
+ }
+ http_judgeContentEncoding(a_http, a_tcp, thread_seq, a_packet);
+ return rec;
+}
+
+/**********************************************************
+ * ���ܣ���ȡchunked�ij���.
+ * a_http_node:��Ϣ�ڵ�,�������������Ҳ�Ƿ��ز�����
+ * chunked_len:���ֵ��chunked���ݳ���.
+ * cur_half����ǰ���ݡ�
+ * return : HTTP_RETURN_SPAN_PACKET HTTP_RETURN_UNNORM
+ **********************************************************/
+uchar http_readChunkedLength(struct streaminfo *a_tcp, http_parser_t *a_http, char *tcp_data, uint32 tcp_data_len,int thread_seq)
+{
+ uint32 end_flag = 0;
+ char* cr_pos = NULL;
+ uint32 data_len = 0;
+ uint32 i=0;
+ char chunklen_buf[32] = {0};
+ uint32* offset = &a_http->processed_offset;
+
+ /*��һ��buf������*/
+ if(0==a_http->buflen)
+ {
+ http_deleteEmptyRow_chunk(offset, tcp_data, tcp_data_len);
+ }
+ data_len = tcp_data_len-*offset;
+ cr_pos = http_findCRLF_Chunk(tcp_data+*offset, data_len, &end_flag);
+ if(NULL==cr_pos)
+ {
+ if(data_len>0)
+ {
+ a_http->pbuf = (char*)dictator_realloc(thread_seq,a_http->pbuf, a_http->buflen+data_len);
+ memcpy(a_http->pbuf+a_http->buflen, tcp_data+*offset, data_len);
+ a_http->buflen += data_len;
+ *offset += data_len;
+ }
+ return GO_BACK;
+ }
+ if(a_http->buflen>0)
+ {
+ if(a_http->buflen>=sizeof(chunklen_buf)) return ERROR;
+ memcpy(chunklen_buf, a_http->pbuf, a_http->buflen);
+ http_freeBuf(thread_seq, &a_http->pbuf, &a_http->buflen);
+ }
+ data_len = cr_pos-tcp_data-*offset;
+ if(data_len>=sizeof(chunklen_buf)-strlen(chunklen_buf)) return ERROR;
+ memcpy(chunklen_buf+strlen(chunklen_buf), tcp_data + *offset, data_len);
+ *offset += data_len+end_flag;
+
+ for(i=0;i<strlen(chunklen_buf);i++)
+ {
+ if(0==isxdigit(*(chunklen_buf+i))) return ERROR;
+ }
+
+ sscanf(chunklen_buf, "%Lx", &(a_http->packet_entity_len));
+ a_http->chunk_state = HTTP_CHUNK_STATE_LENGTH;
+ if((int)(a_http->packet_entity_len)<0)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "chunk_len errpr %lld:%s", (int)(a_http->packet_entity_len), printaddr(&a_tcp->addr,thread_seq));
+ return ERROR;
+ }
+ else if(0==a_http->packet_entity_len)
+ {
+ /*delete 0\r\n\r\n...*/
+ http_deleteEmptyRow_chunk(offset, tcp_data, tcp_data_len);
+ }
+ return OK;
+}
+
+uchar http_doWithChunkedData(http_parser_t *cur_http_node, http_stream *a_http_stream,
+ struct streaminfo *a_tcp,int thread_seq, void *a_packet)
+{
+ uchar rec=OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ /*malloc to cache chunk_length*/
+ while(1)
+ {
+ if(cur_http_node->chunk_state==HTTP_CHUNK_STATE_UNKONWN)
+ {
+ rec = http_readChunkedLength(a_tcp, cur_http_node, (char*)(tcp_detail->pdata), tcp_detail->datalen, thread_seq);
+ if(GO_BACK==rec) return GO_BACK;
+ if(ERROR==rec)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_RESET;
+ return ERROR;
+ }
+ /*chunk over*/
+ if(0==cur_http_node->packet_entity_len)
+ {
+ cur_http_node->parser.http_state = HTTP_DATA_END;
+ cur_http_node->parser.cont_length = cur_http_node->acc_cont_length;
+ return OK;
+ }
+ }
+ if(cur_http_node->chunk_state==HTTP_CHUNK_STATE_LENGTH)
+ {
+ if(OK!=http_findChunkedDataStartPos(cur_http_node, (uchar*)(tcp_detail->pdata),tcp_detail->datalen)) return GO_BACK;
+ }
+ if(cur_http_node->chunk_state==HTTP_CHUNK_STATE_DATA)
+ {
+ if(OK!=http_readChunkedData(cur_http_node, a_tcp, thread_seq, a_packet)) return GO_BACK;
+ }
+ }
+ return OK;
+}
+
+/*return GO_BACK OK ERROR*/
+uchar http_doWithEntity(http_parser_t *cur_http_node, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ uint32 len = ((struct tcpdetail*)a_tcp->pdetail)->datalen - cur_http_node->processed_offset;
+
+ if(len<=0) return GO_BACK;
+
+ if(HTTP_TRANS_ENCOD_CHUNKED==cur_http_node->parser.trans_encoding)
+ {
+ rec = http_doWithChunkedData(cur_http_node, a_http_stream, a_tcp,thread_seq, a_packet);
+ }
+ else if(HTTP_TRANS_ENCOD_CNNTCLOSE==cur_http_node->parser.trans_encoding)
+ {
+ rec = http_doWithCnntcloseData(cur_http_node, a_http_stream,a_tcp,thread_seq, a_packet);
+ }
+ /*Switching Protocols*/
+ else if(cur_http_node->parser.res_code==101)
+ {
+ rec = http_doWithCnntcloseData(cur_http_node, a_http_stream,a_tcp,thread_seq, a_packet);
+ }
+ else if(a_http_stream->is_proxy)
+ {
+ rec = http_doWithProxyData(cur_http_node, a_http_stream,a_tcp,thread_seq, a_packet);
+ }
+ else
+ {
+ rec = http_doWithDefaultData(cur_http_node, a_http_stream, a_tcp,thread_seq, a_packet);
+ }
+
+ if(HTTP_DATA_END==cur_http_node->parser.http_state)
+ {
+ if(DIR_C2S==a_http_stream->dir||DIR_S2C==cur_http_node->parser.curdir||DIR_S2C==a_tcp->curdir)
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_OVER);
+ }
+ /*output http state or http over*/
+ if(g_http_prog_para.need_http_state|| FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER))
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK);
+ if(g_http_prog_para.need_http_state)
+ {
+ cur_http_node->interested_reg_mask = HTTP_STATE_MASK;
+ }
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ }
+ return OK;
+}
+
+uchar http_judgeRequestEntityPresent(http_parser_t *cur_http_node, http_stream *a_http_stream,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ /*have not entity*/
+ if(0==cur_http_node->parser.cont_length && HTTP_TRANS_ENCOD_CHUNKED != cur_http_node->parser.trans_encoding && !a_http_stream->is_proxy)
+ {
+ //one-way traffic
+ if(DIR_C2S==a_http_stream->dir)
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_OVER);
+ }
+
+ cur_http_node->parser.http_state = HTTP_DATA_END;
+ /*output http state or http over*/
+ if(g_http_prog_para.need_http_state||FLAG_TEST(cur_http_node->flag, HTTP_FLAG_OVER))
+ {
+ FLAG_SET(cur_http_node->flag, HTTP_FLAG_BATCH_CALLBACK);
+ if(g_http_prog_para.need_http_state)
+ {
+ cur_http_node->interested_reg_mask = HTTP_STATE_MASK;
+ }
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ return ERROR;
+ }
+ return OK;
+}
+
+uchar http_judgeResponseEntityPresent(http_parser_t *a_http, http_stream* a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ /*temp ack: reset response */
+ if(a_http->parser.res_code==100)
+ {
+ http_resetResponseSpace(a_http, thread_seq);
+ return ERROR;
+ }
+
+ if(
+ (0==a_http->parser.cont_length && HTTP_TRANS_ENCOD_CHUNKED != a_http->parser.trans_encoding && HTTP_TRANS_ENCOD_CNNTCLOSE!= a_http->parser.trans_encoding && !a_http_stream->is_proxy && a_http->parser.res_code!=101) ||
+ HTTP_METHOD_HEAD==a_http->parser.method ||
+ (a_http->parser.res_code>101 && a_http->parser.res_code<200) ||
+ 204==(a_http->parser.res_code) ||
+ 304==a_http->parser.res_code
+ )
+ {
+ FLAG_SET(a_http->flag, HTTP_FLAG_OVER);
+ a_http->parser.http_state = HTTP_DATA_END;
+
+ /*output http state or http over*/
+ if(g_http_prog_para.need_http_state||FLAG_TEST(a_http->flag, HTTP_FLAG_OVER))
+ {
+ FLAG_SET(a_http->flag, HTTP_FLAG_BATCH_CALLBACK);
+ if(g_http_prog_para.need_http_state)
+ {
+ a_http->interested_reg_mask = HTTP_STATE_MASK;
+ }
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+ return ERROR;
+ }
+ return OK;
+}/*http_judgeResponseEntityPresent*/
+
+uchar http_judgeEntityPresent(http_parser_t *cur_http_node, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec=OK;
+ if(DIR_S2C==a_http_stream->res_req)
+ {
+ rec = http_judgeResponseEntityPresent(cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ else
+ {
+ rec = http_judgeRequestEntityPresent(cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ return rec;
+}
+
+uchar http_findAndDoWithEntity(uchar* msg_status, http_parser_t *a_http, http_stream* a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+
+ if(HTTP_DATA!=a_http->parser.http_state && HTTP_DATA_BEGIN!=a_http->parser.http_state) return OK;
+
+ if(a_http->parser.http_state==HTTP_DATA_BEGIN)
+ {
+ rec = http_judgeEntityPresent(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ if(ERROR==rec)/*have not entity*/
+ {
+ *msg_status = a_http->mgs_status;
+ a_http->mgs_status = HTTP_RETURN_GIVEME;
+ http_updatePktOffset(a_http, a_http_stream, a_tcp);
+ if(HTTP_DATA_END==a_http->parser.http_state)
+ {
+ http_clearSpace(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ return OK;
+ }
+ else /*have entity*/
+ {
+ a_http->parser.http_state = HTTP_DATA;
+ a_http->interested_reg_mask = HTTP_CONTENT_MASK;
+ }
+ }
+
+ if(a_http->parser.http_state==HTTP_DATA)
+ {
+ rec = http_doWithEntity(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ http_updatePktOffset(a_http, a_http_stream, a_tcp);
+ *msg_status = a_http->mgs_status;
+ a_http->mgs_status = HTTP_RETURN_GIVEME;
+ if(HTTP_DATA_END==a_http->parser.http_state)
+ {
+ http_clearSpace(a_http_stream, a_tcp, thread_seq, a_packet);
+ }
+ }
+ return rec;
+}
diff --git a/src/HTTP_Message_Entry.h b/src/HTTP_Message_Entry.h
new file mode 100644
index 0000000..86492d4
--- /dev/null
+++ b/src/HTTP_Message_Entry.h
@@ -0,0 +1,17 @@
+#ifndef HTTP_MESSAGE_ENTRY_H_
+#define HTTP_MESSAGE_ENTRY_H_
+
+#include "HTTP_Analyze.h"
+#include "HTTP_Message.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+uchar http_findAndDoWithEntity(uchar *mgs_status, http_parser_t* a_http, http_stream* a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/HTTP_Message_Header.c b/src/HTTP_Message_Header.c
new file mode 100644
index 0000000..fc72042
--- /dev/null
+++ b/src/HTTP_Message_Header.c
@@ -0,0 +1,872 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "HTTP_Message.h"
+#include "HTTP_Message_Header.h"
+#include "HTTP_Common.h"
+#include "HTTP_Message_Region.h"
+#include "HTTP_Message_Entry.h"
+#include "HTTP_Analyze.h"
+#include "MESA_handle_logger.h"
+#include "base64.h"
+#include "field_stat.h"
+
+
+extern http_prog_runtime_parameter_t g_http_prog_para;
+
+/**********************************************************
+ * ���ܣ���ʼ������������
+ * a_http:http��������
+***********************************************************/
+void http_inintRegionParam(http_parser_t *cur_node, int thread_seq)
+{
+ cur_node->poneline_data = NULL;
+ cur_node->poneline_datalen = 0;
+ http_freeBuf(thread_seq, &(cur_node->pbuf), &(cur_node->buflen));
+}
+
+void http_initHttpCommonInfor( http_parser_t *a_http, int thread_seq)
+{
+ if(NULL==a_http) return;
+
+ http_inintRegionParam(a_http, thread_seq);
+ FLAG_CLEAR(a_http->flag, HTTP_FLAG_CONNECT_CLOSE);
+ a_http->chunk_state = HTTP_CHUNK_STATE_UNKONWN;
+ FLAG_CLEAR(a_http->flag, HTTP_FLAG_TRANS_LEN);
+ a_http->mgs_status = HTTP_RETURN_GIVEME;
+ a_http->interested_reg_mask = HTTP_INTEREST_KEY_MASK;
+ //a_http->processed_offset = 0;
+ a_http->packet_entity_len = 0;
+ a_http->acc_cont_length = 0;
+
+ if(a_http->ungzip_handle!=NULL)
+ {
+ docanalyze_endstream(a_http->ungzip_handle);
+ a_http->ungzip_handle = NULL;
+ }
+
+ /*http_parser*/
+ a_http->parser.http_state = HTTP_STATE_UNKNOWN;
+ a_http->parser.cont_encoding = HTTP_CONT_ENCOD_UNKNOWN;
+ a_http->parser.trans_encoding = HTTP_TRANS_ENCOD_UNKNOWN;
+ a_http->parser.cont_length = 0;
+ if(a_http->parser.cont_range!=NULL)
+ {
+ dictator_free(thread_seq, a_http->parser.cont_range);
+ a_http->parser.cont_range = NULL;
+ }
+ return;
+}
+
+ /**********************************************************
+ * ���ܣ���Ӧ��Ϣ����ʱ�������Ӧ��������Ϣ��Ϣ��
+ * a_http:��ǰ�ڵ㡣
+ **********************************************************/
+ void http_resetResponseSpace(http_parser_t *a_http, int thread_seq)
+ {
+ if(NULL==a_http) return;
+ http_initHttpCommonInfor(a_http, thread_seq);
+ return;
+ }/*http_clearHttpInfor*/
+
+ void http_setSessionSeq(http_parser_t *cur_http_node, http_stream* a_http_stream)
+ {
+ /*20160527 cal http session seq only when http session ok*/
+ if(cur_http_node->parser.http_session_seq==0)
+ {
+ if(-1!=a_http_stream->http_session_num)
+ {
+ a_http_stream->http_session_num++;
+ }
+ cur_http_node->parser.http_session_seq = a_http_stream->http_session_num;
+ }
+ }
+ /**********************************************************
+ * ���ܣ���ʼ����һ��http �ڵ㡣
+ **********************************************************/
+ http_parser_t *http_initHttpLinkInfor(http_stream *a_http_stream, int thread_seq, struct streaminfo *a_tcp, void *a_packet)
+ {
+ /* create tcpdatalen>0 after tcpdata delete special */
+ uint32 offset = 0;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ http_deleteEmptyRow(&offset,(char*)tcp_detail->pdata+a_http_stream->packet_offset, tcp_detail->datalen-a_http_stream->packet_offset);
+ if(tcp_detail->datalen - a_http_stream->packet_offset - offset <=0)
+ {
+ a_http_stream->packet_offset += offset ;
+ return NULL;
+ }
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s-pending", printaddr(&a_tcp->addr,thread_seq));
+ }
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_CREATE], FS_OP_TYPE_ADD, 1);
+ }
+ http_parser_t *a_http = (http_parser_t*)dictator_malloc(thread_seq, sizeof(http_parser_t));
+ memset(a_http, 0, sizeof(http_parser_t));
+ a_http->business.return_value = PROT_STATE_GIVEME;
+ a_http_stream->uncomplete_count++;
+ a_http_stream->create_infor_num++;
+ http_initHttpCommonInfor(a_http, thread_seq);
+ FLAG_CLEAR(a_http->flag, HTTP_FLAG_NO_UNGZIP);
+ http_setSessionSeq(a_http,a_http_stream);
+ /*http batch*/
+ if(HTTP_CALLBACK_MODE_BATCH == g_http_prog_para.callback_mode)
+ {
+ a_http->parser.batch_infor = (batch_infor_t*)dictator_malloc(thread_seq, sizeof(batch_infor_t));
+ a_http->parser.batch_infor->field_cnt = 0;
+ a_http->parser.batch_infor->field = (field_infor_t*)dictator_malloc(thread_seq, g_http_prog_para.batch_field_maxnum*sizeof(field_infor_t));
+ memset(a_http->parser.batch_infor->field, 0, g_http_prog_para.batch_field_maxnum*sizeof(field_infor_t));
+ }
+ return a_http;
+ }
+
+ /**********************************************************
+ * ���ܣ�����HTTP����������
+ * a_http����ǰ��������
+ * curdir:tcp���ݰ��ķ��򣬱�����˫�����
+ * dir����ǰ���ķ���
+ *********************************************************/
+ void http_buildHttpInforLink(http_stream *a_http_stream, int thread_seq, struct streaminfo *a_tcp, void *a_packet)
+ {
+ http_parser_t *new_node=NULL;
+ http_parser_t *prev_http_node = (a_http_stream->res_req==DIR_C2S)? a_http_stream->last_link_node:a_http_stream->first_link_node;
+
+ /*http proxy and switch protocol, not change http_infor*/
+ if(HTTP_DATA_END==prev_http_node->parser.http_state || a_http_stream->res_req != a_tcp->curdir)
+ {
+ /*20150601 20150917*/
+ if(a_tcp->curdir==DIR_C2S)
+ {
+ if(a_http_stream->is_proxy || prev_http_node->parser.res_code==101)
+ {
+ a_http_stream->res_req = a_tcp->curdir;
+ return ;
+ }
+ new_node=http_initHttpLinkInfor(a_http_stream,thread_seq, a_tcp, a_packet);
+ if(NULL!=new_node)
+ {
+ new_node->next = NULL;
+ new_node->prev = a_http_stream->last_link_node;
+ a_http_stream->last_link_node->next = new_node;
+ a_http_stream->last_link_node = new_node;
+ }
+ }
+ else
+ {
+ if(DIR_DOUBLE!=a_tcp->dir)
+ {
+ if(a_http_stream->is_proxy || prev_http_node->parser.res_code==101)
+ {
+ a_http_stream->res_req = a_tcp->curdir;
+ return ;
+ }
+ new_node=http_initHttpLinkInfor(a_http_stream,thread_seq, a_tcp, a_packet);
+ if(NULL!=new_node)
+ {
+ a_http_stream->first_link_node->prev = new_node;
+ new_node->next = a_http_stream->first_link_node;
+ new_node->prev = NULL;
+ a_http_stream->first_link_node = new_node;
+ }
+ }
+ else
+ {
+ /*20160528 response come, clear*/
+ //if(a_http_stream->first_link_node->packet_entity_len==0)
+ {
+ if((a_http_stream->is_proxy && prev_http_node->parser.res_code!=0)|| prev_http_node->parser.res_code==101)
+ {
+ a_http_stream->res_req = a_tcp->curdir;
+ return ;
+ }
+ /*20170425 response_line span*/
+ if(HTTP_START_LINE!=a_http_stream->first_link_node->parser.http_state)
+ {
+ http_resetResponseSpace((a_http_stream->first_link_node), thread_seq);
+ }
+ }
+ }
+ }
+ }
+
+ /*20160601 S2C come but C2S not over, clear c2s*/
+ if(NULL!=prev_http_node)
+ {
+ if(HTTP_DATA_END!=prev_http_node->parser.http_state && DIR_C2S==prev_http_node->parser.curdir && DIR_S2C == a_tcp->curdir)
+ {
+ if(HTTP_START_LINE!=a_http_stream->first_link_node->parser.http_state)
+ {
+ http_resetResponseSpace((a_http_stream->first_link_node), thread_seq);
+ }
+ }
+ }
+ a_http_stream->res_req = a_tcp->curdir;
+ }
+
+/**********************************************************
+ * ���ܣ���ʼ��HTTP���ӡ�
+ * curdir:tcp���ݰ��ķ��򣬱�����˫�����
+ * dir����ǰ���ķ���
+ * pme������������
+***********************************************************/
+void http_initHttpConnection(http_stream *a_http_stream, int thread_seq, struct streaminfo *a_tcp, void *a_packet)
+{
+ //��������ʱ�򣬵�һ������
+ if(0==a_http_stream->uncomplete_count)
+ {
+ a_http_stream->res_req = a_tcp->curdir;
+ a_http_stream->last_link_node = http_initHttpLinkInfor(a_http_stream, thread_seq, a_tcp, a_packet);
+ a_http_stream->first_link_node = a_http_stream->last_link_node;
+ }
+ else
+ {
+ http_buildHttpInforLink(a_http_stream, thread_seq, a_tcp, a_packet);
+ }
+ /*set one-way or two-way*/
+ if(a_http_stream->dir==0)
+ {
+ if(DIR_DOUBLE==a_tcp->dir)
+ {
+ a_http_stream->dir = a_tcp->dir;
+ }
+ else
+ {
+ if(a_tcp->curdir==DIR_C2S)
+ {
+ if(DIR_DOUBLE!=a_tcp->dir && g_http_prog_para.singleway_seq >0 && a_http_stream->create_infor_num > g_http_prog_para.singleway_seq)
+ {
+ a_http_stream->dir = DIR_C2S;
+ }
+ }
+ else
+ {
+ if(DIR_DOUBLE!=a_tcp->dir && g_http_prog_para.singleway_seq >0 && a_http_stream->create_infor_num > g_http_prog_para.singleway_seq)
+ {
+ a_http_stream->dir = DIR_S2C;
+ }
+ }
+ }
+ }
+
+ /*http have set one-way traffic, but sapp become two-way traffic*/
+ if(a_tcp->dir==DIR_DOUBLE && (a_http_stream->dir==DIR_S2C||a_http_stream->dir==DIR_C2S))
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http set single, but sapp become double, addr:%s.",
+ printaddr(&a_tcp->addr,thread_seq));
+ }
+}
+
+/**********************************************************
+
+ **********************************************************/
+static void http_reseaseHttpInforList(http_parser_t**a_http, UINT16 uncomplete_count,
+ uchar curdir, int thread_seq)
+{
+ http_parser_t *cur = NULL;
+ if(NULL==*a_http) return;
+ if(uncomplete_count==1 || (NULL==(*a_http)->prev && NULL==(*a_http)->next))
+ {
+ (*a_http)->next = NULL;
+ (*a_http)->prev = NULL;
+ dictator_free(thread_seq,*a_http);
+ (*a_http)=NULL;
+ return;
+ }
+ cur = *a_http;
+ if(DIR_C2S==curdir)
+ {
+ if(NULL!=(*a_http)->prev)
+ {
+ (*a_http)->prev->next = (*a_http)->next;
+ }
+ *a_http = (*a_http)->prev;
+ }
+ else
+ {
+ if(NULL!=(*a_http)->next)
+ {
+ (*a_http)->next->prev = (*a_http)->prev;
+ }
+ *a_http = (*a_http)->next;
+ }
+ dictator_free(thread_seq,cur);
+ cur = NULL;
+ return;
+}/*http_ReseaseHttpInforList*/
+
+/**********************************************************
+ * ���ܣ��ͷŽڵ㡣
+ * a_http:��ǰ�ڵ㡣
+ * curdir����ǰ���ݵķ���
+ * delete cur_node when http_infor be proccessd over
+ * the different with http_releaseHttpLinkNode:http_reseaseHttpInfor is delete cur_node,and proc prev and next
+ **********************************************************/
+ void http_reseaseHttpInfor(http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ http_parser_t *cur_http_node = (DIR_C2S==a_http_stream->res_req)? a_http_stream->last_link_node: a_http_stream->first_link_node;
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s-close", printaddr(&a_tcp->addr,thread_seq));
+ }
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_RELEASE], FS_OP_TYPE_ADD, 1);
+ }
+ if(cur_http_node->ungzip_handle!=NULL)
+ {
+ docanalyze_endstream(cur_http_node->ungzip_handle);
+ }
+ if(cur_http_node->parser.cont_range!=NULL)
+ {
+ dictator_free(thread_seq, cur_http_node->parser.cont_range);
+ cur_http_node->parser.cont_range = NULL;
+ }
+
+ http_freeBuf(thread_seq,&(cur_http_node->url_buf), &(cur_http_node->url_buflen));
+ cur_http_node->parser.p_url = NULL;
+ cur_http_node->parser.url_len = 0;
+ http_freeBuf(thread_seq,&(cur_http_node->pbuf), &(cur_http_node->buflen));
+ /*batch free*/
+ if(HTTP_CALLBACK_MODE_BATCH==g_http_prog_para.callback_mode)
+ {
+ /*clear fold buf*/
+ if(NULL!=cur_http_node->pbuf_fold)
+ {
+ for(int j=0;j<cur_http_node->pbuf_fold->cnt;j++)
+ {
+ if(NULL!=cur_http_node->pbuf_fold->fold[j].buf)
+ {
+ dictator_free(thread_seq, cur_http_node->pbuf_fold->fold[j].buf);
+ }
+ }
+ if(NULL!=cur_http_node->pbuf_fold->fold)
+ {
+ dictator_free(thread_seq, cur_http_node->pbuf_fold->fold);
+ }
+ dictator_free(thread_seq, cur_http_node->pbuf_fold);
+ }
+ /*clear batch infor*/
+ if(NULL!=cur_http_node->parser.batch_infor)
+ {
+ if(NULL!=cur_http_node->parser.batch_infor->field)
+ {
+ dictator_free(thread_seq, cur_http_node->parser.batch_infor->field);
+ }
+ dictator_free(thread_seq, cur_http_node->parser.batch_infor);
+ }
+ }
+
+ http_reseaseHttpInforList(&cur_http_node, a_http_stream->uncomplete_count, a_http_stream->res_req, thread_seq);
+ a_http_stream->uncomplete_count--;
+
+ if(a_http_stream->uncomplete_count<=1)
+ {
+ a_http_stream->last_link_node = cur_http_node;
+ a_http_stream->first_link_node = cur_http_node;
+ return;
+ }
+ else
+ {
+ if(DIR_C2S==a_http_stream->res_req)
+ {
+ a_http_stream->last_link_node = cur_http_node;
+ }
+ else
+ {
+ a_http_stream->first_link_node = cur_http_node;
+ }
+ }
+ return;
+}
+
+/*cording with http_method*/
+const char* g_http_method[] =
+{
+ "unkonw",
+ "get",
+ "post",
+ "connect",
+ "head",
+ "put",
+ "options",
+ "delete",
+ "trace",
+};
+
+char http_judgeHttpMethod(uchar *method, char *data, uchar curdir)
+{
+ int i=0;
+ if(curdir==DIR_C2S)
+ {
+ for(i=1;i<=HTTP_METHOD_TRACE;i++)
+ {
+ if(0==strncasecmp(data,g_http_method[i],strlen(g_http_method[i])))
+ {
+ *method = i;
+ return OK;
+ }
+ }
+ }
+ else
+ {
+ /*content maybe have http, so set http/*/
+ if(strncasecmp(data,"HTTP/",5)==0) return OK;
+
+ }
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ /*log*/
+ char buf[HTTP_START_FLAGS_LEN+1] = {0};
+ memcpy(buf, data, HTTP_START_FLAGS_LEN);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "http_judgeHttpMethod error, data=%s.",buf);
+ }
+ return ERROR;
+}
+
+/**********************************************************
+return :
+error
+ok
+***********************************************************/
+uchar http_tripleMatching(http_parser_t *cur_http_node, http_stream* a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ char* frist_pos=NULL;
+ char* last_pos=NULL;
+ char* last_http_pos=NULL;
+ uchar curdir = a_http_stream->res_req;
+ uint16* res_code = &(cur_http_node->parser.res_code);
+ char* oneline = cur_http_node->poneline_data;
+ uint32 oneline_len = cur_http_node->poneline_datalen;
+ char dig[4]={0} ;
+ char* http_flag = NULL;
+
+ frist_pos = (char*)memchr(oneline, HTTP_SP, oneline_len);
+ if(NULL==frist_pos)
+ {
+ char* buf = (char*)calloc(1, oneline_len+1);
+ memcpy(buf, oneline, oneline_len);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching frist_space error: addr:%s, oneline:%s",
+ printaddr(&a_tcp->addr,thread_seq), buf);
+ free(buf);
+ return ERROR;
+ }
+ /*20161219*/
+ if(DIR_C2S==curdir)
+ {
+ if(cur_http_node->parser.method==0)
+ {
+ char* buf = (char*)calloc(1, oneline_len+1);
+ memcpy(buf, oneline, oneline_len);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching C2S method==0: addr:%s, oneline:%s",
+ printaddr(&a_tcp->addr,thread_seq), buf);
+ return ERROR;
+ }
+ /*POST http://web.superhub.sandai.net:80/HTTP/1.1*/
+ last_http_pos = (char*)memcasemem(oneline, oneline_len, "HTTP/", 5);
+ if(NULL!=last_http_pos)
+ {
+ http_flag = (char*)(last_http_pos);
+ /* HTTP/ HTTP1.1*/
+ if(oneline+oneline_len-http_flag < HTTP_VERSIONS_LEN)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching HTTP_C2S version len error: addr:%s, version_len=%d",
+ printaddr(&a_tcp->addr,thread_seq), oneline+oneline_len-http_flag);
+ return ERROR;
+ }
+ }
+ else if(NULL!=(last_http_pos = (char*)memcasemem(oneline, oneline_len, "HTTP1", 5)))
+ {
+ http_flag = (char*)(last_http_pos);
+ /* HTTP/ HTTP1.1*/
+ if(oneline+oneline_len-http_flag < 7)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching HTTP_C2S version len error: addr:%s, version_len=%d",
+ printaddr(&a_tcp->addr,thread_seq), oneline+oneline_len-http_flag);
+ return ERROR;
+ }
+ }
+ else
+ {
+ char* buf = (char*)calloc(1, oneline_len+1);
+ memcpy(buf, oneline, oneline_len);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching HTTP_C2S last_space NULL: addr:%s, oneline:%s",
+ printaddr(&a_tcp->addr,thread_seq), buf);
+ free(buf);
+ return ERROR;
+ }
+
+
+ last_pos = last_http_pos-1;
+ while(*last_pos==HTTP_SP && last_pos>frist_pos)
+ {
+ last_pos--;
+ }
+
+ /*last_pos-first_pos to make sure url != NULL*/
+ if(last_pos-frist_pos>0)
+ {
+ cur_http_node->url_buflen = last_pos-frist_pos;
+ cur_http_node->url_buf = (char*)dictator_malloc(thread_seq, cur_http_node->url_buflen);
+ memcpy(cur_http_node->url_buf , frist_pos+1, cur_http_node->url_buflen);
+ }
+
+ cur_http_node->parser.curdir = DIR_C2S;
+ /*output uri*/
+ if(last_pos-frist_pos>0)
+ {
+ cur_http_node->interested_reg_mask = HTTP_URI_MASK;
+ cur_http_node->session.buf =cur_http_node->url_buf;
+ cur_http_node->session.buflen = cur_http_node->url_buflen;
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+ }
+ cur_http_node->interested_reg_mask = HTTP_REQ_LINE_MASK;
+
+ /*http proxy*/
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(cur_http_node->parser.method==HTTP_METHOD_CONNECT)
+ {
+ cur_http_node->proxy_flag = DIR_C2S;
+ }
+ }
+#endif
+
+ /*http stat*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_REQ], FS_OP_TYPE_ADD,1);
+ if(DIR_C2S==a_http_stream->dir)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_C2S], FS_OP_TYPE_ADD, 1);
+ }
+ }
+
+ /*http log*/
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ char url[64] = {0};
+ memcpy(url, cur_http_node->url_buf, MIN(sizeof(url)-1, cur_http_node->url_buflen));
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s:%lu URI:%s",
+ printaddr(&a_tcp->addr,thread_seq),cur_http_node->parser.http_session_seq,url);
+ }
+ }
+ else
+ {
+ last_pos = (char*)memchr((frist_pos)+1, HTTP_SP, oneline_len-(frist_pos-oneline+1));
+ if(NULL==last_pos)
+ {
+ last_pos = oneline + oneline_len;
+ }
+ if(HTTP_RESPONSE_CODE_LEN!=(last_pos-frist_pos-1))
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching HTTP_S2C code_len error: addr:%s, code_len=%d",
+ printaddr(&a_tcp->addr,thread_seq), last_pos-frist_pos-1);
+ return ERROR;
+ }
+
+ /*proc res code*/
+ memcpy(dig,frist_pos+1,HTTP_RESPONSE_CODE_LEN);
+ *res_code = strtoul(dig, NULL, 10);
+
+ /*HTTP/1.1 999 Unable to process request at this time -- error 999*/
+ if((*res_code<100) || (*res_code>600 && *res_code!=999))
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "http_tripleMatching HTTP_S2C code error: addr:%s, code=%hu",
+ printaddr(&a_tcp->addr,thread_seq), *res_code);
+ return ERROR;
+ }
+
+ /*http proxy*/
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(*res_code==200 && NULL!=memcasemem(oneline, oneline_len, PROXY_CONNECTION_SUCC, sizeof(PROXY_CONNECTION_SUCC)))
+ {
+ cur_http_node->proxy_flag = DIR_S2C;
+ }
+ }
+#endif
+
+ /*http stat*/
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_RES], FS_OP_TYPE_ADD,1);
+ if(DIR_S2C==a_http_stream->dir)
+ {
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_S2C], FS_OP_TYPE_ADD, 1);
+ }
+ }
+
+ cur_http_node->parser.curdir = DIR_S2C;
+ cur_http_node->interested_reg_mask = HTTP_RES_LINE_MASK;
+ }
+ return OK;
+}
+
+/**********************************************************
+ * ���ܣ�ʶ��ʼ�У�������ʼ�С�
+ * cur_http_node����ǰ�����ڵ㡣
+ * curdir����ǰ���ݷ���
+ * is_http��http��ʼ��־λ��
+ * cur_halfstream����ǰ�������ݡ�
+ * return : HTTP_RETURN_SPAN_PACKET
+***********************************************************/
+uchar http_doWithStartLine(http_parser_t*cur_http_node, http_stream* a_http_stream, struct streaminfo *a_tcp, int thread_seq, void* a_packet)
+{
+ uchar rec = 0;
+
+ rec = http_positioningACompleteLine(0, cur_http_node, a_tcp, thread_seq);
+ if(rec!=OK) return rec;
+
+ /*get three tuple*/
+ rec = http_tripleMatching(cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ if(rec!=OK)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_RESET;
+ return rec;
+ }
+
+ /*20150603*/
+ a_http_stream->is_http_falgs = HTTP_TRUE;
+
+ /*output : req line and res line*/
+ cur_http_node->session.buf = cur_http_node->poneline_data;
+ cur_http_node->session.buflen = cur_http_node->poneline_datalen;
+ http_callPlugin(cur_http_node, a_tcp, thread_seq, a_packet);
+
+ http_inintRegionParam(cur_http_node, thread_seq);
+
+ cur_http_node->parser.http_state = HTTP_REGION;
+ return OK;
+}
+
+#if HTTP_PROXY
+uchar http_processHttpProxy(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp,int thread_seq,void *a_packet)
+{
+ if(a_http->proxy_flag==0 || NULL==a_http_stream->p_stream_proxy) return ERROR;
+
+ struct streaminfo *pProxy = a_http_stream->p_stream_proxy;
+ char* user_pos = NULL;
+ char* pwd_pos = NULL;
+ int user_len = 0;
+ char user_ped_decode[512] = {0};
+
+ struct proxydetail*pProxydetail=NULL;
+ pProxydetail=(struct proxydetail *)(pProxy->pdetail);
+
+ a_http_stream->is_proxy = 1;
+
+ if(pProxydetail->dealstate==PROXY_STATE_SEL)
+ {
+ /*not add host url*/
+ if(a_http->url_buf!=NULL&&pProxydetail->append==NULL)
+ {
+ pProxydetail->append = (uchar*)dictator_malloc(thread_seq,a_http->url_buflen);
+ memcpy(pProxydetail->append,a_http->url_buf,a_http->url_buflen);
+ pProxydetail->uiApendLen = a_http->url_buflen;
+ }
+
+ //���������������Ϣ��
+ /*user and passwd in C2S*/
+ if(a_http->parser.curdir==DIR_C2S)
+ {
+ //process http_proxy infor: base 64
+ if(pProxydetail->pUser!=NULL)
+ {
+ user_pos = memcasemem((const char*)pProxydetail->pUser, pProxydetail->uiUserLen, "Basic ", sizeof("Basic"));
+ if(user_pos!=NULL)
+ {
+ user_pos += sizeof("Basic");
+ }
+ else
+ {
+ user_pos = (char*)pProxydetail->pUser;
+ }
+ user_len = pProxydetail->uiUserLen-(user_pos-(char*)pProxydetail->pUser);
+ http_proxy_base64_decode(0, user_pos, user_len, user_ped_decode);
+ pwd_pos = (char*)memchr(user_ped_decode, ':', strlen(user_ped_decode));
+ dictator_free(thread_seq, pProxydetail->pUser);
+ if(pwd_pos==NULL)
+ {
+ pProxydetail->uiUserLen = strlen(user_ped_decode);
+ pProxydetail->pUser = (uchar*)dictator_malloc(thread_seq, pProxydetail->uiUserLen);
+ memcpy(pProxydetail->pUser, user_ped_decode, pProxydetail->uiUserLen);
+ }
+ else
+ {
+ pProxydetail->uiUserLen = pwd_pos - user_ped_decode;
+ pProxydetail->pUser = (uchar*)dictator_malloc(thread_seq, pProxydetail->uiUserLen);
+ memcpy(pProxydetail->pUser, user_ped_decode, pProxydetail->uiUserLen);
+
+ pProxydetail->uiPwdLen = strlen(user_ped_decode) - (pwd_pos - user_ped_decode+1);
+ pProxydetail->pPwd = (uchar*)dictator_malloc(thread_seq, pProxydetail->uiPwdLen);
+ memcpy(pProxydetail->pPwd, pwd_pos+1, pProxydetail->uiPwdLen);
+ }
+ }
+ }
+ pProxydetail->dealstate = PROXY_STATE_LINK_IN;
+ set_proxy_fstream(a_tcp, pProxy);
+ }
+ return OK;
+}
+
+uchar http_analyseHttpProxy(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ /*not repeat*/
+ if(a_http->proxy_flag==0 || NULL!=a_http_stream->p_stream_proxy) return OK;
+
+ /*log*/
+ if(g_http_prog_para.http_log_level<=RLOG_LV_INFO)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "HTTP_PROXY:%s:%lu",
+ printaddr(&a_tcp->addr,thread_seq), a_http->parser.http_session_seq);
+ }
+ /*http_proxy capfile*/
+#if HTTP_PROXY_CAPFILE
+ project_req_add_char(a_tcp, g_http_prog_para.capfile_project_id, 1);
+#endif
+ a_http_stream->p_stream_proxy = (struct streaminfo*)dictator_malloc(thread_seq,sizeof(struct streaminfo));
+ memset(a_http_stream->p_stream_proxy,0,sizeof(struct streaminfo));
+ a_http_stream->p_stream_proxy->type = STREAM_TYPE_HTTP_PROXY;
+
+ struct proxydetail* pProxydetail = (struct proxydetail *)(a_http_stream->p_stream_proxy->pdetail);
+ //������״ν���
+ if(pProxydetail==NULL)
+ {
+ pProxydetail=(struct proxydetail*)dictator_malloc(thread_seq,sizeof(struct proxydetail));
+ memset(pProxydetail,0,sizeof(struct proxydetail));
+ pProxydetail->iType = STREAM_TYPE_HTTP_PROXY;
+ a_http_stream->p_stream_proxy->pdetail=pProxydetail;
+ /*IP and PORT*/
+ if(a_tcp->addr.addrtype==ADDR_TYPE_IPV4)
+ {
+ pProxydetail->uiIP = a_tcp->addr.tuple4_v4->daddr;
+ pProxydetail->uiPort = a_tcp->addr.tuple4_v4->dest;
+ }
+ if(a_tcp->addr.addrtype==ADDR_TYPE_IPV6)
+ {
+ pProxydetail->pIpv6 = (uchar*)dictator_malloc(thread_seq, sizeof(a_tcp->addr.tuple4_v6->daddr));
+ memcpy(pProxydetail->pIpv6,a_tcp->addr.tuple4_v6->daddr,sizeof(a_tcp->addr.tuple4_v6->daddr));
+ pProxydetail->uiPort = a_tcp->addr.tuple4_v6->dest;
+ }
+ }
+ return OK;
+}
+
+#endif
+
+/**********************************************************
+ * ���ܣ���ȡhttp��־��Ϊȷ����ʼ��־��׼����
+ * buffer:ƴ�տ�ʼǰHTTP_START_FLAGS_LEN���ֽڵ���ʱ��������
+ * offset����ǰ�������Ѵ������ݵ�ƫ������
+ * method��������Ϣ������ʽ��
+ * is_http:httpȷ����־λ��
+ * dir����ǰ���ݵķ���
+ * data����ǰ���ݡ�
+ * data_len����ǰ���ݳ��ȡ�
+ return : OK GO_BACK ERROR
+***********************************************************/
+uchar http_findtStartFlag(http_parser_t *cur_node, uchar curdir,struct tcpdetail *tcp_detail, int thread_seq)
+{
+ uint32 *buflen = &(cur_node->buflen);
+ uint32 *offset = &(cur_node->processed_offset);
+ uchar *method = &(cur_node->parser.method);
+ //��һ������ȥ�����У��ո��Ʊ�������HTTP_START_FLAGS_LEN�ֽ�
+ if(0==*buflen)
+ {
+ if(tcp_detail->datalen < HTTP_START_FLAGS_LEN+*offset)
+ {
+ if(tcp_detail->datalen-*offset > 0)
+ {
+ cur_node->pbuf = (char*)dictator_malloc(thread_seq, tcp_detail->datalen-*offset);
+ memcpy((void*)(cur_node->pbuf), (void*)((uchar*)tcp_detail->pdata+*offset),tcp_detail->datalen-*offset);
+ *buflen = tcp_detail->datalen-*offset;
+ }
+ return GO_BACK;
+ }
+ return http_judgeHttpMethod(method, (char*)tcp_detail->pdata+*offset, curdir);
+ }
+
+ //һֱ�ȹ�HTTP_START_FLAGS_LEN�ֽ�
+ if(0<*buflen)
+ {
+ if(tcp_detail->datalen+*buflen < HTTP_START_FLAGS_LEN+*offset && tcp_detail->datalen-*offset>0)
+ {
+ if(tcp_detail->datalen-*offset > 0)
+ {
+ cur_node->pbuf = (char*)dictator_realloc(thread_seq, cur_node->pbuf, (*buflen)+ tcp_detail->datalen-*offset);
+ memcpy((void*)(cur_node->pbuf+(*buflen)), (void*)((uchar*)tcp_detail->pdata+*offset),tcp_detail->datalen-*offset);
+ *buflen += tcp_detail->datalen-*offset;
+ }
+ return GO_BACK;
+ }
+ //��־һ������buffer���棬һ������data����
+ cur_node->pbuf = (char*)dictator_realloc(thread_seq, cur_node->pbuf, HTTP_START_FLAGS_LEN);
+ memcpy((void*)(cur_node->pbuf+(*buflen)), (void*)((uchar*)tcp_detail->pdata+*offset),HTTP_START_FLAGS_LEN-*buflen);
+ *offset += HTTP_START_FLAGS_LEN-*buflen;
+ *buflen = HTTP_START_FLAGS_LEN;
+ return http_judgeHttpMethod(method, cur_node->pbuf, curdir);
+ }
+ return ERROR;
+}
+
+/**********************************************************
+ * ���ܣ�����HTTP����,���ݲ�ͬ����Ϣ��ִ�в�ͬ�IJ�����
+ * a_http:http��������
+ * tcp_detail����ǰtcp���ݡ�
+***********************************************************/
+uchar http_analyseHttpReqResHeader(http_parser_t* a_http, http_stream* a_http_stream, struct streaminfo* a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+ //��ʼ�з���
+ if(HTTP_STATE_UNKNOWN==a_http->parser.http_state)
+ {
+ /*20170207 POST������ һ�� �� �� SP+URI������һ���� */
+ if(a_http->pbuf==NULL)
+ {
+ /*delete \r\n \0 ...... GET֮ǰ�пո�*/
+ http_deleteEmptyRow(&(a_http->processed_offset),(char*)(tcp_detail->pdata), tcp_detail->datalen);
+ }
+ rec = http_findtStartFlag(a_http, a_http_stream->res_req, tcp_detail, thread_seq);
+ if(rec==ERROR)
+ {
+ a_http->mgs_status = HTTP_RETURN_RESET;
+ return ERROR;
+ }
+ else if(rec==GO_BACK)
+ {
+ return GO_BACK;
+ }
+ a_http->parser.http_state = HTTP_START_LINE;
+ /*20150603 set http_begin*/
+ a_http->phttp_begin = (char*)(tcp_detail->pdata)+a_http->processed_offset;
+ }
+ if(HTTP_START_LINE==a_http->parser.http_state)
+ {
+ rec = http_doWithStartLine(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ if(rec!=OK) return rec;
+ /*proxy proc : malloc proxy region*/
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ http_analyseHttpProxy(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ // http_processHttpProxy(a_http,a_http_stream,a_tcp,thread_seq,a_packet);
+ }
+#endif
+ }
+
+ //ͷ������
+ if(HTTP_REGION==a_http->parser.http_state)
+ {
+ rec = http_findAndDoWithRegion(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ if(rec!=OK) return rec;
+ }
+ return OK;
+}
diff --git a/src/HTTP_Message_Header.h b/src/HTTP_Message_Header.h
new file mode 100644
index 0000000..aa733e2
--- /dev/null
+++ b/src/HTTP_Message_Header.h
@@ -0,0 +1,44 @@
+#ifndef HTTP_MESSAGE_HEADER_H_
+#define HTTP_MESSAGE_HEADER_H_
+
+#include "HTTP_Message.h"
+#include "HTTP_Analyze.h"
+
+#define HTTP_START_FLAGS_LEN 9
+#define HTTP_RESPONSE_CODE_LEN 3
+#define HTTP_VERSIONS_LEN 8
+
+/*positioning a completeLine*/
+#define HTTP_OLD_MEM 0
+#define HTTP_MALLOC_MEM 1
+#define HTTP_NO_MEM 2
+
+typedef enum
+{
+ HTTP_VERSIONS_UNKNOWN=9,
+ HTTP_09,
+ HTTP_10,
+ HTTP_11
+}http_versions;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void http_resetResponseSpace(http_parser_t *a_http, int thread_seq);
+char http_judgeHttpMethod(uchar *method, char *data, uchar curdir);
+void http_initHttpConnection(http_stream *a_http_stream, int thread_seq, struct streaminfo *a_tcp, void *a_packet);
+uchar http_analyseHttpReqResHeader(http_parser_t*a_http, http_stream *a_http_stream,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+void http_inintRegionParam(http_parser_t *cur_node, int thread_seq);
+void http_reseaseHttpInfor(http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+uchar http_analyseHttpProxy(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+uchar http_processHttpProxy(http_parser_t *a_http, http_stream *a_http_stream, struct streaminfo *a_tcp,int thread_seq,void *a_packet);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTP_HEADER_H_ */
diff --git a/src/HTTP_Message_Region.c b/src/HTTP_Message_Region.c
new file mode 100644
index 0000000..0fc926e
--- /dev/null
+++ b/src/HTTP_Message_Region.c
@@ -0,0 +1,767 @@
+#include <ctype.h>
+#include <assert.h>
+#include <arpa/inet.h>
+
+
+#include "HTTP_Message_Region.h"
+#include "HTTP_Common.h"
+#include "HTTP_Message_Header.h"
+#include "MESA_handle_logger.h"
+#include "MESA_htable.h"
+#include "field_stat.h"
+
+extern http_prog_runtime_parameter_t g_http_prog_para;
+extern string_map_t g_http_regions[];
+
+uchar http_doWithProxyRegion(http_parser_t *a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ if(a_http->proxy_flag == HTTP_TRUE && NULL!=((http_stream*)(a_http_stream))->p_stream_proxy)
+ {
+ struct proxydetail* p_proxy_detail = (struct proxydetail *)(((http_stream*)(a_http_stream))->p_stream_proxy->pdetail);
+ if(p_proxy_detail!=NULL)
+ {
+ p_proxy_detail->pUser = (UCHAR*)dictator_malloc(thread_seq, valuelen);
+ memcpy(p_proxy_detail->pUser, (uchar*)value, valuelen);
+ }
+ }
+ }
+#endif
+ return http_doWithDefaultRegion(a_http, a_http_stream, value, valuelen,a_tcp, thread_seq, a_packet);
+}
+
+uchar http_doWithCharset(http_parser_t *a_http, char* value, uint32 valuelen, char *semicolon_pos,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ char* equals_pos=NULL;
+ uint32 charset_type_len = 0,start_pos=0;
+ char region_name[REGION_NAME_LEN] = {0};
+
+ equals_pos = (char*)memchr(semicolon_pos,'=',valuelen-(semicolon_pos-value));
+ if(equals_pos==NULL)
+ {
+ equals_pos = (char*)memchr(semicolon_pos,':',valuelen-(semicolon_pos-value));
+ }
+ if(equals_pos!=NULL)
+ {
+ memcpy(region_name, semicolon_pos+1, MIN(REGION_NAME_LEN-1, equals_pos-(semicolon_pos+1)));
+ if(NULL==memcasemem(region_name, strlen(region_name), "charset", sizeof("charset")-1)) return OK;
+ charset_type_len = valuelen-(equals_pos-value)-1;
+ http_deleteEmptyRow(&start_pos, equals_pos+1, charset_type_len);
+ charset_type_len -= start_pos;
+ a_http->interested_reg_mask = HTTP_CHARSET_MASK;
+ a_http->session.buf = equals_pos+1+start_pos;
+ a_http->session.buflen = charset_type_len;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+ return OK;
+}
+
+/**********************************************************
+
+***********************************************************/
+uchar http_doWithContentType(http_parser_t *a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ char *semicolon_pos=(char*)memchr(value,';',valuelen);;
+ uint32 cont_type_dellen=0;
+ if(NULL!=semicolon_pos)
+ {
+ http_doWithCharset(a_http, value, valuelen, semicolon_pos, a_tcp,thread_seq, a_packet);
+ a_http->interested_reg_mask = HTTP_CONT_TYPE_MASK;
+ valuelen = semicolon_pos-value;
+ http_deleteSPHTCRLFAtLast(&cont_type_dellen, value, valuelen);
+ a_http->session.buf = value;
+ a_http->session.buflen = cont_type_dellen;
+ }
+ else
+ {
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ }
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+/**********************************************************
+
+***********************************************************/
+uchar http_doWithHost(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(a_tcp->curdir==DIR_S2C) return OK;
+ char* uri = NULL;
+ uint32 urilen = 0;
+ uint64 region_flag_host = g_http_prog_para.http_interested_region_flag & HTTP_HOST ;
+ uint64 region_flag_url = g_http_prog_para.http_interested_region_flag & HTTP_MESSAGE_URL;
+
+ FLAG_SET(a_http->flag, HTTP_FLAG_GET_URL);
+
+ /*not joint URL when proxy and absolute uri*/
+ if(a_http->parser.method!=HTTP_METHOD_CONNECT && (a_http->url_buf==NULL||a_http->url_buf[0]=='/'))
+ {
+ uri = (char*)dictator_malloc(thread_seq, a_http->url_buflen);
+ urilen = a_http->url_buflen;
+ memcpy(uri, a_http->url_buf, a_http->url_buflen);
+ if(a_http->url_buf!=NULL) dictator_free(thread_seq, a_http->url_buf);
+ a_http->url_buf = NULL;
+ a_http->url_buflen = valuelen+urilen;
+ a_http->url_buf = (char*)dictator_malloc(thread_seq, a_http->url_buflen);
+ memcpy(a_http->url_buf, value, valuelen);
+ memcpy(a_http->url_buf+valuelen, uri, urilen);
+ if(uri!=NULL)
+ {
+ dictator_free(thread_seq, uri);
+ uri = NULL;
+ }
+ }
+ a_http->parser.p_url = a_http->url_buf;
+ a_http->parser.url_len = a_http->url_buflen;
+
+ if(region_flag_host && valuelen>0)
+ {
+ a_http->interested_reg_mask = HTTP_HOST_MASK;
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+
+ if(region_flag_url)
+ {
+ a_http->interested_reg_mask = HTTP_MESSAGE_URL_MASK;
+ a_http->session.buf = a_http->url_buf;
+ a_http->session.buflen = a_http->url_buflen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s:%lu HOST_URL:%s",
+ printaddr(&a_tcp->addr,thread_seq),a_http->parser.http_session_seq,a_http->url_buf);
+ }
+ }
+ return OK;
+}
+
+uchar http_recogniseTransferEncoding(uchar *trans_Encoding, char *value_data,uint32 value_data_len, int thread_seq)
+{
+ if(0==strncasecmp(value_data,"chunked",sizeof("chunked")-1))
+ *trans_Encoding = HTTP_TRANS_ENCOD_CHUNKED;
+ else
+ *trans_Encoding = HTTP_TRANS_ENCOD_OTHERS;
+
+ return OK;
+}
+uchar http_recogniseContentEncoding(uchar *Cont_Encoding, char *value_data,uint32 value_data_len, int thread_seq)
+{
+ if(0==strncasecmp(value_data,"gzip", sizeof("gzip")-1))
+ *Cont_Encoding = HTTP_CONT_ENCOD_GZIP;
+ else if(0==strncasecmp(value_data,"compress",sizeof("compress")-1))
+ *Cont_Encoding = HTTP_CONT_ENCOD_COMPRESS;
+ else if(0==strncasecmp(value_data,"deflate",sizeof("deflate")-1))
+ *Cont_Encoding = HTTP_CONT_ENCOD_DEFLATE;
+ else if(0==strncasecmp(value_data,"default",sizeof("default")-1))
+ *Cont_Encoding = HTTP_CONT_ENCOD_DEFAULT;
+ else
+ *Cont_Encoding = HTTP_CONT_ENCOD_OTHERS;
+ return OK;
+}
+
+uchar http_doWithEncoding(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ switch(a_http->interested_reg_mask)
+ {
+ case HTTP_TRANSFER_ENCODING_MASK:
+ http_recogniseTransferEncoding(&(a_http->parser.trans_encoding),(char*)value,valuelen, thread_seq);
+ break;
+ case HTTP_CONT_ENCODING_MASK:
+ http_recogniseContentEncoding(&(a_http->parser.cont_encoding), (char*)value,valuelen, thread_seq);
+ break;
+ default:
+ return OK;
+ break;
+ }
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_doWithLength(http_parser_t *a_http, int64 *cont_len, char* value, uint32 valuelen, struct streaminfo *a_tcp, int thread_seq)
+{
+ char char_len[HTTP_MAX_UINT64_LEN]={0};
+
+ memcpy(char_len, value, MIN(valuelen,HTTP_MAX_UINT64_LEN-1));
+ *cont_len = strtol(char_len, NULL, 10);
+ //20150323 content-length : -1
+ if(*cont_len==-1)
+ {
+ a_http->mgs_status = HTTP_RETURN_RESET;
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "content length error. addr:%s, content-length:%lld",
+ printaddr(&a_tcp->addr, thread_seq), *cont_len);
+ return ERROR;
+ }
+ return OK;
+}
+
+uchar http_doWithTransferLength(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(HTTP_TRANS_ENCOD_CHUNKED==a_http->parser.trans_encoding ) return OK;
+ int64 len = 0;
+ uchar rec = http_doWithLength(a_http, &len, value, valuelen, a_tcp, thread_seq);
+ if(ERROR==rec) return ERROR;
+ a_http->parser.cont_length = len;
+ a_http->packet_entity_len = len;
+ FLAG_SET(a_http->flag, HTTP_FLAG_TRANS_LEN);
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_doWithContentLength(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(HTTP_TRANS_ENCOD_CHUNKED==a_http->parser.trans_encoding ) return OK;
+ int64 len=0;
+ uchar rec = http_doWithLength(a_http, &len, value, valuelen, a_tcp, thread_seq);
+ if(ERROR==rec) return ERROR;
+ if(!FLAG_TEST(a_http->flag, HTTP_FLAG_TRANS_LEN))
+ {
+ a_http->parser.cont_length = len;
+ a_http->packet_entity_len = len;
+ }
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_doWithContentRange(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int rec = 0;
+ char range[HTTP_MAX_UINT64_LEN] = {0};
+ char* digit = value;
+ uint32 i = 0;
+ /*only get digit*/
+ for(i=0;i<valuelen;i++)
+ {
+ if( *(value+i)>='0' && *(value+i)<='9' )
+ {
+ digit = value+i;
+ break;
+ }
+ }
+ if(i==valuelen)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "content range error. addr:%s, range:%s",
+ printaddr(&a_tcp->addr, thread_seq), range);
+ return ERROR;
+ }
+ a_http->parser.cont_range = (cont_range_t*)dictator_malloc(thread_seq, sizeof(cont_range_t));
+ //memset(cur_http_node->parser.cont_range, 0, sizeof(cur_http_node->parser.cont_range));
+ memcpy(range, digit, MIN(HTTP_MAX_UINT64_LEN-1,valuelen));
+ rec = sscanf(range, "%llu-%llu/%llu", &(a_http->parser.cont_range->start), &(a_http->parser.cont_range->end), &(a_http->parser.cont_range->len));
+ if(rec==-1)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "content range error. addr:%s, range:%s",
+ printaddr(&a_tcp->addr, thread_seq), range);
+ dictator_free(thread_seq, a_http->parser.cont_range);
+ a_http->parser.cont_range = NULL;
+ return ERROR;
+ }
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_doWithDefaultRegion(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_doWithConnection(http_parser_t* a_http, http_stream *a_http_stream, char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ if(0==strncasecmp((char*)value,"keep-alive", sizeof("keep-alive")-1))
+ {
+ FLAG_CLEAR(a_http->flag, HTTP_FLAG_CONNECT_CLOSE);
+ }
+ else if(0==strncasecmp((char*)value,"close",sizeof("close")-1))
+ {
+ FLAG_SET(a_http->flag, HTTP_FLAG_CONNECT_CLOSE);
+ }
+ a_http->session.buf = value;
+ a_http->session.buflen = valuelen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ return OK;
+}
+
+uchar http_outPutUrl(http_parser_t *a_http, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ char* uri = NULL;
+ uint32 urilen = 0;
+ char serverIP_str[64] = {0};
+ struct stream_tuple4_v4* paddr = NULL;
+ struct stream_tuple4_v6* paddr6 = NULL;
+
+ if( FLAG_TEST(a_http->flag, HTTP_FLAG_GET_URL)) return OK;
+
+ FLAG_SET(a_http->flag, HTTP_FLAG_GET_URL);
+
+ if(DIR_C2S==a_http->parser.curdir && a_http->url_buf!=NULL)
+ {
+ /*releative url*/
+ if(a_http->url_buf[0]=='/')
+ {
+ uri = (char*)dictator_malloc(thread_seq, a_http->url_buflen);
+ urilen = a_http->url_buflen;
+ memcpy(uri, a_http->url_buf, a_http->url_buflen);
+ if(a_http->url_buf!=NULL)
+ {
+ dictator_free(thread_seq, a_http->url_buf);
+ a_http->url_buf = NULL;
+ }
+
+ switch(a_tcp->addr.addrtype)
+ {
+ case ADDR_TYPE_IPV4:
+ paddr = a_tcp->addr.tuple4_v4;
+ inet_ntop(AF_INET, &paddr->daddr, serverIP_str, 64);
+ break;
+
+ case ADDR_TYPE_IPV6:
+ paddr6 = a_tcp->addr.tuple4_v6;
+ inet_ntop(AF_INET6, &paddr6->daddr, serverIP_str, 64);
+ break;
+
+ default:
+ break;
+ }
+
+ a_http->url_buflen = strlen(serverIP_str)+urilen;
+ a_http->url_buf = (char*)dictator_malloc(thread_seq, a_http->url_buflen);
+ memcpy(a_http->url_buf, serverIP_str, strlen(serverIP_str));
+ memcpy(a_http->url_buf+strlen(serverIP_str), uri, urilen);
+ if(uri!=NULL)
+ {
+ dictator_free(thread_seq, uri);
+ uri = NULL;
+ }
+ }
+ a_http->parser.p_url = a_http->url_buf;
+ a_http->parser.url_len = a_http->url_buflen;
+ if(g_http_prog_para.http_log_level<=RLOG_LV_DEBUG)
+ {
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_DEBUG, HTTP_PLUGIN_NAME, "%s:%lu IP_URL:%s",
+ printaddr(&a_tcp->addr,thread_seq),a_http->parser.http_session_seq,a_http->url_buf);
+ }
+
+ a_http->interested_reg_mask = HTTP_MESSAGE_URL_MASK;
+ a_http->session.buf = a_http->url_buf;
+ a_http->session.buflen = a_http->url_buflen;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+ return OK;
+}
+
+int http_recogniseRequestRegion(const char *region_name, uint32 region_name_len)
+{
+ switch(region_name_len)
+ {
+ case 13:
+ if(0==strncasecmp(region_name, "authorization", 13)) return HTTP_AUTHORIZATION_MASK;
+ break;
+ case 19:
+ if(0==strncasecmp(region_name, "proxy-authorization", 19)) return HTTP_PROXY_AUTHORIZATION_MASK;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return -1;
+}
+
+int http_recogniseResponseRegion(const char *region_name, uint32 region_name_len)
+{
+ switch(region_name_len)
+ {
+ case 6:
+ if(0==strncasecmp(region_name, "server", 6)) return HTTP_SERVER_MASK;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return -1;
+}
+
+int http_recogniseGeneralEntityRegion(const char *region_name, uint32 region_name_len)
+{
+ switch(region_name_len)
+ {
+ case 3:
+ if(0==strncasecmp(region_name, "via", 3)) return HTTP_VIA_MASK;
+ break;
+ case 4:
+ if(0==strncasecmp(region_name, "host", 4)) return HTTP_HOST_MASK;
+ if(0==strncasecmp(region_name, "etag", 4)) return HTTP_ETAG_MASK;
+ if(0==strncasecmp(region_name, "date", 4)) return HTTP_DATE_MASK;
+ break;
+ case 6:
+ if(0==strncasecmp(region_name, "cookie", 6)) return HTTP_COOKIE_MASK;
+ if(0==strncasecmp(region_name, "pragma", 6)) return HTTP_PRAGMA_MASK;
+ break;
+ case 7:
+ if(0==strncasecmp(region_name, "referer", 7)) return HTTP_REFERER_MASK;
+ if(0==strncasecmp(region_name, "trailer", 7)) return HTTP_TRAILER_MASK;
+ if(0==strncasecmp(region_name, "expires", 7)) return HTTP_EXPIRES_MASK;
+ if(0==strncasecmp(region_name, "charset", 7)) return HTTP_CHARSET_MASK;
+ break;
+ case 8:
+ if(0==strncasecmp(region_name, "location", 8)) return HTTP_LOCATION_MASK;
+ break;
+ case 10:
+ if(0==strncasecmp(region_name, "connection", 10)) return HTTP_CONNECTION_MASK;
+ if(0==strncasecmp(region_name, "user-agent", 10)) return HTTP_USER_AGENT_MASK;
+ break;
+ case 12:
+ if(0==strncasecmp(region_name, "content-type", 12)) return HTTP_CONT_TYPE_MASK;
+ break;
+ case 13:
+ if(0==strncasecmp(region_name, "content-range", 13)) return HTTP_CONT_RANGE_MASK;
+ break;
+ case 14:
+ if(0==strncasecmp(region_name, "content-length", 14)) return HTTP_CONT_LENGTH_MASK;
+ break;
+ case 15:
+ if(0==strncasecmp(region_name, "transfer-length", 15)) return HTTP_TRANSFER_LENGTH_MASK;
+ if(0==strncasecmp(region_name, "x-flash-version", 15)) return HTTP_X_FLASH_VERSION_MASK;
+ break;
+ case 16:
+ if(0==strncasecmp(region_name, "content-location", 16)) return HTTP_CONT_LOCATION_MASK;
+ if(0==strncasecmp(region_name, "content-encoding", 16)) return HTTP_CONT_ENCODING_MASK;
+ if(0==strncasecmp(region_name, "content-language", 16)) return HTTP_CONT_LANGUAGE_MASK;
+ break;
+ case 17:
+ if(0==strncasecmp(region_name, "transfer-encoding", 17)) return HTTP_TRANSFER_ENCODING_MASK;
+ break;
+ case 19:
+ if(0==strncasecmp(region_name, "content-disposition", 19)) return HTTP_CONT_DISPOSITION_MASK;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return -1;
+}
+
+int http_analyseRegion(char curdir, const char *region_name, uint32 region_name_len)
+{
+ int rec = -1;
+
+ if(curdir==DIR_C2S)
+ {
+ rec = http_recogniseRequestRegion(region_name, region_name_len);
+ }
+ else
+ {
+ rec = http_recogniseResponseRegion(region_name, region_name_len);
+ }
+
+ if(-1==rec)
+ {
+ rec = http_recogniseGeneralEntityRegion(region_name, region_name_len);
+ }
+ if(-1==rec)
+ {
+ return HTTP_OTHER_REGIONS_MASK;
+ }
+ return rec;
+}
+
+/*return : ERROR, OK*/
+uchar http_doWithACompleteRegion(http_parser_t *cur_http_node, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ int region_id = 0;
+ int* region_id_hash= NULL;
+ char* data = cur_http_node->poneline_data;
+ uint32 datalen = cur_http_node->poneline_datalen;
+ uint32 start_pos=0, end_pos = datalen;
+ uchar rec=OK;
+ char* colon_pos=NULL;
+ char* value = NULL;
+ uint32 valuelen=0, sp_offset=0;
+ uint32 reg_name_len=0, del_data_len=0;
+ char* region_name = NULL;
+ char copy_region_name[128] = {0};
+#if HTTP_STATIC
+ long long before_str = 0, after_str = 0;
+#endif
+#if HTTP_REGION_HASH
+ long long before_hash = 0, after_hash = 0;
+#endif
+
+ unsigned long long region_flag = g_http_prog_para.http_interested_region_flag;
+ int64 prot_flag = 0;
+
+
+ http_deleteEmptyRow(&start_pos, data, datalen);
+ /*region name process*/
+ colon_pos = (char*)memchr(data+start_pos,':',end_pos-start_pos);
+ /*span pkt*/
+ if(NULL==(colon_pos))
+ {
+ //cur_http_node->mgs_status = HTTP_RETURN_RESET;
+ char* buf = (char*)calloc(1, datalen+1);
+ memcpy(buf, data, datalen);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_INFO, HTTP_PLUGIN_NAME, "get region name error, addr:%s, oneline:%s, onelinelen:%u",
+ printaddr(&a_tcp->addr,thread_seq), buf, datalen);
+ free(buf);
+ return ERROR;
+ }
+ reg_name_len = colon_pos - data;
+ http_deleteSPHTCRLFAtLast(&del_data_len, data+start_pos, reg_name_len);
+ reg_name_len = del_data_len;
+ if(reg_name_len>=REGION_NAME_LEN)
+ {
+ cur_http_node->mgs_status = HTTP_RETURN_RESET;
+ char* buf = (char*)calloc(1, datalen+1);
+ memcpy(buf, data, datalen);
+ MESA_handle_runtime_log(g_http_prog_para.http_log_handle, RLOG_LV_FATAL, HTTP_PLUGIN_NAME, "region name len is more than %d, addr:%s, oneline:%s, onelinelen:%u",
+ REGION_NAME_LEN, printaddr(&a_tcp->addr,thread_seq), buf, datalen);
+ free(buf);
+ return ERROR;
+ }
+ region_name = data+start_pos;
+
+#if HTTP_STATIC
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ before_str = rdtsc();
+ }
+#endif
+ region_id = http_analyseRegion(cur_http_node->parser.curdir, (const char*)region_name, reg_name_len);
+#if HTTP_STATIC
+ if(g_http_prog_para.http_stat_cycle)
+ {
+ after_str = rdtsc();
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_REGION_TIME_STR], FS_OP_TYPE_ADD, (after_str-before_str));
+ }
+#endif
+
+#if HTTP_REGION_HASH
+ before_hash = rdtsc();
+ memcpy(copy_region_name, region_name, reg_name_len);
+ stringA_to_stringa(copy_region_name, reg_name_len);
+ region_id_hash = (int*)MESA_htable_search(g_http_prog_para.region_hash, (const uchar*)copy_region_name, reg_name_len);
+ after_hash = rdtsc();
+ stat_field_operation(g_http_prog_para.stat_handler, g_http_prog_para.stat_field[HTTP_STAT_REGION_TIME_HASH], FS_OP_TYPE_ADD, after_hash-before_hash);
+ if(-1!=region_id && HTTP_OTHER_REGIONS_MASK!=region_id && NULL!=region_id_hash && NULL!=g_http_regions[*region_id_hash].handler)
+ {
+ if(region_id!=*region_id_hash)
+ {
+ assert(0);
+ }
+#else
+ if(-1!=region_id && NULL!=g_http_regions[region_id].handler)
+ {
+#endif
+ /*standard header*/
+ cur_http_node->interested_reg_mask = (interested_region_mask)(region_id);
+ prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ region_flag &= prot_flag ;
+
+ /*region value process, url in proc function*/
+ if(g_http_regions[region_id].handler!=NULL&&
+ (region_flag||
+ cur_http_node->interested_reg_mask==HTTP_HOST_MASK||
+ cur_http_node->interested_reg_mask==HTTP_CHARSET_MASK||
+ cur_http_node->interested_reg_mask==HTTP_TRANSFER_ENCODING_MASK||
+ cur_http_node->interested_reg_mask==HTTP_CONNECTION_MASK||
+ cur_http_node->interested_reg_mask==HTTP_CONT_ENCODING_MASK||
+ cur_http_node->interested_reg_mask==HTTP_CONT_LENGTH_MASK||
+ cur_http_node->interested_reg_mask==HTTP_TRANSFER_LENGTH_MASK||
+ cur_http_node->interested_reg_mask==HTTP_PROXY_AUTHORIZATION_MASK))
+ {
+ /*standard append*/
+ cur_http_node->parser.append_infor.content = data+start_pos;
+ cur_http_node->parser.append_infor.contlen = datalen-start_pos;
+ valuelen = data+end_pos - colon_pos-1;
+ http_deleteEmptyRow(&sp_offset, colon_pos+1, valuelen);
+ value = colon_pos+1+sp_offset;
+ valuelen -= sp_offset;
+ /*proc url when host through host is NULL*/
+ if(valuelen>0 || cur_http_node->interested_reg_mask==HTTP_HOST_MASK)
+ {
+ rec = g_http_regions[region_id].handler(cur_http_node, a_http_stream, value, valuelen, a_tcp, thread_seq, a_packet);
+ }
+ cur_http_node->parser.append_infor.content = NULL;
+ cur_http_node->parser.append_infor.contlen = 0;
+ }
+ }
+ else //other region
+ {
+ //if have expand head ,use hash to identify
+ if(g_http_prog_para.http_region_cnt>HTTP_REGION_NUM)
+ {
+ memcpy(copy_region_name, region_name, reg_name_len);
+ stringA_to_stringa(copy_region_name, reg_name_len);
+ region_id_hash = (int*)MESA_htable_search(g_http_prog_para.region_hash, (const uchar*)copy_region_name, reg_name_len);
+ }
+
+ /*expand region*/
+ if(NULL!=region_id_hash)
+ {
+ cur_http_node->interested_reg_mask = (interested_region_mask)(*region_id_hash);
+
+ }
+ /*other region*/
+ else
+ {
+ cur_http_node->interested_reg_mask = HTTP_OTHER_REGIONS_MASK;
+ }
+ prot_flag = (((int64)1)<<cur_http_node->interested_reg_mask);
+ region_flag &= prot_flag ;
+ if(region_flag)
+ {
+ /*expand append*/
+ cur_http_node->parser.append_infor.content = data+start_pos;
+ cur_http_node->parser.append_infor.contlen = datalen-start_pos;
+ valuelen = data+end_pos - colon_pos-1;
+ http_deleteEmptyRow(&sp_offset, colon_pos+1, valuelen);
+ value = colon_pos+1+sp_offset;
+ valuelen -= sp_offset;
+ rec = http_doWithDefaultRegion(cur_http_node, a_http_stream, value, valuelen, a_tcp, thread_seq, a_packet);
+ cur_http_node->parser.append_infor.content = NULL;
+ cur_http_node->parser.append_infor.contlen = 0;
+ }
+ }
+ return rec;
+}
+
+/**********************************************************
+***********************************************************/
+uchar http_analyseACompleteRegion(http_parser_t *cur_http_node, http_stream *a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ rec = http_positioningACompleteLine(1, cur_http_node, a_tcp, thread_seq);
+ /*error : too long . go_back : not long enough*/
+ if(rec!=OK) return rec;
+ rec = http_doWithACompleteRegion(cur_http_node, a_http_stream, a_tcp, thread_seq, a_packet);
+ /*after oneline , clear*/
+ http_inintRegionParam(cur_http_node, thread_seq);
+ if(rec!=OK) return rec;
+ return OK;
+}
+
+uchar http_findAndDoWithRegion(http_parser_t *a_http, http_stream *a_http_stream,struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ uchar rec = OK;
+ struct tcpdetail *tcp_detail = (struct tcpdetail*)a_tcp->pdetail;
+
+ while(1)
+ {
+ rec = http_judgeHeaderOver(a_http, (char*)(tcp_detail->pdata), tcp_detail->datalen, thread_seq);
+ if(OK==rec)
+ {
+ /*output : URL*/
+ http_outPutUrl(a_http, a_tcp, thread_seq, a_packet);
+
+ /*output : http state*/
+ a_http->parser.http_state = HTTP_DATA_BEGIN;
+
+ /*proxy header proc*/
+#if HTTP_PROXY
+ if(g_http_prog_para.proxy_switch)
+ {
+ http_processHttpProxy(a_http,a_http_stream,a_tcp,thread_seq,a_packet);
+ }
+#endif
+ if(g_http_prog_para.need_http_state)
+ {
+ FLAG_SET(a_http->flag, HTTP_FLAG_BATCH_CALLBACK);
+ a_http->session.buf = a_http->phttp_begin;
+ a_http->session.buflen = (char*)(tcp_detail->pdata)+a_http->processed_offset-a_http->phttp_begin;
+ a_http->interested_reg_mask = HTTP_STATE_MASK;
+ http_callPlugin(a_http, a_tcp, thread_seq, a_packet);
+ }
+ break;
+ }
+ if(GO_BACK==rec) return GO_BACK;
+ rec = http_analyseACompleteRegion(a_http, a_http_stream, a_tcp, thread_seq, a_packet);
+ if(rec!=OK) return rec;
+ }
+ if(HTTP_TRANS_ENCOD_UNKNOWN==a_http->parser.trans_encoding)
+ {
+ a_http->parser.trans_encoding = HTTP_TRANS_ENCOD_DEFAULT;
+ }
+ if(HTTP_TRANS_ENCOD_CHUNKED==a_http->parser.trans_encoding)
+ {
+ a_http->parser.cont_length = 0;
+ }
+ if( FLAG_TEST(a_http->flag, HTTP_FLAG_CONNECT_CLOSE) && a_http->parser.cont_length == 0 && a_http->parser.trans_encoding != HTTP_TRANS_ENCOD_CHUNKED)
+ {
+ a_http->parser.trans_encoding = HTTP_TRANS_ENCOD_CNNTCLOSE;
+ }
+ if(HTTP_CONT_ENCOD_UNKNOWN==a_http->parser.cont_encoding)
+ {
+ a_http->parser.cont_encoding = HTTP_CONT_ENCOD_DEFAULT;
+ }
+ http_inintRegionParam(a_http,thread_seq);
+ return OK;
+}
+
+string_map_t g_http_regions[] =
+{
+ {"", HTTP_INTEREST_KEY_MASK, NULL},
+ {"", HTTP_ALL_MASK, NULL},
+ {"", HTTP_OTHER_REGIONS_MASK, NULL},
+ {"", HTTP_STATE_MASK, NULL},
+ {"", HTTP_REQ_LINE_MASK, NULL},
+ {"", HTTP_RES_LINE_MASK, NULL},
+ {"", HTTP_CONTENT_MASK, NULL},
+ {"", HTTP_UNGZIP_CONTENT_MASK, NULL},
+ {"", HTTP_MESSAGE_URL_MASK, NULL},
+ {"", HTTP_URI_MASK, NULL},
+
+ {"host", HTTP_HOST_MASK, http_doWithHost},
+ {"referer", HTTP_REFERER_MASK, http_doWithDefaultRegion},
+ {"user-agent", HTTP_USER_AGENT_MASK, http_doWithDefaultRegion},
+ {"cookie", HTTP_COOKIE_MASK, http_doWithDefaultRegion},
+ {"proxy-authorization", HTTP_PROXY_AUTHORIZATION_MASK, http_doWithProxyRegion},
+ {"authorization", HTTP_AUTHORIZATION_MASK, http_doWithDefaultRegion},
+
+ {"location", HTTP_LOCATION_MASK, http_doWithDefaultRegion},
+ {"server", HTTP_SERVER_MASK, http_doWithDefaultRegion},
+ {"etag", HTTP_ETAG_MASK, http_doWithDefaultRegion},
+
+ {"date", HTTP_DATE_MASK, http_doWithDefaultRegion},
+ {"trailer", HTTP_TRAILER_MASK, http_doWithDefaultRegion},
+ {"transfer-encoding", HTTP_TRANSFER_ENCODING_MASK, http_doWithEncoding},
+ {"via", HTTP_VIA_MASK, http_doWithDefaultRegion},
+ {"pragma", HTTP_PRAGMA_MASK, http_doWithDefaultRegion},
+ {"connection", HTTP_CONNECTION_MASK, http_doWithConnection},
+
+ {"content-encoding", HTTP_CONT_ENCODING_MASK, http_doWithEncoding},
+ {"content-language", HTTP_CONT_LANGUAGE_MASK, http_doWithDefaultRegion},
+ {"content-location", HTTP_CONT_LOCATION_MASK, http_doWithDefaultRegion},
+ {"content-disposition", HTTP_CONT_DISPOSITION_MASK, http_doWithDefaultRegion},
+ {"content-range", HTTP_CONT_RANGE_MASK, http_doWithContentRange},
+ {"content-length", HTTP_CONT_LENGTH_MASK, http_doWithContentLength},
+ {"content-type", HTTP_CONT_TYPE_MASK, http_doWithContentType},
+ {"charset", HTTP_CHARSET_MASK, http_doWithDefaultRegion},
+ {"expires", HTTP_EXPIRES_MASK, http_doWithDefaultRegion},
+ {"x-flash-version", HTTP_X_FLASH_VERSION_MASK, http_doWithDefaultRegion},
+ {"transfer-length", HTTP_TRANSFER_LENGTH_MASK, http_doWithTransferLength},
+};
+
diff --git a/src/HTTP_Message_Region.h b/src/HTTP_Message_Region.h
new file mode 100644
index 0000000..c38e6a0
--- /dev/null
+++ b/src/HTTP_Message_Region.h
@@ -0,0 +1,23 @@
+#ifndef HTTP_MESSAGE_REGION_H_
+#define HTTP_MESSAGE_REGION_H_
+
+#include "HTTP_Message.h"
+#include "HTTP_Analyze.h"
+
+#define HTTP_MAX_UINT64_LEN 64
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uchar http_findAndDoWithRegion(http_parser_t* a_http, http_stream *a_http_stream, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+uchar http_doWithDefaultRegion(http_parser_t* a_http, http_stream *a_http_stream,char* value, uint32 valuelen,
+ struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+uchar http_outPutUrl(http_parser_t *cur_http_node, struct streaminfo *a_tcp, int thread_seq, void *a_packet);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..4ebf63a
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,64 @@
+vpath %.a ../lib
+vpath %.h ./inc
+
+PAPP_PATH=/home/lishu/DDP/sapp_run/
+
+#CFLAGS = -g3 -Wall -fPIC -Werror -O
+#CFLAGS = -g3 -Wall -fPIC -O
+CFLAGS = -g3 -Wall -fPIC
+CFLAGS += $(INCLUDES)
+CC = g++
+CCC = g++
+INCLUDES = -I./inc/
+INCLUDES += -I/usr/include/MESA/
+
+LIB = -L./lib/
+LIB += -lMESA_handle_logger
+LIB += -lMESA_prof_load
+LIB += -lMESA_htable
+LIB += -lMESA_field_stat
+LIB += -ldocumentanalyze
+
+LIB_FILE = $(wildcard ../lib/*.a)
+SOURCES = $(wildcard *.c)
+OBJECTS = $(SOURCES:.c=.o)
+DEPS = $(SOURCES:.c=.d)
+
+TARGET = http.so
+
+.PHONY:clean all
+
+all:$(TARGET)
+
+$(TARGET):$(OBJECTS) $(LIB_FILE)
+ $(CCC) -shared $(CFLAGS) $(OBJECTS) $(LIB) -o $@ -Wl,--version-script=http_global.map
+ cp http.so ../bin/
+
+.c.o:
+%.d:%.c
+ $(CCC) $< -MM $(INCLUDES) > $@
+
+-include $(DEPS)
+
+clean :
+ rm -f $(OBJECTS) $(DEPS) $(TARGET)
+
+
+PLUGIN_PATH=./plug/protocol
+CONFLIST_NAME=conflist_protocol.inf
+PLUGIN_DIR_NAME=http
+PLUGIN_INF_NAME=http.inf
+
+TARGET_DIR=$(PAPP_PATH)/$(PLUGIN_PATH)/$(PLUGIN_DIR_NAME)/
+INSERT_FILE=$(PAPP_PATH)/$(PLUGIN_PATH)/$(CONFLIST_NAME)
+INSERT_CONTENT=$(PLUGIN_PATH)/$(PLUGIN_DIR_NAME)/$(PLUGIN_INF_NAME)
+install:
+ mkdir -p $(TARGET_DIR)
+ cp -r ../bin/http.inf $(TARGET_DIR)
+ cp -r ../bin/http.so $(TARGET_DIR)
+ @ret=`cat $(INSERT_FILE)|grep $(INSERT_CONTENT)|wc -l`;if [ $$ret -eq 0 ];then echo $(INSERT_CONTENT) >>$(INSERT_FILE);fi
+
+CONF_DIR=$(PAPP_PATH)/conf/
+conf:
+ mkdir -p $(CONF_DIR)
+ cp -r ../bin/http $(CONF_DIR)
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 0000000..2bc0e1f
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,186 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base64.h"
+/****************************************************************
+20060905 lqy
+(1)mailsubject_base64_decode ��������������base64����,'='���ַ���ĩβ��
+ ����Ĵ���
+*****************************************************************
+20061130 LQY
+mime_base64_decode ��������������base64����,'='���ַ���ĩβ��
+ ����Ĵ���
+
+****************************************************************/
+/* The following diagram shows the logical steps by which three octets
+ get transformed into eight Base64 characters. It helps understanding
+ shifts and masks in the transformation functions.
+
+ .--------. .--------. .--------.
+ |aaaaaabb| |bbbbcccc| |ccdddddd|
+ `--------' `--------' `--------'
+ 6 2 4 4 2 6
+ .--------+--------+--------+--------.
+ |00aaaaaa|00bbbbbb|00cccccc|00dddddd|
+ `--------+--------+--------+--------'
+
+ .--------+--------+--------+--------.
+ |AAAAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|
+ `--------+--------+--------+--------'
+
+ The octets are divided into 6 bit chunks, which are then encoded into
+ Base64 characters. */
+
+/* Table of characters coding the 64 values. */
+char httpproxy_base64_value_to_char[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
+ 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
+ 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
+ '8', '9', '+', '/' /* 60-63 */
+};
+
+/* Table of base64 values for first 128 characters. */
+#define z -1
+int httpproxy_base64_char_to_value[128] =
+{
+ z, z, z, z, z, z, z, z, z, z, /* 0- 9 */
+ z, z, z, z, z, z, z, z, z, z, /* 10- 19 */
+ z, z, z, z, z, z, z, z, z, z, /* 20- 29 */
+ z, z, z, z, z, z, z, z, z, z, /* 30- 39 */
+ z, z, z, 62, z, z, z, 63, 52, 53, /* 40- 49 */
+ 54, 55, 56, 57, 58, 59, 60, 61, z, z, /* 50- 59 */
+ z, z, z, z, z, 0, 1, 2, 3, 4, /* 60- 69 */
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
+ 25, z, z, z, z, z, z, 26, 27, 28, /* 90- 99 */
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
+ 49, 50, 51, z, z, z, z, z /* 120-127 */
+};
+#undef z
+
+int http_proxy_base64_decode(int flag_quote,char *src_buf,int srclen, char *dest)
+{
+ unsigned long value=0;
+ char *temp=NULL;
+ char *inputend=NULL;
+ int result=0;
+ char *dst_buf=NULL;
+ int dst_len=0;
+
+ if(srclen==0)
+ {
+ return 0;
+ }
+
+
+ temp=src_buf;
+ inputend=src_buf+srclen;
+ dst_buf=dest;
+
+ if(flag_quote==1)
+ {
+
+ strcpy(dst_buf,"\"");
+ dst_len++;
+ }
+ else
+ {
+ strcpy(dst_buf,"");
+ }
+ while(temp<inputend)
+ {
+ if(*temp=='\n'||*temp=='\r')
+ {
+ temp=temp+1;
+ continue;
+ }
+ // process first byte of a quadruplet.
+ if(IS_BASE64(*temp))
+ value=httpproxy_base64_char_to_value[(int)*temp]<<18;
+ else
+ value=0;
+ temp=temp+1;
+ //process second byte of a quadruplet.
+ if(temp==inputend)
+ {
+ result=-1;
+ goto dowith;
+ }
+ else
+ {
+ if(IS_BASE64(*temp))
+ {
+ value|=httpproxy_base64_char_to_value[(int)*temp]<<12;
+ }
+ dst_buf[dst_len++]=(unsigned char)(value>>16);
+ dst_buf[dst_len]='\0';
+ }
+ temp=temp+1;
+ // process third byte of a quadruple
+ if(temp==inputend)
+ {
+ result=-1;
+ goto dowith;
+ }
+ else
+ {
+ if(*temp=='=')
+ {
+ temp=temp+1;
+ //add by lqy 060905
+ if(temp==inputend)
+ {
+ goto dowith;
+ }
+ temp=temp+1;
+ continue;
+ }
+ if(IS_BASE64(*temp))
+ {
+ value|=httpproxy_base64_char_to_value[(int)*temp]<<6;
+ }
+ dst_buf[dst_len++]=(unsigned char)(MASK(8)&(value>>8));
+ dst_buf[dst_len]='\0';
+ }
+ temp=temp+1;
+ if(temp==inputend)
+ {
+ result=-1;
+ goto dowith;
+ }
+ else
+ {
+ if(*temp=='=')
+ {
+ temp=temp+1;
+ continue;
+ }
+ if(IS_BASE64(*temp))
+ {
+ value|=httpproxy_base64_char_to_value[(int)*temp];
+ }
+ dst_buf[dst_len++]=(unsigned char)(MASK(8)&value);
+ dst_buf[dst_len]='\0';
+ }
+ temp=temp+1;
+ }
+
+ if(flag_quote==1)
+ {
+ strcat(dst_buf," \"");
+ }
+
+dowith:
+
+ return result;
+}
+
+
+
+
diff --git a/src/base64.d b/src/base64.d
new file mode 100644
index 0000000..4d6dade
--- /dev/null
+++ b/src/base64.d
@@ -0,0 +1 @@
+base64.o: base64.c base64.h
diff --git a/src/base64.h b/src/base64.h
new file mode 100644
index 0000000..ea0f5b2
--- /dev/null
+++ b/src/base64.h
@@ -0,0 +1,38 @@
+
+#ifndef H_HTTP_BASE64_H
+#define H_HTTP_BASE64_H
+
+
+/* Generate a mask of LENGTH one-bits, right justified in a word. */
+#define MASK(Length) ((unsigned) ~(~0 << (Length)))
+
+/* Indicate if CHARACTER holds into 7 bits. */
+#define IS_ASCII(Character) \
+ (!((Character) & ~MASK (7)))
+
+/* Maximum number of characters per MIME line. */
+#define MIME_LINE_LENGTH 76
+
+/* Tables declared in base64.c and also used in utf7.c. */
+extern char httpproxy_base64_value_to_char[64];
+extern int httpproxy_base64_char_to_value[128];
+extern char base64_charset[64];
+
+/* Macros. */
+#define IS_BASE64(Character) \
+ (IS_ASCII (Character) && httpproxy_base64_char_to_value[(int)(Character)] >= 0)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int http_proxy_base64_decode(int flag_quote,char *src_buf,int srclen, char *dest);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // H_MIME_BASE64_H
diff --git a/src/field_stat.cpp b/src/field_stat.cpp
new file mode 100644
index 0000000..2fc7920
--- /dev/null
+++ b/src/field_stat.cpp
@@ -0,0 +1,105 @@
+#include "field_stat.h"
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#define MAX_STAT_FIELD_NUM 256
+#define FIELD_PER_LINE 8
+struct stat_field_t
+{
+ char *filed_name;
+ long long current_value;
+ long long last_output_value;
+};
+struct screen_stat_space_t
+{
+ int stat_cycle;
+ int screen_print_trigger;
+ FILE* fp;
+ struct stat_field_t stat_array[MAX_STAT_FIELD_NUM];
+ int inuse_num;
+};
+void *thread_screen_print(void *arg)
+{
+ struct screen_stat_space_t* handle=(struct screen_stat_space_t*)arg;
+ int i=0,j=0;
+ long long differenc_valule;
+ time_t now;
+ char print_buf[1024*64]={0};
+ char*pos=NULL;
+ while(1)
+ {
+ now=time(NULL);
+ pos=print_buf;
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"=====================================================%s",ctime(&now));
+ while(i<handle->inuse_num)
+ {
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\t");
+ for(j=0;j<FIELD_PER_LINE&&i+j<handle->inuse_num;j++)
+ {
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"%10s\t",handle->stat_array[i+j].filed_name);
+ }
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\nsum\t");
+ for(j=0;j<FIELD_PER_LINE&&i+j<handle->inuse_num;j++)
+ {
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"%10lld\t",handle->stat_array[i+j].current_value);
+ }
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\nspeed/s\t");
+ for(j=0;j<FIELD_PER_LINE&&i+j<handle->inuse_num;j++)
+ {
+ differenc_valule=handle->stat_array[i+j].current_value-handle->stat_array[i+j].last_output_value;
+ handle->stat_array[i+j].last_output_value=handle->stat_array[i+j].current_value;
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"%10lld\t",differenc_valule/handle->stat_cycle);
+ }
+ i+=j;
+ pos+=snprintf(pos,sizeof(print_buf)-(pos-print_buf),"\n");
+ }
+ fprintf(handle->fp,"%s",print_buf);
+ i=0;
+ sleep(handle->stat_cycle);
+ }
+ return NULL;
+}
+screen_stat_handle_t init_screen_stat(FILE* output_fp,int stat_cycle,int screen_print_trigger)
+{
+ struct screen_stat_space_t* handle=(struct screen_stat_space_t*)calloc(sizeof(struct screen_stat_space_t),1);
+ handle->fp=output_fp;
+ handle->stat_cycle=stat_cycle;
+ handle->screen_print_trigger=screen_print_trigger;
+ pthread_t cfg_mon_t;
+ if(handle->screen_print_trigger==1)
+ {
+ pthread_create(&cfg_mon_t, NULL, thread_screen_print, (void*)handle);
+ }
+ return handle;
+}
+
+int stat_field_register(screen_stat_handle_t handle,const char* field_name)
+{
+ struct screen_stat_space_t* _handle=(struct screen_stat_space_t*)handle;
+ int idx=_handle->inuse_num++;
+ _handle->stat_array[idx].filed_name=(char*)calloc(strlen(field_name)+1,1);
+ memcpy(_handle->stat_array[idx].filed_name,field_name,strlen(field_name));
+ return idx;
+}
+
+int stat_field_operation(screen_stat_handle_t handle,int field_id,int operation,long long value)
+{
+ struct screen_stat_space_t* _handle=(struct screen_stat_space_t*)handle;
+ switch(operation)
+ {
+ case FS_OP_TYPE_ADD:
+ _handle->stat_array[field_id].current_value+=value;
+ break;
+ case FS_OP_TYPE_SET:
+ _handle->stat_array[field_id].current_value=value;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
+}
+
diff --git a/src/field_stat.h b/src/field_stat.h
new file mode 100644
index 0000000..630161b
--- /dev/null
+++ b/src/field_stat.h
@@ -0,0 +1,19 @@
+#ifndef H_SCREEN_STAT_H_INCLUDE
+#define H_SCREEN_STAT_H_INCLUDE
+#include <stdio.h>
+
+typedef void* screen_stat_handle_t;
+
+
+screen_stat_handle_t init_screen_stat(FILE* output_fp,int stat_cycle,int screen_print_trigger);
+
+//return field_id >=0 when success, return -1 when failed.
+int stat_field_register(screen_stat_handle_t handle,const char* field_name);
+
+//return >=0 when success, return -1 when failed.
+#define FS_OP_TYPE_ADD 1
+#define FS_OP_TYPE_SET 2
+int stat_field_operation(screen_stat_handle_t handle,int field_id,int operation,long long value);
+
+#endif
+
diff --git a/src/http.h b/src/http.h
new file mode 100644
index 0000000..85c5071
--- /dev/null
+++ b/src/http.h
@@ -0,0 +1,235 @@
+#ifndef HTTP_H_
+#define HTTP_H_
+
+#define HTTP_H_VERSION_4_20160905 0
+//#define HTTP_H_VERSION_3_20150320 0
+//20160905 add http_line2region
+
+#ifndef uchar
+typedef unsigned char uchar;
+#endif
+#ifndef int64
+typedef long long int64;
+#endif
+#ifndef uint8
+typedef unsigned char uint8;
+#endif
+#ifndef uint64
+typedef unsigned long long uint64;
+#endif
+#ifndef uint32
+typedef unsigned int uint32;
+#endif
+#ifndef uint16
+typedef unsigned short uint16;
+#endif
+
+/*interest region*/
+typedef enum
+{
+ /*#http_special1*/
+ HTTP_INTEREST_KEY_MASK=0,
+ HTTP_ALL_MASK,
+ HTTP_OTHER_REGIONS_MASK,
+ HTTP_STATE_MASK,
+ HTTP_REQ_LINE_MASK,
+ HTTP_RES_LINE_MASK,
+ HTTP_CONTENT_MASK,
+ HTTP_UNGZIP_CONTENT_MASK,
+ HTTP_MESSAGE_URL_MASK,
+ HTTP_URI_MASK,
+
+ /*#http_request*/
+ HTTP_HOST_MASK,
+ HTTP_REFERER_MASK,
+ HTTP_USER_AGENT_MASK,
+ HTTP_COOKIE_MASK,
+ HTTP_PROXY_AUTHORIZATION_MASK,
+ HTTP_AUTHORIZATION_MASK,
+
+ /*#http_response*/
+ HTTP_LOCATION_MASK,
+ HTTP_SERVER_MASK,
+ HTTP_ETAG_MASK,
+
+ /*#http_general*/
+ HTTP_DATE_MASK,
+ HTTP_TRAILER_MASK,
+ HTTP_TRANSFER_ENCODING_MASK,
+ HTTP_VIA_MASK,
+ HTTP_PRAGMA_MASK,
+ HTTP_CONNECTION_MASK,
+
+ /*#http_content*/
+ HTTP_CONT_ENCODING_MASK,
+ HTTP_CONT_LANGUAGE_MASK,
+ HTTP_CONT_LOCATION_MASK,
+ HTTP_CONT_DISPOSITION_MASK,
+ HTTP_CONT_RANGE_MASK,
+ HTTP_CONT_LENGTH_MASK,
+ HTTP_CONT_TYPE_MASK,
+ HTTP_CHARSET_MASK,
+ HTTP_EXPIRES_MASK,
+ HTTP_X_FLASH_VERSION_MASK,
+ HTTP_TRANSFER_LENGTH_MASK,
+
+ HTTP_REGION_NUM=36,
+}interested_region_mask;
+/*HTTP_REGION_NUM=36*/
+#define HTTP_INTEREST_KEY ((long long)1<<HTTP_INTEREST_KEY_MASK)
+#define HTTP_ALL ((long long)1<<HTTP_ALL_MASK)
+#define HTTP_OTHER_REGIONS ((long long)1<<HTTP_OTHER_REGIONS_MASK)
+#define HTTP_STATE ((long long)1<<HTTP_STATE_MASK)
+#define HTTP_REQ_LINE ((long long)1<<HTTP_REQ_LINE_MASK)
+#define HTTP_RES_LINE ((long long)1<<HTTP_RES_LINE_MASK)
+#define HTTP_CONTENT ((long long)1<<HTTP_CONTENT_MASK)
+#define HTTP_UNGZIP_CONTENT ((long long)1<<HTTP_UNGZIP_CONTENT_MASK)
+#define HTTP_MESSAGE_URL ((long long)1<<HTTP_MESSAGE_URL_MASK)
+#define HTTP_URI ((long long)1<<HTTP_URI_MASK)
+
+#define HTTP_HOST ((long long)1<<HTTP_HOST_MASK)
+#define HTTP_REFERER ((long long)1<<HTTP_REFERER_MASK)
+#define HTTP_USER_AGENT ((long long)1<<HTTP_USER_AGENT_MASK)
+#define HTTP_COOKIE ((long long)1<<HTTP_COOKIE_MASK)
+#define HTTP_PROXY_AUTHORIZATION ((long long)1<<HTTP_PROXY_AUTHORIZATION_MASK)
+#define HTTP_AUTHORIZATION ((long long)1<<HTTP_AUTHORIZATION_MASK)
+
+#define HTTP_LOCATION ((long long)1<<HTTP_LOCATION_MASK)
+#define HTTP_SERVER ((long long)1<<HTTP_SERVER_MASK)
+#define HTTP_ETAG ((long long)1<<HTTP_ETAG_MASK)
+
+#define HTTP_DATE ((long long)1<<HTTP_DATE_MASK)
+#define HTTP_TRAILER ((long long)1<<HTTP_TRAILER_MASK)
+#define HTTP_TRANSFER_ENCODING ((long long)1<<HTTP_TRANSFER_ENCODING_MASK)
+#define HTTP_VIA ((long long)1<<HTTP_VIA_MASK)
+#define HTTP_PRAGMA ((long long)1<<HTTP_PRAGMA_MASK)
+#define HTTP_CONNECTION ((long long)1<<HTTP_CONNECTION_MASK)
+
+#define HTTP_CONT_ENCODING ((long long)1<<HTTP_CONT_ENCODING_MASK)
+#define HTTP_CONT_LANGUAGE ((long long)1<<HTTP_CONT_LANGUAGE_MASK)
+#define HTTP_CONT_LOCATION ((long long)1<<HTTP_CONT_LOCATION_MASK)
+#define HTTP_CONT_RANGE ((long long)1<<HTTP_CONT_RANGE_MASK)
+#define HTTP_CONT_LENGTH ((long long)1<<HTTP_CONT_LENGTH_MASK)
+#define HTTP_CONT_TYPE ((long long)1<<HTTP_CONT_TYPE_MASK)
+#define HTTP_CONT_DISPOSITION ((long long)1<<HTTP_CONT_DISPOSITION_MASK)
+#define HTTP_CHARSET ((long long)1<<HTTP_CHARSET_MASK)
+#define HTTP_EXPIRES ((long long)1<<HTTP_EXPIRES_MASK)
+#define HTTP_X_FLASH_VERSION ((long long)1<<HTTP_X_FLASH_VERSION_MASK)
+#define HTTP_TRANSFER_LENGTH ((long long)1<<HTTP_TRANSFER_LENGTH_MASK)
+
+/*http_state*/
+#define HTTP_STATE_UNKNOWN 0x00
+#define HTTP_START_LINE 0x01 /*start line over*/
+#define HTTP_REGION 0x02
+#define HTTP_DATA_BEGIN 0x03 /*header over*/
+#define HTTP_DATA 0x04 /*have entity*/
+#define HTTP_DATA_END 0x05
+
+/*���ݱ��뷽ʽcont_encoding*/
+#define HTTP_CONT_ENCOD_UNKNOWN 0X00//��ʼ״̬
+#define HTTP_CONT_ENCOD_DEFAULT 0X01
+#define HTTP_CONT_ENCOD_GZIP 0X02
+#define HTTP_CONT_ENCOD_COMPRESS 0X03
+#define HTTP_CONT_ENCOD_DEFLATE 0X04
+#define HTTP_CONT_ENCOD_OTHERS 0X05
+
+/*������뷽ʽtran_encoding*/
+#define HTTP_TRANS_ENCOD_UNKNOWN 0X00//��ʼ״̬
+#define HTTP_TRANS_ENCOD_CHUNKED 0X01//chunked����13
+#define HTTP_TRANS_ENCOD_DEFAULT 0X02//default
+#define HTTP_TRANS_ENCOD_OTHERS 0X03//����״̬
+
+/*���󷽷�method*/
+#define HTTP_METHOD_UNKNOWN 0X00//��ʼ״̬
+#define HTTP_METHOD_GET 0X01
+#define HTTP_METHOD_POST 0X02
+#define HTTP_METHOD_CONNECT 0X03
+#define HTTP_METHOD_HEAD 0X04
+#define HTTP_METHOD_PUT 0X05
+#define HTTP_METHOD_OPTIONS 0X06
+#define HTTP_METHOD_DELETE 0X07
+#define HTTP_METHOD_TRACE 0X08
+
+typedef struct _cont_range_t
+{
+ uint64 start;
+ uint64 end;
+ uint64 len;
+}cont_range_t;
+
+typedef struct _append_infor_t
+{
+ char* content; //data: origin data when ungzip; region:all complete line when enpand region
+ uint32 contlen;
+}append_infor_t;
+
+typedef struct _region_t
+{
+ char* pdata;
+ uint32 datalen;
+}region_t;
+
+typedef struct _field_infor_t
+{
+ long long prot_flag; //��ǰ�ֶ�flag
+ void* buf; //��ǰ����֮����ֶ�
+ void* src_buf; //��չ�ֶ�ָ�������У�����ָ��ԭʼ����(��ѹ��֮ǰ����ͬ�Ľ������Խ���)
+ int buflen; //��ǰ�ֶγ���
+ int src_buflen; //��ǰ�ֶγ���
+}field_infor_t;
+
+typedef struct _batch_infor_t
+{
+ int field_cnt; //���������ֶ���Ŀ
+ field_infor_t* field; //�ֶ���Ϣ��stFieldInfo
+}batch_infor_t;
+
+typedef struct http_infor_t
+{
+ char* p_url;
+ uint32 url_len;
+ int http_session_seq;
+ uint64 cont_length;
+ cont_range_t* cont_range;
+
+ uchar curdir;
+ uchar http_state;
+ uchar cont_encoding;
+ uchar trans_encoding;
+
+ uchar method;
+ uchar _pad_;
+ uint16 res_code;
+ append_infor_t append_infor;
+ batch_infor_t* batch_infor;
+}http_infor;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+*����������(key:value)���key ��key_len
+*����ֵ0�ɹ���-1:ʧ��
+*_key_:_value,ֻ����key
+*/
+int http_line2region(const char *line, uint32 line_len, char** region, uint32* region_len);
+/*
+* �����ֶ�����region ����ֶε�proto_flag
+* region : ������host (in pcap)��Ҳ������HTTP_HOST(in http.conf)
+*/
+long long http_region2proto_flag(const char *region, uint32 region_len);
+/*
+*����proto_flag����ֶ�����
+*����ֵ��http.conf�е��ַ���
+*/
+const char* http_proto_flag2region(long long proto_flag);
+const char* http_get_method(uchar method);
+char* http_url_decode(char *data, int* data_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/src/http_global.map b/src/http_global.map
new file mode 100644
index 0000000..e72f54f
--- /dev/null
+++ b/src/http_global.map
@@ -0,0 +1,16 @@
+{
+global:
+ HTTP_INIT;
+ HTTP_ENTRY;
+ HTTP_DESTROY;
+ HTTP_FLAG_CHANGE;
+ HTTP_PROT_FUNSTAT;
+ HTTP_GETPLUGID;
+ http_line2region;
+ http_region2proto_flag;
+ http_proto_flag2region;
+ http_get_method;
+ http_url_decode;
+local: *;
+};
+