1.修复策略日志中host为乱码
2.修复http2请求体替换内容无效 3.修复evbuffer_pullup获取数据长度问题
This commit is contained in:
@@ -144,7 +144,7 @@ tfe_h2_header_modify_field(struct tfe_h2_header *header, nghttp2_nv *hdrs, const
|
||||
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)))
|
||||
@@ -229,6 +229,10 @@ static nghttp2_session * tfe_h2_stream_get_nghttp2_peer_session(struct tfe_h2_st
|
||||
return (dir==CONN_DIR_UPSTREAM?connection->as_client: connection->as_server);
|
||||
}
|
||||
|
||||
static struct tfe_h2_half_private *tfe_h2_stream_get_half(struct tfe_h2_session *h2_session, enum tfe_conn_dir dir)
|
||||
{
|
||||
return (dir==CONN_DIR_UPSTREAM?h2_session->resp: h2_session->req);
|
||||
}
|
||||
|
||||
static nghttp2_settings_entry*
|
||||
nghttp2_iv_packet(nghttp2_settings settings,
|
||||
@@ -410,8 +414,18 @@ finish:
|
||||
return xret;
|
||||
}
|
||||
|
||||
static void delete_http_req_spec(struct tfe_http_req_spec *req_spec)
|
||||
{
|
||||
if (req_spec->uri)
|
||||
free((char *)req_spec->uri);
|
||||
if (req_spec->host)
|
||||
free((char *)req_spec->host);
|
||||
if (req_spec->url)
|
||||
free((char *)req_spec->url);
|
||||
}
|
||||
|
||||
void delete_stream_half_data(struct tfe_h2_half_private **data,
|
||||
int body_flag)
|
||||
int body_flag, enum tfe_conn_dir dir)
|
||||
{
|
||||
if (*data){
|
||||
|
||||
@@ -427,6 +441,11 @@ void delete_stream_half_data(struct tfe_h2_half_private **data,
|
||||
FREE(&((*data)->url_storage));
|
||||
delete_nv_packet_data(&((*data)->header));
|
||||
|
||||
if (dir == CONN_DIR_DOWNSTREAM)
|
||||
{
|
||||
struct tfe_http_req_spec *req_spec = &((*data)->half_public.req_spec);
|
||||
delete_http_req_spec(req_spec);
|
||||
}
|
||||
if((*data)->event_cb_user_deleter != NULL)
|
||||
(*data)->event_cb_user_deleter((*data)->event_cb_user);
|
||||
free(*data);
|
||||
@@ -439,7 +458,7 @@ void h2_half_ops_free(struct tfe_http_half * half)
|
||||
{
|
||||
struct tfe_h2_half_private * h2_private = nghttp2_to_half_private(half);
|
||||
|
||||
delete_stream_half_data(&h2_private, 1);
|
||||
delete_stream_half_data(&h2_private, 1, CONN_DIR_DOWNSTREAM);
|
||||
|
||||
free(h2_private);
|
||||
h2_private = NULL;
|
||||
@@ -658,8 +677,8 @@ upstream_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
ssize_t datalen = 0, inputlen=0;
|
||||
|
||||
struct tfe_h2_payload *to_send_body = (struct tfe_h2_payload *)source->ptr;
|
||||
if (!to_send_body->evbuf_body || !(input = evbuffer_pullup(to_send_body->evbuf_body, -1))
|
||||
|| 0==(inputlen = evbuffer_get_length(to_send_body->evbuf_body)))
|
||||
if (!to_send_body->evbuf_body || 0==(inputlen = evbuffer_get_length(to_send_body->evbuf_body))
|
||||
||!(input = evbuffer_pullup(to_send_body->evbuf_body, MIN(length, inputlen))))
|
||||
{
|
||||
if ((to_send_body->flags & NGHTTP2_FLAG_END_STREAM) == 0)
|
||||
{
|
||||
@@ -676,7 +695,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,
|
||||
nghttp2_frame_submit_built_resp(struct tfe_h2_stream *h2_stream_info,
|
||||
struct tfe_h2_session *h2_session)
|
||||
{
|
||||
int rv = -1;
|
||||
@@ -721,20 +740,70 @@ nghttp2_server_frame_submit_response(struct tfe_h2_stream *h2_stream_info,
|
||||
}
|
||||
|
||||
static enum tfe_stream_action
|
||||
server_frame_submit_data(struct tfe_h2_stream *connection,
|
||||
struct tfe_h2_session *h2_session,
|
||||
enum tfe_conn_dir dir)
|
||||
nghttp2_frame_submit_built_req(struct tfe_h2_stream *h2_stream_info,
|
||||
struct tfe_h2_session *h2_session)
|
||||
{
|
||||
int32_t stream_id = -1;
|
||||
struct tfe_h2_header *h2_header = NULL;
|
||||
struct tfe_h2_half_private *plugin_built_req = h2_session->plugin_built_req;
|
||||
|
||||
if (plugin_built_req->message_state != H2_READ_STATE_COMPLETE){
|
||||
return (enum tfe_stream_action)ACTION_USER_DATA;
|
||||
}
|
||||
h2_header = &plugin_built_req->header;
|
||||
if (h2_header->nvlen <= 0)
|
||||
return ACTION_FORWARD_DATA;
|
||||
|
||||
struct tfe_h2_payload *body = &plugin_built_req->h2_payload;
|
||||
body->flags = NGHTTP2_FLAG_END_STREAM;
|
||||
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 encoding_field = {TFE_HTTP_CONT_LENGTH, NULL};
|
||||
tfe_http_field_write(&plugin_built_req->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];
|
||||
/*Adapt Http uri Settings**/
|
||||
stream_id = nghttp2_submit_request(h2_stream_info->as_client, NULL,
|
||||
tfe_h2_header_modify_field(h2_header, hdrs, ":path", plugin_built_req->url_storage),
|
||||
h2_header->nvlen, &data_prd, h2_session);
|
||||
|
||||
if (stream_id < 0){
|
||||
TFE_LOG_ERROR(logger()->handle, "Could not submit request: %s",
|
||||
nghttp2_strerror(stream_id));
|
||||
return ACTION_FORWARD_DATA;
|
||||
}
|
||||
delete_nv_packet_data(h2_header);
|
||||
|
||||
return ACTION_DROP_DATA;
|
||||
}
|
||||
|
||||
static enum tfe_stream_action
|
||||
nghttp2_submit_data_by_h2_half(struct tfe_h2_stream *connection,
|
||||
struct tfe_h2_session *h2_session,
|
||||
enum tfe_conn_dir dir)
|
||||
{
|
||||
enum tfe_stream_action stream_action = ACTION_DROP_DATA;
|
||||
|
||||
struct tfe_h2_half_private *resp = (dir == CONN_DIR_UPSTREAM) ? h2_session->resp : h2_session->req;
|
||||
struct tfe_h2_half_private *h2_half = (dir == CONN_DIR_UPSTREAM) ? h2_session->resp : h2_session->req;
|
||||
nghttp2_session *ngh2_session = tfe_h2_stream_get_nghttp2_session(connection, dir);
|
||||
|
||||
if (h2_session->plugin_built_resp){
|
||||
stream_action = nghttp2_server_frame_submit_response(connection, h2_session);
|
||||
}else{
|
||||
if (h2_session->plugin_built_resp)
|
||||
{
|
||||
stream_action = nghttp2_frame_submit_built_resp(connection, h2_session);
|
||||
}
|
||||
else if (h2_session->plugin_built_req)
|
||||
{
|
||||
stream_action = nghttp2_frame_submit_built_req(connection, h2_session);
|
||||
}
|
||||
else
|
||||
{
|
||||
int rv = -1;
|
||||
struct tfe_h2_payload *body = &resp->h2_payload;
|
||||
struct tfe_h2_payload *body = &h2_half->h2_payload;
|
||||
|
||||
nghttp2_data_provider upstream_data_provider;
|
||||
upstream_data_provider.source.ptr = (void *)body;
|
||||
@@ -927,9 +996,9 @@ void delete_http2_stream_data(struct tfe_h2_session *h2_session,
|
||||
const struct tfe_stream *tf_stream,
|
||||
int body_flag)
|
||||
{
|
||||
delete_stream_half_data(&h2_session->req, body_flag);
|
||||
delete_stream_half_data(&h2_session->req, body_flag, CONN_DIR_DOWNSTREAM);
|
||||
|
||||
delete_stream_half_data(&h2_session->resp, body_flag);
|
||||
delete_stream_half_data(&h2_session->resp, body_flag, CONN_DIR_UPSTREAM);
|
||||
}
|
||||
|
||||
void nghttp2_disect_goaway(struct tfe_h2_stream *h2_stream_info)
|
||||
@@ -1028,7 +1097,7 @@ nghttp2_submit_frame_window_update(struct tfe_h2_stream *connection,const nghttp
|
||||
}
|
||||
|
||||
static int
|
||||
nghttp2_submit_end_header(struct tfe_h2_stream *h2_stream_info,
|
||||
nghttp2_submit_header_by_not_modify(struct tfe_h2_stream *h2_stream_info,
|
||||
struct tfe_h2_session *h2_session)
|
||||
{
|
||||
int xret = -1;
|
||||
@@ -1064,32 +1133,38 @@ nghttp2_submit_end_header(struct tfe_h2_stream *h2_stream_info,
|
||||
}
|
||||
|
||||
static int
|
||||
nghttp2_submit_end_stream_payload(struct tfe_h2_stream *h2_stream_info,
|
||||
struct tfe_h2_session *h2_session)
|
||||
nghttp2_submit_complete_data(struct tfe_h2_stream *h2_stream_info,
|
||||
struct tfe_h2_session *h2_session, enum tfe_conn_dir dir)
|
||||
{
|
||||
int xret = -1;
|
||||
enum tfe_stream_action stream_action = ACTION_DROP_DATA;
|
||||
|
||||
struct tfe_h2_half_private *h2_half = tfe_h2_stream_get_half(h2_session, dir);
|
||||
nghttp2_session *ngh2_session = tfe_h2_stream_get_nghttp2_session(h2_stream_info, dir);
|
||||
|
||||
struct tfe_h2_half_private *resp = h2_session->resp;
|
||||
|
||||
enum tfe_http_event http_body_event = (dir==CONN_DIR_UPSTREAM?EV_HTTP_RESP_BODY_END: EV_HTTP_REQ_BODY_END);
|
||||
enum tfe_http_event http_event = (dir==CONN_DIR_UPSTREAM?EV_HTTP_RESP_END: EV_HTTP_REQ_END);
|
||||
|
||||
if (resp->body_state != H2_READ_STATE_BEGIN){
|
||||
if (resp->event_cb) {
|
||||
resp->event_cb(resp, EV_HTTP_RESP_BODY_END, NULL, 0,
|
||||
resp->event_cb_user);
|
||||
if (h2_half->body_state != H2_READ_STATE_BEGIN)
|
||||
{
|
||||
if (h2_half->event_cb) {
|
||||
h2_half->event_cb(h2_half, http_body_event, NULL, 0,
|
||||
h2_half->event_cb_user);
|
||||
}
|
||||
if (resp->event_cb) {
|
||||
resp->event_cb(resp, EV_HTTP_RESP_END, NULL, 0,
|
||||
resp->event_cb_user);
|
||||
if (h2_half->event_cb) {
|
||||
h2_half->event_cb(h2_half, http_event, NULL, 0,
|
||||
h2_half->event_cb_user);
|
||||
}
|
||||
}
|
||||
struct tfe_h2_payload *payload = &resp->h2_payload;
|
||||
struct tfe_h2_payload *payload = &h2_half->h2_payload;
|
||||
payload->flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
resp->body_state = H2_READ_STATE_COMPLETE;
|
||||
resp->message_state = H2_READ_STATE_COMPLETE;
|
||||
h2_half->body_state = H2_READ_STATE_COMPLETE;
|
||||
h2_half->message_state = H2_READ_STATE_COMPLETE;
|
||||
|
||||
stream_action = server_frame_submit_data(h2_stream_info, h2_session, CONN_DIR_UPSTREAM);
|
||||
stream_action = nghttp2_submit_data_by_h2_half(h2_stream_info, h2_session, CONN_DIR_UPSTREAM);
|
||||
if (stream_action == ACTION_DROP_DATA){
|
||||
xret = nghttp2_session_send(h2_stream_info->as_server);
|
||||
xret = nghttp2_session_send(ngh2_session);
|
||||
if (xret != 0) {
|
||||
stream_action = ACTION_FORWARD_DATA;
|
||||
TFE_LOG_ERROR(logger()->handle, "Fatal upstream send error: %s %d\n",nghttp2_strerror(xret), __LINE__);
|
||||
@@ -1105,28 +1180,26 @@ static int
|
||||
nghttp2_submit_frame_data(struct tfe_h2_stream *h2_stream_info,const nghttp2_frame *frame,
|
||||
enum tfe_conn_dir dir)
|
||||
{
|
||||
struct tfe_h2_half_private *resp = NULL;
|
||||
struct tfe_h2_session *h2_session = NULL;
|
||||
|
||||
if (dir == CONN_DIR_DOWNSTREAM){
|
||||
goto finish;
|
||||
h2_session = TAILQ_LIST_FIND(h2_stream_info, frame->hd.stream_id);
|
||||
if (NULL == h2_session)
|
||||
{
|
||||
TFE_LOG_ERROR(logger()->handle, "id %d, can't find stream information(addr = %p)",
|
||||
frame->hd.stream_id, h2_stream_info);
|
||||
return 0;;
|
||||
}
|
||||
struct tfe_h2_half_private *h2_half = tfe_h2_stream_get_half(h2_session, dir);
|
||||
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM){
|
||||
h2_session = (struct tfe_h2_session *)nghttp2_session_get_stream_user_data(h2_stream_info->as_client,
|
||||
frame->hd.stream_id);
|
||||
if (!h2_session){
|
||||
TFE_LOG_ERROR(logger()->handle, "Upstream id %d, can't find stream information(addr = %p)",
|
||||
frame->hd.stream_id, h2_stream_info);
|
||||
goto finish;
|
||||
}
|
||||
resp = h2_session->resp;
|
||||
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);
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)
|
||||
{
|
||||
if (dir == CONN_DIR_UPSTREAM)
|
||||
h2_half->h2_payload.padlen = frame->data.padlen;
|
||||
|
||||
if (h2_half->body_state != H2_READ_STATE_COMPLETE){
|
||||
nghttp2_submit_complete_data(h2_stream_info, h2_session, dir);
|
||||
}
|
||||
}
|
||||
finish:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1459,12 +1532,12 @@ fill_req_spec_from_handle(struct tfe_h2_half_private *half_private)
|
||||
continue;
|
||||
}
|
||||
if (!strncmp((char *)(h2_field->nv.name), ":authority", strlen(":authority"))){
|
||||
req_spec->host = (const char *)(h2_field->nv.value);
|
||||
req_spec->host = tfe_strdup((const char *)(h2_field->nv.value));
|
||||
urllen += h2_field->nv.valuelen;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp((char *)(h2_field->nv.name), ":path", strlen(":path"))){
|
||||
req_spec->uri = (const char*)(h2_field->nv.value);
|
||||
req_spec->uri = tfe_strdup((const char*)(h2_field->nv.value));
|
||||
urllen += h2_field->nv.valuelen;
|
||||
continue;
|
||||
}
|
||||
@@ -1516,7 +1589,7 @@ nghttp2_submit_built_response(struct tfe_h2_stream *h2_stream_info,
|
||||
snprintf(value, sizeof(value), "%d", resp->method_or_status);
|
||||
tfe_h2_header_add_field(&resp->header, &field, (const char *)value, 0);
|
||||
|
||||
stream_action = nghttp2_server_frame_submit_response(h2_stream_info, h2_session);
|
||||
stream_action = nghttp2_frame_submit_built_resp(h2_stream_info, h2_session);
|
||||
if (stream_action == ACTION_DROP_DATA){
|
||||
xret = nghttp2_session_send(h2_stream_info->as_server);
|
||||
if (xret != 0) {
|
||||
@@ -1571,18 +1644,20 @@ nghttp2_client_frame_submit_header(struct tfe_h2_stream *h2_stream_info,
|
||||
if (req == NULL){
|
||||
return ACTION_FORWARD_DATA;
|
||||
}
|
||||
if (h2_session->plugin_built_resp){
|
||||
|
||||
if (h2_session->plugin_built_resp)
|
||||
{
|
||||
stream_action = nghttp2_submit_built_response(h2_stream_info, h2_session);
|
||||
return stream_action;
|
||||
}
|
||||
|
||||
headers = &req->header;
|
||||
if (headers->nvlen <= 0){
|
||||
if (headers->nvlen <= 0)
|
||||
{
|
||||
return ACTION_FORWARD_DATA;
|
||||
}
|
||||
/*Create C' half_private_resp**/
|
||||
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);
|
||||
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];
|
||||
@@ -1590,6 +1665,11 @@ nghttp2_client_frame_submit_header(struct tfe_h2_stream *h2_stream_info,
|
||||
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){
|
||||
if (h2_session->plugin_built_req)
|
||||
{
|
||||
stream_action = (enum tfe_stream_action)ACTION_USER_DATA;
|
||||
return stream_action;
|
||||
}
|
||||
stream_id = nghttp2_submit_headers(h2_stream_info->as_client, headers->flag,
|
||||
-1, NULL, tfe_h2_header_modify_field(headers, hdrs, ":path", req->url_storage),
|
||||
headers->nvlen, h2_session);
|
||||
@@ -1796,7 +1876,7 @@ nghttp2_on_stream_close(nghttp2_session *session, const nghttp2_frame *frame, co
|
||||
if (error_code == 0 && resp->body_state != H2_READ_STATE_COMPLETE){
|
||||
if (resp->body_state == H2_READ_STATE_BEGIN &&
|
||||
h2_stream_info->stream_action != ACTION_DEFER_DATA)
|
||||
nghttp2_submit_end_header(h2_stream_info, h2_session);
|
||||
nghttp2_submit_header_by_not_modify(h2_stream_info, h2_session);
|
||||
goto end;
|
||||
}
|
||||
finish:
|
||||
@@ -1915,7 +1995,7 @@ nghttp2_client_on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
}
|
||||
if (uncompr_len) FREE(&uncompr);
|
||||
|
||||
stream_action = server_frame_submit_data(h2_stream_info, h2_session, CONN_DIR_UPSTREAM);
|
||||
stream_action = nghttp2_submit_data_by_h2_half(h2_stream_info, h2_session, CONN_DIR_UPSTREAM);
|
||||
if (stream_action == ACTION_DROP_DATA){
|
||||
xret = nghttp2_session_send(h2_stream_info->as_server);
|
||||
if (xret != 0) {
|
||||
@@ -2209,9 +2289,32 @@ nghttp2_server_on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
data = input;
|
||||
len = input_len;
|
||||
/*todo post data scan**/
|
||||
if (req->body_state == H2_READ_STATE_BEGIN){
|
||||
if (req->event_cb) {
|
||||
req->event_cb(req, EV_HTTP_REQ_BODY_BEGIN, NULL, len,
|
||||
req->event_cb_user);
|
||||
}
|
||||
if (flags == NGHTTP2_FLAG_END_STREAM){
|
||||
req->h2_payload.flags = 0;
|
||||
}else{
|
||||
req->h2_payload.flags = flags;
|
||||
}
|
||||
req->body_state = H2_READ_STATE_READING;
|
||||
}
|
||||
if (req->body_state == H2_READ_STATE_READING){
|
||||
if (req->event_cb) {
|
||||
req->event_cb(req, EV_HTTP_REQ_BODY_CONT, data, len,
|
||||
req->event_cb_user);
|
||||
}
|
||||
if (flags == NGHTTP2_FLAG_END_STREAM){
|
||||
req->h2_payload.flags = 0;
|
||||
}else{
|
||||
req->h2_payload.flags = flags;
|
||||
}
|
||||
}
|
||||
if (uncompr_len) FREE(&uncompr);
|
||||
|
||||
stream_action = server_frame_submit_data(h2_stream_info, h2_session, CONN_DIR_DOWNSTREAM);
|
||||
stream_action = nghttp2_submit_data_by_h2_half(h2_stream_info, h2_session, CONN_DIR_DOWNSTREAM);
|
||||
if (stream_action == ACTION_DROP_DATA){
|
||||
xret = nghttp2_session_send(h2_stream_info->as_client);
|
||||
if (xret != 0) {
|
||||
@@ -2219,11 +2322,6 @@ nghttp2_server_on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
|
||||
TFE_LOG_ERROR(logger()->handle, "Fatal upstream send error: %s, %d\n",nghttp2_strerror(xret), __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TFE_LOG_HTTP2
|
||||
TFE_LOG_INFO(logger()->handle, "%s, %d, submit data %d, stream_id:%d, action:%d", h2_stream_info->tf_stream->str_stream_info,
|
||||
0, (int)input_len, stream_id, h2_stream_info->stream_action);
|
||||
#endif
|
||||
if (stream_action == ACTION_USER_DATA)
|
||||
stream_action = ACTION_DROP_DATA;
|
||||
h2_stream_info->stream_action = stream_action;
|
||||
|
||||
Reference in New Issue
Block a user