From 74a4bd5ecd83ce1fde0dba8a642d3daaa99d916e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 May 2015 16:44:00 +0200 Subject: [PATCH] http2: store incoming h2 SETTINGS --- lib/http.h | 8 ++++++++ lib/http2.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/http.h b/lib/http.h index a2f702d02..53d2bfeba 100644 --- a/lib/http.h +++ b/lib/http.h @@ -175,6 +175,13 @@ struct HTTP { typedef int (*sending)(void); /* Curl_send */ typedef int (*recving)(void); /* Curl_recv */ +/* h2 settings for this connection */ +struct h2settings { + uint32_t max_concurrent_streams; + bool enable_push; +}; + + struct http_conn { #ifdef USE_NGHTTP2 #define H2_BINSETTINGS_LEN 80 @@ -195,6 +202,7 @@ struct http_conn { /* this is a hash of all individual streams (SessionHandle structs) */ struct curl_hash streamsh; + struct h2settings settings; #else int unused; /* prevent a compiler warning */ #endif diff --git a/lib/http2.c b/lib/http2.c index 1987c120e..6014f3d19 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -187,6 +187,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { struct connectdata *conn = (struct connectdata *)userp; + struct http_conn *httpc = &conn->proto.httpc; struct SessionHandle *data_s = NULL; struct HTTP *stream = NULL; int rv; @@ -201,7 +202,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(stream_id) { /* get the stream from the hash based on Stream ID, stream ID zero is for connection-oriented stuff */ - data_s = Curl_hash_pick(&conn->proto.httpc.streamsh, &stream_id, + data_s = Curl_hash_pick(&httpc->streamsh, &stream_id, sizeof(stream_id)); if(!data_s) { /* Receiving a Stream ID not in the hash should not happen, this is an @@ -289,6 +290,23 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, return rv; } break; + case NGHTTP2_SETTINGS: + DEBUGF(infof(conn->data, "Got SETTINGS for stream %x!\n", stream_id)); + httpc->settings.max_concurrent_streams = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); + httpc->settings.enable_push = + nghttp2_session_get_remote_settings( + session, NGHTTP2_SETTINGS_ENABLE_PUSH); + DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n", + httpc->settings.max_concurrent_streams)); + DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n", + httpc->settings.enable_push?"TRUE":"false")); + break; + default: + DEBUGF(infof(conn->data, "Got frame type %x for stream %x!\n", + frame->hd.type, stream_id)); + break; } return 0; } @@ -929,6 +947,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, char *end; nghttp2_data_provider data_prd; int32_t stream_id; + nghttp2_session *h2 = httpc->h2; (void)sockindex; @@ -939,8 +958,8 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, are going to send or sending request body in DATA frame */ httpc->upload_mem = mem; httpc->upload_len = len; - nghttp2_session_resume_data(httpc->h2, stream->stream_id); - rv = nghttp2_session_send(httpc->h2); + nghttp2_session_resume_data(h2, stream->stream_id); + rv = nghttp2_session_send(h2); if(nghttp2_is_fatal(rv)) { *err = CURLE_SEND_ERROR; return -1; @@ -1048,11 +1067,11 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, case HTTPREQ_PUT: data_prd.read_callback = data_source_read_callback; data_prd.source.ptr = NULL; - stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + stream_id = nghttp2_submit_request(h2, NULL, nva, nheader, &data_prd, NULL); break; default: - stream_id = nghttp2_submit_request(httpc->h2, NULL, nva, nheader, + stream_id = nghttp2_submit_request(h2, NULL, nva, nheader, NULL, NULL); } @@ -1076,7 +1095,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, return -1; } - rv = nghttp2_session_send(httpc->h2); + rv = nghttp2_session_send(h2); if(rv != 0) { *err = CURLE_SEND_ERROR; @@ -1092,7 +1111,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, writable socket check is performed. To workaround this, we issue nghttp2_session_resume_data() here to bring back DATA transmission from deferred state. */ - nghttp2_session_resume_data(httpc->h2, stream->stream_id); + nghttp2_session_resume_data(h2, stream->stream_id); } return len;