Working example, no json query
authorJeroen van der Heijden <jeroen@transceptor.technology>
Thu, 9 Jan 2020 10:01:13 +0000 (11:01 +0100)
committerJeroen van der Heijden <jeroen@transceptor.technology>
Thu, 9 Jan 2020 10:01:13 +0000 (11:01 +0100)
24 files changed:
Debug/makefile
Debug/sources.mk
Debug/src/base64/subdir.mk [new file with mode: 0644]
Debug/src/qpjson/subdir.mk [new file with mode: 0644]
Debug/src/siri/subdir.mk
Release/makefile
Release/sources.mk
Release/src/base64/subdir.mk [new file with mode: 0644]
Release/src/qpjson/subdir.mk [new file with mode: 0644]
Release/src/siri/subdir.mk
include/qpjson/qpjson.h
include/siri/api.h
include/siri/db/db.h
include/siri/version.h
itest/test_http_api.py [new file with mode: 0644]
src/qpjson/qpjson.c
src/siri/api.c
src/siri/cfg/cfg.c
src/siri/db/db.c
src/siri/db/users.c
src/siri/heartbeat.c
src/siri/net/pkg.c
src/siri/net/stream.c
src/siri/siri.c

index e700a33055432525ebfcd2d65d02ff294d70140c..c43b8139d85ac0b24de1e3827cb3c71b6cccf890 100644 (file)
@@ -4,6 +4,7 @@ RM := rm -rf
 
 # All of the sources participating in the build are defined here
 -include sources.mk
+-include src/base64/subdir.mk
 -include src/xpath/subdir.mk
 -include src/xmath/subdir.mk
 -include src/timeit/subdir.mk
@@ -20,6 +21,7 @@ RM := rm -rf
 -include src/siri/args/subdir.mk
 -include src/siri/subdir.mk
 -include src/qpack/subdir.mk
+-include src/qpjson/subdir.mk
 -include src/procinfo/subdir.mk
 -include src/owcrypt/subdir.mk
 -include src/motd/subdir.mk
index 0e90c356fdf7d319fc87f1be17b0a672343732fe..35930d3fcefa2299821ba8df11a1a4c2b2484783 100644 (file)
@@ -11,6 +11,7 @@ C_DEPS :=
 SUBDIRS := \
 . \
 src/argparse \
+src/base64 \
 src/cexpr \
 src/cfgparser \
 src/ctree \
@@ -24,6 +25,7 @@ src/logger \
 src/owcrypt \
 src/procinfo \
 src/qpack \
+src/qpjson \
 src/siri/service \
 src/siri/args \
 src/siri \
diff --git a/Debug/src/base64/subdir.mk b/Debug/src/base64/subdir.mk
new file mode 100644 (file)
index 0000000..e9ad583
--- /dev/null
@@ -0,0 +1,20 @@
+# Add inputs and outputs from these tool invocations to the build variables
+C_SRCS += \
+../src/base64/base64.c
+
+OBJS += \
+./src/base64/base64.o
+
+C_DEPS += \
+./src/base64/base64.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/base64/%.o: ../src/base64/%.c
+       @echo 'Building file: $<'
+       @echo 'Invoking: GCC C Compiler'
+       gcc -I../include -O0 -g3 -Wall -Wextra $(CPPFLAGS) $(CFLAGS) -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
+       @echo 'Finished building: $<'
+       @echo ' '
+
+
diff --git a/Debug/src/qpjson/subdir.mk b/Debug/src/qpjson/subdir.mk
new file mode 100644 (file)
index 0000000..5a0007c
--- /dev/null
@@ -0,0 +1,20 @@
+# Add inputs and outputs from these tool invocations to the build variables
+C_SRCS += \
+../src/qpjson/qpjson.c
+
+OBJS += \
+./src/qpjson/qpjson.o
+
+C_DEPS += \
+./src/qpjson/qpjson.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/qpjson/%.o: ../src/qpjson/%.c
+       @echo 'Building file: $<'
+       @echo 'Invoking: GCC C Compiler'
+       gcc -I../include -O0 -g3 -Wall -Wextra $(CPPFLAGS) $(CFLAGS) -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
+       @echo 'Finished building: $<'
+       @echo ' '
+
+
index 1e4e9bb5a8277f0b011652df43f7da5a6fd19d05..0ee94fb2e54fac593334380a13da9026786b5779 100644 (file)
@@ -1,5 +1,6 @@
 # Add inputs and outputs from these tool invocations to the build variables
 C_SRCS += \
