diff options
Diffstat (limited to 'Utilities/cmcurl/lib/http2.c')
-rw-r--r-- | Utilities/cmcurl/lib/http2.c | 195 |
1 files changed, 96 insertions, 99 deletions
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c index f194c18..a3de607 100644 --- a/Utilities/cmcurl/lib/http2.c +++ b/Utilities/cmcurl/lib/http2.c @@ -146,12 +146,12 @@ static CURLcode http2_disconnect(struct Curl_easy *data, (void)data; #endif - H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT starts now")); nghttp2_session_del(c->h2); Curl_safefree(c->inbuf); - H2BUGF(infof(data, "HTTP/2 DISCONNECT done\n")); + H2BUGF(infof(data, "HTTP/2 DISCONNECT done")); return CURLE_OK; } @@ -196,11 +196,13 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn) data, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result); if(nread != -1) { infof(data, - "%d bytes stray data read before trying h2 connection\n", + "%d bytes stray data read before trying h2 connection", (int)nread); httpc->nread_inbuf = 0; httpc->inbuflen = nread; - (void)h2_process_pending_input(data, httpc, &result); + if(h2_process_pending_input(data, httpc, &result) < 0) + /* immediate error, considered dead */ + dead = TRUE; } else /* the read failed so let's say this is dead anyway */ @@ -350,13 +352,12 @@ static const struct Curl_handler Curl_handler_http2_ssl = { }; /* - * Store nghttp2 version info in this buffer, Prefix with a space. Return - * total length written. + * Store nghttp2 version info in this buffer. */ -int Curl_http2_ver(char *p, size_t len) +void Curl_http2_ver(char *p, size_t len) { nghttp2_info *h2 = nghttp2_version(0); - return msnprintf(p, len, "nghttp2/%s", h2->version_str); + (void)msnprintf(p, len, "nghttp2/%s", h2->version_str); } /* @@ -551,7 +552,7 @@ static int push_promise(struct Curl_easy *data, const nghttp2_push_promise *frame) { int rv; /* one of the CURL_PUSH_* defines */ - H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", + H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!", frame->promised_stream_id)); if(data->multi->push_cb) { struct HTTP *stream; @@ -563,7 +564,7 @@ static int push_promise(struct Curl_easy *data, /* clone the parent */ struct Curl_easy *newhandle = duphandle(data); if(!newhandle) { - infof(data, "failed to duplicate handle\n"); + infof(data, "failed to duplicate handle"); rv = CURL_PUSH_DENY; /* FAIL HARD */ goto fail; } @@ -571,7 +572,7 @@ static int push_promise(struct Curl_easy *data, heads.data = data; heads.frame = frame; /* ask the application */ - H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n")); + H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!")); stream = data->req.p.http; if(!stream) { @@ -619,7 +620,7 @@ static int push_promise(struct Curl_easy *data, state with the given connection !*/ rc = Curl_multi_add_perform(data->multi, newhandle, conn); if(rc) { - infof(data, "failed to add handle to multi\n"); + infof(data, "failed to add handle to multi"); http2_stream_free(newhandle->req.p.http); newhandle->req.p.http = NULL; Curl_close(&newhandle); @@ -632,15 +633,17 @@ static int push_promise(struct Curl_easy *data, frame->promised_stream_id, newhandle); if(rv) { - infof(data, "failed to set user_data for stream %d\n", + infof(data, "failed to set user_data for stream %d", frame->promised_stream_id); DEBUGASSERT(0); rv = CURL_PUSH_DENY; goto fail; } + Curl_dyn_init(&newstream->header_recvbuf, DYN_H2_HEADERS); + Curl_dyn_init(&newstream->trailer_recvbuf, DYN_H2_TRAILERS); } else { - H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); + H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!")); rv = CURL_PUSH_DENY; } fail: @@ -676,21 +679,21 @@ 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(data, "Got SETTINGS\n")); + H2BUGF(infof(data, "Got SETTINGS")); 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(data, "MAX_CONCURRENT_STREAMS == %d\n", + H2BUGF(infof(data, "MAX_CONCURRENT_STREAMS == %d", httpc->settings.max_concurrent_streams)); - H2BUGF(infof(data, "ENABLE_PUSH == %s\n", + H2BUGF(infof(data, "ENABLE_PUSH == %s", httpc->settings.enable_push?"TRUE":"false")); if(max_conn != httpc->settings.max_concurrent_streams) { /* only signal change if the value actually changed */ infof(data, - "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", + "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!", httpc->settings.max_concurrent_streams); multi_connchanged(data->multi); } @@ -700,19 +703,19 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, data_s = nghttp2_session_get_stream_user_data(session, stream_id); if(!data_s) { H2BUGF(infof(data, - "No Curl_easy associated with stream: %x\n", + "No Curl_easy associated with stream: %x", stream_id)); return 0; } stream = data_s->req.p.http; if(!stream) { - H2BUGF(infof(data_s, "No proto pointer for stream: %x\n", + H2BUGF(infof(data_s, "No proto pointer for stream: %x", stream_id)); return NGHTTP2_ERR_CALLBACK_FAILURE; } - H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n", + H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x", frame->hd.type, stream_id)); switch(frame->hd.type) { @@ -760,7 +763,8 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, ncopy); stream->nread_header_recvbuf += ncopy; - H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n", + DEBUGASSERT(stream->mem); + H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p", ncopy, stream_id, stream->mem)); stream->len -= ncopy; @@ -782,13 +786,13 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(nghttp2_is_fatal(h2)) return NGHTTP2_ERR_CALLBACK_FAILURE; else if(rv == CURL_PUSH_ERROROUT) { - DEBUGF(infof(data_s, "Fail the parent stream (too)\n")); + DEBUGF(infof(data_s, "Fail the parent stream (too)")); return NGHTTP2_ERR_CALLBACK_FAILURE; } } break; default: - H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n", + H2BUGF(infof(data_s, "Got frame type %x for stream %u!", frame->hd.type, stream_id)); break; } @@ -833,7 +837,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, Curl_expire(data_s, 0, EXPIRE_RUN_NOW); H2BUGF(infof(data_s, "%zu data received for stream %u " - "(%zu left in buffer %p, total %zu)\n", + "(%zu left in buffer %p, total %zu)", nread, stream_id, stream->len, stream->mem, stream->memlen)); @@ -842,7 +846,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, stream->pausedata = mem + nread; stream->pauselen = len - nread; H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" - ", stream %u\n", + ", stream %u", len - nread, stream_id)); data_s->conn->proto.httpc.pause_stream_id = stream_id; @@ -880,7 +884,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, decided to reject stream (e.g., PUSH_PROMISE). */ return 0; } - H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", + H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u", nghttp2_http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.p.http; if(!stream) @@ -895,15 +899,15 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, /* remove the entry from the hash as the stream is now gone */ rv = nghttp2_session_set_stream_user_data(session, stream_id, 0); if(rv) { - infof(data_s, "http/2: failed to clear user_data for stream %d!\n", + infof(data_s, "http/2: failed to clear user_data for stream %d!", stream_id); DEBUGASSERT(0); } if(stream_id == httpc->pause_stream_id) { - H2BUGF(infof(data_s, "Stopped the pause stream!\n")); + H2BUGF(infof(data_s, "Stopped the pause stream!")); httpc->pause_stream_id = 0; } - H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); + H2BUGF(infof(data_s, "Removed stream %u hash!", stream_id)); stream->stream_id = 0; /* cleared */ } return 0; @@ -921,7 +925,7 @@ static int on_begin_headers(nghttp2_session *session, return 0; } - H2BUGF(infof(data_s, "on_begin_headers() was called\n")); + H2BUGF(infof(data_s, "on_begin_headers() was called")); if(frame->hd.type != NGHTTP2_HEADERS) { return 0; @@ -1049,7 +1053,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(stream->bodystarted) { /* This is a trailer */ - H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, + H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s", namelen, name, valuelen, value)); result = Curl_dyn_addf(&stream->trailer_recvbuf, "%.*s: %.*s\r\n", namelen, name, @@ -1082,7 +1086,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n", + H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)", stream->status_code, data_s)); return 0; } @@ -1106,7 +1110,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(get_transfer(httpc) != data_s) Curl_expire(data_s, 0, EXPIRE_RUN_NOW); - H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen, + H2BUGF(infof(data_s, "h2 header: %.*s: %.*s", namelen, name, valuelen, value)); return 0; /* 0 is successful */ @@ -1156,7 +1160,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session, return NGHTTP2_ERR_DEFERRED; H2BUGF(infof(data_s, "data_source_read_callback: " - "returns %zu bytes stream %u\n", + "returns %zu bytes stream %u", nread, stream_id)); return nread; @@ -1223,7 +1227,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) (void)nghttp2_session_send(httpc->h2); if(http->stream_id == httpc->pause_stream_id) { - infof(data, "stopped the pause stream!\n"); + infof(data, "stopped the pause stream!"); httpc->pause_stream_id = 0; } } @@ -1236,7 +1240,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) int rv = nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0); if(rv) { - infof(data, "http/2: failed to clear user_data for stream %d!\n", + infof(data, "http/2: failed to clear user_data for stream %d!", http->stream_id); DEBUGASSERT(0); } @@ -1383,7 +1387,7 @@ static int h2_process_pending_input(struct Curl_easy *data, if(nread == rv) { H2BUGF(infof(data, "h2_process_pending_input: All data in connection buffer " - "processed\n")); + "processed")); httpc->inbuflen = 0; httpc->nread_inbuf = 0; } @@ -1391,7 +1395,7 @@ static int h2_process_pending_input(struct Curl_easy *data, httpc->nread_inbuf += rv; H2BUGF(infof(data, "h2_process_pending_input: %zu bytes left in connection " - "buffer\n", + "buffer", httpc->inbuflen - httpc->nread_inbuf)); } @@ -1412,7 +1416,7 @@ static int h2_process_pending_input(struct Curl_easy *data, if(should_close_session(httpc)) { struct HTTP *stream = data->req.p.http; H2BUGF(infof(data, - "h2_process_pending_input: nothing to do in this session\n")); + "h2_process_pending_input: nothing to do in this session")); if(stream->error) *err = CURLE_HTTP2; else { @@ -1456,7 +1460,7 @@ CURLcode Curl_http2_done_sending(struct Curl_easy *data, struct SingleRequest *k = &data->req; int rv; - H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data)); + H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)", data)); /* and attempt to send the pending frames */ rv = h2_session_send(data, h2); @@ -1495,7 +1499,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ stream->closed = FALSE; if(stream->error == NGHTTP2_REFUSED_STREAM) { - H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", + H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!", stream->stream_id)); connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ data->state.refused_stream = TRUE; @@ -1544,7 +1548,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, stream->close_handled = TRUE; - H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); + H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close")); return 0; } @@ -1587,7 +1591,7 @@ static int h2_session_send(struct Curl_easy *data, h2_pri_spec(data, &pri_spec); - H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n", + H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)", stream->stream_id, data)); DEBUGASSERT(stream->stream_id != -1); rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id, @@ -1611,7 +1615,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(should_close_session(httpc)) { H2BUGF(infof(data, - "http2_recv: nothing to do in this session\n")); + "http2_recv: nothing to do in this session")); if(conn->bits.close) { /* already marked for closure, return OK and we're done */ *err = CURLE_OK; @@ -1621,10 +1625,6 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } - if(stream->closed) - /* closed overrides paused */ - return http2_handle_stream_close(conn, data, stream, err); - /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ stream->upload_mem = NULL; @@ -1645,12 +1645,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, stream->nread_header_recvbuf, ncopy); stream->nread_header_recvbuf += ncopy; - H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n", + H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf", (int)ncopy)); return ncopy; } - H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n", + H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u", data, stream->stream_id, nghttp2_session_get_local_window_size(httpc->h2), nghttp2_session_get_stream_local_window_size(httpc->h2, @@ -1658,7 +1658,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, )); if((data->state.drain) && stream->memlen) { - H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n", + H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)", stream->memlen, stream->stream_id, stream->mem, mem)); if(mem != stream->mem) { @@ -1686,7 +1686,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, stream->pauselen -= nread; if(stream->pauselen == 0) { - H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id)); + H2BUGF(infof(data, "Unpaused by stream %u", stream->stream_id)); DEBUGASSERT(httpc->pause_stream_id == stream->stream_id); httpc->pause_stream_id = 0; @@ -1704,7 +1704,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } } - H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n", + H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u", nread, stream->stream_id)); return nread; } @@ -1720,7 +1720,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(stream->closed) /* closed overrides paused */ return 0; - H2BUGF(infof(data, "stream %x is paused, pause id: %x\n", + H2BUGF(infof(data, "stream %x is paused, pause id: %x", stream->stream_id, httpc->pause_stream_id)); *err = CURLE_AGAIN; return -1; @@ -1758,12 +1758,12 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, return -1; } - H2BUGF(infof(data, "end of stream\n")); + H2BUGF(infof(data, "end of stream")); *err = CURLE_OK; return 0; } - H2BUGF(infof(data, "nread=%zd\n", nread)); + H2BUGF(infof(data, "nread=%zd", nread)); httpc->inbuflen = nread; @@ -1772,7 +1772,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, else { nread = httpc->inbuflen - httpc->nread_inbuf; (void)nread; /* silence warning, used in debug */ - H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n", + H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd", nread)); } @@ -1781,14 +1781,14 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, } if(stream->memlen) { ssize_t retlen = stream->memlen; - H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n", + H2BUGF(infof(data, "http2_recv: returns %zd for stream %u", retlen, stream->stream_id)); stream->memlen = 0; if(httpc->pause_stream_id == stream->stream_id) { /* data for this stream is returned now, but this stream caused a pause already so we need it called again asap */ - H2BUGF(infof(data, "Data returned for PAUSED stream %u\n", + H2BUGF(infof(data, "Data returned for PAUSED stream %u", stream->stream_id)); } else if(!stream->closed) { @@ -1803,7 +1803,7 @@ static ssize_t http2_recv(struct Curl_easy *data, int sockindex, if(stream->closed) return http2_handle_stream_close(conn, data, stream, err); *err = CURLE_AGAIN; - H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n", + H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u", stream->stream_id)); return -1; } @@ -1907,11 +1907,11 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, (void)sockindex; - H2BUGF(infof(data, "http2_send len=%zu\n", len)); + H2BUGF(infof(data, "http2_send len=%zu", len)); if(stream->stream_id != -1) { if(stream->close_handled) { - infof(data, "stream %d closed\n", stream->stream_id); + infof(data, "stream %d closed", stream->stream_id); *err = CURLE_HTTP2_STREAM; return -1; } @@ -1940,7 +1940,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, stream->upload_len = 0; if(should_close_session(httpc)) { - H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session")); *err = CURLE_HTTP2; return -1; } @@ -1953,7 +1953,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, nghttp2_session_resume_data(h2, stream->stream_id); } - H2BUGF(infof(data, "http2_send returns %zu for stream %u\n", len, + H2BUGF(infof(data, "http2_send returns %zu for stream %u", len, stream->stream_id)); return len; } @@ -2116,7 +2116,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, for(i = 0; i < nheader; ++i) { acc += nva[i].namelen + nva[i].valuelen; - H2BUGF(infof(data, "h2 header: %.*s:%.*s\n", + H2BUGF(infof(data, "h2 header: %.*s:%.*s", nva[i].namelen, nva[i].name, nva[i].valuelen, nva[i].value)); } @@ -2124,13 +2124,13 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, if(acc > MAX_ACC) { infof(data, "http2_send: Warning: The cumulative length of all " "headers exceeds %d bytes and that could cause the " - "stream to be rejected.\n", MAX_ACC); + "stream to be rejected.", MAX_ACC); } } h2_pri_spec(data, &pri_spec); - H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)\n", + H2BUGF(infof(data, "http2_send request allowed %d (easy handle %p)", nghttp2_session_check_request_allowed(h2), (void *)data)); switch(data->state.httpreq) { @@ -2158,20 +2158,20 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, if(stream_id < 0) { H2BUGF(infof(data, - "http2_send() nghttp2_submit_request error (%s)%d\n", + "http2_send() nghttp2_submit_request error (%s)%d", nghttp2_strerror(stream_id), stream_id)); *err = CURLE_SEND_ERROR; return -1; } - infof(data, "Using Stream ID: %x (easy handle %p)\n", + infof(data, "Using Stream ID: %x (easy handle %p)", stream_id, (void *)data); stream->stream_id = stream_id; rv = h2_session_send(data, h2); if(rv) { H2BUGF(infof(data, - "http2_send() nghttp2_session_send error (%s)%d\n", + "http2_send() nghttp2_session_send error (%s)%d", nghttp2_strerror(rv), rv)); *err = CURLE_SEND_ERROR; @@ -2179,7 +2179,7 @@ static ssize_t http2_send(struct Curl_easy *data, int sockindex, } if(should_close_session(httpc)) { - H2BUGF(infof(data, "http2_send: nothing to do in this session\n")); + H2BUGF(infof(data, "http2_send: nothing to do in this session")); *err = CURLE_HTTP2; return -1; } @@ -2215,6 +2215,22 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS); Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS); + stream->upload_left = 0; + stream->upload_mem = NULL; + stream->upload_len = 0; + stream->mem = data->state.buffer; + stream->len = data->set.buffer_size; + + httpc->inbuflen = 0; + httpc->nread_inbuf = 0; + + httpc->pause_stream_id = 0; + httpc->drain_total = 0; + + multi_connchanged(data->multi); + /* below this point only connection related inits are done, which only needs + to be done once per connection */ + if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) return CURLE_OK; /* already done */ @@ -2230,25 +2246,13 @@ CURLcode Curl_http2_setup(struct Curl_easy *data, return result; } - infof(data, "Using HTTP2, server supports multi-use\n"); - stream->upload_left = 0; - stream->upload_mem = NULL; - stream->upload_len = 0; - stream->mem = data->state.buffer; - stream->len = data->set.buffer_size; - - httpc->inbuflen = 0; - httpc->nread_inbuf = 0; - - httpc->pause_stream_id = 0; - httpc->drain_total = 0; + infof(data, "Using HTTP2, server supports multiplexing"); conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ conn->httpversion = 20; conn->bundle->multiuse = BUNDLE_MULTIPLEX; - infof(data, "Connection state changed (HTTP/2 confirmed)\n"); - multi_connchanged(data->multi); + infof(data, "Connection state changed (HTTP/2 confirmed)"); return CURLE_OK; } @@ -2287,7 +2291,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, stream->stream_id, data); if(rv) { - infof(data, "http/2: failed to set user_data for stream %d!\n", + infof(data, "http/2: failed to set user_data for stream %d!", stream->stream_id); DEBUGASSERT(0); } @@ -2327,7 +2331,7 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, } infof(data, "Copying HTTP/2 data in stream buffer to connection buffer" - " after upgrade: len=%zu\n", + " after upgrade: len=%zu", nread); if(nread) @@ -2337,15 +2341,8 @@ CURLcode Curl_http2_switched(struct Curl_easy *data, DEBUGASSERT(httpc->nread_inbuf == 0); - /* Good enough to call it an end once the remaining payload is copied to the - * connection buffer. - * Some servers (e.g. nghttpx v1.43.0) may fulfill stream 1 immediately - * following the protocol switch other than waiting for the client-side - * connection preface. If h2_process_pending_input is invoked here to parse - * the remaining payload, stream 1 would be marked as closed too early and - * thus ignored in http2_recv (following 252790c53). - * The logic in lib/http.c and lib/transfer.c guarantees a following - * http2_recv would be invoked very soon. */ + if(-1 == h2_process_pending_input(data, httpc, &result)) + return CURLE_HTTP2; return CURLE_OK; } @@ -2378,7 +2375,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) if(rv) return CURLE_SEND_ERROR; - DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n", + DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u", window, stream->stream_id)); #ifdef DEBUGBUILD @@ -2387,7 +2384,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause) uint32_t window2 = nghttp2_session_get_stream_local_window_size(httpc->h2, stream->stream_id); - DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n", + DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u", window2, stream->stream_id)); } #endif |