]> granicus.if.org Git - curl/commitdiff
http2: handle PING frames
authorMax Dymond <max.dymond@metaswitch.com>
Wed, 31 May 2017 13:00:45 +0000 (14:00 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 30 Jun 2017 08:27:41 +0000 (10:27 +0200)
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

lib/http2.c

index a93348641ceae5b4ad984dee38ee083cea018126..0e5580133fcbd6c75cd2a1103fa5eb6747e7321f 100644 (file)
@@ -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 */