+../src/siri/api.c \
 ../src/siri/async.c \
 ../src/siri/backup.c \
 ../src/siri/buffersync.c \
@@ -11,6 +12,7 @@ C_SRCS += \
 ../src/siri/version.c
 
 OBJS += \
+./src/siri/api.o \
 ./src/siri/async.o \
 ./src/siri/backup.o \
 ./src/siri/buffersync.o \
@@ -22,6 +24,7 @@ OBJS += \
 ./src/siri/version.o
 
 C_DEPS += \
+./src/siri/api.d \
 ./src/siri/async.d \
 ./src/siri/backup.d \
 ./src/siri/buffersync.d \
index d6ca27fd3420e913bcd95a72b9c54f3b0a2f339e..cb978b7ba3f5cc0fce119f08bfad2fb13bad52f4 100644 (file)
@@ -4,6 +4,7 @@ RM := rm -rf
 
 # All of the sources participating in the build are defined here
 -include sources.mk
+-include src/base64/subdir.mk
 -include src/xpath/subdir.mk
 -include src/xmath/subdir.mk
 -include src/timeit/subdir.mk
@@ -20,6 +21,7 @@ RM := rm -rf
 -include src/siri/args/subdir.mk
 -include src/siri/subdir.mk
 -include src/qpack/subdir.mk
+-include src/qpjson/subdir.mk
 -include src/procinfo/subdir.mk
 -include src/owcrypt/subdir.mk
 -include src/motd/subdir.mk
index 0e90c356fdf7d319fc87f1be17b0a672343732fe..35930d3fcefa2299821ba8df11a1a4c2b2484783 100644 (file)
@@ -11,6 +11,7 @@ C_DEPS :=
 SUBDIRS := \
 . \
 src/argparse \
+src/base64 \
 src/cexpr \
 src/cfgparser \
 src/ctree \
@@ -24,6 +25,7 @@ src/logger \
 src/owcrypt \
 src/procinfo \
 src/qpack \
+src/qpjson \
 src/siri/service \
 src/siri/args \
 src/siri \
diff --git a/Release/src/base64/subdir.mk b/Release/src/base64/subdir.mk
new file mode 100644 (file)
index 0000000..31aeb9c
--- /dev/null
@@ -0,0 +1,20 @@
+# Add inputs and outputs from these tool invocations to the build variables
+C_SRCS += \
+../src/base64/base64.c
+
+OBJS += \
+./src/base64/base64.o
+
+C_DEPS += \
+./src/base64/base64.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/base64/%.o: ../src/base64/%.c
+       @echo 'Building file: $<'
+       @echo 'Invoking: GCC C Compiler'
+       gcc -DNDEBUG -I../include -O3 -Wall -Wextra $(CPPFLAGS) $(CFLAGS) -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
+       @echo 'Finished building: $<'
+       @echo ' '
+
+
diff --git a/Release/src/qpjson/subdir.mk b/Release/src/qpjson/subdir.mk
new file mode 100644 (file)
index 0000000..515d5b6
--- /dev/null
@@ -0,0 +1,20 @@
+# Add inputs and outputs from these tool invocations to the build variables
+C_SRCS += \
+../src/qpjson/qpjson.c
+
+OBJS += \
+./src/qpjson/qpjson.o
+
+C_DEPS += \
+./src/qpjson/qpjson.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/qpjson/%.o: ../src/qpjson/%.c
+       @echo 'Building file: $<'
+       @echo 'Invoking: GCC C Compiler'
+       gcc -DNDEBUG -I../include -O3 -Wall -Wextra $(CPPFLAGS) $(CFLAGS) -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
+       @echo 'Finished building: $<'
+       @echo ' '
+
+
index e29641ded9ec48b39a49c8828ab1bb56fbdaa42e..d22d9d8aa64069db7e6637a50eca6aa0ec6d7182 100644 (file)
@@ -1,5 +1,6 @@
 # Add inputs and outputs from these tool invocations to the build variables
 C_SRCS += \
+../src/siri/api.c \
 ../src/siri/async.c \
 ../src/siri/backup.c \
 ../src/siri/buffersync.c \
@@ -11,6 +12,7 @@ C_SRCS += \
 ../src/siri/version.c
 
 OBJS += \
+./src/siri/api.o \
 ./src/siri/async.o \
 ./src/siri/backup.o \
 ./src/siri/buffersync.o \
@@ -22,6 +24,7 @@ OBJS += \
 ./src/siri/version.o
 
 C_DEPS += \
+./src/siri/api.d \
 ./src/siri/async.d \
 ./src/siri/backup.d \
 ./src/siri/buffersync.d \
