diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/HTTP_Analyze.c | 1226 | ||||
| -rw-r--r-- | src/HTTP_Analyze.h | 60 | ||||
| -rw-r--r-- | src/HTTP_Common.c | 269 | ||||
| -rw-r--r-- | src/HTTP_Common.h | 31 | ||||
| -rw-r--r-- | src/HTTP_Message.c | 1098 | ||||
| -rw-r--r-- | src/HTTP_Message.h | 246 | ||||
| -rw-r--r-- | src/HTTP_Message_Entry.c | 607 | ||||
| -rw-r--r-- | src/HTTP_Message_Entry.h | 17 | ||||
| -rw-r--r-- | src/HTTP_Message_Header.c | 872 | ||||
| -rw-r--r-- | src/HTTP_Message_Header.h | 44 | ||||
| -rw-r--r-- | src/HTTP_Message_Region.c | 767 | ||||
| -rw-r--r-- | src/HTTP_Message_Region.h | 23 | ||||
| -rw-r--r-- | src/Makefile | 64 | ||||
| -rw-r--r-- | src/base64.c | 186 | ||||
| -rw-r--r-- | src/base64.d | 1 | ||||
| -rw-r--r-- | src/base64.h | 38 | ||||
| -rw-r--r-- | src/field_stat.cpp | 105 | ||||
| -rw-r--r-- | src/field_stat.h | 19 | ||||
| -rw-r--r-- | src/http.h | 235 | ||||
| -rw-r--r-- | src/http_global.map | 16 |
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", ®ion_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: *; +}; + |
