mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
http2: more stream-oriented data, stream ID 0 is for connections
This commit is contained in:
parent
2c238ea1fc
commit
84c6b6561f
@ -168,6 +168,8 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
|
||||
http->status_code = -1;
|
||||
http->data = NULL;
|
||||
http->datalen = 0;
|
||||
http->error_code = NGHTTP2_NO_ERROR;
|
||||
http->closed = FALSE;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
@ -164,6 +164,8 @@ struct HTTP {
|
||||
int status_code; /* HTTP status code */
|
||||
const uint8_t *data; /* pointer to data chunk, received in on_data_chunk */
|
||||
size_t datalen; /* the number of bytes left in data */
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
uint32_t error_code; /* HTTP/2 error code */
|
||||
};
|
||||
|
||||
typedef int (*sending)(void); /* Curl_send */
|
||||
@ -179,8 +181,6 @@ struct http_conn {
|
||||
size_t len; /* size of the buffer 'mem' points to */
|
||||
sending send_underlying; /* underlying send Curl_send callback */
|
||||
recving recv_underlying; /* underlying recv Curl_recv callback */
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
uint32_t error_code; /* HTTP/2 error code */
|
||||
char *inbuf; /* buffer to receive data from underlying socket */
|
||||
/* We need separate buffer for transmission and reception because we
|
||||
may call nghttp2_session_send() after the
|
||||
|
45
lib/http2.c
45
lib/http2.c
@ -379,23 +379,30 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code, void *userp)
|
||||
{
|
||||
struct connectdata *conn = (struct connectdata *)userp;
|
||||
struct http_conn *c = &conn->proto.httpc;
|
||||
struct HTTP *stream = conn->data->req.protop;
|
||||
struct SessionHandle *data_s;
|
||||
struct HTTP *stream;
|
||||
(void)session;
|
||||
(void)stream_id;
|
||||
DEBUGF(infof(conn->data, "on_stream_close() was called, error_code = %d\n",
|
||||
error_code));
|
||||
DEBUGF(infof(conn->data, "on_stream_close(), error_code = %d, stream %x\n",
|
||||
error_code, stream_id));
|
||||
|
||||
if(stream_id != stream->stream_id) {
|
||||
DEBUGF(infof(conn->data, "on_stream_close() "
|
||||
"got stream %x, expected stream %x\n",
|
||||
stream_id, stream->stream_id));
|
||||
return 0;
|
||||
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,
|
||||
sizeof(stream_id));
|
||||
if(!data_s) {
|
||||
/* Receiving a Stream ID not in the hash should not happen, this is an
|
||||
internal error more than anything else! */
|
||||
failf(conn->data, "Received frame on Stream ID: %x not in stream hash!",
|
||||
stream_id);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
stream = data_s->req.protop;
|
||||
|
||||
c->error_code = error_code;
|
||||
c->closed = TRUE;
|
||||
|
||||
stream->error_code = error_code;
|
||||
stream->closed = TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -732,10 +739,10 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
|
||||
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
|
||||
|
||||
if(httpc->closed) {
|
||||
if(stream->closed) {
|
||||
/* Reset to FALSE to prevent infinite loop in readwrite_data
|
||||
function. */
|
||||
httpc->closed = FALSE;
|
||||
stream->closed = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -826,14 +833,14 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
}
|
||||
/* If stream is closed, return 0 to signal the http routine to close
|
||||
the connection */
|
||||
if(httpc->closed) {
|
||||
if(stream->closed) {
|
||||
/* Reset to FALSE to prevent infinite loop in readwrite_data
|
||||
function. */
|
||||
httpc->closed = FALSE;
|
||||
if(httpc->error_code != NGHTTP2_NO_ERROR) {
|
||||
stream->closed = FALSE;
|
||||
if(stream->error_code != NGHTTP2_NO_ERROR) {
|
||||
failf(conn->data,
|
||||
"HTTP/2 stream = %x was not closed cleanly: error_code = %d",
|
||||
stream->stream_id, httpc->error_code);
|
||||
stream->stream_id, stream->error_code);
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
@ -1058,8 +1065,6 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
|
||||
return result;
|
||||
|
||||
infof(conn->data, "Using HTTP2, server supports multi-use\n");
|
||||
httpc->error_code = NGHTTP2_NO_ERROR;
|
||||
httpc->closed = FALSE;
|
||||
httpc->upload_left = 0;
|
||||
httpc->upload_mem = NULL;
|
||||
httpc->upload_len = 0;
|
||||
|
@ -317,8 +317,7 @@ static int data_pending(const struct connectdata *conn)
|
||||
TRUE. The thing is if we read everything, then http2_recv won't
|
||||
be called and we cannot signal the HTTP/2 stream has closed. As
|
||||
a workaround, we return nonzero here to call http2_recv. */
|
||||
((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20 &&
|
||||
conn->proto.httpc.closed);
|
||||
((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion == 20);
|
||||
#else
|
||||
Curl_ssl_data_pending(conn, FIRSTSOCKET);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user