index b83a93453fc8308641d9949398a2ed958f7fe928..629e05e090cf9d67d4120620ed10be1a23a04d7f 100644 (file)
@@ -17,7 +17,7 @@ enum
 
 
 yajl_gen_status qpjson_qp_to_json(
-        const void * src,
+        void * src,
         size_t src_n,
         unsigned char ** dst,
         size_t * dst_n,
index 901575f2a63d3f8f22b253695517d2b8745da0d3..09551e1f2cb13a31e18495b8bc8d474a22e54099 100644 (file)
@@ -6,14 +6,7 @@
 
 #include <lib/http_parser.h>
 #include <uv.h>
-
-
-typedef enum
-{
-    SIRIDB_API_STATE_NONE,
-    SIRIDB_API_STATE_CONTENT_TYPE,
-    SIRIDB_API_STATE_AUTHORIZATION,
-} siridb_api_state_t;
+#include <siri/db/db.h>
 
 typedef enum
 {
@@ -21,43 +14,27 @@ typedef enum
     SIRIDB_API_CT_JSON,
 } siridb_api_content_t;
 
-typedef enum
-{
-    SIRIDB_API_FLAG_IS_CLOSED       =1<<0,
-    SIRIDB_API_FLAG_IN_USE          =1<<1,
-    SIRIDB_API_FLAG_JSON_BEAUTY     =1<<2,
-    SIRIDB_API_FLAG_JSON_UTF8       =1<<3,
-} siridb_api_flags_t;
-
 typedef struct siri_api_request_s siri_api_request_t;
 
+typedef int (*on_state_cb_t)(siri_api_request_t * ar, const char * at, size_t n);
+
 int siri_api_init(void);
-void siri_ali_close(siri_api_request_t * web_request);
-static inline _Bool siri_api_is_handle(uv_handle_t * handle);
+int siri_api_send(siri_api_request_t * ar, unsigned char * src, size_t n);
 
 struct siri_api_request_s
 {
     uint32_t tp;        /* maps to siridb_tee_t flags for cleanup */
     uint32_t ref;
-    on_data_cb_t on_data;
+    on_state_cb_t on_state;
     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;
     http_parser parser;
+    uv_write_t req;
 };
 
-static inline _Bool siri_api_is_handle(uv_handle_t * handle)
-{
-    return
-        handle->type == UV_TCP &&
-        handle->data &&
-        (((siri_api_request_t *) handle->data)->ref_ & SIRIDB_API_FLAG);
-}
-
 #endif /* SIRI_API_H_ */
index 0b183cd932c1822a9f153e2962ea615f5dae10c7..b5b5a3fe9491c86d8a9fc11a9965910c52c61b53 100644 (file)
@@ -44,6 +44,7 @@ int8_t siridb_get_idle_percentage(siridb_t * siridb);
 int siridb_is_db_path(const char * dbpath);
 siridb_t * siridb_new(const char * dbpath, int lock_flags);
 siridb_t * siridb_get(llist_t * siridb_list, const char * dbname);
+siridb_t * siridb_getn(llist_t * siridb_list, const char * dbname, size_t n);
 siridb_t * siridb_get_by_qp(llist_t * siridb_list, qp_obj_t * qp_dbname);
 int siridb_decref_cb(siridb_t * siridb, void * args);
 ssize_t siridb_get_file(char ** buffer, siridb_t * siridb);
index c1ff0cac1c61b2abfb60111a0d6288a0ba6febec..36fc27505190bc33f310c470b5c4c397e2980b87 100644 (file)
@@ -15,7 +15,7 @@
  * Note that debian alpha packages should use versions like this:
  *   2.0.34-0alpha0
  */
-#define SIRIDB_VERSION_PRE_RELEASE "-alpha-1"
+#define SIRIDB_VERSION_PRE_RELEASE "-alpha-2"
 
 #ifndef NDEBUG
 #define SIRIDB_VERSION_BUILD_RELEASE "+debug"
diff --git a/itest/test_http_api.py b/itest/test_http_api.py
new file mode 100644 (file)
index 0000000..dfe4074
--- /dev/null
@@ -0,0 +1,16 @@
+import requests
+import json
+
+data = {
+    'q': 'select * from *'
+}
+
+x = requests.post(
+    f'http://localhost:9020/query/dbtest',
+    data=json.dumps(data),
+    auth=('iris', 'siri'),
+    headers={'Content-Type': 'application/json'}
+)
+
+
+print(x.content)
\ No newline at end of file
index 76eff9af1c071f2decea547afff0cd086d01de74..da854953e47ae6cb04c1da69d06298d9c51eb736 100644 (file)
 /*
  * qpjson.c - Convert between QPack and JSON
  */
-
+#include <assert.h>
 #include <qpjson/qpjson.h>
+#include <qpack/qpack.h>
 
-yajl_gen_status mpjson_mp_to_json(
-        const void * src,
+static yajl_gen_status qp__to_json(yajl_gen g, qp_unpacker_t * up, qp_obj_t * obj)
+{
+    switch (obj->tp)
+    {
+    case QP_ERR:
+    case QP_ARRAY_CLOSE:
+    case QP_MAP_CLOSE:
+    case QP_END:
+        /* END, ARRAY_CLOSE and MAP_CLOSE should never occur since they can
+         * only happen after "*OPEN", and this case is handled in the *OPEN
+         * parts itself
+         */
+        return yajl_gen_in_error_state;
+    case QP_INT64:
+        return yajl_gen_integer(g, obj->via.int64);
+    case QP_DOUBLE:
+        return yajl_gen_double(g, obj->via.real);
+    case QP_RAW:
+        return yajl_gen_string(
+                g, (unsigned char *) obj->via.raw, obj->len);
+    case QP_TRUE:
+        return yajl_gen_bool(g, 1 /* true */);
+    case QP_FALSE:
+        return yajl_gen_bool(g, 0 /* false */);
+    case QP_NULL:
+        return yajl_gen_null(g);
+    case QP_ARRAY0:
+    case QP_ARRAY1:
+    case QP_ARRAY2:
+    case QP_ARRAY3:
+    case QP_ARRAY4:
+    case QP_ARRAY5:
+    {
+        size_t i = obj->tp - QP_ARRAY0;
+
+        yajl_gen_status stat;
+        if ((stat = yajl_gen_array_open(g)) != yajl_gen_status_ok)
+            return stat;
+
+        while (i--)
+        {
+            qp_next(up, obj);
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+        }
+
+        return yajl_gen_array_close(g);
+    }
+    case QP_MAP0:
+    case QP_MAP1:
+    case QP_MAP2:
+    case QP_MAP3:
+    case QP_MAP4:
+    case QP_MAP5:
+    {
+        size_t i = obj->tp - QP_MAP0;
+        yajl_gen_status stat;
+        if ((stat = yajl_gen_map_open(g)) != yajl_gen_status_ok)
+            return stat;
+
+        while (i--)
+        {
+            qp_next(up, obj);
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+
+            qp_next(up, obj);
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+        }
+
+        return yajl_gen_map_close(g);
+    }
+    case QP_ARRAY_OPEN:
+    {
+        yajl_gen_status stat;
+        if ((stat = yajl_gen_array_open(g)) != yajl_gen_status_ok)
+            return stat;
+
+        while(qp_next(up, obj) && obj->tp != QP_ARRAY_CLOSE)
+        {
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+        }
+
+        return yajl_gen_array_close(g);
+    }
+    case QP_MAP_OPEN:
+    {
+        yajl_gen_status stat;
+        if ((stat = yajl_gen_map_open(g)) != yajl_gen_status_ok)
+            return stat;
+
+        while(qp_next(up, obj) && obj->tp != QP_MAP_CLOSE)
+        {
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+
+            qp_next(up, obj);
+            if ((stat = qp__to_json(g, up, obj)) != yajl_gen_status_ok)
+                return stat;
+        }
+        return yajl_gen_map_close(g);
+    }
+    }
+    return yajl_gen_in_error_state;
+}
+
+
+yajl_gen_status qpjson_qp_to_json(
+        void * src,
         size_t src_n,
         unsigned char ** dst,
         size_t * dst_n,
         int flags)
+{
+    qp_unpacker_t up;
+    qp_obj_t obj;
+    yajl_gen g;
+    yajl_status stat;
+
+    assert (src_n);
+    qp_unpacker_init(&up, src, src_n);
+
+    g = yajl_gen_alloc(NULL);
+    if (!g)
+        return yajl_gen_in_error_state;
+
+    yajl_gen_config(g, yajl_gen_beautify, flags & QPJSON_FLAG_BEAUTIFY);
+    yajl_gen_config(g, yajl_gen_validate_utf8, flags & QPJSON_FLAG_VALIDATE_UTF8);
+
+    qp_next(&up, &obj);
+
+    assert (obj.tp != QP_END);
+
+    if ((stat = qp__to_json(g, &up, &obj)) == yajl_status_ok)
+    {
+        const unsigned char * tmp;
+        yajl_gen_get_buf(g, &tmp, dst_n);
+        *dst = malloc(*dst_n);
+        if (*dst)
+            memcpy(*dst, tmp, *dst_n);
+        else
+            stat = yajl_gen_in_error_state;
+    }
+
+    yajl_gen_free(g);
+    return stat;
+}
+
+
+yajl_status qpjson_json_to_qp(
+        const void * src,
+        size_t src_n,
+        char ** dst,
+        size_t * dst_n)
+{
+    yajl_handle hand;
+    yajl_status stat = yajl_status_error;
+    qp_packer_t * packer = qp_packer_new(src_n);
+    if (!packer)
+        return stat;
+
+//    hand = yajl_alloc(&callbacks, NULL, c);
+//    if (!hand)
+//        goto fail1;
+//
+//    stat = yajl_parse(hand, src, src_n);
+//    if (stat == yajl_status_ok)
+//        take_buffer(&buffer, dst, dst_n);
+//    yajl_free(hand);
+
+    qp_packer_free(packer);
+    return stat;
+}
index 1f30e6c177166253c5a65458923e6de92712a789..58e9523ebfd28f40ff6b919065be79349ff40aaa 100644 (file)
@@ -2,7 +2,11 @@
  * api.c
  */
 #include <siri/api.h>
+#include <assert.h>
 #include <siri/siri.h>
+#include <siri/db/users.h>
+#include <qpjson/qpjson.h>
+#include <siri/db/query.h>
 
 #define API__HEADER_MAX_SZ 256
 #define CONTENT_TYPE_JSON "application/json"
@@ -10,6 +14,9 @@
 static uv_tcp_t api__uv_server;
 static http_parser_settings api__settings;
 
+#define API__ICMP_WITH(__s, __n, __w) \
+    __n == strlen(__w) && strncasecmp(__s, __w, __n) == 0
+
 static const char api__content_type[2][20] = {
         "text/plain",
         "application/json",
@@ -49,6 +56,24 @@ typedef enum
     E503_SERVICE_UNAVAILABLE
 } api__header_t;
 
+inline static int api__header(
+        char * ptr,
+        const api__header_t ht,
+        const siridb_api_content_t ct,
+        size_t content_length)
+{
+    int len = sprintf(
+        ptr,
+        "HTTP/1.1 %s\r\n" \
+        "Content-Type: %s\r\n" \
+        "Content-Length: %zu\r\n" \
+        "\r\n",
+        api__html_header[ht],
+        api__content_type[ct],
+        content_length);
+    return len;
+}
+
 static inline _Bool api__starts_with(
         const char ** str,
         size_t * strn,
@@ -56,15 +81,17 @@ static inline _Bool api__starts_with(
         size_t withn)
 {
     if (*strn < withn || strncasecmp(*str, with, withn))
+    {
         return false;
+    }
     *str += withn;
     *strn -= withn;
     return true;
 }
 
 static void api__alloc_cb(
-        uv_handle_t * UNUSED(handle),
-        size_t UNUSED(sugsz),
+        uv_handle_t * UNUSED_handle __attribute__((unused)),
+        size_t UNUSED_sugsz __attribute__((unused)),
         uv_buf_t * buf)
 {
     buf->base = malloc(HTTP_MAX_HEADER_SIZE);
@@ -79,7 +106,7 @@ static void api__data_cb(
     size_t parsed;
     siri_api_request_t * ar = uvstream->data;
 
-    if (ar->flags & SIRIDB_API_FLAG_IS_CLOSED)
+    if (!ar->ref)
         goto done;
 
     if (n < 0)
@@ -87,7 +114,6 @@ static void api__data_cb(
         if (n != UV_EOF)
             log_error(uv_strerror(n));
 
-        ar->flags |= SIRIDB_API_FLAG_IS_CLOSED;
         sirinet_stream_decref(ar);
         goto done;
     }
@@ -107,7 +133,6 @@ static void api__data_cb(
     else if (parsed != (size_t) n)
     {
         log_warning("error parsing HTTP API request");
-        ar->flags |= SIRIDB_API_FLAG_IS_CLOSED;
         sirinet_stream_decref(ar);
     }
 
@@ -123,8 +148,9 @@ static int api__headers_complete_cb(http_parser * parser)
 
     ar->buf = malloc(parser->content_length);
     if (ar->len)
+    {
         ar->len = parser->content_length;
-
+    }
     return 0;
 }
 
@@ -132,7 +158,14 @@ static int api__url_cb(http_parser * parser, const char * at, size_t n)
 {
     siri_api_request_t * ar = parser->data;
 
-
+    if (api__starts_with(&at, &n, "/query/", strlen("/query/")))
+    {
+        ar->siridb = siridb_getn(siri.siridb_list, at, n);
+        if (ar->siridb)
+        {
+            siridb_incref(ar->siridb);
+        }
+    }
 
     return 0;
 }
@@ -166,7 +199,8 @@ static void api__connection_cb(uv_stream_t * server, int status)
     }
 
     ar->tp = STREAM_API_CLIENT;
-    ar->on_data = NULL;
+    ar->ref = 1;
+    ar->on_state = NULL;
 
     (void) uv_tcp_init(siri.loop, (uv_tcp_t *) ar->stream);
 
@@ -177,7 +211,7 @@ static void api__connection_cb(uv_stream_t * server, int status)
     if (rc)
     {
         log_error("cannot accept HTTP API request: `%s`", uv_strerror(rc));
-        ti_api_close(ar);
+        sirinet_stream_decref(ar);
         return;
     }
 
@@ -187,78 +221,68 @@ static void api__connection_cb(uv_stream_t * server, int status)
     if (rc)
     {
         log_error("cannot read HTTP API request: `%s`", uv_strerror(rc));
-        ti_api_close(ar);
+        sirinet_stream_decref(ar);
         return;
     }
 }
 
-static int api__header_field_cb(http_parser * parser, const char * at, size_t n)
+static int api__on_content_type(siri_api_request_t * ar, const char * at, size_t n)
 {
-    siri_api_request_t * ar = parser->data;
-
-    if (API__ICMP_WITH(at, n, "content-type"))
+    if (API__ICMP_WITH(at, n, CONTENT_TYPE_JSON))
     {
-        ar->state = SIRIDB_API_STATE_CONTENT_TYPE;
+        ar->content_type = SIRIDB_API_CT_JSON;
         return 0;
     }
 
-    if (API__ICMP_WITH(at, n, "authorization"))
+    if (API__ICMP_WITH(at, n, "text/json"))
     {
-        ar->state = SIRIDB_API_STATE_AUTHORIZATION;
+        ar->content_type = SIRIDB_API_CT_JSON;
         return 0;
     }
 
-    ar->state = SIRIDB_API_STATE_NONE;
+    /* invalid content type */
+    log_debug("unsupported content-type: %.*s", (int) n, at);
     return 0;
 }
 
-static int api__header_value_cb(http_parser * parser, const char * at, size_t n)
+static int api__on_authorization(siri_api_request_t * ar, const char * at, size_t n)
 {
-    siri_api_request_t * ar = parser->data;
+    if (api__starts_with(&at, &n, "token ", strlen("token ")))
+    {
+        log_debug("token authorization is not supported yet");
+    }
 
-    switch (ar->state)
+    if (api__starts_with(&at, &n, "basic ", strlen("basic ")))
     {
-    case SIRIDB_API_STATE_NONE:
-        break;
+        siridb_user_t * user;
+        user = siridb_users_get_user_from_basic(ar->siridb, at, n);
 
-    case SIRIDB_API_STATE_CONTENT_TYPE:
-        if (API__ICMP_WITH(at, n, CONTENT_TYPE_JSON))
+        if (user)
         {
-            ar->content_type = SIRIDB_API_CT_JSON;
-            break;
+            siridb_user_incref(user);
+            ar->origin = user;
         }
-        if (API__ICMP_WITH(at, n, "text/json"))
-        {
-            ar->content_type = SIRIDB_API_CT_JSON;
-            break;
-        }
-
-        /* invalid content type */
-        log_debug("unsupported content-type: %.*s", (int) n, at);
-        break;
+        return 0;
+    }
 
-    case SIRIDB_API_STATE_AUTHORIZATION:
-        if (api__starts_with(&at, &n, "token ", strlen("token ")))
-        {
-            log_debug("token authorization is not supported yet");
-        }
+    log_debug("invalid authorization type: %.*s", (int) n, at);
+    return 0;
+}
+static int api__header_value_cb(http_parser * parser, const char * at, size_t n)
+{
+    siri_api_request_t * ar = parser->data;
+    return ar->on_state ? ar->on_state(ar, at, n) : 0;
+}
 
-        if (api__starts_with(&at, &n, "basic ", strlen("basic ")))
-        {
-            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;
-        }
+static int api__header_field_cb(http_parser * parser, const char * at, size_t n)
+{
+    siri_api_request_t * ar = parser->data;
 
-        log_debug("invalid authorization type: %.*s", (int) n, at);
-        break;
-    }
+    ar->on_state = API__ICMP_WITH(at, n, "content-type")
+            ? api__on_content_type
+            : API__ICMP_WITH(at, n, "authorization")
+            ? api__on_authorization
+            : NULL;
     return 0;
 }
 
@@ -285,7 +309,6 @@ static void api__write_cb(uv_write_t * req, int status)
                 uv_strerror(status));
 
     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)
