diff options
author | Max Dymond <max.dymond@metaswitch.com> | 2017-05-31 14:00:45 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2017-06-30 10:27:41 +0200 |
commit | c98e97e9c32b7c55d9002860655bdd7fb5eefd66 (patch) | |
tree | c075e1f692ea3e486d4ad3081aa87a5b842064d0 | |
parent | c75f63d7c432ab42614c05f8a8081edf4beb9ee9 (diff) |
http2: handle PING frames
Add a connection check function to HTTP2 based off RTSP. This causes
PINGs to be handled the next time the connection is reused.
Closes #1521
-rw-r--r-- | lib/http2.c | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/lib/http2.c b/lib/http2.c index a93348641..0e5580133 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -28,6 +28,7 @@ #include "http2.h" #include "http.h" #include "sendf.h" +#include "select.h" #include "curl_base64.h" #include "strcase.h" #include "multiif.h" @@ -151,6 +152,49 @@ static CURLcode http2_disconnect(struct connectdata *conn, return CURLE_OK; } +/* + * The server may send us data at any point (e.g. PING frames). Therefore, + * we cannot assume that an HTTP/2 socket is dead just because it is readable. + * + * 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) +{ + int sval; + bool ret_val = TRUE; + + sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0); + if(sval == 0) { + /* timeout */ + ret_val = FALSE; + } + else if(sval & CURL_CSELECT_ERR) { + /* socket is in an error state */ + ret_val = TRUE; + } + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + ret_val = !Curl_connalive(check); + } + + return ret_val; +} + + +static unsigned int http2_conncheck(struct connectdata *check, + unsigned int checks_to_perform) +{ + unsigned int ret_val = CONNRESULT_NONE; + + if(checks_to_perform & CONNCHECK_ISDEAD) { + if(http2_connisdead(check)) + ret_val |= CONNRESULT_DEAD; + } + + return ret_val; +} + /* called from Curl_http_setup_conn */ void Curl_http2_setup_req(struct Curl_easy *data) { @@ -196,7 +240,7 @@ static const struct Curl_handler Curl_handler_http2 = { http2_perform_getsock, /* perform_getsock */ http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ - ZERO_NULL, /* connection_check */ + http2_conncheck, /* connection_check */ PORT_HTTP, /* defport */ CURLPROTO_HTTP, /* protocol */ PROTOPT_STREAM /* flags */ @@ -217,7 +261,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = { http2_perform_getsock, /* perform_getsock */ http2_disconnect, /* disconnect */ ZERO_NULL, /* readwrite */ - ZERO_NULL, /* connection_check */ + http2_conncheck, /* connection_check */ PORT_HTTP, /* defport */ CURLPROTO_HTTPS, /* protocol */ PROTOPT_SSL | PROTOPT_STREAM /* flags */ |