aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/http2.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/lib/http2.c b/lib/http2.c
index c15630eca..6758f9554 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -41,6 +41,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+#define H2_BUFSIZE 32768
#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
@@ -71,6 +72,16 @@
#define H2BUGF(x) do { } WHILE_FALSE
#endif
+
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err);
+static bool http2_connisdead(struct connectdata *conn);
+static int h2_session_send(struct Curl_easy *data,
+ nghttp2_session *h2);
+static int h2_process_pending_input(struct connectdata *conn,
+ struct http_conn *httpc,
+ CURLcode *err);
+
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
@@ -164,29 +175,51 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *check)
+static bool http2_connisdead(struct connectdata *conn)
{
int sval;
- bool ret_val = TRUE;
+ bool dead = TRUE;
- sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
+ if(conn->bits.close)
+ return TRUE;
+
+ sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
- ret_val = FALSE;
+ dead = FALSE;
}
else if(sval & CURL_CSELECT_ERR) {
/* socket is in an error state */
- ret_val = TRUE;
+ dead = TRUE;
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
- ret_val = !Curl_connalive(check);
+ dead = !Curl_connalive(conn);
+ if(!dead) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other thransfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t nread = ((Curl_recv *)httpc->recv_underlying)(
+ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ if(nread != -1) {
+ infof(conn->data,
+ "%d bytes stray data read before trying h2 connection\n",
+ (int)nread);
+ httpc->nread_inbuf = 0;
+ httpc->inbuflen = nread;
+ (void)h2_process_pending_input(conn, httpc, &result);
+ }
+ else
+ /* the read failed so let's say this is dead anyway */
+ dead = TRUE;
+ }
}
- return ret_val;
+ return dead;
}
-
static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
@@ -1039,8 +1072,6 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
return nread;
}
-#define H2_BUFSIZE 32768
-
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
static int error_callback(nghttp2_session *session,
const char *msg,
@@ -1227,9 +1258,6 @@ static int should_close_session(struct http_conn *httpc)
!nghttp2_session_want_write(httpc->h2);
}
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2);
-
/*
* h2_process_pending_input() processes pending input left in
* httpc->inbuf. Then, call h2_session_send() to send pending data.