also did some json code
authorJeroen van der Heijden <jeroen@transceptor.technology>
Tue, 7 Jan 2020 15:31:23 +0000 (16:31 +0100)
committerJeroen van der Heijden <jeroen@transceptor.technology>
Tue, 7 Jan 2020 15:31:23 +0000 (16:31 +0100)
Debug/objects.mk
Release/objects.mk
include/qpjson/qpjson.h
include/siri/api.h
include/siri/net/stream.h
src/qpjson/qpjson.c
src/siri/api.c
src/siri/net/stream.c

index 5a47d0bc8c710f8a53fb668aefce3823c6090a42..bc2d853e13faa22bde4299f8bfafd6f6ad3ab54b 100644 (file)
@@ -1,4 +1,4 @@
 USER_OBJS :=
 
-LIBS := -luv -lm -lpcre2-8 -lcleri
+LIBS := -luv -lm -lpcre2-8 -lcleri -lyajl
 
index 5a47d0bc8c710f8a53fb668aefce3823c6090a42..bc2d853e13faa22bde4299f8bfafd6f6ad3ab54b 100644 (file)
@@ -1,4 +1,4 @@
 USER_OBJS :=
 
-LIBS := -luv -lm -lpcre2-8 -lcleri
+LIBS := -luv -lm -lpcre2-8 -lcleri -lyajl
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b83a93453fc8308641d9949398a2ed958f7fe928 100644 (file)
@@ -0,0 +1,33 @@
+/*
+ * qpjson.h - Convert between QPack and JSON
+ */
+#ifndef QPJSON_H_
+#define QPJSON_H_
+
+#include <stddef.h>
+#include <yajl/yajl_gen.h>
+#include <yajl/yajl_parse.h>
+
+enum
+{
+    /* flags map to the API flags */
+    QPJSON_FLAG_BEAUTIFY        =1<<2,
+    QPJSON_FLAG_VALIDATE_UTF8   =1<<3,
+};
+
+
+yajl_gen_status qpjson_qp_to_json(
+        const void * src,
+        size_t src_n,
+        unsigned char ** dst,
+        size_t * dst_n,
+        int flags);
+
+yajl_status qpjson_json_to_qp(
+        const void * src,
+        size_t src_n,
+        char ** dst,
+        size_t * dst_n);
+
+
+#endif  /* QPJSON_H_ */
index 8a57d4dc9af2b237878d493e6f3236a2f847dcf1..901575f2a63d3f8f22b253695517d2b8745da0d3 100644 (file)
@@ -7,7 +7,6 @@
 #include <lib/http_parser.h>
 #include <uv.h>
 
-#define SIRIDB_API_FLAG 1<<29
 
 typedef enum
 {
@@ -38,17 +37,19 @@ static inline _Bool siri_api_is_handle(uv_handle_t * handle);
 
 struct siri_api_request_s
 {
-    uint32_t ref_;  /* maps to sirnet_stream_t for cleanup */
+    uint32_t tp;        /* maps to siridb_tee_t flags for cleanup */
+    uint32_t ref;
+    on_data_cb_t on_data;
+    siridb_t * siridb;
+    void * origin;      /* can be a user, server or NULL */
+    char * buf;
+    size_t len;
+    size_t size;
+    uv_stream_t * stream;
     siridb_api_flags_t flags;
     siridb_api_state_t state;
     siridb_api_content_t content_type;
-    size_t content_n;
-    uv_write_t req;
-    uv_stream_t uvstream;
     http_parser parser;
-    char * content;
-    siridb_t * siridb;
-    siridb_user_t * user;
 };
 
 static inline _Bool siri_api_is_handle(uv_handle_t * handle)
index c99db4664a4eb726b7f5ef5075bc1b6e957641b7..16c79b3ff787a455c5eed7a5c75069335c914834 100644 (file)
@@ -13,6 +13,7 @@ typedef enum
     STREAM_TCP_SERVER,
     STREAM_TCP_MANAGE,
     STREAM_PIPE_CLIENT,
+    STREAM_API_CLIENT,
 } sirinet_stream_tp_t;
 
 typedef struct sirinet_stream_s sirinet_stream_t;
@@ -43,9 +44,6 @@ void sirinet__stream_free(uv_stream_t * uvclient);
         (uv_handle_t *) (client)->stream,           \
         (uv_close_cb) sirinet__stream_free)
 