@@ -298,8 +321,6 @@ 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] = {
@@ -307,12 +328,25 @@ 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(req, ar->stream, uvbufs, 2, api__write_cb);
+        (void) uv_write(&ar->req, ar->stream, uvbufs, 2, api__write_cb);
         return 0;
     }
     return -1;
 }
 
+static int api__query(siri_api_request_t * ar)
+{
+    const char q[100] = "select * from 'aggr'";
+
+    siridb_query_run(
+                    0,
+                    (sirinet_stream_t *) ar,
+                    q, strlen(q),
+                    0.0,
+                    SIRIDB_QUERY_FLAG_MASTER);
+    return 0;
+}
+
 static int api__message_complete_cb(http_parser * parser)
 {
     siri_api_request_t * ar = parser->data;
@@ -325,17 +359,11 @@ static int api__message_complete_cb(http_parser * parser)
 
     switch (ar->content_type)
     {
+    case SIRIDB_API_CT_TEXT:
+        /* Or, shall we allow text and return we some sort of CSV format? */
+        return api__plain_response(ar, E400_BAD_REQUEST);
     case SIRIDB_API_CT_JSON:
-    {
-        char * data;
-        size_t size;
-        if (qpjson_json_to_qp(ar->buf, ar->len, &data, &size))
-            return api__plain_response(ar, E400_BAD_REQUEST);
-
-        free(ar->buf);
-        ar->buf = data;
-        ar->len = size;
-    }
+        return api__query(ar);
     }
 
     return api__plain_response(ar, E500_INTERNAL_SERVER_ERROR);
@@ -353,6 +381,31 @@ static int api__chunk_complete_cb(http_parser * parser)
     return 0;
 }
 
