#include #include #include #include #include #include #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" static int g_iThreadNum = 1; 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 is_absolute_uri(void* app_info) { return ((http_infor*)app_info)->is_ab_uri; } 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; } int http_line2value(const char *line, uint32 line_len, char** value, uint32* value_len) { /*line来自业务层,即append,所以line前面的空格已经删除,只需要删除: 之后的空格*/ uint32 vlen=0, sp_offset=0; char* colon_pos = (char*)memchr(line, ':', line_len); if(NULL==colon_pos) return -1; vlen = line_len - (colon_pos - line + 1); http_deleteEmptyRow(&sp_offset, colon_pos+1, vlen); *value = colon_pos+1+sp_offset; *value_len = vlen-sp_offset; 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) { *q++ = *p++; break; } 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; } */ #define li_cton(c,n) \ (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) char hex2int(unsigned char hex) { unsigned char n; return li_cton(hex,n) ? (char)n : 0xFF; } char* http_url_decode(char* url, int *len) { if(url == NULL || *len <= 0) return 0; const char *ptr = url; char *src =(char*)memchr(url, '%', *len); if (NULL == src) return 0; char *dst = src; do { /* *src == '%' */ unsigned char high = ((unsigned char *)src)[1]; unsigned char low = high ? hex2int(((unsigned char *)src)[2]) : 0xFF; if (0xFF != (high = hex2int(high)) && 0xFF != low) { high = (high << 4) | low; /* map ctrls to '_' */ *dst = (high >= 32 && high != 127) ? high : '_'; src += 2; } /* else ignore this '%'; leave as-is and move on */ while ((*++dst = *++src) != '%' && *src) ; } while (*src); *len = (dst - ptr) + 1; return url; } 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 { int i=0; for(i=0;i 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"); MESA_load_profile_short_def(filename, "FUNCTION", "s2c_head_check_switch", (short*)&g_http_prog_para.s2c_head_check_switch,0); return 0; } void http_proto_tag_free(int thread_seq, void *value) { if(value!=NULL) { dictator_free(thread_seq, value); value=NULL; } return; } int http_add_proto_tag(int projetc_id, struct streaminfo *a_stream, const char* value, int len) { if(projetc_id < 0)return -1; struct http_proto_tag_t* proto_tag = (struct http_proto_tag_t*)project_req_get_struct(a_stream,projetc_id); if(proto_tag == NULL) { proto_tag = (struct http_proto_tag_t *)dictator_malloc(a_stream->threadnum, sizeof(struct http_proto_tag_t)); if(0 != project_req_add_struct(a_stream, projetc_id, proto_tag)) { dictator_free(a_stream->threadnum, proto_tag); return -1; } } memcpy(proto_tag->buf, value, len); proto_tag->buf[len]='\0'; return 0; } int HTTP_INIT(void) { g_iThreadNum = get_thread_count(); 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; } /*MESA_proto*/ g_http_prog_para.proto_tag_id = project_producer_register("MESA_PROTO","struct",http_proto_tag_free); #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)<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_r0 && !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;ipbuf = (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:当前数据的长度。 ***********************************************************/ 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_BUFLENbuflen) { 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; } }