diff options
-rw-r--r-- | lib/http.h | 1 | ||||
-rw-r--r-- | lib/http2.c | 41 |
2 files changed, 36 insertions, 6 deletions
diff --git a/lib/http.h b/lib/http.h index 253687148..7ce803cdb 100644 --- a/lib/http.h +++ b/lib/http.h @@ -167,6 +167,7 @@ struct http_conn { Curl_send_buffer *header_recvbuf; /* store response headers */ size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into upper layer */ + int32_t stream_id; /* stream we are interested in */ #else int unused; /* prevent a compiler warning */ #endif diff --git a/lib/http2.c b/lib/http2.c index a479f0142..a65d4122f 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -118,12 +118,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, { struct connectdata *conn = (struct connectdata *)userp; struct http_conn *c = &conn->proto.httpc; + int rv; (void)session; (void)frame; infof(conn->data, "on_frame_recv() was called with header %x\n", frame->hd.type); - if(frame->hd.type == NGHTTP2_HEADERS && - frame->headers.cat == NGHTTP2_HCAT_RESPONSE) { + switch(frame->hd.type) { + case NGHTTP2_HEADERS: + if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE) + break; c->bodystarted = TRUE; Curl_add_buffer(c->header_recvbuf, "\r\n", 2); c->nread_header_recvbuf = c->len < c->header_recvbuf->size_used ? @@ -133,10 +136,14 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, c->mem += c->nread_header_recvbuf; c->len -= c->nread_header_recvbuf; - } - if((frame->hd.type == NGHTTP2_HEADERS || frame->hd.type == NGHTTP2_DATA) && - frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - infof(conn->data, "stream_id=%d closed\n", frame->hd.stream_id); + break; + case NGHTTP2_PUSH_PROMISE: + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->hd.stream_id, NGHTTP2_CANCEL); + if(nghttp2_is_fatal(rv)) { + return rv; + } + break; } return 0; } @@ -165,6 +172,10 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, infof(conn->data, "on_data_chunk_recv() " "len = %u, stream = %x\n", len, stream_id); + if(stream_id != c->stream_id) { + return 0; + } + if(len <= c->len) { memcpy(c->mem, data, len); c->mem += len; @@ -183,9 +194,15 @@ static int before_frame_send(nghttp2_session *session, void *userp) { struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *c = &conn->proto.httpc; (void)session; (void)frame; infof(conn->data, "before_frame_send() was called\n"); + if(frame->hd.type == NGHTTP2_HEADERS && + frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + /* Get stream ID of our request */ + c->stream_id = frame->hd.stream_id; + } return 0; } static int on_frame_send(nghttp2_session *session, @@ -219,6 +236,10 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, infof(conn->data, "on_stream_close() was called, error_code = %d\n", error_code); + if(stream_id != c->stream_id) { + return 0; + } + c->closed = TRUE; return 0; @@ -261,6 +282,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, (void)session; (void)frame; + if(frame->hd.stream_id != c->stream_id) { + return 0; + } + if(namelen == sizeof(":status") - 1 && memcmp(STATUS, name, namelen) == 0) { snprintf(c->header_recvbuf->buffer, 13, "HTTP/2.0 %s", value); @@ -599,6 +624,8 @@ int Curl_http2_switched(struct connectdata *conn) &rc); assert(rv == 24); if(conn->data->req.upgr101 == UPGR101_RECEIVED) { + /* stream 1 is opened implicitly on upgrade */ + httpc->stream_id = 1; /* queue SETTINGS frame (again) */ rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, httpc->binlen, NULL); @@ -609,6 +636,8 @@ int Curl_http2_switched(struct connectdata *conn) } } else { + /* stream ID is unknown at this point */ + httpc->stream_id = -1; rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); if(rv != 0) { failf(conn->data, "nghttp2_submit_settings() failed: %s(%d)", |