summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2021-01-24 18:59:21 +0100
committerDaniel Stenberg <daniel@haxx.se>2021-01-24 18:59:21 +0100
commit12d6b851f17a4bf628c5278a9b54a92367ad1c16 (patch)
treead0e9fd01e015671a8028423ea62c4cee85cced4
parentecb13416e316fc1c781f865d2bb7e74462ef793b (diff)
downloadcurl-12d6b851f17a4bf628c5278a9b54a92367ad1c16.tar.gz
http2: remove conn->data usebagder/h2-conn-data
Starting here, the code sets the 'data' pointer as user-data even for the connection, and the callbacks need to find the connection using 'data->conn'. Since the transfer can come and go over the life time of the connection it thus becomes important to always set the correct "current transfer" when calling nghttp2 so that it doesn't get the *old* transfer that previously used the connection.
-rw-r--r--lib/http.c2
-rw-r--r--lib/http2.c76
-rw-r--r--lib/http2.h2
3 files changed, 45 insertions, 35 deletions
diff --git a/lib/http.c b/lib/http.c
index 40773e6da..af479c8d0 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -3155,7 +3155,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
(data->set.httpversion == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
over SSL */
- result = Curl_http2_request_upgrade(&req, conn);
+ result = Curl_http2_request_upgrade(&req, data);
if(result) {
Curl_dyn_free(&req);
return result;
diff --git a/lib/http2.c b/lib/http2.c
index 197ba1d3c..a7aa51fe5 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -247,6 +247,7 @@ static unsigned int http2_conncheck(struct Curl_easy *data,
}
if(send_frames) {
+ (void)nghttp2_session_set_user_data(c->h2, data);
rc = nghttp2_session_send(c->h2);
if(rc)
failf(data, "nghttp2_session_send() failed: %s(%d)",
@@ -347,7 +348,8 @@ static ssize_t send_callback(nghttp2_session *h2,
const uint8_t *mem, size_t length, int flags,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct connectdata *conn = data->conn;
struct http_conn *c = &conn->proto.httpc;
ssize_t written;
CURLcode result = CURLE_OK;
@@ -359,7 +361,7 @@ static ssize_t send_callback(nghttp2_session *h2,
/* called before setup properly! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- written = ((Curl_send*)c->send_underlying)(conn->data, FIRSTSOCKET,
+ written = ((Curl_send*)c->send_underlying)(data, FIRSTSOCKET,
mem, length, &result);
if(result == CURLE_AGAIN) {
@@ -367,7 +369,7 @@ static ssize_t send_callback(nghttp2_session *h2,
}
if(written == -1) {
- failf(conn->data, "Failed sending HTTP2 data");
+ failf(data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -629,7 +631,8 @@ static void multi_connchanged(struct Curl_multi *multi)
static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct connectdata *conn = data->conn;
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
@@ -642,30 +645,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- H2BUGF(infof(conn->data, "Got SETTINGS\n"));
+ H2BUGF(infof(data, "Got SETTINGS\n"));
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);
- H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d\n",
httpc->settings.max_concurrent_streams));
- H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(data, "ENABLE_PUSH == %s\n",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
- infof(conn->data,
+ infof(data,
"Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
httpc->settings.max_concurrent_streams);
- multi_connchanged(conn->data->multi);
+ multi_connchanged(data->multi);
}
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
if(!data_s) {
- H2BUGF(infof(conn->data,
+ H2BUGF(infof(data,
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
@@ -768,15 +771,15 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
- const uint8_t *data, size_t len, void *userp)
+ const uint8_t *mem, size_t len, void *userp)
{
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct connectdata *conn = data->conn;
struct HTTP *stream;
struct Curl_easy *data_s;
size_t nread;
- struct connectdata *conn = (struct connectdata *)userp;
(void)session;
(void)flags;
- (void)data;
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@@ -792,7 +795,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
return NGHTTP2_ERR_CALLBACK_FAILURE;
nread = CURLMIN(stream->len, len);
- memcpy(&stream->mem[stream->memlen], data, nread);
+ memcpy(&stream->mem[stream->memlen], mem, nread);
stream->len -= nread;
stream->memlen += nread;
@@ -800,7 +803,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
drain_this(data_s, &conn->proto.httpc);
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "%zu data received for stream %u "
@@ -810,7 +813,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
stream->memlen));
if(nread < len) {
- stream->pausedata = data + nread;
+ stream->pausedata = mem + nread;
stream->pauselen = len - nread;
H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
", stream %u\n",
@@ -822,7 +825,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* pause execution of nghttp2 if we received data for another handle
in order to process them first. */
- if(conn->data != data_s) {
+ if(data != data_s) {
data_s->conn->proto.httpc.pause_stream_id = stream_id;
return NGHTTP2_ERR_PAUSE;
@@ -836,13 +839,14 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
{
struct Curl_easy *data_s;
struct HTTP *stream;
- struct connectdata *conn = (struct connectdata *)userp;
+ struct Curl_easy *data = (struct Curl_easy *)userp;
int rv;
(void)session;
(void)stream_id;
if(stream_id) {
struct http_conn *httpc;
+ struct connectdata *conn = data->conn;
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
@@ -940,10 +944,11 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
uint8_t flags,
void *userp)
{
+ struct Curl_easy *data = (struct Curl_easy *)userp;
+ struct connectdata *conn = data->conn;
struct HTTP *stream;
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
- struct connectdata *conn = (struct connectdata *)userp;
CURLcode result;
(void)flags;
@@ -1049,7 +1054,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
@@ -1073,7 +1078,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
- if(conn->data != data_s)
+ if(data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
@@ -1138,27 +1143,28 @@ static int error_callback(nghttp2_session *session,
size_t len,
void *userp)
{
- struct connectdata *conn = (struct connectdata *)userp;
(void)session;
- infof(conn->data, "http2 error: %.*s\n", len, msg);
+ (void)msg;
+ (void)len;
+ (void)userp;
return 0;
}
#endif
-static void populate_settings(struct connectdata *conn,
+static void populate_settings(struct Curl_easy *data,
struct http_conn *httpc)
{
nghttp2_settings_entry *iv = httpc->local_settings;
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
- iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi);
+ iv[0].value = Curl_multi_max_concurrent_streams(data->multi);
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
- iv[2].value = conn->data->multi->push_cb != NULL;
+ iv[2].value = data->multi->push_cb != NULL;
httpc->local_settings_num = 3;
}
@@ -1188,8 +1194,10 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
if(premature) {
/* RST_STREAM */
if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
- http->stream_id, NGHTTP2_STREAM_CLOSED))
+ http->stream_id, NGHTTP2_STREAM_CLOSED)) {
+ (void)nghttp2_session_set_user_data(httpc->h2, data);
(void)nghttp2_session_send(httpc->h2);
+ }
if(http->stream_id == httpc->pause_stream_id) {
infof(data, "stopped the pause stream!\n");
@@ -1253,7 +1261,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
/* The nghttp2 session is not yet setup, do it */
- rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
+ rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, data);
nghttp2_session_callbacks_del(callbacks);
@@ -1269,18 +1277,18 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
- struct connectdata *conn)
+ struct Curl_easy *data)
{
CURLcode result;
ssize_t binlen;
char *base64;
size_t blen;
- struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
+ struct connectdata *conn = data->conn;
uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc;
- populate_settings(conn, httpc);
+ populate_settings(data, httpc);
/* this returns number of bytes it wrote */
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
@@ -1542,6 +1550,7 @@ static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
struct HTTP *stream = data->req.p.http;
+ (void)nghttp2_session_set_user_data(h2, data);
if((data->set.stream_weight != data->state.stream_weight) ||
(data->set.stream_depends_e != data->state.stream_depends_e) ||
(data->set.stream_depends_on != data->state.stream_depends_on) ) {
@@ -2119,6 +2128,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex,
/* this does not call h2_session_send() since there can not have been any
* priority update since the nghttp2_submit_request() call above */
+ (void)nghttp2_session_set_user_data(h2, data);
rv = nghttp2_session_send(h2);
if(rv != 0) {
H2BUGF(infof(data,
@@ -2244,7 +2254,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data,
}
}
else {
- populate_settings(conn, httpc);
+ populate_settings(data, httpc);
/* stream ID is unknown at this point */
stream->stream_id = -1;
diff --git a/lib/http2.h b/lib/http2.h
index 119e584a8..150f7219f 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -43,7 +43,7 @@ CURLcode Curl_http2_init(struct connectdata *conn);
void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
- struct connectdata *conn);
+ struct Curl_easy *data);
CURLcode Curl_http2_setup(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_http2_switched(struct Curl_easy *data,
const char *ptr, size_t nread);