ithewei пре 6 година
родитељ
комит
61f4061083
5 измењених фајлова са 68 додато и 9 уклоњено
  1. 29 4
      http/Http2Session.cpp
  2. 7 2
      http/Http2Session.h
  3. 9 3
      http/HttpSession.cpp
  4. 3 0
      http/HttpSession.h
  5. 20 0
      http/server/HttpServer.cpp

+ 29 - 4
http/Http2Session.cpp

@@ -44,7 +44,6 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
 
 
 Http2Session::Http2Session(http_session_type type) {
-    this->type = type;
     if (cbs == NULL) {
         nghttp2_session_callbacks_new(&cbs);
         nghttp2_session_callbacks_set_on_header_callback(cbs, on_header_callback);
@@ -57,7 +56,6 @@ Http2Session::Http2Session(http_session_type type) {
     }
     else if (type == HTTP_SERVER) {
         nghttp2_session_server_new(&session, cbs, NULL);
-        state = HSS_SEND_SETTINGS;
     }
     nghttp2_session_set_user_data(session, this);
     submited = NULL;
@@ -70,6 +68,9 @@ Http2Session::Http2Session(http_session_type type) {
     };
     nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, settings, ARRAY_SIZE(settings));
     state = HSS_SEND_SETTINGS;
+
+    //nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
+    //state = HSS_SEND_PING;
 }
 
 Http2Session::~Http2Session() {
@@ -152,7 +153,7 @@ int Http2Session::GetSendData(char** data, size_t* len) {
     else if (state == HSS_SEND_DATA) {
         state = HSS_SEND_DONE;
         if (submited->ContentType() == APPLICATION_GRPC) {
-            if (type == HTTP_SERVER) {
+            if (type == HTTP_SERVER && stream_closed) {
                 // grpc HEADERS grpc-status
                 printd("grpc HEADERS grpc-status-----------------\n");
                 int flags = NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS;
@@ -169,6 +170,7 @@ int Http2Session::GetSendData(char** data, size_t* len) {
 
 int Http2Session::FeedRecvData(const char* data, size_t len) {
     printd("nghttp2_session_mem_recv %d\n", len);
+    state = HSS_RECVING;
     size_t ret = nghttp2_session_mem_recv(session, (const uint8_t*)data, len);
     if (ret != len) {
         error = ret;
@@ -177,7 +179,13 @@ int Http2Session::FeedRecvData(const char* data, size_t len) {
 }
 
 bool Http2Session::WantRecv() {
-    return stream_id == -1 || stream_closed == 0;
+    if (stream_id == -1) return true;
+    if (stream_closed) return false;
+    if (state == HSS_RECV_DATA ||
+        state == HSS_RECV_PING) {
+        return false;
+    }
+    return true;
 }
 
 int Http2Session::SubmitRequest(HttpRequest* req) {
@@ -248,6 +256,8 @@ int Http2Session::SubmitResponse(HttpResponse* res) {
             res->headers["content-type"] = http_content_type_str(APPLICATION_GRPC);
         }
         //res->headers["accept-encoding"] = "identity";
+        //hss->state = HSS_RECV_PING;
+        //break;
         //res->headers["grpc-accept-encoding"] = "identity";
         //res->headers["grpc-status"] = "0";
 #ifdef TEST_PROTOBUF
@@ -395,7 +405,22 @@ int on_frame_recv_callback(nghttp2_session *session,
             hss->stream_closed = 1;
         }
         break;
+    default:
+        break;
+    }
+
+    switch (frame->hd.type) {
+    case NGHTTP2_DATA:
+        hss->state = HSS_RECV_DATA;
+        break;
+    case NGHTTP2_HEADERS:
+        hss->state = HSS_RECV_HEADERS;
+        break;
+    case NGHTTP2_SETTINGS:
+        hss->state = HSS_RECV_SETTINGS;
+        break;
     case NGHTTP2_PING:
+        hss->state = HSS_RECV_PING;
         break;
     default:
         break;

+ 7 - 2
http/Http2Session.h

@@ -11,15 +11,20 @@
 enum http2_session_state {
     HSS_SEND_MAGIC,
     HSS_SEND_SETTINGS,
+    HSS_SEND_PING,
     HSS_SEND_HEADERS,
     HSS_SEND_DATA_FRAME_HD,
     HSS_SEND_DATA,
-    HSS_SEND_DONE
+    HSS_SEND_DONE,
+    HSS_RECVING,
+    HSS_RECV_SETTINGS,
+    HSS_RECV_PING,
+    HSS_RECV_HEADERS,
+    HSS_RECV_DATA,
 };
 
 class Http2Session : public HttpSession {
 public:
-    http_session_type               type;
     static nghttp2_session_callbacks* cbs;
     nghttp2_session*                session;
     http2_session_state             state;

+ 9 - 3
http/HttpSession.cpp

@@ -4,16 +4,22 @@
 #include "Http2Session.h"
 
 HttpSession* HttpSession::New(http_session_type type, http_version version) {
+    HttpSession* hs = NULL;
     if (version == HTTP_V1) {
-        return new Http1Session(type);
+        hs = new Http1Session(type);
     }
     else if (version == HTTP_V2) {
 #ifdef WITH_NGHTTP2
-        return new Http2Session(type);
+        hs = new Http2Session(type);
 #else
         fprintf(stderr, "Please recompile WITH_NGHTTP2!\n");
 #endif
     }
 
-    return NULL;
+    if (hs) {
+        hs->version = version;
+        hs->type = type;
+    }
+
+    return hs;
 }

+ 3 - 0
http/HttpSession.h

@@ -5,6 +5,9 @@
 
 class HttpSession {
 public:
+    http_version        version;
+    http_session_type   type;
+
     static HttpSession* New(http_session_type type = HTTP_CLIENT, http_version version = HTTP_V1);
     virtual ~HttpSession() {}
 

+ 20 - 0
http/server/HttpServer.cpp

@@ -7,6 +7,7 @@
 #include "http2def.h"
 #include "FileCache.h"
 #include "HttpHandler.h"
+#include "Http2Session.h"
 
 #define RECV_BUFSIZE    8192
 #define SEND_BUFSIZE    8192
@@ -88,6 +89,25 @@ static void on_recv(hio_t* io, void* _buf, int readbytes) {
         return;
     }
 
+    if (session->version == HTTP_V2) {
+        // HTTP2 extra processing steps
+        Http2Session* h2s = (Http2Session*)session;
+        if (h2s->state == HSS_RECV_PING) {
+            char* data = NULL;
+            size_t len = 0;
+            while (session->GetSendData(&data, &len)) {
+                hio_write(io, data, len);
+            }
+            return;
+        }
+        else if (
+                h2s->state != HSS_RECV_HEADERS &&
+                h2s->state != HSS_RECV_DATA) {
+            // ignore other http2 frame
+            return;
+        }
+    }
+
     // Upgrade: h2
     auto iter_upgrade = req->headers.find("upgrade");
     if (iter_upgrade != req->headers.end()) {