*修改nghttp2对于控制帧(set ping等)自动回复数据,造成原服务数据冗余发送goaway帧
*修改下发替换规则后,csdn页面数据图片无法显示问题 (原因:由于数据Header,在不同流中,且不同流中存在多个流id) *修改模拟C对推送承诺帧drop处理,造成当前流中数据丢失 *修改页面访问新浪sinaere.js失败 *修改流id数据未及时释放造成页面刷新延缓
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
2
vendor/CMakeLists.txt
vendored
2
vendor/CMakeLists.txt
vendored
@@ -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)
|
||||
|
||||
|
||||
BIN
vendor/nghttp2-1.24.0.tar.gz
vendored
BIN
vendor/nghttp2-1.24.0.tar.gz
vendored
Binary file not shown.
Reference in New Issue
Block a user