+static void api__write_free_cb(uv_write_t * req, int status)
+{
+    free(req->data);
+    api__write_cb(req, status);
+}
+
+static int api__close_resp(siri_api_request_t * ar, void * data, size_t size)
+{
+    char header[API__HEADER_MAX_SZ];
+    int header_size = 0;
+
+    header_size = api__header(header, E200_OK, ar->content_type, size);
+
+    uv_buf_t uvbufs[2] = {
+            uv_buf_init(header, (unsigned int) header_size),
+            uv_buf_init(data, size),
+    };
+
+    /* bind response to request to we can free in the callback */
+    ar->req.data = data;
+
+    uv_write(&ar->req, ar->stream, uvbufs, 2, api__write_free_cb);
+    return 0;
+}
+
 int siri_api_init(void)
 {
     int rc;
@@ -393,3 +446,36 @@ int siri_api_init(void)
     log_info("start listening for HTTP API requests on TCP port %u", port);
     return 0;
 }
+
+int siri_api_send(siri_api_request_t * ar, unsigned char * src, size_t n)
+{
+    unsigned char * data;
+    if (ar->content_type == SIRIDB_API_CT_JSON)
+    {
+        size_t tmp_sz;
+        yajl_gen_status stat = qpjson_qp_to_json(
+                src,
+                n,
+                &data,
+                &tmp_sz,
+                0);
+        if (stat)
+        {
+            // api__set_yajl_gen_status_error(&ar->e, stat);
+            // return ti_api_close_with_err(ar, &ar->e);
+            // TODO : return error
+            LOGC("HERE: %d", stat);
+        }
+        n = tmp_sz;
+    }
+    else
+    {
+        data = malloc(n);
+        if (data == NULL)
+        {
+            // TODO : return error
+        }
+        memcpy(data, src, n);
+    }
+    return api__close_resp(ar, data, n);
+}
index 1de320fc6c51cc44acc64c590b086e12735841ed..8fa1861d5b24823d33228a7af52c168c14c03380 100644 (file)
@@ -23,6 +23,7 @@
 
 static siri_cfg_t siri_cfg = {
         .http_status_port=0,    /* 0=disabled, 1-16535=enabled */
+        .http_api_port=9020,    /* 0=disabled, 1-16535=enabled */
         .listen_client_port=9000,
         .listen_backend_port=9010,
         .bind_client_addr=NULL,
index a9562660df6c9ab22914797cc4e3207cae949c4b..fb2c4bf597b6beb52f59f05c0b900afdd5474aa5 100644 (file)
@@ -530,6 +530,28 @@ siridb_t * siridb_get(llist_t * siridb_list, const char * dbname)
     return NULL;
 }
 
