*修改nghttp2对于控制帧(set ping等)自动回复数据,造成原服务数据冗余发送goaway帧

*修改下发替换规则后,csdn页面数据图片无法显示问题
(原因:由于数据Header,在不同流中,且不同流中存在多个流id)
*修改模拟C对推送承诺帧drop处理,造成当前流中数据丢失
*修改页面访问新浪sinaere.js失败
*修改流id数据未及时释放造成页面刷新延缓
This commit is contained in:
fengweihao
2019-03-14 10:51:15 +08:00
committed by zhengchao
parent 67d8523de0
commit fcde7bfbf3
6 changed files with 88 additions and 70 deletions

View File

@@ -416,7 +416,7 @@ enum tfe_stream_action http_connection_entry(const struct tfe_stream * stream, e
{
hf_private_in->stream_action = hf_private_in->user_stream_action;
}
/* Call user callback, tell user we resume from suspend */
assert(hs_private->resume_tag_singal);
hs_private->resume_tag_singal = false;
@@ -540,7 +540,6 @@ enum tfe_stream_action http_connection_entry_data(const struct tfe_stream * stre
enum tfe_conn_dir dir, const unsigned char * data, size_t len, void ** pme)
{
struct http_connection_private * ht_conn = (struct http_connection_private *) (*pme);
if (ht_conn->is_preempted == 0)
{
/* If the server push response before client send request, this must not be HTTP, detach the stream */

View File

@@ -82,6 +82,7 @@ struct h2_stream_data_t{
int spd_set;
int spd_valid;
int rse_set;
int flag_end;
tfe_http_event spd_event;
struct http_frame_session_ctx *frame_ctx;

View File

@@ -128,7 +128,6 @@ http2_stream_data(const struct tfe_stream * stream, unsigned int thread_id,
struct stream_tap_info_t *tapinfo = (struct stream_tap_info_t *)(*pme);
if (tapinfo->preempted == 0){
if (dir == CONN_DIR_UPSTREAM){
if (len < SET_FRAME_LENGTH){
defer_bytes = SET_FRAME_LENGTH;
@@ -146,7 +145,6 @@ http2_stream_data(const struct tfe_stream * stream, unsigned int thread_id,
goto finish;
}
}
if (dir == CONN_DIR_DOWNSTREAM){
/* Protocol Identification, we need 24 bytes at least to tell it is HTTP2 or not */
if (len < MAGIC_FRAME_LENGTH){

View File

@@ -73,22 +73,6 @@ static const struct value_string headers_vals[] =
{TFE_HTTP_LAST_MODIFIED, "last-modified"},
};
/* ACK Header : 0x000x000x000x040x010x000x000x000x00*/
static uint8_t ackheader[] = {
0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00
};
static int ping(const unsigned char *data, size_t len)
{
if (len >= 8 &&
(data[3] == 0x6 &&
(data[4] == 0x1 || data[4] == 0x0) &&
(data[16] == 0x0 || data[16] == 0x1))){
return 1;
}
return 0;
}
struct user_event_dispatch
{
const struct tfe_stream *tf_stream;
@@ -803,6 +787,35 @@ nghttp2_client_send(nghttp2_session *session, const uint8_t *data,
return (ssize_t)length;
}
void nghttp2_disect_goaway(struct tfe_session_info_t *session_info, int server)
{
unsigned int thread_id = session_info->thread_id;
const struct tfe_stream * stream = session_info->tf_stream;
struct h2_stream_data_t *h2_stream = NULL;
struct h2_stream_data_t *_h2_stream = NULL;
TAILQ_FOREACH_SAFE(h2_stream, &session_info->list, next, _h2_stream){
TAILQ_REMOVE(&session_info->list, h2_stream, next);
if (h2_stream->frame_ctx){
http_frame_raise_session_end(h2_stream->frame_ctx, stream, &h2_stream->tfe_session,
thread_id);
h2_stream->frame_ctx = NULL;
}
delete_http2_stream_data(h2_stream, session_info->tf_stream, 1);
free(h2_stream);
h2_stream = NULL;
}
if (session_info->as_client && !server){
nghttp2_session_del(session_info->as_client);
session_info->as_client = NULL;
}
if (session_info->as_server && server){
nghttp2_session_del(session_info->as_server);
session_info->as_server = NULL;
}
}
static int
nghttp2_client_on_frame_recv(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
@@ -822,20 +835,21 @@ nghttp2_client_on_frame_recv(nghttp2_session *session,
stream_set_id(&session_info->h2_id, frame->hd.stream_id);
break;
case NGHTTP2_HEADERS:
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
frame->hd.flags & NGHTTP2_FLAG_END_HEADERS){
if ((frame->headers.cat == NGHTTP2_HCAT_RESPONSE) &&
(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)){
h2_stream = (struct h2_stream_data_t *)nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if (!h2_stream){
TFE_LOG_ERROR(rt_log_data()->run_log_handle, "Upstream id %d, can't find stream information(addr = %p)",
frame->hd.stream_id, session_info);
break;
}
resp = h2_stream->resp;
suspend_start(h2_stream, resp, session_info->tf_stream);
fill_resp_spec_from_handle(h2_stream->resp);
h2_stream->frame_type |= TFE_NGHTTP2_HEADERS;
stream_set_id(&session_info->h2_id, frame->hd.stream_id);
resp->event_cb(resp, EV_HTTP_RESP_HDR, NULL, 0, resp->event_cb_user);
if (h2_stream->spd_set){
h2_stream->spd_event = EV_HTTP_RESP_HDR;
@@ -846,8 +860,13 @@ nghttp2_client_on_frame_recv(nghttp2_session *session,
break;
case NGHTTP2_WINDOW_UPDATE:
break;
case NGHTTP2_PING:
break;
case NGHTTP2_PRIORITY:
break;
case NGHTTP2_GOAWAY:
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Upstream(as client) control frame goaway");
nghttp2_disect_goaway(session_info, 1);
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Up stream control frame goaway");
break;
}
return 0;
@@ -864,12 +883,17 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
const unsigned char *data;
struct http2_half_private * resp = NULL;
struct tfe_session_info_t *session_info = (struct tfe_session_info_t *)user_data;
struct h2_stream_data_t *h2_stream = (struct h2_stream_data_t *)nghttp2_session_get_stream_user_data(session, stream_id);
if (!h2_stream){
TFE_LOG_ERROR(rt_log_data()->run_log_handle, "On data callback can't get downstream information, id = %d",
stream_id);
goto finish;
}
h2_stream->frame_type |= TFE_NGHTTP2_DATA;
stream_set_id(&session_info->h2_id, stream_id);
resp = h2_stream->resp;
if (resp->body.gzip != HTTP2_CONTENT_ENCODING_NONE){
ret = inflate_read(input, input_len, &uncompr, &uncompr_len,
@@ -907,6 +931,7 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
resp->event_cb(resp, EV_HTTP_RESP_END, NULL, 0,
resp->event_cb_user);
}
resp->body.flags = flags;
resp->body_state = MANAGE_STAGE_COMPLETE;
resp->message_state = MANAGE_STAGE_COMPLETE;
@@ -924,8 +949,9 @@ nghttp2_client_on_stream_close(nghttp2_session *session, int32_t stream_id,
struct h2_stream_data_t *h2_stream;
struct tfe_session_info_t *session_info = (struct tfe_session_info_t *)user_data;
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Client stream close stream_id = %d, error_code = %d",
stream_id, error_code);
if (error_code != 0)
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Up stream abnormal exit, id = %d, error_code = %d",
stream_id, error_code);
h2_stream = TAILQ_LIST_FIND(session_info, stream_id);
if (!h2_stream) {
@@ -944,12 +970,17 @@ nghttp2_client_on_stream_close(nghttp2_session *session, int32_t stream_id,
resp->event_cb_user);
}
}
resp->body.flags = NGHTTP2_FLAG_END_STREAM;
resp->body_state = MANAGE_STAGE_COMPLETE;
resp->message_state = MANAGE_STAGE_COMPLETE;
h2_stream->frame_type |= TFE_NGHTTP2_DATA;
stream_set_id(&session_info->h2_id, stream_id);
}else{
TAILQ_REMOVE(&session_info->list, h2_stream, next);
delete_http2_stream_data(h2_stream, session_info->tf_stream, 1);
free(h2_stream);
h2_stream = NULL;
}
return 0;
}
@@ -977,7 +1008,6 @@ nghttp2_client_on_header(nghttp2_session *session,
frame->hd.stream_id, session_info);
break;
}
//printf("%d, %s %s, %d\n",frame->hd.stream_id, name, value, frame->hd.flags);
resp = h2_stream->resp;
head = ALLOC(struct header_data, 1);
head->nv.name = (uint8_t *)tfe_strdup((const char *)name);
@@ -999,8 +1029,7 @@ nghttp2_client_on_header(nghttp2_session *session,
headers = &resp->headers;
headers->flag = frame->hd.flags;
headers_add_tail(headers, head);
h2_stream->frame_type |= TFE_NGHTTP2_HEADERS;
stream_set_id(&session_info->h2_id, frame->hd.stream_id);
break;
case NGHTTP2_PUSH_PROMISE:
if (frame->headers.cat != NGHTTP2_HCAT_REQUEST)
@@ -1185,8 +1214,13 @@ nghttp2_server_on_frame_recv(nghttp2_session *session,
break;
case NGHTTP2_WINDOW_UPDATE:
break;
case NGHTTP2_PING:
break;
case NGHTTP2_PRIORITY:
break;
case NGHTTP2_GOAWAY:
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Control frame goaway");
nghttp2_disect_goaway(session_info, 0);
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Down stream control frame goaway");
break;
default:
break;
@@ -1218,8 +1252,10 @@ nghttp2_server_on_stream_close(nghttp2_session *session, int32_t stream_id,
if (!h2_stream) {
return 0;
}
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "downstream(as server) %d is close, error_code = %d", stream_id, error_code);
return 0;
if (error_code != 0)
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Down stream abnormal exit, id = %d, error_code = %d",
stream_id, error_code);
return 0;
}
static int
@@ -1423,7 +1459,7 @@ finish:
}
static enum tfe_stream_action
nghttp2_server_frame_submit_data(struct tfe_session_info_t *session_info, struct h2_stream_data_t **h2_stream,
server_frame_submit_data(struct tfe_session_info_t *session_info, struct h2_stream_data_t **h2_stream,
uint16_t *nghttp2_type)
{
enum tfe_stream_action stream_action = ACTION_FORWARD_DATA;
@@ -1437,8 +1473,7 @@ nghttp2_server_frame_submit_data(struct tfe_session_info_t *session_info, struct
struct data_t *body = &resp->body;
if (body->flags == NGHTTP2_FLAG_END_STREAM &&
resp->message_state == MANAGE_STAGE_COMPLETE){
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Remove stream id(%d), h2_stream addr %p",
(*h2_stream)->stream_id, *h2_stream);
TFE_LOG_DEBUG(rt_log_data()->run_log_handle, "Data stream exit, id = %d", (*h2_stream)->stream_id);
TAILQ_REMOVE(&session_info->list, *h2_stream, next);
delete_http2_stream_data(*h2_stream, session_info->tf_stream, 1);
@@ -1655,7 +1690,7 @@ finish:
static enum tfe_stream_action
nghttp2_server_frame_submit_header(struct h2_stream_data_t *h2_stream,
uint16_t *nghttp2_type)
uint16_t *nghttp2_type)
{
enum tfe_stream_action stream_action = ACTION_FORWARD_DATA;
@@ -1711,7 +1746,7 @@ finish:
return;
}
static enum tfe_stream_action
static enum tfe_stream_action __attribute__((__unused__))
nghttp2_server_frame_submit_push_promise(struct tfe_session_info_t *session_info,
struct h2_stream_data_t *h2_stream)
{
@@ -1766,27 +1801,26 @@ nghttp2_server_frame_submit_response(struct tfe_session_info_t *session_info,
int rv = -1;
nghttp2_nv hdrs[128] = {0};
struct http2_headers *headers = NULL;
struct http2_half_private *resp = NULL;
struct http2_half_private *pangu_resp = NULL;
resp = h2_stream->pangu_resp;
if (resp == NULL)
pangu_resp = h2_stream->pangu_resp;
if (pangu_resp == NULL)
return ACTION_FORWARD_DATA;
if (resp->message_state != MANAGE_STAGE_COMPLETE){
if (pangu_resp->message_state != MANAGE_STAGE_COMPLETE){
session_info->state = 0;
return ACTION_DROP_DATA;
}
headers = &resp->headers;
headers = &pangu_resp->headers;
if (headers->nvlen <= 0)
return ACTION_FORWARD_DATA;
struct data_t *body = &resp->body;
struct data_t *body = &pangu_resp->body;
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(&resp->half_public, &__cont_encoding_length_name, str_sz_evbuf_body);
tfe_http_field_write(&pangu_resp->half_public, &__cont_encoding_length_name, str_sz_evbuf_body);
nghttp2_data_provider data_prd;
data_prd.source.ptr = (void *)body;
@@ -1820,7 +1854,7 @@ nghttp2_server_frame_submit(struct tfe_session_info_t *session_info)
nghttp2_stream->frame_type &= ~TFE_NGHTTP2_HEADERS;
}
if (nghttp2_stream->frame_type & TFE_NGHTTP2_DATA){
stream_action = nghttp2_server_frame_submit_data(session_info, &nghttp2_stream, &nghttp2_stream->frame_type);
stream_action = server_frame_submit_data(session_info, &nghttp2_stream, &nghttp2_stream->frame_type);
if (nghttp2_stream)
nghttp2_stream->frame_type &= ~TFE_NGHTTP2_DATA;
else
@@ -1831,7 +1865,11 @@ nghttp2_server_frame_submit(struct tfe_session_info_t *session_info)
nghttp2_stream->frame_type &= ~TFE_NGHTTP2_SETTINGS;
}
if (nghttp2_stream->frame_type & TFE_NGHTTP2_PUSH_PROMISE){
stream_action = nghttp2_server_frame_submit_push_promise(session_info, nghttp2_stream);
/*Because a data stream contains multiple stream ids, resulting in data drop,
there is no processing of the committed push frame at present.
Under the condition that the main process is not affected,
the committed push frame is not encapsulated ***/
//stream_action = nghttp2_server_frame_submit_push_promise(session_info, nghttp2_stream);
nghttp2_stream->frame_type &= ~TFE_NGHTTP2_PUSH_PROMISE;
}
if (nghttp2_stream->frame_type & TFE_NGHTTP2_RESPONSE){
@@ -1840,7 +1878,6 @@ nghttp2_server_frame_submit(struct tfe_session_info_t *session_info)
}
}
nghttp2_stream_disable_rid(&session_info->h2_id);
return stream_action;
}
@@ -1871,14 +1908,6 @@ detect_up_stream_protocol(struct tfe_session_info_t *session_info, const struct
int readlen = 0;
enum tfe_stream_action stream_action = ACTION_FORWARD_DATA;
if (len >= 9 && !memcmp(data, ackheader, 9)){
len = 9;
goto finish;
}
if (len > 9 && !memcmp((data + len - 9), ackheader, 9)){
len = len - 9;
}
readlen = nghttp2_session_mem_recv(session_info->as_client, data, len);
if (readlen < 0){
TFE_LOG_ERROR(rt_log_data()->run_log_handle, "Failed to process server requests. Link message %s",
@@ -1897,7 +1926,7 @@ detect_up_stream_protocol(struct tfe_session_info_t *session_info, const struct
}
err:
tfe_stream_detach(tfe_stream);
finish:
tfe_stream_action_set_opt(tfe_stream, ACTION_OPT_DROP_BYTES, &len, sizeof(len));
return ACTION_DROP_DATA;
}
@@ -1912,15 +1941,6 @@ detect_down_stream_protocol(struct tfe_session_info_t *session_info, const struc
session_info->tf_stream = tfe_stream;
session_info->thread_id = thread_id;
if (len >= 9 && !memcmp(data, ackheader, 9)){
/** todo: confirmation frames are automatically replied by the local agent, Immediately forward */
len = 9;
goto finish;
}
if (len > 9 && !memcmp((data + len - 9), ackheader, 9)){
len = len - 9;
}
readlen = nghttp2_session_mem_recv(session_info->as_server, data, len);
if (readlen < 0){
TFE_LOG_ERROR(rt_log_data()->run_log_handle, "Failed to process client requests. Link message %s",
@@ -1939,7 +1959,7 @@ detect_down_stream_protocol(struct tfe_session_info_t *session_info, const struc
}
err:
tfe_stream_detach(tfe_stream);
finish:
tfe_stream_action_set_opt(tfe_stream, ACTION_OPT_DROP_BYTES, &len, sizeof(len));
return ACTION_DROP_DATA;
}

View File

@@ -81,7 +81,7 @@ set_property(TARGET http-parser-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${
ExternalProject_Add(nghttp2
PREFIX nghttp2
URL ${CMAKE_CURRENT_SOURCE_DIR}/nghttp2-1.24.0.tar.gz
URL_MD5 d3bf46ac99772d39fa60fa8fd2ab91e5
URL_MD5 1bf8209fc10da2d46012b03a158e6693
CONFIGURE_COMMAND ./configure --prefix=<INSTALL_DIR> --disable-shared
BUILD_IN_SOURCE 1)

Binary file not shown.