فهرست منبع

Add HttpHandler::error

ithewei 2 سال پیش
والد
کامیت
9b18255272
2فایلهای تغییر یافته به همراه34 افزوده شده و 13 حذف شده
  1. 30 13
      http/server/HttpHandler.cpp
  2. 4 0
      http/server/HttpHandler.h

+ 30 - 13
http/server/HttpHandler.cpp

@@ -22,6 +22,8 @@ using namespace hv;
 HttpHandler::HttpHandler(hio_t* io) :
     protocol(HttpHandler::UNKNOWN),
     state(WANT_RECV),
+    error(0),
+    // flags
     ssl(false),
     keepalive(true),
     proxy(false),
@@ -29,14 +31,17 @@ HttpHandler::HttpHandler(hio_t* io) :
     port(0),
     pid(0),
     tid(0),
+    // for http
     io(io),
     service(NULL),
     ws_service(NULL),
     api_handler(NULL),
-    last_send_ping_time(0),
-    last_recv_pong_time(0),
+    // for sendfile
     files(NULL),
-    file(NULL)
+    file(NULL),
+    // for websocket
+    last_send_ping_time(0),
+    last_recv_pong_time(0)
 {
     // Init();
 }
@@ -72,6 +77,7 @@ bool HttpHandler::Init(int http_version) {
     parser->InitRequest(req.get());
     // NOTE: hook http_cb
     req->http_cb = [this](HttpMessage* msg, http_parser_state state, const char* data, size_t size) {
+        if (this->state == WANT_CLOSE || this->error != 0) return;
         switch (state) {
         case HP_HEADERS_COMPLETE:
             onHeadersComplete();
@@ -98,6 +104,7 @@ bool HttpHandler::Init(int http_version) {
 
 void HttpHandler::Reset() {
     state = WANT_RECV;
+    error = 0;
     req->Reset();
     resp->Reset();
     ctx = NULL;
@@ -361,13 +368,13 @@ void HttpHandler::onMessageComplete() {
             if (io) hio_write(io, HTTP2_UPGRADE_RESPONSE, strlen(HTTP2_UPGRADE_RESPONSE));
             if (!SwitchHTTP2()) {
                 hloge("[%s:%d] unsupported HTTP2", ip, port);
-                if (io) hio_close(io);
+                error = ERR_INVALID_PROTOCOL;
                 return;
             }
         }
         else {
             hloge("[%s:%d] unsupported Upgrade: %s", upgrade_proto);
-            if (io) hio_close(io);
+            error = ERR_INVALID_PROTOCOL;
             return;
         }
     } else {
@@ -397,7 +404,7 @@ void HttpHandler::onMessageComplete() {
     if (upgrade && upgrade_protocol == HttpHandler::WEBSOCKET) {
         if (!SwitchWebSocket()) {
             hloge("[%s:%d] unsupported websocket", ip, port);
-            if (io) hio_close(io);
+            error = ERR_INVALID_PROTOCOL;
             return;
         }
         // onopen
@@ -409,7 +416,7 @@ void HttpHandler::onMessageComplete() {
         if (keepalive) {
             Reset();
         } else {
-            if (io) hio_close(io);
+            state = WANT_CLOSE;
         }
     }
 }
@@ -665,7 +672,6 @@ int HttpHandler::defaultErrorHandler() {
 }
 
 int HttpHandler::FeedRecvData(const char* data, size_t len) {
-    int nfeed = 0;
     if (protocol == HttpHandler::UNKNOWN) {
         int http_version = 1;
 #if WITH_NGHTTP2
@@ -676,21 +682,25 @@ int HttpHandler::FeedRecvData(const char* data, size_t len) {
         // check request-line
         if (len < MIN_HTTP_REQUEST_LEN) {
             hloge("[%s:%d] http request-line too small", ip, port);
-            return 0;
+            error = ERR_REQUEST;
+            return -1;
         }
         for (int i = 0; i < MIN_HTTP_REQUEST_LEN; ++i) {
             if (!IS_GRAPH(data[i])) {
                 hloge("[%s:%d] http request-line not plain", ip, port);
-                return 0;
+                error = ERR_REQUEST;
+                return -1;
             }
         }
 #endif
         if (!Init(http_version)) {
             hloge("[%s:%d] unsupported HTTP%d", ip, port, http_version);
-            return 0;
+            error = ERR_INVALID_PROTOCOL;
+            return -1;
         }
     }
 
+    int nfeed = 0;
     switch (protocol) {
     case HttpHandler::HTTP_V1:
     case HttpHandler::HTTP_V2:
@@ -700,20 +710,26 @@ int HttpHandler::FeedRecvData(const char* data, size_t len) {
         nfeed = parser->FeedRecvData(data, len);
         if (nfeed != len) {
             hloge("[%s:%d] http parse error: %s", ip, port, parser->StrError(parser->GetError()));
+            error = ERR_PARSE;
+            return -1;
         }
         break;
     case HttpHandler::WEBSOCKET:
         nfeed = ws_parser->FeedRecvData(data, len);
         if (nfeed != len) {
             hloge("[%s:%d] websocket parse error!", ip, port);
+            error = ERR_PARSE;
+            return -1;
         }
         break;
     default:
         hloge("[%s:%d] unknown protocol", ip, port);
-        return 0;
+        error = ERR_INVALID_PROTOCOL;
+        return -1;
     }
 
-    return nfeed;
+    if (state == WANT_CLOSE) return 0;
+    return error ? -1 : nfeed;
 }
 
 int HttpHandler::GetSendData(char** data, size_t* len) {
@@ -835,6 +851,7 @@ int HttpHandler::sendFile() {
     size_t nread = file->read(file->buf.base, readbytes);
     if (nread <= 0) {
         hloge("read file error!");
+        error = ERR_READ_FILE;
         writer->close(true);
         return nread;
     }

+ 4 - 0
http/server/HttpHandler.h

@@ -26,8 +26,12 @@ public:
         SEND_HEADER,
         SEND_BODY,
         SEND_DONE,
+        WANT_CLOSE,
     } state;
 
+    // errno
+    int                     error;
+
     // flags
     unsigned ssl:           1;
     unsigned keepalive:     1;