summaryrefslogtreecommitdiff
path: root/plugin/protocol/http2/src/http2_stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/protocol/http2/src/http2_stream.cpp')
-rw-r--r--plugin/protocol/http2/src/http2_stream.cpp150
1 files changed, 85 insertions, 65 deletions
diff --git a/plugin/protocol/http2/src/http2_stream.cpp b/plugin/protocol/http2/src/http2_stream.cpp
index 73ab8f7..b848fc2 100644
--- a/plugin/protocol/http2/src/http2_stream.cpp
+++ b/plugin/protocol/http2/src/http2_stream.cpp
@@ -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;
}