serf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1709280 - /serf/trunk/protocols/http2_protocol.c
Date Sun, 18 Oct 2015 14:00:16 GMT
Author: rhuijben
Date: Sun Oct 18 14:00:16 2015
New Revision: 1709280

URL: http://svn.apache.org/viewvc?rev=1709280&view=rev
Log:
Implement a basic frame parser for the http2 protocol. This currently
parses a SETTINGS and WINDOW_UPDATE frame when used against one of the
google servers via serf_get's --http2 mode.

* serf-dev/dev/protocols/http2_protocol.c
  (HTTP2_DEFAULT_MAX_FRAME_SIZE,
   HTTP2_FLAG_PADDED): New defines.
  (serf_http2_procotol_state_t): Add some state variables.
  (http2_read): New function that just reads all http2 frames encountered
    on the connection.
  (http2_protocol_read): Call http2_read.

Modified:
    serf/trunk/protocols/http2_protocol.c

Modified: serf/trunk/protocols/http2_protocol.c
URL: http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1709280&r1=1709279&r2=1709280&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Sun Oct 18 14:00:16 2015
@@ -41,10 +41,20 @@ http2_protocol_hangup(serf_connection_t
 static void
 http2_protocol_teardown(serf_connection_t *conn);
 
+#define HTTP2_DEFAULT_MAX_FRAME_SIZE 16384
+
+#define HTTP2_FLAG_PADDED 0x08
+
 typedef struct serf_http2_procotol_state_t
 {
   apr_pool_t *pool;
 
+  char buffer[HTTP2_DEFAULT_MAX_FRAME_SIZE];
+  apr_size_t buffer_used;
+  serf_bucket_t *cur_frame;
+  serf_bucket_t *cur_payload;
+  int in_payload;
+
 } serf_http2_procotol_state_t;
 
 static apr_status_t
@@ -78,11 +88,121 @@ void serf__http2_protocol_init(serf_conn
 }
 
 static apr_status_t
+http2_read(serf_connection_t *conn)
+{
+  serf_http2_procotol_state_t *ctx = conn->protocol_baton;
+  apr_status_t status = APR_SUCCESS;
+
+  while (TRUE)
+    {
+      status = APR_SUCCESS;
+
+      if (ctx->cur_frame)
+        {
+          const char *data;
+          apr_size_t len;
+
+          if (! ctx->in_payload)
+            {
+              unsigned char flags;
+
+              status = serf_bucket_http2_unframe_read_info(ctx->cur_frame,
+                                                           NULL, NULL, &flags);
+
+              if (!SERF_BUCKET_READ_ERROR(status))
+                {
+                  ctx->in_payload = TRUE;
+
+                  if (flags & HTTP2_FLAG_PADDED)
+                    {
+                      ctx->cur_payload =
+                        serf_bucket_http2_unpad_create(
+                              ctx->cur_frame, TRUE,
+                              ctx->cur_frame->allocator);
+                    }
+                  else
+                    ctx->cur_payload = ctx->cur_frame;
+                }
+
+              if (status)
+                break;
+            }
+
+          status = serf_bucket_read(ctx->cur_frame,
+                                    sizeof(ctx->buffer) - ctx->buffer_used,
+                                    &data, &len);
+
+          if (!SERF_BUCKET_READ_ERROR(status))
+            {
+              memcpy(&ctx->buffer[ctx->buffer_used], data, len);
+              ctx->buffer_used += len;
+            }
+
+          if (APR_STATUS_IS_EOF(status))
+            {
+              apr_int32_t streamid;
+              unsigned char frametype;
+              unsigned char flags;
+
+              status = serf_bucket_http2_unframe_read_info(ctx->cur_frame,
+                                                           &streamid, &frametype,
+                                                           &flags);
+              serf__log(LOGLVL_INFO, LOGCOMP_CONN, __FILE__, conn->config,
+                        "Read 0x%02x http2 frame on stream 0x%x, flags=0x%x\n",
+                        (int)frametype, (int)streamid, (int)flags);
+
+              serf_bucket_destroy(ctx->cur_payload);
+              ctx->cur_frame = ctx->cur_payload = NULL;
+              ctx->in_payload = FALSE;
+              ctx->buffer_used = 0;
+            }
+          else if (status)
+            break;
+        }
+
+      if (APR_STATUS_IS_EOF(status))
+        {
+          const char *data;
+          apr_size_t len;
+          status = serf_bucket_peek(conn->stream, &data, &len);
+
+          if (SERF_BUCKET_READ_ERROR(status)
+              || APR_STATUS_IS_EOF(status))
+            {
+              /* We have a real EOF*/
+              break;
+            }
+        }
+
+      ctx->cur_frame = ctx->cur_payload =
+            serf_bucket_http2_unframe_create(conn->stream, FALSE,
+                                             HTTP2_DEFAULT_MAX_FRAME_SIZE,
+                                             conn->stream->allocator);
+    }
+
+  return status;
+}
+
+static apr_status_t
 http2_protocol_read(serf_connection_t *conn)
 {
-  /* serf_http2_procotol_state_t *ctx = conn->protocol_baton; */
+  apr_status_t status = http2_read(conn);
 
-  return APR_EGENERAL;
+  if (!status)
+    return APR_SUCCESS;
+  else if (APR_STATUS_IS_EOF(status))
+    {
+      /* TODO: Teardown connection, reset if necessary, etc. */
+      return status;
+    }
+  else if (APR_STATUS_IS_EAGAIN(status)
+           || status == SERF_ERROR_WAIT_CONN)
+    {
+      /* Update pollset, etc. etc. */
+      return APR_SUCCESS;
+    }
+  else
+    return status;
 }
 
 static apr_status_t
@@ -90,7 +210,7 @@ http2_protocol_write(serf_connection_t *
 {
   /* serf_http2_procotol_state_t *ctx = conn->protocol_baton; */
 
-  return APR_EGENERAL;
+  return APR_SUCCESS;
 }
 
 static apr_status_t



Mime
View raw message