Add encoder for monitoring responses
authorJennifer Richards <jennifer@painless-security.com>
Wed, 11 Apr 2018 21:06:29 +0000 (17:06 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Wed, 11 Apr 2018 21:06:29 +0000 (17:06 -0400)
  * add response encoder
  * add partial test of response encoder
  * move tr_mon.h to include directory
  * move code common to req/resp from tr_mon_req.c to tr_mon.c
  * fix a couple warnings

15 files changed:
CMakeLists.txt
Makefile.am
include/tr_mon.h [moved from mon/tr_mon_req.h with 80% similarity]
mon/tests/resp_reconfigure_error.test [new file with mode: 0644]
mon/tests/resp_reconfigure_success.test [new file with mode: 0644]
mon/tests/resp_show_success.test [new file with mode: 0644]
mon/tests/test_mon_req_decode.c
mon/tests/test_mon_req_encode.c
mon/tests/test_mon_resp_encode.c [new file with mode: 0644]
mon/tr_mon.c [new file with mode: 0644]
mon/tr_mon_req.c
mon/tr_mon_req_decode.c
mon/tr_mon_req_encode.c
mon/tr_mon_resp.c [new file with mode: 0644]
mon/tr_mon_resp_encode.c [new file with mode: 0644]

index c97e39c..a0c2ff6 100644 (file)
@@ -90,14 +90,18 @@ set(SOURCE_FILES
     trp/trp_rtable.c
     trp/trp_upd.c
     trp/trpc.c
     trp/trp_rtable.c
     trp/trp_upd.c
     trp/trpc.c
-    trp/trps.c include/tr_name_internal.h mon/tr_mon_req.c mon/tr_mon_req.h mon/tr_mon_req_encode.c mon/tr_mon_req_decode.c)
+    trp/trps.c include/tr_name_internal.h mon/tr_mon_req.c mon/tr_mon_req_encode.c mon/tr_mon_req_decode.c
+        mon/tr_mon_resp.c mon/tr_mon.c mon/tr_mon_resp_encode.c)
 
 # Does not actually build!
 add_executable(trust_router ${SOURCE_FILES})
 
 # Test build targets - for debugging
 
 # Does not actually build!
 add_executable(trust_router ${SOURCE_FILES})
 
 # Test build targets - for debugging
-add_executable(test_mon_req_encode mon/tr_mon_req.c mon/tr_mon_req.h mon/tests/test_mon_req_encode.c mon/tr_mon_req_encode.c)
+add_executable(test_mon_req_encode mon/tr_mon.c mon/tr_mon_req.c mon/tests/test_mon_req_encode.c mon/tr_mon_req_encode.c)
 target_link_libraries(test_mon_req_encode jansson talloc glib-2.0)
 
 target_link_libraries(test_mon_req_encode jansson talloc glib-2.0)
 
-add_executable(test_mon_req_decode mon/tr_mon_req.c mon/tr_mon_req.h mon/tests/test_mon_req_decode.c mon/tr_mon_req_decode.c)
+add_executable(test_mon_req_decode mon/tr_mon.c mon/tr_mon_req.c mon/tests/test_mon_req_decode.c mon/tr_mon_req_decode.c)
 target_link_libraries(test_mon_req_decode jansson talloc glib-2.0)
 target_link_libraries(test_mon_req_decode jansson talloc glib-2.0)
+
+add_executable(test_mon_resp_encode mon/tr_mon.c mon/tr_mon_req.c mon/tr_mon_resp.c mon/tr_mon_resp_encode.c common/tr_name.c mon/tests/test_mon_resp_encode.c)
+target_link_libraries(test_mon_resp_encode jansson talloc glib-2.0)
index 2e27e3f..ddfd8d2 100644 (file)
@@ -1,9 +1,10 @@
+ACLOCAL_AMFLAGS = -I m4
 DISTCHECK_CONFIGURE_FLAGS = \
        --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/tests/tr_dh_test common/tests/mq_test \
               common/tests/thread_test trp/msgtst trp/test/rtbl_test trp/test/ptbl_test common/tests/cfg_test \
               common/tests/commtest common/tests/name_test common/tests/filt_test mon/tests/test_mon_req_encode \
 DISTCHECK_CONFIGURE_FLAGS = \
        --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/tests/tr_dh_test common/tests/mq_test \
               common/tests/thread_test trp/msgtst trp/test/rtbl_test trp/test/ptbl_test common/tests/cfg_test \
               common/tests/commtest common/tests/name_test common/tests/filt_test mon/tests/test_mon_req_encode \
