]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/http: refactor header_callback()
authorTomas Krizek <tomas.krizek@nic.cz>
Mon, 17 Aug 2020 11:42:44 +0000 (13:42 +0200)
committerTomas Krizek <tomas.krizek@nic.cz>
Tue, 13 Oct 2020 10:55:24 +0000 (12:55 +0200)
daemon/http.c

index f62fab143d9528d1e560835daa7bb51a9b2084ab..8c6748615253a99d86c877193c8ae6e2a952a8c5 100644 (file)
@@ -39,16 +39,61 @@ struct http_data_buffer {
        size_t pos;
 };
 
-static ssize_t send_callback(nghttp2_session *session, const uint8_t *data, size_t length, int flags, void *user_data)
+static ssize_t send_callback(nghttp2_session *session, const uint8_t *data, size_t length,
+                            int flags, void *user_data)
 {
        struct http_ctx *ctx = (struct http_ctx *)user_data;
        return ctx->send_cb(data, length, ctx->user_ctx);
 }
 
-static int header_callback(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags, void *user_data)
+/*
+ * Process a query from URI path if there's base64url encoded dns variable.
+ */
+static int process_uri_path(struct http_ctx *ctx, const char* path, int32_t stream_id)
 {
-       struct http_ctx *ctx = (struct http_ctx *)user_data;
+       if (!ctx || !path)
+               return kr_error(EINVAL);
+
        static const char key[] = "dns=";
+       char *beg = strstr((const char *)path, key);
+       char *end;
+       size_t remaining;
+       ssize_t ret;
+       uint8_t *dest;
+
+       if (!beg)  /* No dns variable in path. */
+               return 0;
+
+       beg += sizeof(key) - 1;
+       end = strchrnul(beg, '&');
+       ctx->buf_pos = sizeof(uint16_t);  /* Reserve 2B for dnsmsg len. */
+       remaining = ctx->buf_size - ctx->submitted - ctx->buf_pos;
+       dest = ctx->buf + ctx->buf_pos;
+
+       ret = kr_base64url_decode((uint8_t*)beg, end - beg, dest, remaining);
+       if (ret < 0) {
+               ctx->buf_pos = 0;
+               kr_log_verbose("[http] base64url decode failed %s\n",
+                              strerror(ret));
+               return ret;
+       }
+
+       ctx->buf_pos += ret;
+       queue_push(ctx->streams, stream_id);
+       return 0;
+}
+
+static void refuse_stream(nghttp2_session *session, int32_t stream_id)
+{
+       nghttp2_submit_rst_stream(
+               session, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_REFUSED_STREAM);
+}
+
+static int header_callback(nghttp2_session *session, const nghttp2_frame *frame,
+                          const uint8_t *name, size_t namelen, const uint8_t *value,
+                          size_t valuelen, uint8_t flags, void *user_data)
+{
+       struct http_ctx *ctx = (struct http_ctx *)user_data;
        int32_t stream_id = frame->hd.stream_id;
 
        /* If the HEADERS don't have END_STREAM set, there are some DATA frames,
@@ -59,29 +104,14 @@ static int header_callback(nghttp2_session *session, const nghttp2_frame *frame,
 
        /* If there is incomplete data in the buffer, we can't process the new stream. */
        if (ctx->incomplete_stream) {
-               kr_log_verbose("[http] refusing new http stream due to incomplete data from other stream\n");
-               nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_REFUSED_STREAM);
+               kr_log_verbose("[http] previous stream incomplete, refusing\n");
+               refuse_stream(session, stream_id);
                return 0;
        }
 
        if (!strcasecmp(":path", (const char *)name)) {
-               char *beg = strstr((const char *)value, key);
-               if (beg) {
-                       beg += sizeof(key) - 1;
-                       char *end = strchrnul(beg, '&');
-                       ctx->buf_pos = sizeof(uint16_t);
-                       ssize_t remaining = ctx->buf_size - ctx->submitted - ctx->buf_pos;
-                       uint8_t* dest = ctx->buf + ctx->buf_pos;
-                       ssize_t ret = kr_base64url_decode((uint8_t*)beg, end - beg, dest, remaining);
-                       if (ret < 0) {
-                               ctx->buf_pos = 0;
-                               nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_REFUSED_STREAM);
-                               kr_log_verbose("[http] refusing GET request, insufficient buffer size\n");
-                               return 0;
-                       }
-                       ctx->buf_pos += ret;
-                       queue_push(ctx->streams, stream_id);
-               }
+               if (process_uri_path(ctx, (const char*)value, stream_id) < 0)
+                       refuse_stream(session, stream_id);
        }
        return 0;
 }