http2: move stream_id to the HTTP struct (per-stream)

This commit is contained in:
Daniel Stenberg 2015-04-27 13:54:47 +02:00
parent f858624052
commit d6440d7366
2 changed files with 24 additions and 13 deletions

View File

@ -152,6 +152,9 @@ struct HTTP {
void *send_buffer; /* used if the request couldn't be sent in one chunk, void *send_buffer; /* used if the request couldn't be sent in one chunk,
points to an allocated send_buffer struct */ points to an allocated send_buffer struct */
/* for HTTP/2 we store stream-local data here */
int32_t stream_id; /* stream we are interested in */
}; };
typedef int (*sending)(void); /* Curl_send */ typedef int (*sending)(void); /* Curl_send */
@ -175,7 +178,6 @@ struct http_conn {
response headers into it. */ response headers into it. */
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf size_t nread_header_recvbuf; /* number of bytes in header_recvbuf
fed into upper layer */ fed into upper layer */
int32_t stream_id; /* stream we are interested in */
const uint8_t *data; /* pointer to data chunk, received in const uint8_t *data; /* pointer to data chunk, received in
on_data_chunk */ on_data_chunk */
size_t datalen; /* the number of bytes left in data */ size_t datalen; /* the number of bytes left in data */

View File

@ -291,6 +291,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
{ {
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
struct http_conn *c = &conn->proto.httpc; struct http_conn *c = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
size_t nread; size_t nread;
(void)session; (void)session;
(void)flags; (void)flags;
@ -298,7 +299,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
DEBUGF(infof(conn->data, "on_data_chunk_recv() " DEBUGF(infof(conn->data, "on_data_chunk_recv() "
"len = %u, stream = %x\n", len, stream_id)); "len = %u, stream = %x\n", len, stream_id));
if(stream_id != c->stream_id) { if(stream_id != stream->stream_id) {
return 0; return 0;
} }
@ -355,12 +356,13 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
{ {
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
struct http_conn *c = &conn->proto.httpc; struct http_conn *c = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
(void)session; (void)session;
(void)stream_id; (void)stream_id;
DEBUGF(infof(conn->data, "on_stream_close() was called, error_code = %d\n", DEBUGF(infof(conn->data, "on_stream_close() was called, error_code = %d\n",
error_code)); error_code));
if(stream_id != c->stream_id) { if(stream_id != stream->stream_id) {
return 0; return 0;
} }
@ -418,6 +420,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
{ {
struct connectdata *conn = (struct connectdata *)userp; struct connectdata *conn = (struct connectdata *)userp;
struct http_conn *c = &conn->proto.httpc; struct http_conn *c = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
int rv; int rv;
int goodname; int goodname;
int goodheader; int goodheader;
@ -431,7 +434,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
return 0; return 0;
} }
if(frame->hd.stream_id != c->stream_id) { if(frame->hd.stream_id != stream->stream_id) {
return 0; return 0;
} }
@ -680,6 +683,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
ssize_t rv; ssize_t rv;
ssize_t nread; ssize_t nread;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */ (void)sockindex; /* we always do HTTP2 on sockindex 0 */
@ -778,7 +782,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
if(httpc->error_code != NGHTTP2_NO_ERROR) { if(httpc->error_code != NGHTTP2_NO_ERROR) {
failf(conn->data, failf(conn->data,
"HTTP/2 stream = %x was not closed cleanly: error_code = %d", "HTTP/2 stream = %x was not closed cleanly: error_code = %d",
httpc->stream_id, httpc->error_code); stream->stream_id, httpc->error_code);
*err = CURLE_HTTP2; *err = CURLE_HTTP2;
return -1; return -1;
} }
@ -803,6 +807,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
*/ */
int rv; int rv;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
nghttp2_nv *nva; nghttp2_nv *nva;
size_t nheader; size_t nheader;
size_t i; size_t i;
@ -816,12 +821,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
DEBUGF(infof(conn->data, "http2_send len=%zu\n", len)); DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(httpc->stream_id != -1) { if(stream->stream_id != -1) {
/* If stream_id != -1, we have dispatched request HEADERS, and now /* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */ are going to send or sending request body in DATA frame */
httpc->upload_mem = mem; httpc->upload_mem = mem;
httpc->upload_len = len; httpc->upload_len = len;
nghttp2_session_resume_data(httpc->h2, httpc->stream_id); nghttp2_session_resume_data(httpc->h2, stream->stream_id);
rv = nghttp2_session_send(httpc->h2); rv = nghttp2_session_send(httpc->h2);
if(nghttp2_is_fatal(rv)) { if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR; *err = CURLE_SEND_ERROR;
@ -945,7 +950,8 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
return -1; return -1;
} }
httpc->stream_id = stream_id; infof(conn->data, "Using Stream ID: %x\n", stream_id);
stream->stream_id = stream_id;
rv = nghttp2_session_send(httpc->h2); rv = nghttp2_session_send(httpc->h2);
@ -954,7 +960,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
return -1; return -1;
} }
if(httpc->stream_id != -1) { if(stream->stream_id != -1) {
/* If whole HEADERS frame was sent off to the underlying socket, /* If whole HEADERS frame was sent off to the underlying socket,
the nghttp2 library calls data_source_read_callback. But only the nghttp2 library calls data_source_read_callback. But only
it found that no data available, so it deferred the DATA it found that no data available, so it deferred the DATA
@ -963,7 +969,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
writable socket check is performed. To workaround this, we writable socket check is performed. To workaround this, we
issue nghttp2_session_resume_data() here to bring back DATA issue nghttp2_session_resume_data() here to bring back DATA
transmission from deferred state. */ transmission from deferred state. */
nghttp2_session_resume_data(httpc->h2, httpc->stream_id); nghttp2_session_resume_data(httpc->h2, stream->stream_id);
} }
return len; return len;
@ -973,6 +979,9 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
{ {
CURLcode result; CURLcode result;
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
stream->stream_id = -1;
if((conn->handler == &Curl_handler_http2_ssl) || if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2)) (conn->handler == &Curl_handler_http2))
@ -998,7 +1007,6 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
httpc->upload_left = 0; httpc->upload_left = 0;
httpc->upload_mem = NULL; httpc->upload_mem = NULL;
httpc->upload_len = 0; httpc->upload_len = 0;
httpc->stream_id = -1;
httpc->status_code = -1; httpc->status_code = -1;
conn->httpversion = 20; conn->httpversion = 20;
@ -1014,6 +1022,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
struct http_conn *httpc = &conn->proto.httpc; struct http_conn *httpc = &conn->proto.httpc;
int rv; int rv;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct HTTP *stream = conn->data->req.protop;
result = Curl_http2_setup(conn); result = Curl_http2_setup(conn);
if(result) if(result)
@ -1040,7 +1049,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
if(conn->data->req.upgr101 == UPGR101_RECEIVED) { if(conn->data->req.upgr101 == UPGR101_RECEIVED) {
/* stream 1 is opened implicitly on upgrade */ /* stream 1 is opened implicitly on upgrade */
httpc->stream_id = 1; stream->stream_id = 1;
/* queue SETTINGS frame (again) */ /* queue SETTINGS frame (again) */
rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings, rv = nghttp2_session_upgrade(httpc->h2, httpc->binsettings,
httpc->binlen, NULL); httpc->binlen, NULL);
@ -1052,7 +1061,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
} }
else { else {
/* stream ID is unknown at this point */ /* stream ID is unknown at this point */
httpc->stream_id = -1; stream->stream_id = -1;
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
if(rv != 0) { if(rv != 0) {
failf(data, "nghttp2_submit_settings() failed: %s(%d)", failf(data, "nghttp2_submit_settings() failed: %s(%d)",