-              mon/tests/test_mon_req_decode
+              mon/tests/test_mon_req_decode mon/tests/test_mon_resp_encode
 AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
 AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
 SUBDIRS = gsscon 
 AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
 AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
 SUBDIRS = gsscon 
@@ -37,9 +38,12 @@ common/tr_config.c \
 common/tr_mq.c
 
 mon_srcs =                      \
 common/tr_mq.c
 
 mon_srcs =                      \
+    mon/tr_mon.c                \
     mon/tr_mon_req.c            \
     mon/tr_mon_req_encode.c     \
     mon/tr_mon_req.c            \
     mon/tr_mon_req_encode.c     \
-    mon/tr_mon_req_decode.c
+    mon/tr_mon_req_decode.c     \
+    mon/tr_mon_resp.c           \
+    mon/tr_mon_resp_encode.c
 
 check_PROGRAMS = common/t_constraint
 TESTS = common/t_constraint
 
 check_PROGRAMS = common/t_constraint
 TESTS = common/t_constraint
@@ -171,15 +175,23 @@ common_tests_filt_test_LDFLAGS = $(AM_LDFLAGS) -ltalloc -pthread
 common_tests_filt_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
 mon_tests_test_mon_req_encode_SOURCES = mon/tests/test_mon_req_encode.c \
 common_tests_filt_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
 mon_tests_test_mon_req_encode_SOURCES = mon/tests/test_mon_req_encode.c \
-    $(mon_srcs)
+    $(mon_srcs) \
+    common/tr_name.c
 mon_tests_test_mon_req_encode_LDADD = $(GLIB_LIBS)
 mon_tests_test_mon_req_encode_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
 mon_tests_test_mon_req_decode_SOURCES = mon/tests/test_mon_req_decode.c \
 mon_tests_test_mon_req_encode_LDADD = $(GLIB_LIBS)
 mon_tests_test_mon_req_encode_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
 mon_tests_test_mon_req_decode_SOURCES = mon/tests/test_mon_req_decode.c \
-    $(mon_srcs)
+    $(mon_srcs) \
+    common/tr_name.c
 mon_tests_test_mon_req_decode_LDADD = $(GLIB_LIBS)
 mon_tests_test_mon_req_decode_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
 mon_tests_test_mon_req_decode_LDADD = $(GLIB_LIBS)
 mon_tests_test_mon_req_decode_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 
+mon_tests_test_mon_resp_encode_SOURCES = mon/tests/test_mon_resp_encode.c \
+    $(mon_srcs) \
+    common/tr_name.c
+mon_tests_test_mon_resp_encode_LDADD = $(GLIB_LIBS)
+mon_tests_test_mon_resp_encode_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
 pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
        include/tr_debug.h include/trust_router/trp.h \
        include/trust_router/tr_dh.h \
 pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
        include/tr_debug.h include/trust_router/trp.h \
        include/trust_router/tr_dh.h \
similarity index 80%
rename from mon/tr_mon_req.h
rename to include/tr_mon.h
index d32b262..dc255ba 100644 (file)
 #include <talloc.h>
 #include <jansson.h>
 #include <gmodule.h>
 #include <talloc.h>
 #include <jansson.h>
 #include <gmodule.h>
+#include <tr_name_internal.h>
 
 /* Typedefs */
 typedef struct tr_mon_req TR_MON_REQ;
 
 /* Typedefs */
 typedef struct tr_mon_req TR_MON_REQ;
+typedef struct tr_mon_resp TR_MON_RESP;
 
 typedef enum tr_mon_cmd TR_MON_CMD;
 
 typedef enum tr_mon_cmd TR_MON_CMD;
+typedef enum tr_mon_resp_code TR_MON_RESP_CODE;
 
 typedef struct tr_mon_opt TR_MON_OPT;
 typedef enum tr_mon_opt_type TR_MON_OPT_TYPE;
 
 typedef struct tr_mon_opt TR_MON_OPT;
 typedef enum tr_mon_opt_type TR_MON_OPT_TYPE;
@@ -66,6 +69,12 @@ enum tr_mon_cmd {
   MON_CMD_SHOW
 };
 
   MON_CMD_SHOW
 };
 
