psyc \
rps \
social \
- $(CONSENSUS) \
+ $(CONSENSUS) \
$(SECRETSHARING) \
$(SENSOR) \
$(SENSORDASHBOARD)
endif
if HAVE_REST
- EXP_DIR += identity-provider
+ PROVIDER_DIR = identity-provider
+endif
+
+if HAVE_JSON
+ JSON_DIR = json
endif
if BUILD_PULSE_HELPERS
SUBDIRS = \
include $(INTLEMU_SUBDIRS) \
util \
- $(REST_DIR) \
+ $(JSON_DIR) \
+ $(REST_DIR) \
hello \
tun \
block \
exit \
pt \
integration-tests \
- $(EXP_DIR)
+ $(EXP_DIR) \
+ $(PROVIDER_DIR)
endif
gnunet_hello_lib.h \
gnunet_helper_lib.h \
gnunet_identity_service.h \
+ gnunet_json_lib.h \
gnunet_load_lib.h \
gnunet_cadet_service.h \
gnunet_microphone_lib.h \
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file gnunet_json_lib.h
+ * @brief functions to parse JSON objects into GNUnet objects
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <jansson.h>
+
+
+/* ****************** Generic parser interface ******************* */
+
+/**
+ * @brief Entry in parser specification for #GNUNET_JSON_parse().
+ */
+struct GNUNET_JSON_Specification;
+
+
+/**
+ * Function called to parse JSON argument.
+ *
+ * @param cls closure
+ * @param root JSON to parse
+ * @param spec our specification entry with further details
+ * @return #GNUNET_SYSERR on error,
+ * #GNUNET_OK on success
+ */
+typedef int
+(*GNUNET_JSON_Parser)(void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec);
+
+
+/**
+ * Function called to clean up data from earlier parsing.
+ *
+ * @param cls closure
+ * @param spec our specification entry with data to clean.
+ */
+typedef void
+(*GNUNET_JSON_Cleaner)(void *cls,
+ struct GNUNET_JSON_Specification *spec);
+
+
+/**
+ * @brief Entry in parser specification for #GNUNET_JSON_parse().
+ */
+struct GNUNET_JSON_Specification
+{
+ /**
+ * Function for how to parse this type of entry.
+ */
+ GNUNET_JSON_Parser parser;
+
+ /**
+ * Function for how to clean up this type of entry.
+ */
+ GNUNET_JSON_Cleaner cleaner;
+
+ /**
+ * Closure for @e parser and @e cleaner.
+ */
+ void *cls;
+
+ /**
+ * Name of the field to parse, use NULL to get the JSON
+ * of the main object instead of the JSON of an individual field.
+ */
+ const char *field;
+
+ /**
+ * Pointer, details specific to the @e parser.
+ */
+ void *ptr;
+
+ /**
+ * Number of bytes available in @e ptr.
+ */
+ size_t ptr_size;
+
+ /**
+ * Where should we store the final size of @e ptr.
+ */
+ size_t *size_ptr;
+
+};
+
+
+/**
+ * Navigate and parse data in a JSON tree. Tries to parse the @a root
+ * to find all of the values given in the @a spec. If one of the
+ * entries in @a spec cannot be found or parsed, the name of the JSON
+ * field is returned in @a error_json_name, and the offset of the
+ * entry in @a spec is returned in @a error_line.
+ *
+ * @param root the JSON node to start the navigation at.
+ * @param spec parse specification array
+ * @param[out] error_json_name which JSON field was problematic
+ * @param[out] which index into @a spec did we encounter an error
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_JSON_parse (const json_t *root,
+ struct GNUNET_JSON_Specification *spec,
+ const char **error_json_name,
+ unsigned int *error_line);
+
+
+/**
+ * Frees all elements allocated during a #GNUNET_JSON_parse()
+ * operation.
+ *
+ * @param spec specification of the parse operation
+ */
+void
+GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec);
+
+
+
+/* ****************** Canonical parser specifications ******************* */
+
+
+/**
+ * End of a parser specification.
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_end (void);
+
+
+/**
+ * Variable size object (in network byte order, encoded using Crockford
+ * Base32hex encoding).
+ *
+ * @param name name of the JSON field
+ * @param[out] obj pointer where to write the data, must have @a size bytes
+ * @param size number of bytes expected in @a obj
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_fixed (const char *name,
+ void *obj,
+ size_t size);
+
+
+/**
+ * Fixed size object (in network byte order, encoded using Crockford
+ * Base32hex encoding).
+ *
+ * @param name name of the JSON field
+ * @param obj pointer where to write the data (type of `*obj` will determine size)
+ */
+#define GNUNET_JSON_spec_fixed_auto(name,obj) GNUNET_JSON_spec_fixed (name, obj, sizeof (*obj))
+
+
+/**
+ * Variable size object (in network byte order, encoded using
+ * Crockford Base32hex encoding).
+ *
+ * @param name name of the JSON field
+ * @param[out] obj pointer where to write the data, will be allocated
+ * @param[out] size where to store the number of bytes allocated for @a obj
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_varsize (const char *name,
+ void **obj,
+ size_t *size);
+
+
+/**
+ * The expected field stores a string.
+ *
+ * @param name name of the JSON field
+ * @param strptr where to store a pointer to the field
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_string (const char *name,
+ const char **strptr);
+
+/**
+ * JSON object.
+ *
+ * @param name name of the JSON field
+ * @param[out] jsonp where to store the JSON found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_json (const char *name,
+ json_t **jsonp);
+
+
+/**
+ * 8-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u8 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint8 (const char *name,
+ uint8_t *u8);
+
+
+/**
+ * 16-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u16 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint16 (const char *name,
+ uint16_t *u16);
+
+
+/**
+ * 32-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u32 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint32 (const char *name,
+ uint32_t *u32);
+
+
+/**
+ * 64-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u64 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint64 (const char *name,
+ uint64_t *u64);
+
+
+/* ************ GNUnet-specific parser specifications ******************* */
+
+/**
+ * Absolute time.
+ *
+ * @param name name of the JSON field
+ * @param[out] at where to store the absolute time found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_absolute_time (const char *name,
+ struct GNUNET_TIME_Absolute *at);
+
+
+/**
+ * Relative time.
+ *
+ * @param name name of the JSON field
+ * @param[out] rt where to store the relative time found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_relative_time (const char *name,
+ struct GNUNET_TIME_Relative *rt);
+
+
+/**
+ * Specification for parsing an RSA public key.
+ *
+ * @param name name of the JSON field
+ * @param pk where to store the RSA key found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_rsa_public_key (const char *name,
+ struct GNUNET_CRYPTO_rsa_PublicKey **pk);
+
+
+/**
+ * Specification for parsing an RSA signature.
+ *
+ * @param name name of the JSON field
+ * @param sig where to store the RSA signature found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_rsa_signature (const char *name,
+ struct GNUNET_CRYPTO_rsa_Signature **sig);
+
+
+/* ****************** Generic generator interface ******************* */
+
+
+/**
+ * Convert binary data to a JSON string with the base32crockford
+ * encoding.
+ *
+ * @param data binary data
+ * @param size size of @a data in bytes
+ * @return json string that encodes @a data
+ */
+json_t *
+GNUNET_JSON_from_data (const void *data,
+ size_t size);
+
+
+/**
+ * Convert absolute timestamp to a json string.
+ *
+ * @param stamp the time stamp
+ * @return a json string with the timestamp in @a stamp
+ */
+json_t *
+GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp);
+
+
+/**
+ * Convert relative timestamp to a json string.
+ *
+ * @param stamp the time stamp
+ * @return a json string with the timestamp in @a stamp
+ */
+json_t *
+GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp);
+
+
+/**
+ * Convert RSA public key to JSON.
+ *
+ * @param pk public key to convert
+ * @return corresponding JSON encoding
+ */
+json_t *
+GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *pk);
+
+
+/**
+ * Convert RSA signature to JSON.
+ *
+ * @param sig signature to convert
+ * @return corresponding JSON encoding
+ */
+json_t *
+GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *sig);
+
+
+
+
+/* end of gnunet_json_lib.h */
{
/**
- * Format of the rest of the entry, determines the data
- * type that is being added to the query.
+ * Function for how to handle this type of entry.
*/
GNUNET_PQ_QueryConverter conv;
GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel);
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param at time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at);
+
+
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param rt time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt);
+
+
/**
* Return the minimum of two relative time values.
*
--- /dev/null
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+if USE_COVERAGE
+ AM_CFLAGS = --coverage -O0
+ XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+ libgnunetjson.la
+
+libgnunetjson_la_LDFLAGS = \
+ -version-info 0:0:0 \
+ -no-undefined
+libgnunetjson_la_SOURCES = \
+ json.c \
+ json_generator.c \
+ json_helper.c
+libgnunetjson_la_LIBADD = \
+ -lgnunetutil \
+ -ljansson \
+ $(XLIB)
+
+check_PROGRAMS = \
+ test_json
+
+TESTS = \
+ $(check_PROGRAMS)
+
+test_json_SOURCES = \
+ test_json.c
+test_json_LDADD = \
+ libgnunetjson.la \
+ -lgnunetutil \
+ -ljansson
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file json/json.c
+ * @brief functions to parse JSON snippets
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_json_lib.h"
+
+
+/**
+ * Navigate and parse data in a JSON tree. Tries to parse the @a root
+ * to find all of the values given in the @a spec. If one of the
+ * entries in @a spec cannot be found or parsed, the name of the JSON
+ * field is returned in @a error_json_name, and the offset of the
+ * entry in @a spec is returned in @a error_line.
+ *
+ * @param root the JSON node to start the navigation at.
+ * @param spec parse specification array
+ * @param[out] error_json_name which JSON field was problematic
+ * @param[out] which index into @a spec did we encounter an error
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_JSON_parse (const json_t *root,
+ struct GNUNET_JSON_Specification *spec,
+ const char **error_json_name,
+ unsigned int *error_line)
+{
+ unsigned int i;
+ json_t *pos;
+
+ for (i=0;NULL != spec[i].parser;i++)
+ {
+ if (NULL == spec[i].field)
+ pos = (json_t *) root;
+ else
+ pos = json_object_get (root,
+ spec[i].field);
+ if ( (NULL == pos) ||
+ (GNUNET_OK !=
+ spec[i].parser (spec[i].cls,
+ pos,
+ &spec[i])) )
+ {
+ if (NULL != error_json_name)
+ *error_json_name = spec[i].field;
+ if (NULL != error_line)
+ *error_line = i;
+ GNUNET_JSON_parse_free (spec);
+ return GNUNET_SYSERR;
+ }
+ }
+ return GNUNET_OK; /* all OK! */
+}
+
+
+/**
+ * Frees all elements allocated during a #GNUNET_JSON_parse()
+ * operation.
+ *
+ * @param spec specification of the parse operation
+ */
+void
+GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec)
+{
+ unsigned int i;
+
+ for (i=0;NULL != spec[i].parser;i++)
+ if (NULL != spec[i].cleaner)
+ spec[i].cleaner (spec[i].cls,
+ &spec[i]);
+}
+
+
+/* end of json.c */
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file json/json_generator.c
+ * @brief helper functions for generating JSON from GNUnet data structures
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_json_lib.h"
+
+
+/**
+ * Convert binary data to a JSON string
+ * with the base32crockford encoding.
+ *
+ * @param data binary data
+ * @param size size of @a data in bytes
+ * @return json string that encodes @a data
+ */
+json_t *
+GNUNET_JSON_from_data (const void *data,
+ size_t size)
+{
+ char *buf;
+ json_t *json;
+
+ buf = GNUNET_STRINGS_data_to_string_alloc (data, size);
+ json = json_string (buf);
+ GNUNET_free (buf);
+ return json;
+}
+
+
+/**
+ * Convert absolute timestamp to a json string.
+ *
+ * @param stamp the time stamp
+ * @return a json string with the timestamp in @a stamp
+ */
+json_t *
+GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp)
+{
+ json_t *j;
+ char *mystr;
+ int ret;
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_TIME_round_abs (&stamp));
+ if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+ return json_string ("/never/");
+ ret = GNUNET_asprintf (&mystr,
+ "/Date(%llu)/",
+ (unsigned long long) (stamp.abs_value_us / (1000LL * 1000LL)));
+ GNUNET_assert (ret > 0);
+ j = json_string (mystr);
+ GNUNET_free (mystr);
+ return j;
+}
+
+
+/**
+ * Convert relative timestamp to a json string.
+ *
+ * @param stamp the time stamp
+ * @return a json string with the timestamp in @a stamp
+ */
+json_t *
+GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
+{
+ json_t *j;
+ char *mystr;
+ int ret;
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_TIME_round_rel (&stamp));
+ if (stamp.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+ return json_string ("/forever/");
+ ret = GNUNET_asprintf (&mystr,
+ "/Delay(%llu)/",
+ (unsigned long long) (stamp.rel_value_us / (1000LL * 1000LL)));
+ GNUNET_assert (ret > 0);
+ j = json_string (mystr);
+ GNUNET_free (mystr);
+ return j;
+}
+
+
+/**
+ * Convert RSA public key to JSON.
+ *
+ * @param pk public key to convert
+ * @return corresponding JSON encoding
+ */
+json_t *
+GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *pk)
+{
+ char *buf;
+ size_t buf_len;
+ json_t *ret;
+
+ buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk,
+ &buf);
+ ret = GNUNET_JSON_from_data (buf,
+ buf_len);
+ GNUNET_free (buf);
+ return ret;
+}
+
+
+/**
+ * Convert RSA signature to JSON.
+ *
+ * @param sig signature to convert
+ * @return corresponding JSON encoding
+ */
+json_t *
+GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *sig)
+{
+ char *buf;
+ size_t buf_len;
+ json_t *ret;
+
+ buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig,
+ &buf);
+ ret = GNUNET_JSON_from_data (buf,
+ buf_len);
+ GNUNET_free (buf);
+ return ret;
+}
+
+
+/* End of json/json_generator.c */
--- /dev/null
+/*
+ This file is part of GNUnet
+ Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file json/json_helper.c
+ * @brief functions to generate specifciations for JSON parsing
+ * @author Florian Dold
+ * @author Benedikt Mueller
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_json_lib.h"
+
+
+/**
+ * End of a parser specification.
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_end ()
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = NULL,
+ .cleaner = NULL,
+ .cls = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to fixed size data
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_fixed_data (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ const char *enc;
+ unsigned int len;
+
+ if (NULL == (enc = json_string_value (root)))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ len = strlen (enc);
+ if (((len * 5) / 8) != spec->ptr_size)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (enc,
+ len,
+ spec->ptr,
+ spec->ptr_size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Variable size object (in network byte order, encoded using Crockford
+ * Base32hex encoding).
+ *
+ * @param name name of the JSON field
+ * @param[out] obj pointer where to write the data, must have @a size bytes
+ * @param size number of bytes expected in @a obj
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_fixed (const char *name,
+ void *obj,
+ size_t size)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_fixed_data,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = obj,
+ .ptr_size = size,
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to variable size data
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_variable_data (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ const char *str;
+ size_t size;
+ void *data;
+ int res;
+
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ size = (strlen (str) * 5) / 8;
+ if (size >= 1024)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ data = GNUNET_malloc (size);
+ res = GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ data,
+ size);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (data);
+ return GNUNET_SYSERR;
+ }
+ *(void**) spec->ptr = data;
+ *spec->size_ptr = size;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing variable size data
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_variable_data (void *cls,
+ struct GNUNET_JSON_Specification *spec)
+{
+ if (0 != *spec->size_ptr)
+ {
+ GNUNET_free (*(void **) spec->ptr);
+ *(void**) spec->ptr = NULL;
+ *spec->size_ptr = 0;
+ }
+}
+
+
+/**
+ * Variable size object (in network byte order, encoded using
+ * Crockford Base32hex encoding).
+ *
+ * @param name name of the JSON field
+ * @param[out] obj pointer where to write the data, will be allocated
+ * @param[out] size where to store the number of bytes allocated for @a obj
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_varsize (const char *name,
+ void **obj,
+ size_t *size)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_variable_data,
+ .cleaner = &clean_variable_data,
+ .cls = NULL,
+ .field = name,
+ .ptr = obj,
+ .ptr_size = 0,
+ .size_ptr = size
+ };
+ *obj = NULL;
+ *size = 0;
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to string.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_string (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ const char *str;
+
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ *(const char **) spec->ptr = str;
+ return GNUNET_OK;
+}
+
+
+/**
+ * The expected field stores a string.
+ *
+ * @param name name of the JSON field
+ * @param strptr where to store a pointer to the field
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_string (const char *name,
+ const char **strptr)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_string,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = strptr,
+ .ptr_size = 0,
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to a JSON object. (Yes, trivial.)
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_object (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ if (! (json_is_object (root) || json_is_array (root)) )
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ json_incref (root);
+ *(json_t **) spec->ptr = root;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing JSON object.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_object (void *cls,
+ struct GNUNET_JSON_Specification *spec)
+{
+ json_t **ptr = (json_t **) spec->ptr;
+ if (NULL != *ptr)
+ {
+ json_decref (*ptr);
+ *ptr = NULL;
+ }
+}
+
+
+/**
+ * JSON object.
+ *
+ * @param name name of the JSON field
+ * @param[out] jsonp where to store the JSON found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_json (const char *name,
+ json_t **jsonp)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_object,
+ .cleaner = &clean_object,
+ .cls = NULL,
+ .field = name,
+ .ptr = jsonp,
+ .ptr_size = 0,
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to a uint8_t.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_u8 (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ json_int_t val;
+ uint8_t *up = spec->ptr;
+
+ if (! json_is_integer (root))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ val = json_integer_value (root);
+ if ( (0 > val) || (val > UINT8_MAX) )
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ *up = (uint8_t) val;
+ return GNUNET_OK;
+}
+
+
+/**
+ * 8-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u8 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint8 (const char *name,
+ uint8_t *u8)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_u8,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = u8,
+ .ptr_size = sizeof (uint8_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to a uint16_t.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_u16 (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ json_int_t val;
+ uint16_t *up = spec->ptr;
+
+ if (! json_is_integer (root))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ val = json_integer_value (root);
+ if ( (0 > val) || (val > UINT16_MAX) )
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ *up = (uint16_t) val;
+ return GNUNET_OK;
+}
+
+
+/**
+ * 16-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u16 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint16 (const char *name,
+ uint16_t *u16)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_u16,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = u16,
+ .ptr_size = sizeof (uint16_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to a uint32_t.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_u32 (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ json_int_t val;
+ uint32_t *up = spec->ptr;
+
+ if (! json_is_integer (root))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ val = json_integer_value (root);
+ if ( (0 > val) || (val > UINT32_MAX) )
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ *up = (uint32_t) val;
+ return GNUNET_OK;
+}
+
+
+/**
+ * 32-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u32 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint32 (const char *name,
+ uint32_t *u32)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_u32,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = u32,
+ .ptr_size = sizeof (uint32_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to a uint8_t.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_u64 (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ json_int_t val;
+ uint64_t *up = spec->ptr;
+
+ if (! json_is_integer (root))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ val = json_integer_value (root);
+ *up = (uint64_t) val;
+ return GNUNET_OK;
+}
+
+
+/**
+ * 64-bit integer.
+ *
+ * @param name name of the JSON field
+ * @param[out] u64 where to store the integer found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_uint64 (const char *name,
+ uint64_t *u64)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_u64,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = u64,
+ .ptr_size = sizeof (uint64_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/* ************ GNUnet-specific parser specifications ******************* */
+
+/**
+ * Parse given JSON object to absolute time.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_abs_time (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_TIME_Absolute *abs = spec->ptr;
+ const char *val;
+ unsigned long long int tval;
+
+ val = json_string_value (root);
+ if (NULL == val)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if ( (0 == strcasecmp (val,
+ "/forever/")) ||
+ (0 == strcasecmp (val,
+ "/end of time/")) ||
+ (0 == strcasecmp (val,
+ "/never/")) )
+ {
+ *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
+ return GNUNET_OK;
+ }
+ if (1 != sscanf (val,
+ "/Date(%llu)/",
+ &tval))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
+ abs->abs_value_us = tval * 1000LL * 1000LL;
+ if ( (abs->abs_value_us) / 1000LL / 1000LL != tval)
+ {
+ /* Integer overflow */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Absolute time.
+ *
+ * @param name name of the JSON field
+ * @param[out] at where to store the absolute time found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_absolute_time (const char *name,
+ struct GNUNET_TIME_Absolute *at)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_abs_time,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = at,
+ .ptr_size = sizeof (uint64_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to relative time.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_rel_time (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_TIME_Relative *rel = spec->ptr;
+ const char *val;
+ unsigned long long int tval;
+
+ val = json_string_value (root);
+ if (NULL == val)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if ( (0 == strcasecmp (val,
+ "/forever/")) )
+ {
+ *rel = GNUNET_TIME_UNIT_FOREVER_REL;
+ return GNUNET_OK;
+ }
+ if (1 != sscanf (val,
+ "/Delay(%llu)/",
+ &tval))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Relative */
+ rel->rel_value_us = tval * 1000LL * 1000LL;
+ if ( (rel->rel_value_us) / 1000LL / 1000LL != tval)
+ {
+ /* Integer overflow */
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Relative time.
+ *
+ * @param name name of the JSON field
+ * @param[out] rt where to store the relative time found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_relative_time (const char *name,
+ struct GNUNET_TIME_Relative *rt)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_rel_time,
+ .cleaner = NULL,
+ .cls = NULL,
+ .field = name,
+ .ptr = rt,
+ .ptr_size = sizeof (uint64_t),
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_rsa_public_key (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_CRYPTO_rsa_PublicKey **pk = spec->ptr;
+ const char *enc;
+ char *buf;
+ size_t len;
+ size_t buf_len;
+
+ if (NULL == (enc = json_string_value (root)))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ len = strlen (enc);
+ buf_len = (len * 5) / 8;
+ buf = GNUNET_malloc (buf_len);
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (enc,
+ len,
+ buf,
+ buf_len))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (buf);
+ return GNUNET_SYSERR;
+ }
+ if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
+ buf_len)))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (buf);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (buf);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing RSA public key.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_rsa_public_key (void *cls,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_CRYPTO_rsa_PublicKey **pk = spec->ptr;
+
+ if (NULL != *pk)
+ {
+ GNUNET_CRYPTO_rsa_public_key_free (*pk);
+ *pk = NULL;
+ }
+}
+
+
+/**
+ * Specification for parsing an RSA public key.
+ *
+ * @param name name of the JSON field
+ * @param pk where to store the RSA key found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_rsa_public_key (const char *name,
+ struct GNUNET_CRYPTO_rsa_PublicKey **pk)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_rsa_public_key,
+ .cleaner = &clean_rsa_public_key,
+ .cls = NULL,
+ .field = name,
+ .ptr = pk,
+ .ptr_size = 0,
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/**
+ * Parse given JSON object to RSA signature.
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static int
+parse_rsa_signature (void *cls,
+ json_t *root,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_CRYPTO_rsa_Signature **sig = spec->ptr;
+ size_t size;
+ const char *str;
+ int res;
+ void *buf;
+
+ str = json_string_value (root);
+ if (NULL == str)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ size = (strlen (str) * 5) / 8;
+ buf = GNUNET_malloc (size);
+ res = GNUNET_STRINGS_string_to_data (str,
+ strlen (str),
+ buf,
+ size);
+ if (GNUNET_OK != res)
+ {
+ GNUNET_free (buf);
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
+ size)))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (buf);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (buf);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left from parsing RSA signature.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_rsa_signature (void *cls,
+ struct GNUNET_JSON_Specification *spec)
+{
+ struct GNUNET_CRYPTO_rsa_Signature **sig = spec->ptr;
+
+ if (NULL != *sig)
+ {
+ GNUNET_CRYPTO_rsa_signature_free (*sig);
+ *sig = NULL;
+ }
+}
+
+
+/**
+ * Specification for parsing an RSA signature.
+ *
+ * @param name name of the JSON field
+ * @param sig where to store the RSA signature found under @a name
+ */
+struct GNUNET_JSON_Specification
+GNUNET_JSON_spec_rsa_signature (const char *name,
+ struct GNUNET_CRYPTO_rsa_Signature **sig)
+{
+ struct GNUNET_JSON_Specification ret = {
+ .parser = &parse_rsa_signature,
+ .cleaner = &clean_rsa_signature,
+ .cls = NULL,
+ .field = name,
+ .ptr = sig,
+ .ptr_size = 0,
+ .size_ptr = NULL
+ };
+ return ret;
+}
+
+
+/* end of json_helper.c */
--- /dev/null
+/*
+ This file is part of GNUnet
+ (C) 2015, 2016 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file json/test_json.c
+ * @brief Tests for JSON conversion functions
+ * @author Christian Grothoff <christian@grothoff.org>
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_json_lib.h"
+
+
+/**
+ * Test absolute time conversion from/to JSON.
+ *
+ * @return 0 on success
+ */
+static int
+test_abs_time ()
+{
+ json_t *j;
+ struct GNUNET_TIME_Absolute a1;
+ struct GNUNET_TIME_Absolute a2;
+ struct GNUNET_JSON_Specification s1[] = {
+ GNUNET_JSON_spec_absolute_time (NULL, &a2),
+ GNUNET_JSON_spec_end()
+ };
+ struct GNUNET_JSON_Specification s2[] = {
+ GNUNET_JSON_spec_absolute_time (NULL, &a2),
+ GNUNET_JSON_spec_end()
+ };
+
+ a1 = GNUNET_TIME_absolute_get ();
+ GNUNET_TIME_round_abs (&a1);
+ j = GNUNET_JSON_from_time_abs (a1);
+ GNUNET_assert (NULL != j);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (j, s1, NULL, NULL));
+ GNUNET_assert (a1.abs_value_us ==
+ a2.abs_value_us);
+ json_decref (j);
+
+ a1 = GNUNET_TIME_UNIT_FOREVER_ABS;
+ j = GNUNET_JSON_from_time_abs (a1);
+ GNUNET_assert (NULL != j);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (j, s2, NULL, NULL));
+ GNUNET_assert (a1.abs_value_us ==
+ a2.abs_value_us);
+ json_decref (j);
+ return 0;
+}
+
+
+/**
+ * Test relative time conversion from/to JSON.
+ *
+ * @return 0 on success
+ */
+static int
+test_rel_time ()
+{
+ json_t *j;
+ struct GNUNET_TIME_Relative r1;
+ struct GNUNET_TIME_Relative r2;
+ struct GNUNET_JSON_Specification s1[] = {
+ GNUNET_JSON_spec_relative_time (NULL, &r2),
+ GNUNET_JSON_spec_end()
+ };
+ struct GNUNET_JSON_Specification s2[] = {
+ GNUNET_JSON_spec_relative_time (NULL, &r2),
+ GNUNET_JSON_spec_end()
+ };
+
+ r1 = GNUNET_TIME_UNIT_SECONDS;
+ j = GNUNET_JSON_from_time_rel (r1);
+ GNUNET_assert (NULL != j);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (j, s1, NULL, NULL));
+ GNUNET_assert (r1.rel_value_us ==
+ r2.rel_value_us);
+ json_decref (j);
+
+ r1 = GNUNET_TIME_UNIT_FOREVER_REL;
+ j = GNUNET_JSON_from_time_rel (r1);
+ GNUNET_assert (NULL != j);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (j, s2, NULL, NULL));
+ GNUNET_assert (r1.rel_value_us ==
+ r2.rel_value_us);
+ json_decref (j);
+ return 0;
+}
+
+
+/**
+ * Test raw (binary) conversion from/to JSON.
+ *
+ * @return 0 on success
+ */
+static int
+test_raw ()
+{
+ char blob[256];
+ unsigned int i;
+ json_t *j;
+
+ for (i=0;i<=256;i++)
+ {
+ char blob2[256];
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed (NULL, blob2, i),
+ GNUNET_JSON_spec_end()
+ };
+
+ memset (blob, i, i);
+ j = GNUNET_JSON_from_data (blob, i);
+ GNUNET_assert (NULL != j);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (j, spec,
+ NULL, NULL));
+ GNUNET_assert (0 ==
+ memcmp (blob,
+ blob2,
+ i));
+ }
+ return 0;
+}
+
+
+/**
+ * Test rsa conversions from/to JSON.
+ *
+ * @return 0 on success
+ */
+static int
+test_rsa ()
+{
+ struct GNUNET_CRYPTO_rsa_PublicKey *pub;
+ struct GNUNET_CRYPTO_rsa_PublicKey *pub2;
+ struct GNUNET_JSON_Specification pspec[] = {
+ GNUNET_JSON_spec_rsa_public_key (NULL, &pub2),
+ GNUNET_JSON_spec_end()
+ };
+ struct GNUNET_CRYPTO_rsa_Signature *sig;
+ struct GNUNET_CRYPTO_rsa_Signature *sig2;
+ struct GNUNET_JSON_Specification sspec[] = {
+ GNUNET_JSON_spec_rsa_signature (NULL, &sig2),
+ GNUNET_JSON_spec_end()
+ };
+ struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
+ char msg[] = "Hello";
+ json_t *jp;
+ json_t *js;
+
+ priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
+ pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
+ sig = GNUNET_CRYPTO_rsa_sign (priv,
+ msg,
+ sizeof (msg));
+ GNUNET_assert (NULL != (jp = GNUNET_JSON_from_rsa_public_key (pub)));
+ GNUNET_assert (NULL != (js = GNUNET_JSON_from_rsa_signature (sig)));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (jp, pspec,
+ NULL, NULL));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (js, sspec,
+ NULL, NULL));
+ GNUNET_break (0 ==
+ GNUNET_CRYPTO_rsa_signature_cmp (sig,
+ sig2));
+ GNUNET_break (0 ==
+ GNUNET_CRYPTO_rsa_public_key_cmp (pub,
+ pub2));
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_CRYPTO_rsa_signature_free (sig2);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ GNUNET_CRYPTO_rsa_public_key_free (pub);
+ GNUNET_CRYPTO_rsa_public_key_free (pub2);
+ return 0;
+}
+
+
+int
+main(int argc,
+ const char *const argv[])
+{
+ GNUNET_log_setup ("test-json",
+ "WARNING",
+ NULL);
+ if (0 != test_abs_time ())
+ return 1;
+ if (0 != test_rel_time ())
+ return 1;
+ if (0 != test_raw ())
+ return 1;
+ if (0 != test_rsa ())
+ return 1;
+ /* FIXME: test EdDSA signature conversion... */
+ return 0;
+}
+
+/* end of test_json.c */
}
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param at time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
+{
+ if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
+ return GNUNET_OK;
+ if (0 == at->abs_value_us % 1000000)
+ return GNUNET_OK;
+ at->abs_value_us -= at->abs_value_us % 1000000;
+ return GNUNET_NO;
+}
+
+
+/**
+ * Round a time value so that it is suitable for transmission
+ * via JSON encodings.
+ *
+ * @param rt time to round
+ * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
+ * it was just now rounded
+ */
+int
+GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
+{
+ if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+ return GNUNET_OK;
+ if (0 == rt->rel_value_us % 1000000)
+ return GNUNET_OK;
+ rt->rel_value_us -= rt->rel_value_us % 1000000;
+ return GNUNET_NO;
+}
+
+
/**
* Get the current time (works just as "time", just that we use the
* unit of time that the cron-jobs use (and is 64 bit)).