-#define sirinet_stream_is_pipe(client)      \
-    ((client)->tp == STREAM_PIPE_CLIENT)
-
 struct sirinet_stream_s
 {
     uint32_t tp;        /* maps to siridb_tee_t flags for cleanup */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..76eff9af1c071f2decea547afff0cd086d01de74 100644 (file)
@@ -0,0 +1,12 @@
+/*
+ * qpjson.c - Convert between QPack and JSON
+ */
+
+#include <qpjson/qpjson.h>
+
+yajl_gen_status mpjson_mp_to_json(
+        const void * src,
+        size_t src_n,
+        unsigned char ** dst,
+        size_t * dst_n,
+        int flags)
index 8e92dc883e702002c43fad59f95ff84acf82b4b4..1f30e6c177166253c5a65458923e6de92712a789 100644 (file)
@@ -62,17 +62,6 @@ static inline _Bool api__starts_with(
     return true;
 }
 
-static void api__close_cb(uv_handle_t * handle)
-{
-    siri_api_request_t * ar = handle->data;
-    if (ar->siridb)
-        siridb_decref(ar->siridb);
-    if (ar->user)
-        siridb_user_decref(ar->user);
-    free(ar->content);
-    free(ar);
-}
-
 static void api__alloc_cb(
         uv_handle_t * UNUSED(handle),
         size_t UNUSED(sugsz),
@@ -98,7 +87,8 @@ static void api__data_cb(
         if (n != UV_EOF)
             log_error(uv_strerror(n));
 
-        ti_api_close(ar);
+        ar->flags |= SIRIDB_API_FLAG_IS_CLOSED;
+        sirinet_stream_decref(ar);
         goto done;
     }
 
@@ -117,7 +107,8 @@ static void api__data_cb(
     else if (parsed != (size_t) n)
     {
         log_warning("error parsing HTTP API request");
-        ti_api_close(ar);
+        ar->flags |= SIRIDB_API_FLAG_IS_CLOSED;
+        sirinet_stream_decref(ar);
     }
 
 done:
@@ -128,11 +119,11 @@ static int api__headers_complete_cb(http_parser * parser)
 {
     siri_api_request_t * ar = parser->data;
 
-    assert (!ar->content);
+    assert (!ar->buf);
 
-    ar->content = malloc(parser->content_length);
-    if (ar->content)
-        ar->content_n = parser->content_length;
+    ar->buf = malloc(parser->content_length);
+    if (ar->len)
+        ar->len = parser->content_length;
 
     return 0;
 }
@@ -166,13 +157,23 @@ static void api__connection_cb(uv_stream_t * server, int status)
         return;
     }
 
-    (void) uv_tcp_init(siri.loop, (uv_tcp_t *) &ar->uvstream);
+    ar->stream = malloc(sizeof(uv_tcp_t));
+    if (!ar->stream)
+    {
+        free(ar);
+        ERR_ALLOC
+        return;
+    }
+
+    ar->tp = STREAM_API_CLIENT;
+    ar->on_data = NULL;
 
-    ar->flags |= SIRIDB_API_FLAG;
-    ar->uvstream.data = ar;
+    (void) uv_tcp_init(siri.loop, (uv_tcp_t *) ar->stream);
+
+    ar->stream->data = ar;
     ar->parser.data = ar;
 
-    rc = uv_accept(server, &ar->uvstream);
+    rc = uv_accept(server, ar->stream);
     if (rc)
     {
         log_error("cannot accept HTTP API request: `%s`", uv_strerror(rc));
@@ -182,7 +183,7 @@ static void api__connection_cb(uv_stream_t * server, int status)
 
     http_parser_init(&ar->parser, HTTP_REQUEST);
 
-    rc = uv_read_start(&ar->uvstream, api__alloc_cb, api__data_cb);
+    rc = uv_read_start(ar->stream, api__alloc_cb, api__data_cb);
     if (rc)
     {
         log_error("cannot read HTTP API request: `%s`", uv_strerror(rc));
@@ -244,11 +245,14 @@ static int api__header_value_cb(http_parser * parser, const char * at, size_t n)
 
         if (api__starts_with(&at, &n, "basic ", strlen("basic ")))
         {
-            ar->user = siridb_users_get_user_from_basic(ar->siridb, at, n);
-
-            if (ar->user)
-                siridb_user_incref(ar->user);
-
+            siridb_user_t * user;
+            user = siridb_users_get_user_from_basic(ar->siridb, at, n);
+
+            if (user)
+            {
+                siridb_user_incref(user);
+                ar->origin = user;
+            }
             break;
         }
 
@@ -263,12 +267,12 @@ static int api__body_cb(http_parser * parser, const char * at, size_t n)
     size_t offset;
     siri_api_request_t * ar = parser->data;
 
-    if (!n || !ar->content_n)
+    if (!n || !ar->len)
         return 0;
 
-    offset = ar->content_n - (parser->content_length + n);
-    assert (offset + n <= ar->content_n);
-    memcpy(ar->content + offset, at, n);
+    offset = ar->len - (parser->content_length + n);
+    assert (offset + n <= ar->len);
+    memcpy(ar->buf + offset, at, n);
 
     return 0;
 }
@@ -280,7 +284,8 @@ static void api__write_cb(uv_write_t * req, int status)
                 "error writing HTTP API response: `%s`",
                 uv_strerror(status));
 
-    ti_api_close((siri_api_request_t *) req->handle->data);
+    sirinet_stream_decref((siri_api_request_t *) req->handle->data);
+    free(req);
 }
 
 static int api__plain_response(siri_api_request_t * ar, const api__header_t ht)
@@ -292,6 +297,9 @@ static int api__plain_response(siri_api_request_t * ar, const api__header_t ht)
 
     body_size = strlen(body);
     header_size = api__header(header, ht, SIRIDB_API_CT_TEXT, body_size);
+
+    uv_write_t * req = malloc(sizeof(uv_write_t));
+
     if (header_size > 0)
     {
         uv_buf_t uvbufs[2] = {
@@ -299,11 +307,7 @@ static int api__plain_response(siri_api_request_t * ar, const api__header_t ht)
                 uv_buf_init((char *) body, body_size),
         };
 
-        (void) uv_write(
-                &ar->req,
-                &ar->uvstream,
-                uvbufs, 2,
-                api__write_cb);
+        (void) uv_write(req, ar->stream, uvbufs, 2, api__write_cb);
         return 0;
     }
     return -1;
@@ -313,7 +317,10 @@ static int api__message_complete_cb(http_parser * parser)
 {
     siri_api_request_t * ar = parser->data;
 
-    if (!ar->user)
+    if (!ar->siridb)
+        return api__plain_response(ar, E404_NOT_FOUND);
+
+    if (!ar->origin)
         return api__plain_response(ar, E401_UNAUTHORIZED);
 
     switch (ar->content_type)
@@ -322,12 +329,12 @@ static int api__message_complete_cb(http_parser * parser)
     {
         char * data;
         size_t size;
-        if (qpjson_json_to_qp(ar->content, ar->content_n, &data, &size))
+        if (qpjson_json_to_qp(ar->buf, ar->len, &data, &size))
             return api__plain_response(ar, E400_BAD_REQUEST);
 
-        free(ar->content);
-        ar->content = data;
-        ar->content_n = size;
+        free(ar->buf);
+        ar->buf = data;
+        ar->len = size;
     }
     }
 
@@ -386,30 +393,3 @@ int siri_api_init(void)
     log_info("start listening for HTTP API requests on TCP port %u", port);
     return 0;
 }