+/* These should be explicitly numbered because they form part of the public API */
+enum tr_mon_resp_code {
+  MON_RESP_SUCCESS=0,
+  MON_RESP_ERROR=1, // generic error
+};
+
 enum tr_mon_opt_type {
   OPT_TYPE_UNKNOWN=0,
 
 enum tr_mon_opt_type {
   OPT_TYPE_UNKNOWN=0,
 
@@ -92,25 +101,42 @@ struct tr_mon_req {
   GArray *options;
 };
 
   GArray *options;
 };
 
+struct tr_mon_resp {
+  TR_MON_REQ *req; // request this responds to
+  TR_MON_RESP_CODE code;
+  TR_NAME *message;
+  json_t *payload;
+};
+
 /* Prototypes */
 /* Prototypes */
+/* tr_mon.c */
+const char *cmd_to_string(TR_MON_CMD cmd);
+TR_MON_CMD cmd_from_string(const char *s);
+const char *opt_type_to_string(TR_MON_OPT_TYPE opt_type);
+TR_MON_OPT_TYPE opt_type_from_string(const char *s);
+
+/* tr_mon_req.c */
 TR_MON_REQ *tr_mon_req_new(TALLOC_CTX *mem_ctx, TR_MON_CMD cmd);
 void tr_mon_req_free(TR_MON_REQ *req);
 TR_MON_RC tr_mon_req_add_option(TR_MON_REQ *req, TR_MON_OPT_TYPE opt_type);
 size_t tr_mon_req_opt_count(TR_MON_REQ *req);
 TR_MON_OPT *tr_mon_req_opt_index(TR_MON_REQ *req, size_t index);
 
 TR_MON_REQ *tr_mon_req_new(TALLOC_CTX *mem_ctx, TR_MON_CMD cmd);
 void tr_mon_req_free(TR_MON_REQ *req);
 TR_MON_RC tr_mon_req_add_option(TR_MON_REQ *req, TR_MON_OPT_TYPE opt_type);
 size_t tr_mon_req_opt_count(TR_MON_REQ *req);
 TR_MON_OPT *tr_mon_req_opt_index(TR_MON_REQ *req, size_t index);
 
-const char *cmd_to_string(TR_MON_CMD cmd);
-TR_MON_CMD cmd_from_string(const char *s);
-
-const char *opt_type_to_string(TR_MON_OPT_TYPE opt_type);
-TR_MON_OPT_TYPE opt_type_from_string(const char *s);
-
 /* tr_mon_req_encode.c */
 json_t *tr_mon_req_encode(TR_MON_REQ *req);
 
 /* tr_mon_req_decode.c */
 TR_MON_REQ *tr_mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_json);
 
 /* tr_mon_req_encode.c */
 json_t *tr_mon_req_encode(TR_MON_REQ *req);
 
 /* tr_mon_req_decode.c */
 TR_MON_REQ *tr_mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_json);
 
-/* tr_mon_rec_decode.c */
+/* tr_mon_resp.c */
+TR_MON_RESP *tr_mon_resp_new(TALLOC_CTX *mem_ctx,
+                             TR_MON_REQ *req,
+                             TR_MON_RESP_CODE code,
+                             const char *msg,
+                             json_t *payload);
+void tr_mon_resp_free(TR_MON_RESP *resp);
+
+/* tr_mon_resp_encode.c */
+json_t *tr_mon_resp_encode(TR_MON_RESP *resp);
 
 #endif //TRUST_ROUTER_TR_MON_REQ_H
 
 #endif //TRUST_ROUTER_TR_MON_REQ_H
diff --git a/mon/tests/resp_reconfigure_error.test b/mon/tests/resp_reconfigure_error.test
new file mode 100644 (file)
index 0000000..3344bb1
--- /dev/null
@@ -0,0 +1 @@
+{"code": 1, "message": "error"}
diff --git a/mon/tests/resp_reconfigure_success.test b/mon/tests/resp_reconfigure_success.test
new file mode 100644 (file)
index 0000000..392c2e0
--- /dev/null
@@ -0,0 +1 @@
+{"code": 0, "message": "success"}
diff --git a/mon/tests/resp_show_success.test b/mon/tests/resp_show_success.test
new file mode 100644 (file)
index 0000000..bfbec19
--- /dev/null
@@ -0,0 +1 @@
+{"code": 0, "message": "success", "show": {"version": "1.2.3-4", "serial": 86400, "tid_req_pending": 13, "tid_req_count": 1432}}
index 5c1c279..38ee66f 100644 (file)
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <glib.h>
 
 #include <string.h>
 #include <glib.h>
 