+/*
+ * Get a siridb object by name.
+ */
+siridb_t * siridb_getn(llist_t * siridb_list, const char * dbname, size_t n)
+{
+    llist_node_t * node = siridb_list->first;
+    siridb_t * siridb;
+
+    while (node != NULL)
+    {
+        siridb = (siridb_t *) node->data;
+        if (n == strlen(siridb->dbname) &&
+            strncmp(siridb->dbname, dbname, n) == 0)
+        {
+            return siridb;
+        }
+        node = node->next;
+    }
+
+    return NULL;
+}
+
 /*
  * Get a siridb object by qpack name.
  */
index 85e5de45297e7640270935a30073754ac4f6dd1c..1cc8ca0e7b853dacb91470f87a12d11f4c94930d 100644 (file)
@@ -18,6 +18,7 @@
 #include <xpath/xpath.h>
 #include <owcrypt/owcrypt.h>
 #include <siri/db/access.h>
+#include <base64/base64.h>
 
 
 #ifndef __APPLE__
@@ -256,19 +257,26 @@ siridb_user_t * siridb_users_get_user_from_basic(
 {
     size_t size;
     char * b64 = base64_decode(data, n, &size);
+    siridb_user_t * user = NULL;
 
-    for (size_t nn = 0, end = size; n < end; ++nn)
+    for (size_t nn = 0, end = size; nn < end; ++nn)
     {
         if (b64[nn] == ':')
         {
             b64[nn] = '\0';
 
             if (++nn > end)
-                return NULL;
+                break;
 
-            return siridb_users_get_user(siridb, b64, b64 + nn);
+            LOGC("User: %s Pass: %s", b64, b64 + nn);
+
+            user = siridb_users_get_user(siridb, b64, b64 + nn);
+            break;
         }
     }
+
+    free(b64);
+    return user;
 }
 
 /*
index f4ff0dce50e1a80b396b7affbdb4ba820cf23b7e..f0ed77804db34df93b33d82f578227ccf31fab4d 100644 (file)
@@ -84,6 +84,5 @@ static void HEARTBEAT_cb(uv_timer_t * handle __attribute__((unused)))
 
         siridb_node = siridb_node->next;
     }
-
 }
 
index 8ab559a889d695437b95250b6250aaa3e275b3d4..103cb6d36483afdf48c1b3d1160fc018533874fa 100644 (file)
@@ -4,6 +4,7 @@
 #include <assert.h>
 #include <logger/logger.h>
 #include <siri/err.h>
+#include <siri/api.h>
 #include <siri/net/pkg.h>
 #include <siri/net/clserver.h>
 #include <stddef.h>
@@ -134,6 +135,13 @@ sirinet_pkg_t * sirinet_pkg_err(
  */
 int sirinet_pkg_send(sirinet_stream_t * client, sirinet_pkg_t * pkg)
 {
+    if (client->tp == STREAM_API_CLIENT)
+    {
+        siri_api_send((siri_api_request_t *) client, pkg->data, pkg->len);
+        free(pkg);
+        return 0;
+    }
+
     uv_write_t * req = malloc(sizeof(uv_write_t));
 
     if (req == NULL)
index 471bd452a43027fa56b1b1e024447cb644b99003..7af4c6a7b7b049203d66d1d09f0c62703dfe0649 100644 (file)
@@ -140,6 +140,9 @@ void sirinet_stream_on_data(
     size_t total_sz;
     uint8_t check;
 
+    /* this functions should not be used for the API client */
+    assert (client->tp != STREAM_API_CLIENT);
+
     /*
      * client->on_data is NULL when 'sirinet_stream_decref' is called from
      * within this function. We should never call 'sirinet_stream_decref' twice
index 6049816a5d9fe83f4620cd4ba4a9416b80285362..60bb1e26f82a549e8b295d1838173929e176e9e7 100644 (file)
@@ -514,10 +514,6 @@ static void SIRI_walk_close_handlers(
             {
                 siri_health_close((siri_health_request_t *) handle->data);
             }
-            else if (siri_api_is_handle(handle))
-            {
-                siri_api_close((siri_api_request_t *) handle->data);
-            }
             else
             {
                 sirinet_stream_decref((sirinet_stream_t *) handle->data);