-
-siri_api_request_t * siri_api_acquire(siri_api_request_t * ar)
-{
-    ar->flags |= SIRIDB_API_FLAG_IN_USE;
-    return ar;
-}
-
-void ti_api_release(siri_api_request_t * ar)
-{
-    ar->flags &= ~SIRIDB_API_FLAG_IN_USE;
-
-    if (ar->flags & SIRIDB_API_FLAG_IS_CLOSED)
-        uv_close((uv_handle_t *) &ar->uvstream, api__close_cb);
-}
-
-void ti_api_close(siri_api_request_t * ar)
-{
-    if (!ar || (ar->flags & SIRIDB_API_FLAG_IS_CLOSED))
-        return;
-
-    ar->flags |= SIRIDB_API_FLAG_IS_CLOSED;
-
-    if (ar->flags & SIRIDB_API_FLAG_IN_USE)
-        return;
-
-    uv_close((uv_handle_t *) &ar->uvstream, api__close_cb);
-}
index f5d5a5c85d3263b78c64a0ca18d87ea9c8785d97..471bd452a43027fa56b1b1e024447cb644b99003 100644 (file)
@@ -51,6 +51,7 @@ sirinet_stream_t * sirinet_stream_new(sirinet_stream_tp_t tp, on_data_cb_t cb)
 
     switch(tp)
     {
+    case STREAM_API_CLIENT:
     case STREAM_TCP_CLIENT:
     case STREAM_TCP_BACKEND:
     case STREAM_TCP_SERVER:
@@ -87,6 +88,7 @@ char * sirinet_stream_name(sirinet_stream_t * client)
 {
     switch ((sirinet_stream_tp_t) client->tp)
     {
+    case STREAM_API_CLIENT:
     case STREAM_TCP_CLIENT:
     case STREAM_TCP_BACKEND:
     case STREAM_TCP_SERVER:
@@ -244,6 +246,7 @@ void sirinet__stream_free(uv_stream_t * uvclient)
 
     switch ((sirinet_stream_tp_t) client->tp)
     {
+    case STREAM_API_CLIENT:
     case STREAM_PIPE_CLIENT:
     case STREAM_TCP_CLIENT:  /* listens to client connections  */
         log_debug("client connection lost");