-#include "../tr_mon_req.h"
+#include <tr_mon.h>
 
 /**
  * @return reconfigure command
 
 /**
  * @return reconfigure command
index c797cc0..60fe9ca 100644 (file)
@@ -8,7 +8,7 @@
 #include <string.h>
 #include <glib.h>
 
 #include <string.h>
 #include <glib.h>
 
-#include "../tr_mon_req.h"
+#include <tr_mon.h>
 
 #define JSON_DUMP_OPTS 0
 
 
 #define JSON_DUMP_OPTS 0
 
diff --git a/mon/tests/test_mon_resp_encode.c b/mon/tests/test_mon_resp_encode.c
new file mode 100644 (file)
index 0000000..9f9a3bb
--- /dev/null
@@ -0,0 +1,130 @@
+//
+// Created by jlr on 4/9/18.
+//
+
+#include <talloc.h>
+#include <jansson.h>
+#include <assert.h>
+#include <string.h>
+
+#include <tr_mon.h>
+
+#define JSON_DUMP_OPTS 0
+
+static char *reconfigure(TR_MON_RESP_CODE code, const char *message)
+{
+  TR_MON_REQ *req = NULL;
+  TR_MON_RESP *resp = NULL;
+  json_t *resp_json = NULL;
+  char *result = NULL;
+
+  req = tr_mon_req_new(NULL, MON_CMD_RECONFIGURE);
+  assert(req);
+
+  resp = tr_mon_resp_new(NULL, req, code, message, NULL);
+  assert(resp);
+
+  resp_json = tr_mon_resp_encode(resp);
+  assert(resp_json);
+
+  result = json_dumps(resp_json, JSON_DUMP_OPTS);
+  assert(result);
+
+  json_decref(resp_json);
+  tr_mon_resp_free(resp);
+  tr_mon_req_free(req);
+  return result;
+}
+
+static char *reconfigure_success()
+{
+  return reconfigure(MON_RESP_SUCCESS, "success");
+}
+
+static char *reconfigure_error()
+{
+  return reconfigure(MON_RESP_ERROR, "error");
+}
+
+static char *show_success()
+{
+  TR_MON_REQ *req = NULL;
+  TR_MON_RESP *resp = NULL;
+  json_t *resp_json = NULL;
+  json_t *payload = NULL;
+  char *result = NULL;
+
+  req = tr_mon_req_new(NULL, MON_CMD_SHOW);
+  // Only need the command to be set in req, don't actually need the options
+  assert(req);
+
+  payload = json_object();
+  assert(payload);
+  assert(! json_object_set_new(payload,
+                               opt_type_to_string(OPT_TYPE_SHOW_VERSION),
+                               json_string("1.2.3-4")));
+  assert(! json_object_set_new(payload,
+                               opt_type_to_string(OPT_TYPE_SHOW_SERIAL),
+                               json_integer(1234567890)));
+  assert(! json_object_set_new(payload,
+                               opt_type_to_string(OPT_TYPE_SHOW_SERIAL),
+                               json_integer(86400)));
+  assert(! json_object_set_new(payload,
+                               opt_type_to_string(OPT_TYPE_SHOW_TID_REQ_PENDING),
+                               json_integer(13)));
+  assert(! json_object_set_new(payload,
+                               opt_type_to_string(OPT_TYPE_SHOW_TID_REQ_COUNT),
+                               json_integer(1432)));
+
+  resp = tr_mon_resp_new(NULL, req, MON_RESP_SUCCESS, "success", payload);
+  assert(resp);
+
+  resp_json = tr_mon_resp_encode(resp);
+  assert(resp_json);
+
+  result = json_dumps(resp_json, JSON_DUMP_OPTS);
+  assert(result);
+
+  json_decref(resp_json);
+  tr_mon_resp_free(resp);
+  tr_mon_req_free(req);
+  return result;
+}
+
+static char *read_file(const char *filename)
+{
+  FILE *f = fopen(filename, "r");
+  char *s = NULL;
+  size_t nn = 0;
+  ssize_t n = getline(&s, &nn, f);
+  fclose(f);
+
+  if( (n > 0) && (s[n-1] == '\n'))
+    s[n-1] = 0;
+
+  return s;
+}
+
+int run_test(const char *filename, char *(generator)())
+{
+  char *s = NULL;
+  char *expected = NULL;
+
+  // Test reconfigure command
+  s = generator();
+  expected = read_file(filename);
+  assert(expected);
+  assert(strcmp(expected, s) == 0);
+  free(s);
+  free(expected);
+
+  return 1;
+}
+
+int main(void)
+{
+  assert(run_test("resp_reconfigure_success.test", reconfigure_success));
+  assert(run_test("resp_reconfigure_error.test", reconfigure_error));
+  assert(run_test("resp_show_success.test", show_success));
+  return 0;
+}
diff --git a/mon/tr_mon.c b/mon/tr_mon.c
new file mode 100644 (file)
index 0000000..6c613c9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <talloc.h>
+#include <gmodule.h>
+#include <string.h>
+
+#include <tr_mon.h>
+
+// Monitoring common code
+
+/**
+ * This method defines the command strings
+ */
+const char *cmd_to_string(TR_MON_CMD cmd)
+{
+  switch(cmd) {
+    case MON_CMD_UNKNOWN:
+      return NULL;
+
+    case MON_CMD_RECONFIGURE:
+      return "reconfigure";
+
+    case MON_CMD_SHOW:
+      return "show";
+  }
+  return NULL;
+}
+
+// Helper macro for the cmd_from_string method
+#define return_if_matches(s, cmd)            \
+  do {                                       \
+    if (strcmp((s), cmd_to_string(cmd))==0)  \
+      return (cmd);                          \
+  } while(0)
+
+TR_MON_CMD cmd_from_string(const char *s)
+{
+  return_if_matches(s, MON_CMD_RECONFIGURE);
+  return_if_matches(s, MON_CMD_SHOW);
+  return MON_CMD_UNKNOWN;
+}
+#undef return_if_matches
+
+/**
+ * This method defines the option type strings
+ */
+const char *opt_type_to_string(TR_MON_OPT_TYPE opt_type)
+{
+  switch(opt_type) {
+    case OPT_TYPE_UNKNOWN:
+      return NULL;
+
+    case OPT_TYPE_SHOW_VERSION:
+      return "version";
+
+    case OPT_TYPE_SHOW_SERIAL:
+      return "serial";
+
+    case OPT_TYPE_SHOW_UPTIME:
+      return "uptime";
+
+    case OPT_TYPE_SHOW_TID_REQ_COUNT:
+      return "tid_req_count";
+
+    case OPT_TYPE_SHOW_TID_REQ_PENDING:
+      return "tid_req_pending";
+
+    case OPT_TYPE_SHOW_ROUTES:
+      return "routes";
+
+    case OPT_TYPE_SHOW_COMMUNITIES:
+      return "communities";
+  }
+  return NULL;
+}
+
+// Helper macro for the opt_type_from_string method
+#define return_if_matches(s, cmd)                 \
+  do {                                            \
+    if (strcmp((s), opt_type_to_string(cmd))==0)  \
+      return (cmd);                               \
+  } while(0)
+
+TR_MON_OPT_TYPE opt_type_from_string(const char *s)
+{
+  return_if_matches(s, OPT_TYPE_SHOW_VERSION);
+  return_if_matches(s, OPT_TYPE_SHOW_SERIAL);
+  return_if_matches(s, OPT_TYPE_SHOW_UPTIME);
+  return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_COUNT);
+  return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_PENDING);
+  return_if_matches(s, OPT_TYPE_SHOW_ROUTES);
+  return_if_matches(s, OPT_TYPE_SHOW_COMMUNITIES);
+  return OPT_TYPE_UNKNOWN;
+}
+#undef return_if_matches
index 3adb2a3..1660ca4 100644 (file)
@@ -35,9 +35,8 @@
 
 #include <talloc.h>
 #include <gmodule.h>
 
 #include <talloc.h>
 #include <gmodule.h>
