diff options
| author | lishu <[email protected]> | 2018-12-05 19:26:56 +0800 |
|---|---|---|
| committer | lishu <[email protected]> | 2018-12-05 19:26:56 +0800 |
| commit | fe846caaa5a0fbfa417fba266b6192ae4c13aec0 (patch) | |
| tree | 42681bdd020f9ff7fb9954de9942d62b0c91beb7 /src/HTTP_Message_Entry.c | |
create http project
Diffstat (limited to 'src/HTTP_Message_Entry.c')
| -rw-r--r-- | src/HTTP_Message_Entry.c | 607 |
1 files changed, 607 insertions, 0 deletions
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; +} |
