diff --git a/conf/pangu/pangu_pxy.conf b/conf/pangu/pangu_pxy.conf index 4b60256..edbe3cc 100644 --- a/conf/pangu/pangu_pxy.conf +++ b/conf/pangu/pangu_pxy.conf @@ -5,6 +5,7 @@ log_level=10 nic_name=eth4 entrance_id=0 kafka_brokerlist=10.4.34.10:9092,10.4.34.11:9092,10.4.34.12:9092,10.4.34.13:9092,10.4.34.14:9092,10.4.34.15:9092,10.4.34.16:9092,10.4.34.17:9092,10.4.34.18:9092,10.4.34.19:9092 +kafka_topic=policy-event-log #Addresses of minio. Format is defined by WiredLB. minio_ip_list=10.4.35.42-46; minio_listen_port=9000 diff --git a/plugin/business/pangu-http/src/pangu_http.cpp b/plugin/business/pangu-http/src/pangu_http.cpp index 3097386..5e95515 100644 --- a/plugin/business/pangu-http/src/pangu_http.cpp +++ b/plugin/business/pangu-http/src/pangu_http.cpp @@ -667,16 +667,10 @@ void ma_hijack_profile_table_new_cb(int table_id, const char* key, const char* t return; } struct manipulate_profile* ply_profile=ALLOC(struct manipulate_profile, 1); - memset(ply_profile, 0, sizeof(struct manipulate_profile)); - - ply_profile->profile_id=profile_id; ply_profile->ref_cnt=1; - ply_profile->profile_msg = execute_read_file(profile_path, &ply_profile->msg_len); - if (ply_profile->profile_msg == NULL) - { - TFE_LOG_ERROR(g_pangu_rt->local_logger, "Read file failed %d:%s:%s", profile_id, profile_name, profile_path); - } + ply_profile->profile_id=profile_id; + ply_profile->profile_msg=tfe_strdup(profile_path); ply_profile->profile_name=tfe_strdup(hijack_name); ply_profile->profile_type=tfe_strdup(formate); @@ -734,6 +728,7 @@ int maat_table_ex_init(int profile_idx, Maat_plugin_EX_dup_func_t* dup_func) { int table_id = 0; + const char *table_name_map[] = {"PXY_PROFILE_RESPONSE_PAGES", "PXY_PROFILE_INSERT_SCRIPTS", "PXY_PROFILE_HIJACK_FILES"}; @@ -1195,7 +1190,15 @@ static void template_generate(int status_code, int cfg_id, const char* msg, char { ctemplate::TemplateDictionary dict("pg_page_dict"); //dict is automatically finalized after function returned. dict.SetIntValue("cfg_id", cfg_id); - dict.SetValue("msg", msg); + + if (NULL == msg) + { + dict.SetValue("msg", "NULL"); + } + else + { + dict.SetValue("msg", msg); + } std::string output; ctemplate::Template * tpl = NULL; @@ -1378,7 +1381,6 @@ void http_replace(const struct tfe_stream * stream, const struct tfe_http_sessio rewrite_sz = execute_replace_rule(__http_body, __http_body_len, r_zone, rep_ctx->rule, rep_ctx->n_rule, &rewrite_buff); - if (rewrite_sz >0 ) { tfe_http_half_append_body(rep_ctx->replacing, rewrite_buff, rewrite_sz, 0); @@ -1425,7 +1427,7 @@ static void http_reject(const struct tfe_http_session * session, enum tfe_http_e resp_code = param->status_code; msg = param->message; - if (resp_code <= 0 || msg != NULL){ + if (resp_code <= 0){ TFE_LOG_ERROR(g_pangu_rt->local_logger, "Invalid block rule %d", ctx->enforce_rules[0].config_id); ctx->action = PG_ACTION_NONE; return; @@ -1564,22 +1566,35 @@ static void http_hijack(const struct tfe_http_session * session, enum tfe_http_e return; } + char * hijack_buff=NULL; size_t hijack_size=0; + + hijack_buff = execute_read_file(hijack_profile->profile_msg, &hijack_size); + if (NULL == hijack_buff){ + TFE_LOG_ERROR(g_pangu_rt->local_logger, "read hijack file faild, path = %s", hijack_profile->profile_msg); + ctx->action = PG_ACTION_NONE; + return; + } + struct tfe_http_session * to_write_sess = NULL; char cont_len_str[16]; to_write_sess = tfe_http_session_allow_write(session); response = tfe_http_session_response_create(to_write_sess, 200); - int hijack_len = strlen(hijack_profile->profile_name)+strlen("filename=\"\"")+1; - char *hijack_name = ALLOC(char, hijack_len); - snprintf(hijack_name, hijack_len, "filename=\"%s\"", hijack_profile->profile_name); - tfe_http_nonstd_field_write(response, "Content-Disposition", hijack_name); - FREE(&hijack_name); + if (0!=strcasecmp(hijack_profile->profile_name, "null")) + { + int hijack_file_len = strlen(hijack_profile->profile_name)+strlen("filename=\"\"")+1; + char *hijack_file_name = ALLOC(char, hijack_file_len); + snprintf(hijack_file_name, hijack_file_len, "filename=\"%s\"", hijack_profile->profile_name); + tfe_http_nonstd_field_write(response, "Content-Disposition", hijack_file_name); + FREE(&hijack_file_name); + } + tfe_http_std_field_write(response, TFE_HTTP_CONT_TYPE, hijack_profile->profile_type); - snprintf(cont_len_str, sizeof(cont_len_str), "%lu", hijack_profile->msg_len); + snprintf(cont_len_str, sizeof(cont_len_str), "%lu", hijack_size); tfe_http_std_field_write(response, TFE_HTTP_CONT_LENGTH, cont_len_str); - tfe_http_half_append_body(response, hijack_profile->profile_msg, hijack_profile->msg_len, 0); + tfe_http_half_append_body(response, hijack_buff, hijack_size, 0); tfe_http_half_append_body(response, NULL, 0, 0); tfe_http_session_response_set(to_write_sess, response); tfe_http_session_detach(session); @@ -1638,7 +1653,7 @@ static void http_insert(const struct tfe_stream * stream, const struct tfe_http_ int ret=format_insert_rule(param->profile_id, param->position, ins_ctx->rule); if (ret<0) { - TFE_LOG_ERROR(g_pangu_rt->local_logger, "Failed to get policy table, table_id = %d", param->profile_id); + TFE_LOG_ERROR(g_pangu_rt->local_logger, "Failed to get policy table, profile_id = %d", param->profile_id); ctx->action = PG_ACTION_NONE; return; } diff --git a/plugin/business/pangu-http/src/pangu_logger.cpp b/plugin/business/pangu-http/src/pangu_logger.cpp index 4ba4f93..8d9f087 100644 --- a/plugin/business/pangu-http/src/pangu_logger.cpp +++ b/plugin/business/pangu-http/src/pangu_logger.cpp @@ -31,14 +31,14 @@ struct pangu_logger unsigned int en_sendlog; unsigned int en_sendlog_meta; unsigned int en_sendlog_body; - + unsigned int local_ip_nr; void* global_logger; rd_kafka_t *kafka_handle; rd_kafka_topic_t* kafka_topic; pthread_mutex_t mutex; char brokerlist[TFE_STRING_MAX]; - const char* topic_name; + char topic_name[TFE_STRING_MAX]; void* local_logger; @@ -56,7 +56,7 @@ static unsigned int get_ip_by_eth_name(const char *ifname) unsigned int ip; sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (-1 == sockfd) + if (-1 == sockfd) { goto error; } @@ -81,7 +81,7 @@ error: static rd_kafka_t * create_kafka_handle(const char* brokerlist) { char kafka_errstr[1024]; - rd_kafka_t *handle=NULL; + rd_kafka_t *handle=NULL; rd_kafka_conf_t *rdkafka_conf = NULL; rdkafka_conf = rd_kafka_conf_new(); @@ -133,7 +133,7 @@ struct pangu_logger* pangu_log_handle_create(const char* profile, const char* s { return instance; } - + MESA_load_profile_string_def(profile, section, "NIC_NAME",nic_name,sizeof(nic_name),"eth0"); instance->local_ip_nr=get_ip_by_eth_name(nic_name); if(instance->local_ip_nr==INADDR_NONE) @@ -143,7 +143,7 @@ struct pangu_logger* pangu_log_handle_create(const char* profile, const char* s } inet_ntop(AF_INET,&(instance->local_ip_nr),instance->local_ip_str,sizeof(instance->local_ip_str)); - + MESA_load_profile_int_def(profile, section, "ENTRANCE_ID",&(instance->entry_id),0); ret=MESA_load_profile_string_def(profile, section,"KAFKA_BROKERLIST", instance->brokerlist, sizeof(instance->brokerlist), NULL); if(ret<0) @@ -155,17 +155,21 @@ struct pangu_logger* pangu_log_handle_create(const char* profile, const char* s instance->kafka_handle=create_kafka_handle(instance->brokerlist); if(instance->kafka_handle==NULL) { - TFE_LOG_ERROR(local_logger,"Pangu log init failed. Cannot create lafka handle with brokerlist: %s.", instance->brokerlist); + TFE_LOG_ERROR(local_logger,"Pangu log init failed. Cannot create lafka handle with brokerlist: %s.", instance->brokerlist); goto error_out; } - instance->topic_name="PXY-HTTP-LOG"; + MESA_load_profile_string_def(profile, section,"KAFKA_TOPIC", instance->topic_name, sizeof(instance->topic_name), "POLICY-EVENT-LOG"); + + TFE_LOG_INFO(local_logger, "Pangu kafka brokerlist : %s", instance->brokerlist); + TFE_LOG_INFO(local_logger, "Pangu kafka topic : %s", instance->topic_name); + instance->kafka_topic = rd_kafka_topic_new(instance->kafka_handle,instance->topic_name, NULL); log_file_upload_para=cache_evbase_parameter_new(profile, section, local_logger); instance->log_file_upload_instance=cache_evbase_instance_new(log_file_upload_para, local_logger); pthread_mutex_init(&(instance->mutex), NULL); return instance; - + error_out: free(instance); return NULL; @@ -185,11 +189,12 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) char src_ip_str[MAX(INET6_ADDRSTRLEN,INET_ADDRSTRLEN)] = {0}; char dst_ip_str[MAX(INET6_ADDRSTRLEN,INET_ADDRSTRLEN)] = {0}; + const char *app_proto[]= {"unkonw","http1.0", "http2.0"}; - struct json_spec req_fields[]={ {"cookie", TFE_HTTP_COOKIE}, + struct json_spec req_fields[]={ {"cookie", TFE_HTTP_COOKIE}, {"referer", TFE_HTTP_REFERER}, {"user_agent", TFE_HTTP_USER_AGENT} }; - + struct json_spec resp_fields[]={ {"content_type", TFE_HTTP_CONT_TYPE}, {"content_len", TFE_HTTP_CONT_LENGTH} }; @@ -203,7 +208,7 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) cJSON_AddNumberToObject(common_obj, "start_time", cur_time); cJSON_AddNumberToObject(common_obj, "end_time", cur_time); - cJSON_AddNumberToObject(common_obj, "recv_time", cur_time); + cJSON_AddStringToObject(common_obj, "app_proto", app_proto[http->major_version]); switch(addr->addrtype) { @@ -231,11 +236,13 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) break; } cJSON_AddNumberToObject(common_obj, "direction", 0); //0:域内->域外,1:域外->域内,描述的是CLIENT_IP信息 + cJSON_AddNumberToObject(common_obj, "Link_id", 0); cJSON_AddNumberToObject(common_obj, "stream_dir", 3); //1:c2s, 2:s2c, 3:double cJSON_AddStringToObject(common_obj, "cap_ip", handle->local_ip_str); cJSON_AddNumberToObject(common_obj, "entrance_id", handle->entry_id); cJSON_AddNumberToObject(common_obj, "device_id", 0); cJSON_AddStringToObject(common_obj, "url", http->req->req_spec.url); + cJSON_AddStringToObject(common_obj, "host", http->req->req_spec.host); for(size_t i=0;ireq, req_fields[i].field_id); @@ -267,9 +274,9 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) snprintf(cont_type_whole, sizeof(cont_type_whole), "Content-Type:%s", cont_type_val); meta.std_hdr[0]=cont_type_whole; } - tmp=cache_evbase_upload_once_evbuf(handle->log_file_upload_instance, NULL, - log_msg->req_body, - &meta, + tmp=cache_evbase_upload_once_evbuf(handle->log_file_upload_instance, NULL, + log_msg->req_body, + &meta, log_file_upload_path, sizeof(log_file_upload_path)); if(tmp==0) { @@ -292,9 +299,9 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) snprintf(cont_type_whole, sizeof(cont_type_whole), "Content-Type:%s", cont_type_val); meta.std_hdr[0]=cont_type_whole; } - tmp=cache_evbase_upload_once_evbuf(handle->log_file_upload_instance, NULL, - log_msg->resp_body, - &meta, + tmp=cache_evbase_upload_once_evbuf(handle->log_file_upload_instance, NULL, + log_msg->resp_body, + &meta, log_file_upload_path, sizeof(log_file_upload_path)); if(tmp==0) @@ -311,7 +318,7 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) for(size_t i=0; iresult_num; i++) { - + TFE_LOG_DEBUG(handle->local_logger, "URL: %s , hit cfg_id: %d service: %d", http->req->req_spec.url, log_msg->result[i].config_id, @@ -330,7 +337,7 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) TFE_LOG_DEBUG(handle->local_logger, "%s", log_payload); - kafka_status = rd_kafka_produce(handle->kafka_topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, + kafka_status = rd_kafka_produce(handle->kafka_topic, RD_KAFKA_PARTITION_UA, RD_KAFKA_MSG_F_COPY, log_payload, strlen(log_payload), NULL, 0, NULL); free(log_payload); cJSON_Delete(per_hit_obj); @@ -339,7 +346,7 @@ int pangu_send_log(struct pangu_logger* handle, const struct pangu_log* log_msg) TFE_LOG_ERROR(handle->local_logger, "Kafka produce failed: %s", rd_kafka_err2name(rd_kafka_last_error())); } send_cnt++; - } + } cJSON_Delete(common_obj); return send_cnt; diff --git a/plugin/business/pangu-http/src/test_pattern_replace.cpp b/plugin/business/pangu-http/src/test_pattern_replace.cpp index 5017ee5..23638a9 100644 --- a/plugin/business/pangu-http/src/test_pattern_replace.cpp +++ b/plugin/business/pangu-http/src/test_pattern_replace.cpp @@ -152,7 +152,44 @@ TEST(PatternReplace, CaseInsensitiveRussian) EXPECT_TRUE(output_sz>0); EXPECT_TRUE(NULL==strstr(output, find)); EXPECT_TRUE(NULL!=strstr(output, replacement)); - + + free(output); + return; +} + +TEST(PatternReplace, QueryAdd) +{ + const char * find = "(?<=\\?|^|&)q=([^&|^#]*)(?=&|$)"; + const char* replacement="q=find"; + const char* input="https://cn.bing.com/search?ei=pQnxXPS-LPSGr7wP3u6usAY&q=test&oq=test&gs_l=psy-ab.3..0i131i67j0l8j0i131.26791.27227..27885...0.0..0.235.683.0j3j1......0....1..gws-wiz.......0i71j0i67.klHdqBPS88k"; + char* output=NULL; + size_t output_sz=0; + + simple_replace(find, replacement, input, strlen(input),&output, &output_sz); + EXPECT_TRUE(output_sz>0); + EXPECT_TRUE(NULL==strstr(output, find)); + EXPECT_TRUE(NULL!=strstr(output, replacement)); + + printf("%s\n", output); + free(output); + return; +} + +TEST(PatternReplace, QueryDel) +{ + const char * find = "(?<=\\?|^|&)sk=([^&|^#]*)(&|$)"; + const char* replacement=""; + const char* input="https://cn.bing.com/&search?q=find&qs=n&form=QBLH&sp=-1&pq=find&sk="; + + char* output=NULL; + size_t output_sz=0; + + simple_replace(find, replacement, input, strlen(input),&output, &output_sz); + EXPECT_TRUE(output_sz>0); + EXPECT_TRUE(NULL==strstr(output, find)); + EXPECT_TRUE(NULL!=strstr(output, replacement)); + + printf("%s\n", output); free(output); return; } diff --git a/plugin/business/ssl-policy/src/ssl_policy.cpp b/plugin/business/ssl-policy/src/ssl_policy.cpp index ff414fe..8653d5d 100644 --- a/plugin/business/ssl-policy/src/ssl_policy.cpp +++ b/plugin/business/ssl-policy/src/ssl_policy.cpp @@ -184,7 +184,7 @@ enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_p param=(struct intercept_param *)Maat_plugin_get_EX_data(enforcer->maat, enforcer->table_id, policy_id_str); if(param==NULL) { - TFE_LOG_INFO(enforcer->logger, "Failed to get intercept parameter of policy %d.", param->policy_id); + TFE_LOG_INFO(enforcer->logger, "Failed to get intercept parameter of policy %d.", policy_id); return SSL_ACTION_PASSTHROUGH; } int pinning_staus=0, is_ev=0, is_ct=0, is_mauth=0, has_error=0; diff --git a/plugin/protocol/http2/include/internal/http2_stream.h b/plugin/protocol/http2/include/internal/http2_stream.h index 3882d08..2de2ce6 100644 --- a/plugin/protocol/http2/include/internal/http2_stream.h +++ b/plugin/protocol/http2/include/internal/http2_stream.h @@ -59,7 +59,7 @@ struct tfe_h2_half_private int by_stream; char * url_storage; - struct tfe_h2_payload body; + struct tfe_h2_payload h2_payload; struct tfe_h2_header header; struct tfe_h2_header promised; diff --git a/plugin/protocol/http2/src/http2_stream.cpp b/plugin/protocol/http2/src/http2_stream.cpp index 7ebc7db..30eaa25 100644 --- a/plugin/protocol/http2/src/http2_stream.cpp +++ b/plugin/protocol/http2/src/http2_stream.cpp @@ -113,7 +113,7 @@ TAILQ_LIST_FIND(struct tfe_h2_stream *h2_stream_info, int32_t stream_id) return stream; } -static void +static void tfe_h2_header_add_field(struct tfe_h2_header *h2_header, const struct http_field_name * field, const char * value, int at_tail) { struct tfe_h2_field *peer_h2_field = ALLOC(struct tfe_h2_field, 1); @@ -137,6 +137,32 @@ tfe_h2_header_add_field(struct tfe_h2_header *h2_header, const struct http_field TAILQ_INSERT_HEAD(&h2_header->h2_field_list, peer_h2_field, next); } +static nghttp2_nv* +tfe_h2_header_modify_field(struct tfe_h2_header *header, nghttp2_nv *hdrs, const char *field_name, const char *filed_value) +{ + int nvlen = 0; + struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; + + TAILQ_FOREACH_SAFE(h2_field, &header->h2_field_list, next, peer_h2_field) + { + hdrs[nvlen].name = h2_field->nv.name; + hdrs[nvlen].namelen = h2_field->nv.namelen; + if (filed_value && (0==strcasecmp((const char*)h2_field->nv.name, field_name))) + { + hdrs[nvlen].value = (uint8_t *)filed_value; + hdrs[nvlen].valuelen = strlen(filed_value); + } + else + { + hdrs[nvlen].value = h2_field->nv.value; + hdrs[nvlen].valuelen = h2_field->nv.valuelen; + } + hdrs[nvlen].flags = h2_field->nv.flags; + nvlen++; + } + return hdrs; +} + static inline void headers_init(struct tfe_h2_header *header) { @@ -169,12 +195,12 @@ method_to_str_idx(const char * method) } static nghttp2_nv* -nghttp2_nv_packet(struct tfe_h2_header *header, nghttp2_nv *hdrs) +tfe_h2_header_convert_nv(struct tfe_h2_header *header, nghttp2_nv *hdrs) { int nvlen = 0; - struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; + struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; - TAILQ_FOREACH_SAFE(h2_field, &header->h2_field_list, next, peer_h2_field){ + TAILQ_FOREACH_SAFE(h2_field, &header->h2_field_list, next, peer_h2_field){ hdrs[nvlen].name = h2_field->nv.name; hdrs[nvlen].namelen = h2_field->nv.namelen; hdrs[nvlen].value = h2_field->nv.value; @@ -238,7 +264,7 @@ delete_nv_packet_data(struct tfe_h2_header *header) free(h2_filed->field); h2_filed->field = NULL; - + free(h2_filed); h2_filed = NULL; } @@ -267,15 +293,15 @@ void half_set_callback(struct tfe_h2_half_private * half_private, } const char * h2_half_ops_field_read(const struct tfe_http_half * half, const struct http_field_name * field) -{ +{ const struct tfe_h2_half_private *half_private = nghttp2_to_half_private(half); if (unlikely(half_private == NULL)) return NULL; - + struct tfe_h2_field *h2_field=NULL, *peer_h2_field=NULL; const struct tfe_h2_header *h2_header =&(half_private->header); - + TAILQ_FOREACH(h2_field, &h2_header->h2_field_list, next) { if (http_field_name_compare(h2_field->field, field) != 0) continue; @@ -297,7 +323,7 @@ int h2_half_ops_field_write(struct tfe_http_half * half, const struct http_field if (http_field_name_compare(h2_field->field, field) != 0) continue; peer_h2_field = h2_field; break; - } + } if (peer_h2_field != NULL && value != NULL) { @@ -334,7 +360,7 @@ h2_half_ops_allow_write(const struct tfe_http_half * half) const char * h2_half_ops_field_iterate(const struct tfe_http_half * half, void ** iter, struct http_field_name * field) { struct tfe_h2_field **h2_filed = (struct tfe_h2_field **)iter; - const struct tfe_h2_half_private *half_private = nghttp2_to_half_private(half); + const struct tfe_h2_half_private *half_private = nghttp2_to_half_private(half); const struct tfe_h2_header *header = &half_private->header; if (*h2_filed == NULL) @@ -359,25 +385,25 @@ h2_half_ops_append_body(struct tfe_http_half * half, char * buff, size_t size, i { int xret = -1; struct tfe_h2_half_private * resp = nghttp2_to_half_private(half); - struct tfe_h2_payload *body = &resp->body; + struct tfe_h2_payload *body = &resp->h2_payload; if (buff == NULL && size == 0){ if (body->gzip != HTTP2_CONTENT_ENCODING_NONE){ - xret = deflate_write(&body->deflate, NULL, 0, resp->body.evbuf_body, body->gzip, 1); + xret = deflate_write(&body->deflate, NULL, 0, resp->h2_payload.evbuf_body, body->gzip, 1); } resp->message_state = H2_READ_STATE_COMPLETE; goto finish; } - if (resp->body.evbuf_body == NULL){ - resp->body.evbuf_body = evbuffer_new(); + if (resp->h2_payload.evbuf_body == NULL){ + resp->h2_payload.evbuf_body = evbuffer_new(); } if (body->gzip != HTTP2_CONTENT_ENCODING_NONE){ xret = deflate_write(&body->deflate, (const uint8_t *)buff, size, - resp->body.evbuf_body, body->gzip, 0); + resp->h2_payload.evbuf_body, body->gzip, 0); }else{ - xret = evbuffer_add(resp->body.evbuf_body, buff, size); + xret = evbuffer_add(resp->h2_payload.evbuf_body, buff, size); } finish: @@ -389,7 +415,7 @@ void delete_stream_half_data(struct tfe_h2_half_private **data, { if (*data){ - struct tfe_h2_payload *body = &((*data)->body); + struct tfe_h2_payload *body = &((*data)->h2_payload); inflate_finished(&body->inflate); deflate_finished(&body->deflate); @@ -400,6 +426,7 @@ void delete_stream_half_data(struct tfe_h2_half_private **data, if ((*data)->url_storage) FREE(&((*data)->url_storage)); delete_nv_packet_data(&((*data)->header)); + if((*data)->event_cb_user_deleter != NULL) (*data)->event_cb_user_deleter((*data)->event_cb_user); free(*data); @@ -423,7 +450,7 @@ void h2_half_ops_free(struct tfe_http_half * half) int h2_half_ops_body_begin(struct tfe_http_half * half, int by_stream) { struct tfe_h2_half_private * resp = nghttp2_to_half_private(half); - struct tfe_h2_payload *body = &resp->body; + struct tfe_h2_payload *body = &resp->h2_payload; assert(body->evbuf_body == NULL); @@ -455,14 +482,14 @@ int h2_half_ops_body_data(struct tfe_http_half * h2_response, const unsigned cha { int xret = -1; struct tfe_h2_half_private * h2_resp_priv = nghttp2_to_half_private(h2_response); - struct tfe_h2_payload *body = &h2_resp_priv->body; - + struct tfe_h2_payload *body = &h2_resp_priv->h2_payload; + if (body->gzip != HTTP2_CONTENT_ENCODING_NONE){ xret = deflate_write(&body->deflate, (const uint8_t *)data, sz_data, - h2_resp_priv->body.evbuf_body, body->gzip, 0); + h2_resp_priv->h2_payload.evbuf_body, body->gzip, 0); }else{ - xret = evbuffer_add(h2_resp_priv->body.evbuf_body, data, sz_data); + xret = evbuffer_add(h2_resp_priv->h2_payload.evbuf_body, data, sz_data); } return xret; } @@ -557,17 +584,16 @@ tfe_half_private_init(enum tfe_http_direction direction, int32_t stream_id, struct tfe_h2_half_private *half_private = ALLOC(struct tfe_h2_half_private, 1); assert(half_private); - memset(half_private, 0, sizeof(struct tfe_h2_half_private)); - half_private->half_public.direction = direction; - half_private->half_public.major_version = 2; half_private->half_public.ops = &h2_half_ops; headers_init(&half_private->header); headers_init(&half_private->promised); - half_private->body.evbuf_body = evbuffer_new(); - half_private->body.gzip = HTTP2_CONTENT_ENCODING_NONE; - half_private->body.padlen = 0; + half_private->h2_payload.inflate = NULL; + half_private->h2_payload.deflate = NULL; + half_private->h2_payload.evbuf_body = evbuffer_new(); + half_private->h2_payload.gzip = HTTP2_CONTENT_ENCODING_NONE; + half_private->h2_payload.padlen = 0; half_private->stream_id = stream_id; half_private->session = session; @@ -597,7 +623,7 @@ struct tfe_http_half * h2_ops_response_create(struct tfe_http_session * session, resp->method_or_status = resp_code; if (stream->resp) - resp->body.gzip = stream->resp->body.gzip; + resp->h2_payload.gzip = stream->resp->h2_payload.gzip; return &resp->half_public; } @@ -647,7 +673,7 @@ upstream_read_callback(nghttp2_session *session, int32_t stream_id, static enum tfe_stream_action nghttp2_server_frame_submit_response(struct tfe_h2_stream *h2_stream_info, - struct tfe_h2_session *h2_session) + struct tfe_h2_session *h2_session) { int rv = -1; struct tfe_h2_header *h2_header = NULL; @@ -662,19 +688,24 @@ nghttp2_server_frame_submit_response(struct tfe_h2_stream *h2_stream_info, if (h2_header->nvlen <= 0) return ACTION_FORWARD_DATA; - struct tfe_h2_payload *body = &pangu_resp->body; + struct tfe_h2_payload *body = &pangu_resp->h2_payload; char str_sz_evbuf_body[TFE_STRING_MAX]; snprintf(str_sz_evbuf_body, sizeof(str_sz_evbuf_body) - 1, "%lu", evbuffer_get_length(body->evbuf_body)); - const static struct http_field_name __cont_encoding_length_name = {TFE_HTTP_CONT_LENGTH, NULL}; - tfe_http_field_write(&pangu_resp->half_public, &__cont_encoding_length_name, str_sz_evbuf_body); + const static struct http_field_name encoding_field = {TFE_HTTP_CONT_LENGTH, NULL}; + tfe_http_field_write(&pangu_resp->half_public, &encoding_field, str_sz_evbuf_body); nghttp2_data_provider data_prd; data_prd.source.ptr = (void *)body; data_prd.read_callback = upstream_read_callback; - + nghttp2_nv hdrs[h2_header->nvlen]; - rv = nghttp2_submit_response(h2_stream_info->as_server, h2_session->ngh2_stream_id, nghttp2_nv_packet(h2_header, hdrs), + /*Adapt Http uri Settings**/ + + tfe_http_field_write(&pangu_resp->half_public, &encoding_field, str_sz_evbuf_body); + + + rv = nghttp2_submit_response(h2_stream_info->as_server, h2_session->ngh2_stream_id, tfe_h2_header_convert_nv(h2_header, hdrs), h2_header->nvlen, &data_prd); if (rv != 0){ return ACTION_FORWARD_DATA; @@ -698,7 +729,7 @@ server_frame_submit_data(struct tfe_h2_stream *connection, stream_action = nghttp2_server_frame_submit_response(connection, h2_session); }else{ int rv = -1; - struct tfe_h2_payload *body = &resp->body; + struct tfe_h2_payload *body = &resp->h2_payload; nghttp2_data_provider upstream_data_provider; upstream_data_provider.source.ptr = (void *)body; @@ -931,7 +962,7 @@ nghttp2_submit_frame_goaway(struct tfe_h2_stream *connection, const nghttp2_fram { int xret = -1; enum tfe_stream_action stream_action = ACTION_DROP_DATA; - char error[1024] = {0}; + char *error = NULL; size_t eroro_len=0; const nghttp2_goaway *goaway = &frame->goaway; nghttp2_session *ngh2_session = tfe_h2_stream_get_nghttp2_session(connection, dir); @@ -951,10 +982,12 @@ nghttp2_submit_frame_goaway(struct tfe_h2_stream *connection, const nghttp2_fram dir, nghttp2_strerror(xret)); } finish: - snprintf(error, goaway->opaque_data_len, "%s", goaway->opaque_data); + eroro_len = goaway->opaque_data_len; + error = ALLOC(char, eroro_len + 1); + snprintf(error, eroro_len, "%s", goaway->opaque_data); TFE_LOG_DEBUG(logger()->handle, "%s, %d, submit goaway, stream_id:%d, action:%d, errod_code:%d, data:%s", connection->tf_stream->str_stream_info, dir, goaway->last_stream_id, connection->stream_action, goaway->error_code, goaway->opaque_data); - + FREE(&error); connection->goaway = 1; connection->stream_action = stream_action; return 0; @@ -1003,10 +1036,10 @@ nghttp2_submit_end_header(struct tfe_h2_stream *h2_stream_info, if (headers.nvlen <= 0 || ((headers.flag & NGHTTP2_FLAG_END_STREAM)!=1) ){ return 0; } - + nghttp2_nv hdrs[headers.nvlen]; stream_id = nghttp2_submit_headers(h2_stream_info->as_server, headers.flag, - h2_session->ngh2_stream_id, NULL, nghttp2_nv_packet(&headers, hdrs), + h2_session->ngh2_stream_id, NULL, tfe_h2_header_convert_nv(&headers, hdrs), headers.nvlen, h2_session); if (stream_id < 0){ printf("Fatal headers error: %s\n", nghttp2_strerror(stream_id)); @@ -1044,7 +1077,7 @@ nghttp2_submit_end_stream_payload(struct tfe_h2_stream *h2_stream_info, resp->event_cb_user); } } - struct tfe_h2_payload *payload = &resp->body; + struct tfe_h2_payload *payload = &resp->h2_payload; payload->flags |= NGHTTP2_FLAG_END_STREAM; resp->body_state = H2_READ_STATE_COMPLETE; resp->message_state = H2_READ_STATE_COMPLETE; @@ -1083,7 +1116,7 @@ nghttp2_submit_frame_data(struct tfe_h2_stream *h2_stream_info,const nghttp2_fra goto finish; } resp = h2_session->resp; - resp->body.padlen = frame->data.padlen; + resp->h2_payload.padlen = frame->data.padlen; if (resp->body_state != H2_READ_STATE_COMPLETE){ nghttp2_submit_end_stream_payload(h2_stream_info, h2_session); } @@ -1097,6 +1130,7 @@ static int tfe_half_session_init(struct tfe_h2_session *h2_session, int32_t stre { struct tfe_http_session *tfe_session = &h2_session->tfe_session; + tfe_session->major_version = 2; if (direction == TFE_HTTP_REQUEST){ struct tfe_h2_half_private *req = h2_session->req; tfe_session->ops = &nghttp2_session_ops; @@ -1129,7 +1163,7 @@ upstream_create_req(struct tfe_h2_stream *h2_stream_info, nghttp2_session *as_se event->tf_stream = h2_stream_info->tf_stream; event->tfe_session = &h2_session->tfe_session; - half_set_callback(h2_session->req, event, NULL); + half_set_callback(h2_session->req, event, free); /* Call business plugin */ half_private = h2_session->req; @@ -1170,10 +1204,10 @@ nghttp2_server_frame_submit_push_promise(struct tfe_h2_stream *h2_stream_info, /* Create s' half req*/ peer_h2_stream = (struct tfe_h2_session *)ALLOC(struct tfe_h2_session, 1); assert(peer_h2_stream); - + nghttp2_nv hdrs[headers->nvlen]; stream_id = nghttp2_submit_push_promise(h2_stream_info->as_server, headers->flag, - h2_session->ngh2_stream_id, nghttp2_nv_packet(headers, hdrs), + h2_session->ngh2_stream_id, tfe_h2_header_convert_nv(headers, hdrs), headers->nvlen, peer_h2_stream); if (stream_id < 0){ free(peer_h2_stream); @@ -1256,7 +1290,7 @@ suspend_start(struct tfe_h2_session *h2_session, static void fill_resp_spec_from_handle(struct tfe_h2_half_private *half_private) { - struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; + struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; struct tfe_h2_header *header = &half_private->header; struct tfe_http_resp_spec *resp_spec = &(half_private->half_public.resp_spec); @@ -1343,10 +1377,10 @@ nghttp2_server_frame_submit_header(struct tfe_h2_stream *h2_stream_info, headers = &resp->header; if (headers->nvlen <= 0){ return ACTION_FORWARD_DATA; - } + } nghttp2_nv hdrs[headers->nvlen]; xret = nghttp2_submit_headers(h2_stream_info->as_server, headers->flag, - h2_session->ngh2_stream_id, NULL, nghttp2_nv_packet(headers, hdrs), + h2_session->ngh2_stream_id, NULL, tfe_h2_header_convert_nv(headers, hdrs), headers->nvlen, h2_session); if (xret < 0){ printf("Fatal headers error: %s\n", nghttp2_strerror(xret)); @@ -1410,7 +1444,7 @@ static void fill_req_spec_from_handle(struct tfe_h2_half_private *half_private) { int urllen = 0; - struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; + struct tfe_h2_field *h2_field = NULL, *peer_h2_field = NULL; struct tfe_h2_header *header = &half_private->header; struct tfe_http_req_spec *req_spec = &(half_private->half_public.req_spec); @@ -1430,7 +1464,7 @@ fill_req_spec_from_handle(struct tfe_h2_half_private *half_private) continue; } } - char *urltmp = NULL; + char *urltmp = half_private->url_storage; urltmp = (char *)malloc(urllen + 1); if(urltmp){ sprintf(urltmp, "%s%s", (char *)req_spec->host, (char *)req_spec->uri); @@ -1461,10 +1495,10 @@ static enum tfe_stream_action nghttp2_submit_built_response(struct tfe_h2_stream *h2_stream_info, struct tfe_h2_session *h2_session) { - int xret = -1; + int xret = -1; char value[128] = {0}; enum tfe_stream_action stream_action = ACTION_FORWARD_DATA; - struct tfe_h2_half_private *resp = h2_session->plugin_built_resp; + struct tfe_h2_half_private *resp = h2_session->plugin_built_resp; struct http_field_name field; field.field_id = TFE_HTTP_UNKNOWN_FIELD; @@ -1509,7 +1543,7 @@ downstream_create_resp(struct tfe_h2_session *h2_session, nghttp2_session *as_cl event->tf_stream = tf_stream; event->tfe_session = &h2_session->tfe_session; - half_set_callback(h2_session->resp, event, NULL); + half_set_callback(h2_session->resp, event, free); h2_session->resp->frame_ctx = h2_session->frame_ctx; @@ -1545,17 +1579,18 @@ nghttp2_client_frame_submit_header(struct tfe_h2_stream *h2_stream_info, downstream_create_resp(h2_session, h2_stream_info->as_client, h2_stream_info->as_server, h2_stream_info->tf_stream, h2_stream_info->thread_id); nghttp2_session_set_next_stream_id(h2_stream_info->as_client, h2_session->ngh2_stream_id); - + nghttp2_nv hdrs[headers->nvlen]; + method = nghttp2_get_method(h2_session->req); if (method == (enum tfe_http_std_method)NGHTTP2_METHOD_POST || method == (enum tfe_http_std_method)NGHTTP2_METHOD_PUT){ stream_id = nghttp2_submit_headers(h2_stream_info->as_client, headers->flag, - -1, NULL, nghttp2_nv_packet(headers, hdrs), + -1, NULL, tfe_h2_header_modify_field(headers, hdrs, ":path", req->url_storage), headers->nvlen, h2_session); }else{ stream_id = nghttp2_submit_request(h2_stream_info->as_client, NULL, - nghttp2_nv_packet(headers, hdrs), + tfe_h2_header_modify_field(headers, hdrs, ":path", req->url_storage), headers->nvlen, NULL, h2_session); } if (stream_id < 0){ @@ -1565,7 +1600,7 @@ nghttp2_client_frame_submit_header(struct tfe_h2_stream *h2_stream_info, goto finish; } stream_action = ACTION_DROP_DATA; -finish: +finish: delete_nv_packet_data(headers); return stream_action; } @@ -1661,7 +1696,7 @@ nghttp2_fill_up_header(nghttp2_session *ngh2_session, const nghttp2_frame *frame return 0; } struct tfe_h2_half_private *half = (dir == CONN_DIR_UPSTREAM) ? h2_session->resp : h2_session->req; - + struct http_field_name field; field.field_id = (enum tfe_http_std_field)str_to_val((const char *)name, header_vals); if (field.field_id == TFE_HTTP_UNKNOWN_FIELD) @@ -1670,8 +1705,8 @@ nghttp2_fill_up_header(nghttp2_session *ngh2_session, const nghttp2_frame *frame } if (field.field_id == TFE_HTTP_CONT_ENCODING) { - half->body.gzip = method_to_str_idx((const char *)value); - } + half->h2_payload.gzip = method_to_str_idx((const char *)value); + } h2_header = &half->header; tfe_h2_header_add_field(h2_header, &field, (const char *)value, 1); h2_header->flag = frame->hd.flags; @@ -1695,7 +1730,7 @@ nghttp2_fill_up_promise(nghttp2_session *ngh2_session, const nghttp2_frame *fram frame->hd.stream_id); return 0; } - resp = h2_session->resp; + resp = h2_session->resp; struct http_field_name field; field.field_id = (enum tfe_http_std_field)str_to_val((const char *)name, header_vals); if (field.field_id == TFE_HTTP_UNKNOWN_FIELD) @@ -1704,8 +1739,8 @@ nghttp2_fill_up_promise(nghttp2_session *ngh2_session, const nghttp2_frame *fram } if (field.field_id == TFE_HTTP_CONT_ENCODING) { - resp->body.gzip = method_to_str_idx((const char *)value); - } + resp->h2_payload.gzip = method_to_str_idx((const char *)value); + } headers = &resp->promised; tfe_h2_header_add_field(headers, &field, (const char *)value, 1); headers->flag = frame->hd.flags; @@ -1758,9 +1793,14 @@ nghttp2_on_stream_close(nghttp2_session *session, const nghttp2_frame *frame, co h2_stream_info->stream_action != ACTION_DEFER_DATA) nghttp2_submit_end_header(h2_stream_info, h2_session); goto end; - } + } finish: TAILQ_REMOVE(&h2_stream_info->h2_session_list, h2_session, next); + if (h2_session->frame_ctx){ + http_frame_raise_session_end(h2_session->frame_ctx, h2_session->tf_stream, &h2_session->tfe_session, + h2_stream_info->thread_id); + h2_session->frame_ctx = NULL; + } delete_http2_stream_data(h2_session, h2_stream_info->tf_stream, 1); free(h2_session); h2_session = NULL; @@ -1829,14 +1869,17 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags, goto finish; } resp = h2_session->resp; - evbuffer_add(resp->body.evbuf_body, input, input_len); + evbuffer_add(resp->h2_payload.evbuf_body, input, input_len); - if (resp->body.gzip != HTTP2_CONTENT_ENCODING_NONE){ + if (resp->h2_payload.gzip != HTTP2_CONTENT_ENCODING_NONE){ ret = inflate_read(input, input_len, &uncompr, &uncompr_len, - &resp->body.inflate, resp->body.gzip); + &resp->h2_payload.inflate, resp->h2_payload.gzip); if (((ret == Z_STREAM_END) || (ret == Z_OK)) && uncompr > 0){ input = (const uint8_t*)uncompr; input_len = uncompr_len; + }else + { + if (uncompr_len) FREE(&uncompr); } } data = input; @@ -1848,9 +1891,9 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags, resp->event_cb_user); } if (flags == NGHTTP2_FLAG_END_STREAM){ - resp->body.flags = 0; + resp->h2_payload.flags = 0; }else{ - resp->body.flags = flags; + resp->h2_payload.flags = flags; } resp->body_state = H2_READ_STATE_READING; } @@ -1860,11 +1903,12 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags, resp->event_cb_user); } if (flags == NGHTTP2_FLAG_END_STREAM){ - resp->body.flags = 0; + resp->h2_payload.flags = 0; }else{ - resp->body.flags = flags; + resp->h2_payload.flags = flags; } } + if (uncompr_len) FREE(&uncompr); stream_action = server_frame_submit_data(h2_stream_info, h2_session, CONN_DIR_UPSTREAM); if (stream_action == ACTION_DROP_DATA){ @@ -1942,7 +1986,7 @@ create_upstream_data(nghttp2_session *session, int32_t stream_id, event->tf_stream = h2_stream_info->tf_stream; event->tfe_session = &h2_session->tfe_session; - half_set_callback(h2_session->resp, event, NULL); + half_set_callback(h2_session->resp, event, free); h2_session->resp->frame_ctx = h2_session->frame_ctx; @@ -1966,7 +2010,7 @@ static ssize_t nghttp2_client_select_padding_callback(nghttp2_session *session, if (!resp) return frame->hd.length; - return (ssize_t)MIN(max_payloadlen, frame->hd.length + (resp->body.padlen)); + return (ssize_t)MIN(max_payloadlen, frame->hd.length + (resp->h2_payload.padlen)); } static int @@ -2101,7 +2145,7 @@ create_serv_stream_data(nghttp2_session *session, int32_t stream_id, event->tf_stream = h2_stream_info->tf_stream; event->tfe_session = &h2_session->tfe_session; - half_set_callback(h2_session->req, event, NULL); + half_set_callback(h2_session->req, event, free); /* Call business plugin */ half_private = h2_session->req; @@ -2142,19 +2186,25 @@ nghttp2_server_on_data_chunk_recv(nghttp2_session *session, uint8_t flags, goto finish; } req = h2_session->req; - req->body.flags = flags; - evbuffer_add(req->body.evbuf_body, input, input_len); + req->h2_payload.flags = flags; + evbuffer_add(req->h2_payload.evbuf_body, input, input_len); - if (req->body.gzip != HTTP2_CONTENT_ENCODING_NONE){ + if (req->h2_payload.gzip != HTTP2_CONTENT_ENCODING_NONE){ ret = inflate_read(input, input_len, &uncompr, &uncompr_len, - &req->body.inflate, req->body.gzip); + &req->h2_payload.inflate, req->h2_payload.gzip); if (((ret == Z_STREAM_END) || (ret == Z_OK)) && uncompr > 0){ input = (const uint8_t*)uncompr; input_len = uncompr_len; } + else + { + if (uncompr_len) FREE(&uncompr); + } } data = input; len = input_len; + /*todo post data scan**/ + if (uncompr_len) FREE(&uncompr); stream_action = server_frame_submit_data(h2_stream_info, h2_session, CONN_DIR_DOWNSTREAM); if (stream_action == ACTION_DROP_DATA){