-#include <string.h>
 
 
-#include "tr_mon_req.h"
+#include <tr_mon.h>
 
 // Monitoring request message common code
 
 
 // Monitoring request message common code
 
@@ -110,92 +109,6 @@ size_t tr_mon_req_opt_count(TR_MON_REQ *req)
 
 TR_MON_OPT *tr_mon_req_opt_index(TR_MON_REQ *req, size_t index)
 {
 
 TR_MON_OPT *tr_mon_req_opt_index(TR_MON_REQ *req, size_t index)
 {
-  TR_MON_OPT *result = (TR_MON_OPT *) &g_array_index(req->options, TR_MON_OPT, index);
+  TR_MON_OPT *result = &g_array_index(req->options, TR_MON_OPT, index);
   return result;
 }
   return result;
 }
-
-/**
- * This method defines the command strings
- */
-const char *cmd_to_string(TR_MON_CMD cmd)
-{
-  switch(cmd) {
-    case MON_CMD_UNKNOWN:
-      return NULL;
-
-    case MON_CMD_RECONFIGURE:
-      return "reconfigure";
-
-    case MON_CMD_SHOW:
-      return "show";
-  }
-  return NULL;
-}
-
-// Helper macro for the cmd_from_string method
-#define return_if_matches(s, cmd)            \
-  do {                                       \
-    if (strcmp((s), cmd_to_string(cmd))==0)  \
-      return (cmd);                          \
-  } while(0)
-
-TR_MON_CMD cmd_from_string(const char *s)
-{
-  return_if_matches(s, MON_CMD_RECONFIGURE);
-  return_if_matches(s, MON_CMD_SHOW);
-  return MON_CMD_UNKNOWN;
-}
-#undef return_if_matches
-
-/**
- * This method defines the option type strings
- */
-const char *opt_type_to_string(TR_MON_OPT_TYPE opt_type)
-{
-  switch(opt_type) {
-    case OPT_TYPE_UNKNOWN:
-      return NULL;
-
-    case OPT_TYPE_SHOW_VERSION:
-      return "version";
-
-    case OPT_TYPE_SHOW_SERIAL:
-      return "serial";
-
-    case OPT_TYPE_SHOW_UPTIME:
-      return "uptime";
-
-    case OPT_TYPE_SHOW_TID_REQ_COUNT:
-      return "tid_req_count";
-
-    case OPT_TYPE_SHOW_TID_REQ_PENDING:
-      return "tid_req_pending";
-
-    case OPT_TYPE_SHOW_ROUTES:
-      return "routes";
-
-    case OPT_TYPE_SHOW_COMMUNITIES:
-      return "communities";
-  }
-  return NULL;
-}
-
-// Helper macro for the opt_type_from_string method
-#define return_if_matches(s, cmd)                 \
-  do {                                            \
-    if (strcmp((s), opt_type_to_string(cmd))==0)  \
-      return (cmd);                               \
-  } while(0)
-
-TR_MON_OPT_TYPE opt_type_from_string(const char *s)
-{
-  return_if_matches(s, OPT_TYPE_SHOW_VERSION);
-  return_if_matches(s, OPT_TYPE_SHOW_SERIAL);
-  return_if_matches(s, OPT_TYPE_SHOW_UPTIME);
-  return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_COUNT);
-  return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_PENDING);
-  return_if_matches(s, OPT_TYPE_SHOW_ROUTES);
-  return_if_matches(s, OPT_TYPE_SHOW_COMMUNITIES);
-  return OPT_TYPE_UNKNOWN;
-}
-#undef return_if_matches
index 1c441de..ed97a24 100644 (file)
@@ -1,4 +1,4 @@
-#include "tr_mon_req.h"/*
+/*
  * Copyright (c) 2018, JANET(UK)
  * All rights reserved.
  *
  * Copyright (c) 2018, JANET(UK)
  * All rights reserved.
  *
@@ -36,7 +36,7 @@
 #include <talloc.h>
 #include <jansson.h>
 
 #include <talloc.h>
 #include <jansson.h>
 
-#include "tr_mon_req.h"
+#include <tr_mon.h>
 
 // Monitoring request decoders
 
 
 // Monitoring request decoders
 
index 3346b5f..4239b12 100644 (file)
@@ -37,7 +37,7 @@
 #include <jansson.h>
 #include <glib.h>
 
 #include <jansson.h>
 #include <glib.h>
 
-#include "tr_mon_req.h"
+#include <tr_mon.h>
 
 // Monitoring request encoders
 
 
 // Monitoring request encoders
 
diff --git a/mon/tr_mon_resp.c b/mon/tr_mon_resp.c
new file mode 100644 (file)
index 0000000..a8c8f9d
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <talloc.h>
+#include <tr_name_internal.h>
+
+#include <tr_mon.h>
+
+// Monitoring request message common code
+
+/**
+ * Destructor used by talloc to ensure proper cleanup
+ */
+static int tr_mon_resp_destructor(void *object)
+{
+  TR_MON_RESP *resp = talloc_get_type_abort(object, TR_MON_RESP);
+  /* free the message */
+  if (resp->message) {
+    tr_free_name(resp->message);
+  }
+  /* free the payload */
+  if (resp->payload) {
+    json_decref(resp->payload);
+  }
+  return 0;
+}
+
+/**
+ * Allocate a new monitoring response
+ *
+ * Caller must free using tr_mon_resp_free().
+ *
+ * Makes its own copy of the message, so caller can dispose of
+ * that after allocating the response.
+ *
+ * Steals the reference to the payload JSON object. Does not modify the
+ * object. Caller should not modify it after allocating the response or
+ * undefined behavior will result. If allocation fails, the stolen reference
+ * will be released --- if you need to keep a reference, use incref before
+ * calling this.
+ *
+ * @param mem_ctx talloc context for allocation
+ * @param req TR_MON_REQ this response corresponds to
+ * @param code numeric response code
+ * @param msg string description of response code
+ * @param payload JSON object to be send as payload, or null for no payload
+ * @return response allocated in the requested talloc context, null on failure
+ */
+TR_MON_RESP *tr_mon_resp_new(TALLOC_CTX *mem_ctx,
+                             TR_MON_REQ *req,
+                             TR_MON_RESP_CODE code,
+                             const char *msg,
+                             json_t *payload)
+{
+  TR_MON_RESP *resp = talloc(mem_ctx, TR_MON_RESP);
+  if (resp) {
+    resp->req = req;
+    resp->code = code;
+    resp->message = tr_new_name(msg);
+    resp->payload = payload;
+    talloc_set_destructor((void *)resp, tr_mon_resp_destructor);
+    if (resp->message == NULL) {
+      talloc_free(resp); // destructor will be called
+      resp = NULL;
+    }
+  }
+  return resp;
+}
+
+/**
+ * Free a monitoring response
+ *
+ * @param resp request to free, must not be null
+ */
+void tr_mon_resp_free(TR_MON_RESP *resp)
+{
+  talloc_free(resp);
+}
diff --git a/mon/tr_mon_resp_encode.c b/mon/tr_mon_resp_encode.c
new file mode 100644 (file)
index 0000000..19af8c0
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <talloc.h>
+#include <jansson.h>
+
+#include <tr_mon.h>
+
+/* Helper for encoding. Adds a newly allocated JSON object to
+ * jobj. If the allocation or setting fails, returns NULL after
+ * cleaning up. */
+#define object_set_or_free_and_return(jobj, tmp_jval, key, jval)  \
+  do {                                                            \
+    (tmp_jval) = (jval);                                          \
+    if ( (tmp_jval) == NULL) {                                    \
+      json_decref(jobj);                                          \
+      return NULL;                                                \
+    }                                                             \
+    if (json_object_set_new((jobj), (key), (tmp_jval)) == -1) {   \
+      json_decref(tmp_jval);                                      \
+      json_decref(jobj);                                          \
+      return NULL;                                                \
+    }                                                             \
+  } while(0)
+
+/**
+ * Encode a monitoring response as a JSON object
+ *
+ * Caller must ensure json_decref() is used to free the return value.
+ *
+ * @param resp response to encode
+ * @return response as a newly allocated JSON object
+ */
+json_t *tr_mon_resp_encode(TR_MON_RESP *resp)
+{
+  json_t *resp_json = NULL;
+  json_t *jval = NULL;
+  const char *cmd_str = NULL;
+
+  /* Get a JSON object */
+  resp_json = json_object();
+  if (resp_json == NULL)
+    return NULL;
+
+  /* Add properties, cleaning up and returning NULL on failure */
+  object_set_or_free_and_return(resp_json, jval, "code",    json_integer(resp->code));
+  object_set_or_free_and_return(resp_json, jval, "message", tr_name_to_json_string(resp->message));
+
+  /* If we have a payload, add it */
+  if (resp->payload) {
+    cmd_str = cmd_to_string(resp->req->command); // key for the response payload
+    object_set_or_free_and_return(resp_json, jval, cmd_str, resp->payload);
+  }
+
+  return resp_json;
+}