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
-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)
-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)
+
+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)
+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 \
- 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
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_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
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_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_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 \
#include <talloc.h>
#include <jansson.h>
#include <gmodule.h>
+#include <tr_name_internal.h>
/* 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_resp_code TR_MON_RESP_CODE;
typedef struct tr_mon_opt TR_MON_OPT;
typedef enum tr_mon_opt_type TR_MON_OPT_TYPE;
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,
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 */
+/* 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);
-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_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
--- /dev/null
+{"code": 1, "message": "error"}
--- /dev/null
+{"code": 0, "message": "success"}
--- /dev/null
+{"code": 0, "message": "success", "show": {"version": "1.2.3-4", "serial": 86400, "tid_req_pending": 13, "tid_req_count": 1432}}
#include <string.h>
#include <glib.h>
-#include "../tr_mon_req.h"
+#include <tr_mon.h>
/**
* @return reconfigure command
#include <string.h>
#include <glib.h>
-#include "../tr_mon_req.h"
+#include <tr_mon.h>
#define JSON_DUMP_OPTS 0
--- /dev/null
+//
+// 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;
+}
--- /dev/null
+/*
+ * 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
#include <talloc.h>
#include <gmodule.h>
-#include <string.h>
-#include "tr_mon_req.h"
+#include <tr_mon.h>
// Monitoring request message common code
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;
}
-
-/**
- * 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
-#include "tr_mon_req.h"/*
+/*
* Copyright (c) 2018, JANET(UK)
* All rights reserved.
*
#include <talloc.h>
#include <jansson.h>
-#include "tr_mon_req.h"
+#include <tr_mon.h>
// Monitoring request decoders
#include <jansson.h>
#include <glib.h>
-#include "tr_mon_req.h"
+#include <tr_mon.h>
// Monitoring request encoders
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}