aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-03-17 19:24:35 +0000
committerChristian Grothoff <christian@grothoff.org>2016-03-17 19:24:35 +0000
commita5361231e36224607d8c2c1376757c0b99f34f59 (patch)
treeee2ee9fa2c114c6b8e5850f9b31d2bbb54b8c5d2 /src
parent23b982b51e8f1c152053154c0fce4cfc4cfcbf67 (diff)
downloadgnunet-a5361231e36224607d8c2c1376757c0b99f34f59.tar.gz
gnunet-a5361231e36224607d8c2c1376757c0b99f34f59.zip
adding library for basic JSON conversions
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am14
-rw-r--r--src/include/Makefile.am1
-rw-r--r--src/include/gnunet_json_lib.h354
-rw-r--r--src/include/gnunet_pq_lib.h3
-rw-r--r--src/include/gnunet_time_lib.h24
-rw-r--r--src/json/Makefile.am35
-rw-r--r--src/json/json.c92
-rw-r--r--src/json/json_generator.c146
-rw-r--r--src/json/json_helper.c864
-rw-r--r--src/json/test_json.c217
-rw-r--r--src/util/time.c40
11 files changed, 1784 insertions, 6 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index edfbb6922..47d6896cb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,14 +21,18 @@ if HAVE_EXPERIMENTAL
21 psyc \ 21 psyc \
22 rps \ 22 rps \
23 social \ 23 social \
24 $(CONSENSUS) \ 24 $(CONSENSUS) \
25 $(SECRETSHARING) \ 25 $(SECRETSHARING) \
26 $(SENSOR) \ 26 $(SENSOR) \
27 $(SENSORDASHBOARD) 27 $(SENSORDASHBOARD)
28endif 28endif
29 29
30if HAVE_REST 30if HAVE_REST
31 EXP_DIR += identity-provider 31 PROVIDER_DIR = identity-provider
32endif
33
34if HAVE_JSON
35 JSON_DIR = json
32endif 36endif
33 37
34if BUILD_PULSE_HELPERS 38if BUILD_PULSE_HELPERS
@@ -60,7 +64,8 @@ else
60SUBDIRS = \ 64SUBDIRS = \
61 include $(INTLEMU_SUBDIRS) \ 65 include $(INTLEMU_SUBDIRS) \
62 util \ 66 util \
63 $(REST_DIR) \ 67 $(JSON_DIR) \
68 $(REST_DIR) \
64 hello \ 69 hello \
65 tun \ 70 tun \
66 block \ 71 block \
@@ -104,6 +109,7 @@ SUBDIRS = \
104 exit \ 109 exit \
105 pt \ 110 pt \
106 integration-tests \ 111 integration-tests \
107 $(EXP_DIR) 112 $(EXP_DIR) \
113 $(PROVIDER_DIR)
108 114
109endif 115endif
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 626089dbc..82fa9006b 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -65,6 +65,7 @@ gnunetinclude_HEADERS = \
65 gnunet_hello_lib.h \ 65 gnunet_hello_lib.h \
66 gnunet_helper_lib.h \ 66 gnunet_helper_lib.h \
67 gnunet_identity_service.h \ 67 gnunet_identity_service.h \
68 gnunet_json_lib.h \
68 gnunet_load_lib.h \ 69 gnunet_load_lib.h \
69 gnunet_cadet_service.h \ 70 gnunet_cadet_service.h \
70 gnunet_microphone_lib.h \ 71 gnunet_microphone_lib.h \
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h
new file mode 100644
index 000000000..e39938858
--- /dev/null
+++ b/src/include/gnunet_json_lib.h
@@ -0,0 +1,354 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file gnunet_json_lib.h
18 * @brief functions to parse JSON objects into GNUnet objects
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include <jansson.h>
26
27
28/* ****************** Generic parser interface ******************* */
29
30/**
31 * @brief Entry in parser specification for #GNUNET_JSON_parse().
32 */
33struct GNUNET_JSON_Specification;
34
35
36/**
37 * Function called to parse JSON argument.
38 *
39 * @param cls closure
40 * @param root JSON to parse
41 * @param spec our specification entry with further details
42 * @return #GNUNET_SYSERR on error,
43 * #GNUNET_OK on success
44 */
45typedef int
46(*GNUNET_JSON_Parser)(void *cls,
47 json_t *root,
48 struct GNUNET_JSON_Specification *spec);
49
50
51/**
52 * Function called to clean up data from earlier parsing.
53 *
54 * @param cls closure
55 * @param spec our specification entry with data to clean.
56 */
57typedef void
58(*GNUNET_JSON_Cleaner)(void *cls,
59 struct GNUNET_JSON_Specification *spec);
60
61
62/**
63 * @brief Entry in parser specification for #GNUNET_JSON_parse().
64 */
65struct GNUNET_JSON_Specification
66{
67 /**
68 * Function for how to parse this type of entry.
69 */
70 GNUNET_JSON_Parser parser;
71
72 /**
73 * Function for how to clean up this type of entry.
74 */
75 GNUNET_JSON_Cleaner cleaner;
76
77 /**
78 * Closure for @e parser and @e cleaner.
79 */
80 void *cls;
81
82 /**
83 * Name of the field to parse, use NULL to get the JSON
84 * of the main object instead of the JSON of an individual field.
85 */
86 const char *field;
87
88 /**
89 * Pointer, details specific to the @e parser.
90 */
91 void *ptr;
92
93 /**
94 * Number of bytes available in @e ptr.
95 */
96 size_t ptr_size;
97
98 /**
99 * Where should we store the final size of @e ptr.
100 */
101 size_t *size_ptr;
102
103};
104
105
106/**
107 * Navigate and parse data in a JSON tree. Tries to parse the @a root
108 * to find all of the values given in the @a spec. If one of the
109 * entries in @a spec cannot be found or parsed, the name of the JSON
110 * field is returned in @a error_json_name, and the offset of the
111 * entry in @a spec is returned in @a error_line.
112 *
113 * @param root the JSON node to start the navigation at.
114 * @param spec parse specification array
115 * @param[out] error_json_name which JSON field was problematic
116 * @param[out] which index into @a spec did we encounter an error
117 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
118 */
119int
120GNUNET_JSON_parse (const json_t *root,
121 struct GNUNET_JSON_Specification *spec,
122 const char **error_json_name,
123 unsigned int *error_line);
124
125
126/**
127 * Frees all elements allocated during a #GNUNET_JSON_parse()
128 * operation.
129 *
130 * @param spec specification of the parse operation
131 */
132void
133GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec);
134
135
136
137/* ****************** Canonical parser specifications ******************* */
138
139
140/**
141 * End of a parser specification.
142 */
143struct GNUNET_JSON_Specification
144GNUNET_JSON_spec_end (void);
145
146
147/**
148 * Variable size object (in network byte order, encoded using Crockford
149 * Base32hex encoding).
150 *
151 * @param name name of the JSON field
152 * @param[out] obj pointer where to write the data, must have @a size bytes
153 * @param size number of bytes expected in @a obj
154 */
155struct GNUNET_JSON_Specification
156GNUNET_JSON_spec_fixed (const char *name,
157 void *obj,
158 size_t size);
159
160
161/**
162 * Fixed size object (in network byte order, encoded using Crockford
163 * Base32hex encoding).
164 *
165 * @param name name of the JSON field
166 * @param obj pointer where to write the data (type of `*obj` will determine size)
167 */
168#define GNUNET_JSON_spec_fixed_auto(name,obj) GNUNET_JSON_spec_fixed (name, obj, sizeof (*obj))
169
170
171/**
172 * Variable size object (in network byte order, encoded using
173 * Crockford Base32hex encoding).
174 *
175 * @param name name of the JSON field
176 * @param[out] obj pointer where to write the data, will be allocated
177 * @param[out] size where to store the number of bytes allocated for @a obj
178 */
179struct GNUNET_JSON_Specification
180GNUNET_JSON_spec_varsize (const char *name,
181 void **obj,
182 size_t *size);
183
184
185/**
186 * The expected field stores a string.
187 *
188 * @param name name of the JSON field
189 * @param strptr where to store a pointer to the field
190 */
191struct GNUNET_JSON_Specification
192GNUNET_JSON_spec_string (const char *name,
193 const char **strptr);
194
195/**
196 * JSON object.
197 *
198 * @param name name of the JSON field
199 * @param[out] jsonp where to store the JSON found under @a name
200 */
201struct GNUNET_JSON_Specification
202GNUNET_JSON_spec_json (const char *name,
203 json_t **jsonp);
204
205
206/**
207 * 8-bit integer.
208 *
209 * @param name name of the JSON field
210 * @param[out] u8 where to store the integer found under @a name
211 */
212struct GNUNET_JSON_Specification
213GNUNET_JSON_spec_uint8 (const char *name,
214 uint8_t *u8);
215
216
217/**
218 * 16-bit integer.
219 *
220 * @param name name of the JSON field
221 * @param[out] u16 where to store the integer found under @a name
222 */
223struct GNUNET_JSON_Specification
224GNUNET_JSON_spec_uint16 (const char *name,
225 uint16_t *u16);
226
227
228/**
229 * 32-bit integer.
230 *
231 * @param name name of the JSON field
232 * @param[out] u32 where to store the integer found under @a name
233 */
234struct GNUNET_JSON_Specification
235GNUNET_JSON_spec_uint32 (const char *name,
236 uint32_t *u32);
237
238
239/**
240 * 64-bit integer.
241 *
242 * @param name name of the JSON field
243 * @param[out] u64 where to store the integer found under @a name
244 */
245struct GNUNET_JSON_Specification
246GNUNET_JSON_spec_uint64 (const char *name,
247 uint64_t *u64);
248
249
250/* ************ GNUnet-specific parser specifications ******************* */
251
252/**
253 * Absolute time.
254 *
255 * @param name name of the JSON field
256 * @param[out] at where to store the absolute time found under @a name
257 */
258struct GNUNET_JSON_Specification
259GNUNET_JSON_spec_absolute_time (const char *name,
260 struct GNUNET_TIME_Absolute *at);
261
262
263/**
264 * Relative time.
265 *
266 * @param name name of the JSON field
267 * @param[out] rt where to store the relative time found under @a name
268 */
269struct GNUNET_JSON_Specification
270GNUNET_JSON_spec_relative_time (const char *name,
271 struct GNUNET_TIME_Relative *rt);
272
273
274/**
275 * Specification for parsing an RSA public key.
276 *
277 * @param name name of the JSON field
278 * @param pk where to store the RSA key found under @a name
279 */
280struct GNUNET_JSON_Specification
281GNUNET_JSON_spec_rsa_public_key (const char *name,
282 struct GNUNET_CRYPTO_rsa_PublicKey **pk);
283
284
285/**
286 * Specification for parsing an RSA signature.
287 *
288 * @param name name of the JSON field
289 * @param sig where to store the RSA signature found under @a name
290 */
291struct GNUNET_JSON_Specification
292GNUNET_JSON_spec_rsa_signature (const char *name,
293 struct GNUNET_CRYPTO_rsa_Signature **sig);
294
295
296/* ****************** Generic generator interface ******************* */
297
298
299/**
300 * Convert binary data to a JSON string with the base32crockford
301 * encoding.
302 *
303 * @param data binary data
304 * @param size size of @a data in bytes
305 * @return json string that encodes @a data
306 */
307json_t *
308GNUNET_JSON_from_data (const void *data,
309 size_t size);
310
311
312/**
313 * Convert absolute timestamp to a json string.
314 *
315 * @param stamp the time stamp
316 * @return a json string with the timestamp in @a stamp
317 */
318json_t *
319GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp);
320
321
322/**
323 * Convert relative timestamp to a json string.
324 *
325 * @param stamp the time stamp
326 * @return a json string with the timestamp in @a stamp
327 */
328json_t *
329GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp);
330
331
332/**
333 * Convert RSA public key to JSON.
334 *
335 * @param pk public key to convert
336 * @return corresponding JSON encoding
337 */
338json_t *
339GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *pk);
340
341
342/**
343 * Convert RSA signature to JSON.
344 *
345 * @param sig signature to convert
346 * @return corresponding JSON encoding
347 */
348json_t *
349GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *sig);
350
351
352
353
354/* end of gnunet_json_lib.h */
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index dd41406d3..a7525df7e 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -58,8 +58,7 @@ struct GNUNET_PQ_QueryParam
58{ 58{
59 59
60 /** 60 /**
61 * Format of the rest of the entry, determines the data 61 * Function for how to handle this type of entry.
62 * type that is being added to the query.
63 */ 62 */
64 GNUNET_PQ_QueryConverter conv; 63 GNUNET_PQ_QueryConverter conv;
65 64
diff --git a/src/include/gnunet_time_lib.h b/src/include/gnunet_time_lib.h
index b805d1e0a..3dad179b5 100644
--- a/src/include/gnunet_time_lib.h
+++ b/src/include/gnunet_time_lib.h
@@ -259,6 +259,30 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel);
259 259
260 260
261/** 261/**
262 * Round a time value so that it is suitable for transmission
263 * via JSON encodings.
264 *
265 * @param at time to round
266 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
267 * it was just now rounded
268 */
269int
270GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at);
271
272
273/**
274 * Round a time value so that it is suitable for transmission
275 * via JSON encodings.
276 *
277 * @param rt time to round
278 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
279 * it was just now rounded
280 */
281int
282GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt);
283
284
285/**
262 * Return the minimum of two relative time values. 286 * Return the minimum of two relative time values.
263 * 287 *
264 * @param t1 first timestamp 288 * @param t1 first timestamp
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
new file mode 100644
index 000000000..83cd6dd2d
--- /dev/null
+++ b/src/json/Makefile.am
@@ -0,0 +1,35 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9lib_LTLIBRARIES = \
10 libgnunetjson.la
11
12libgnunetjson_la_LDFLAGS = \
13 -version-info 0:0:0 \
14 -no-undefined
15libgnunetjson_la_SOURCES = \
16 json.c \
17 json_generator.c \
18 json_helper.c
19libgnunetjson_la_LIBADD = \
20 -lgnunetutil \
21 -ljansson \
22 $(XLIB)
23
24check_PROGRAMS = \
25 test_json
26
27TESTS = \
28 $(check_PROGRAMS)
29
30test_json_SOURCES = \
31 test_json.c
32test_json_LDADD = \
33 libgnunetjson.la \
34 -lgnunetutil \
35 -ljansson
diff --git a/src/json/json.c b/src/json/json.c
new file mode 100644
index 000000000..aa74bfd48
--- /dev/null
+++ b/src/json/json.c
@@ -0,0 +1,92 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file json/json.c
18 * @brief functions to parse JSON snippets
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include "gnunet_json_lib.h"
25
26
27/**
28 * Navigate and parse data in a JSON tree. Tries to parse the @a root
29 * to find all of the values given in the @a spec. If one of the
30 * entries in @a spec cannot be found or parsed, the name of the JSON
31 * field is returned in @a error_json_name, and the offset of the
32 * entry in @a spec is returned in @a error_line.
33 *
34 * @param root the JSON node to start the navigation at.
35 * @param spec parse specification array
36 * @param[out] error_json_name which JSON field was problematic
37 * @param[out] which index into @a spec did we encounter an error
38 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
39 */
40int
41GNUNET_JSON_parse (const json_t *root,
42 struct GNUNET_JSON_Specification *spec,
43 const char **error_json_name,
44 unsigned int *error_line)
45{
46 unsigned int i;
47 json_t *pos;
48
49 for (i=0;NULL != spec[i].parser;i++)
50 {
51 if (NULL == spec[i].field)
52 pos = (json_t *) root;
53 else
54 pos = json_object_get (root,
55 spec[i].field);
56 if ( (NULL == pos) ||
57 (GNUNET_OK !=
58 spec[i].parser (spec[i].cls,
59 pos,
60 &spec[i])) )
61 {
62 if (NULL != error_json_name)
63 *error_json_name = spec[i].field;
64 if (NULL != error_line)
65 *error_line = i;
66 GNUNET_JSON_parse_free (spec);
67 return GNUNET_SYSERR;
68 }
69 }
70 return GNUNET_OK; /* all OK! */
71}
72
73
74/**
75 * Frees all elements allocated during a #GNUNET_JSON_parse()
76 * operation.
77 *
78 * @param spec specification of the parse operation
79 */
80void
81GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec)
82{
83 unsigned int i;
84
85 for (i=0;NULL != spec[i].parser;i++)
86 if (NULL != spec[i].cleaner)
87 spec[i].cleaner (spec[i].cls,
88 &spec[i]);
89}
90
91
92/* end of json.c */
diff --git a/src/json/json_generator.c b/src/json/json_generator.c
new file mode 100644
index 000000000..4b1ac31b1
--- /dev/null
+++ b/src/json/json_generator.c
@@ -0,0 +1,146 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file json/json_generator.c
18 * @brief helper functions for generating JSON from GNUnet data structures
19 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 */
21#include "platform.h"
22#include "gnunet_util_lib.h"
23#include "gnunet_json_lib.h"
24
25
26/**
27 * Convert binary data to a JSON string
28 * with the base32crockford encoding.
29 *
30 * @param data binary data
31 * @param size size of @a data in bytes
32 * @return json string that encodes @a data
33 */
34json_t *
35GNUNET_JSON_from_data (const void *data,
36 size_t size)
37{
38 char *buf;
39 json_t *json;
40
41 buf = GNUNET_STRINGS_data_to_string_alloc (data, size);
42 json = json_string (buf);
43 GNUNET_free (buf);
44 return json;
45}
46
47
48/**
49 * Convert absolute timestamp to a json string.
50 *
51 * @param stamp the time stamp
52 * @return a json string with the timestamp in @a stamp
53 */
54json_t *
55GNUNET_JSON_from_time_abs (struct GNUNET_TIME_Absolute stamp)
56{
57 json_t *j;
58 char *mystr;
59 int ret;
60
61 GNUNET_assert (GNUNET_OK ==
62 GNUNET_TIME_round_abs (&stamp));
63 if (stamp.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
64 return json_string ("/never/");
65 ret = GNUNET_asprintf (&mystr,
66 "/Date(%llu)/",
67 (unsigned long long) (stamp.abs_value_us / (1000LL * 1000LL)));
68 GNUNET_assert (ret > 0);
69 j = json_string (mystr);
70 GNUNET_free (mystr);
71 return j;
72}
73
74
75/**
76 * Convert relative timestamp to a json string.
77 *
78 * @param stamp the time stamp
79 * @return a json string with the timestamp in @a stamp
80 */
81json_t *
82GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
83{
84 json_t *j;
85 char *mystr;
86 int ret;
87
88 GNUNET_assert (GNUNET_OK ==
89 GNUNET_TIME_round_rel (&stamp));
90 if (stamp.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
91 return json_string ("/forever/");
92 ret = GNUNET_asprintf (&mystr,
93 "/Delay(%llu)/",
94 (unsigned long long) (stamp.rel_value_us / (1000LL * 1000LL)));
95 GNUNET_assert (ret > 0);
96 j = json_string (mystr);
97 GNUNET_free (mystr);
98 return j;
99}
100
101
102/**
103 * Convert RSA public key to JSON.
104 *
105 * @param pk public key to convert
106 * @return corresponding JSON encoding
107 */
108json_t *
109GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_rsa_PublicKey *pk)
110{
111 char *buf;
112 size_t buf_len;
113 json_t *ret;
114
115 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk,
116 &buf);
117 ret = GNUNET_JSON_from_data (buf,
118 buf_len);
119 GNUNET_free (buf);
120 return ret;
121}
122
123
124/**
125 * Convert RSA signature to JSON.
126 *
127 * @param sig signature to convert
128 * @return corresponding JSON encoding
129 */
130json_t *
131GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_rsa_Signature *sig)
132{
133 char *buf;
134 size_t buf_len;
135 json_t *ret;
136
137 buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig,
138 &buf);
139 ret = GNUNET_JSON_from_data (buf,
140 buf_len);
141 GNUNET_free (buf);
142 return ret;
143}
144
145
146/* End of json/json_generator.c */
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
new file mode 100644
index 000000000..cf84ae997
--- /dev/null
+++ b/src/json/json_helper.c
@@ -0,0 +1,864 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file json/json_helper.c
18 * @brief functions to generate specifciations for JSON parsing
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include "gnunet_json_lib.h"
25
26
27/**
28 * End of a parser specification.
29 */
30struct GNUNET_JSON_Specification
31GNUNET_JSON_spec_end ()
32{
33 struct GNUNET_JSON_Specification ret = {
34 .parser = NULL,
35 .cleaner = NULL,
36 .cls = NULL
37 };
38 return ret;
39}
40
41
42/**
43 * Parse given JSON object to fixed size data
44 *
45 * @param cls closure, NULL
46 * @param root the json object representing data
47 * @param[out] spec where to write the data
48 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
49 */
50static int
51parse_fixed_data (void *cls,
52 json_t *root,
53 struct GNUNET_JSON_Specification *spec)
54{
55 const char *enc;
56 unsigned int len;
57
58 if (NULL == (enc = json_string_value (root)))
59 {
60 GNUNET_break_op (0);
61 return GNUNET_SYSERR;
62 }
63 len = strlen (enc);
64 if (((len * 5) / 8) != spec->ptr_size)
65 {
66 GNUNET_break_op (0);
67 return GNUNET_SYSERR;
68 }
69 if (GNUNET_OK !=
70 GNUNET_STRINGS_string_to_data (enc,
71 len,
72 spec->ptr,
73 spec->ptr_size))
74 {
75 GNUNET_break_op (0);
76 return GNUNET_SYSERR;
77 }
78 return GNUNET_OK;
79}
80
81
82/**
83 * Variable size object (in network byte order, encoded using Crockford
84 * Base32hex encoding).
85 *
86 * @param name name of the JSON field
87 * @param[out] obj pointer where to write the data, must have @a size bytes
88 * @param size number of bytes expected in @a obj
89 */
90struct GNUNET_JSON_Specification
91GNUNET_JSON_spec_fixed (const char *name,
92 void *obj,
93 size_t size)
94{
95 struct GNUNET_JSON_Specification ret = {
96 .parser = &parse_fixed_data,
97 .cleaner = NULL,
98 .cls = NULL,
99 .field = name,
100 .ptr = obj,
101 .ptr_size = size,
102 .size_ptr = NULL
103 };
104 return ret;
105}
106
107
108/**
109 * Parse given JSON object to variable size data
110 *
111 * @param cls closure, NULL
112 * @param root the json object representing data
113 * @param[out] spec where to write the data
114 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
115 */
116static int
117parse_variable_data (void *cls,
118 json_t *root,
119 struct GNUNET_JSON_Specification *spec)
120{
121 const char *str;
122 size_t size;
123 void *data;
124 int res;
125
126 str = json_string_value (root);
127 if (NULL == str)
128 {
129 GNUNET_break_op (0);
130 return GNUNET_SYSERR;
131 }
132 size = (strlen (str) * 5) / 8;
133 if (size >= 1024)
134 {
135 GNUNET_break_op (0);
136 return GNUNET_SYSERR;
137 }
138 data = GNUNET_malloc (size);
139 res = GNUNET_STRINGS_string_to_data (str,
140 strlen (str),
141 data,
142 size);
143 if (GNUNET_OK != res)
144 {
145 GNUNET_break_op (0);
146 GNUNET_free (data);
147 return GNUNET_SYSERR;
148 }
149 *(void**) spec->ptr = data;
150 *spec->size_ptr = size;
151 return GNUNET_OK;
152}
153
154
155/**
156 * Cleanup data left from parsing variable size data
157 *
158 * @param cls closure, NULL
159 * @param[out] spec where to free the data
160 */
161static void
162clean_variable_data (void *cls,
163 struct GNUNET_JSON_Specification *spec)
164{
165 if (0 != *spec->size_ptr)
166 {
167 GNUNET_free (*(void **) spec->ptr);
168 *(void**) spec->ptr = NULL;
169 *spec->size_ptr = 0;
170 }
171}
172
173
174/**
175 * Variable size object (in network byte order, encoded using
176 * Crockford Base32hex encoding).
177 *
178 * @param name name of the JSON field
179 * @param[out] obj pointer where to write the data, will be allocated
180 * @param[out] size where to store the number of bytes allocated for @a obj
181 */
182struct GNUNET_JSON_Specification
183GNUNET_JSON_spec_varsize (const char *name,
184 void **obj,
185 size_t *size)
186{
187 struct GNUNET_JSON_Specification ret = {
188 .parser = &parse_variable_data,
189 .cleaner = &clean_variable_data,
190 .cls = NULL,
191 .field = name,
192 .ptr = obj,
193 .ptr_size = 0,
194 .size_ptr = size
195 };
196 *obj = NULL;
197 *size = 0;
198 return ret;
199}
200
201
202/**
203 * Parse given JSON object to string.
204 *
205 * @param cls closure, NULL
206 * @param root the json object representing data
207 * @param[out] spec where to write the data
208 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
209 */
210static int
211parse_string (void *cls,
212 json_t *root,
213 struct GNUNET_JSON_Specification *spec)
214{
215 const char *str;
216
217 str = json_string_value (root);
218 if (NULL == str)
219 {
220 GNUNET_break_op (0);
221 return GNUNET_SYSERR;
222 }
223 *(const char **) spec->ptr = str;
224 return GNUNET_OK;
225}
226
227
228/**
229 * The expected field stores a string.
230 *
231 * @param name name of the JSON field
232 * @param strptr where to store a pointer to the field
233 */
234struct GNUNET_JSON_Specification
235GNUNET_JSON_spec_string (const char *name,
236 const char **strptr)
237{
238 struct GNUNET_JSON_Specification ret = {
239 .parser = &parse_string,
240 .cleaner = NULL,
241 .cls = NULL,
242 .field = name,
243 .ptr = strptr,
244 .ptr_size = 0,
245 .size_ptr = NULL
246 };
247 return ret;
248}
249
250
251/**
252 * Parse given JSON object to a JSON object. (Yes, trivial.)
253 *
254 * @param cls closure, NULL
255 * @param root the json object representing data
256 * @param[out] spec where to write the data
257 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
258 */
259static int
260parse_object (void *cls,
261 json_t *root,
262 struct GNUNET_JSON_Specification *spec)
263{
264 if (! (json_is_object (root) || json_is_array (root)) )
265 {
266 GNUNET_break_op (0);
267 return GNUNET_SYSERR;
268 }
269 json_incref (root);
270 *(json_t **) spec->ptr = root;
271 return GNUNET_OK;
272}
273
274
275/**
276 * Cleanup data left from parsing JSON object.
277 *
278 * @param cls closure, NULL
279 * @param[out] spec where to free the data
280 */
281static void
282clean_object (void *cls,
283 struct GNUNET_JSON_Specification *spec)
284{
285 json_t **ptr = (json_t **) spec->ptr;
286 if (NULL != *ptr)
287 {
288 json_decref (*ptr);
289 *ptr = NULL;
290 }
291}
292
293
294/**
295 * JSON object.
296 *
297 * @param name name of the JSON field
298 * @param[out] jsonp where to store the JSON found under @a name
299 */
300struct GNUNET_JSON_Specification
301GNUNET_JSON_spec_json (const char *name,
302 json_t **jsonp)
303{
304 struct GNUNET_JSON_Specification ret = {
305 .parser = &parse_object,
306 .cleaner = &clean_object,
307 .cls = NULL,
308 .field = name,
309 .ptr = jsonp,
310 .ptr_size = 0,
311 .size_ptr = NULL
312 };
313 return ret;
314}
315
316
317/**
318 * Parse given JSON object to a uint8_t.
319 *
320 * @param cls closure, NULL
321 * @param root the json object representing data
322 * @param[out] spec where to write the data
323 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
324 */
325static int
326parse_u8 (void *cls,
327 json_t *root,
328 struct GNUNET_JSON_Specification *spec)
329{
330 json_int_t val;
331 uint8_t *up = spec->ptr;
332
333 if (! json_is_integer (root))
334 {
335 GNUNET_break_op (0);
336 return GNUNET_SYSERR;
337 }
338 val = json_integer_value (root);
339 if ( (0 > val) || (val > UINT8_MAX) )
340 {
341 GNUNET_break_op (0);
342 return GNUNET_SYSERR;
343 }
344 *up = (uint8_t) val;
345 return GNUNET_OK;
346}
347
348
349/**
350 * 8-bit integer.
351 *
352 * @param name name of the JSON field
353 * @param[out] u8 where to store the integer found under @a name
354 */
355struct GNUNET_JSON_Specification
356GNUNET_JSON_spec_uint8 (const char *name,
357 uint8_t *u8)
358{
359 struct GNUNET_JSON_Specification ret = {
360 .parser = &parse_u8,
361 .cleaner = NULL,
362 .cls = NULL,
363 .field = name,
364 .ptr = u8,
365 .ptr_size = sizeof (uint8_t),
366 .size_ptr = NULL
367 };
368 return ret;
369}
370
371
372/**
373 * Parse given JSON object to a uint16_t.
374 *
375 * @param cls closure, NULL
376 * @param root the json object representing data
377 * @param[out] spec where to write the data
378 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
379 */
380static int
381parse_u16 (void *cls,
382 json_t *root,
383 struct GNUNET_JSON_Specification *spec)
384{
385 json_int_t val;
386 uint16_t *up = spec->ptr;
387
388 if (! json_is_integer (root))
389 {
390 GNUNET_break_op (0);
391 return GNUNET_SYSERR;
392 }
393 val = json_integer_value (root);
394 if ( (0 > val) || (val > UINT16_MAX) )
395 {
396 GNUNET_break_op (0);
397 return GNUNET_SYSERR;
398 }
399 *up = (uint16_t) val;
400 return GNUNET_OK;
401}
402
403
404/**
405 * 16-bit integer.
406 *
407 * @param name name of the JSON field
408 * @param[out] u16 where to store the integer found under @a name
409 */
410struct GNUNET_JSON_Specification
411GNUNET_JSON_spec_uint16 (const char *name,
412 uint16_t *u16)
413{
414 struct GNUNET_JSON_Specification ret = {
415 .parser = &parse_u16,
416 .cleaner = NULL,
417 .cls = NULL,
418 .field = name,
419 .ptr = u16,
420 .ptr_size = sizeof (uint16_t),
421 .size_ptr = NULL
422 };
423 return ret;
424}
425
426
427/**
428 * Parse given JSON object to a uint32_t.
429 *
430 * @param cls closure, NULL
431 * @param root the json object representing data
432 * @param[out] spec where to write the data
433 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
434 */
435static int
436parse_u32 (void *cls,
437 json_t *root,
438 struct GNUNET_JSON_Specification *spec)
439{
440 json_int_t val;
441 uint32_t *up = spec->ptr;
442
443 if (! json_is_integer (root))
444 {
445 GNUNET_break_op (0);
446 return GNUNET_SYSERR;
447 }
448 val = json_integer_value (root);
449 if ( (0 > val) || (val > UINT32_MAX) )
450 {
451 GNUNET_break_op (0);
452 return GNUNET_SYSERR;
453 }
454 *up = (uint32_t) val;
455 return GNUNET_OK;
456}
457
458
459/**
460 * 32-bit integer.
461 *
462 * @param name name of the JSON field
463 * @param[out] u32 where to store the integer found under @a name
464 */
465struct GNUNET_JSON_Specification
466GNUNET_JSON_spec_uint32 (const char *name,
467 uint32_t *u32)
468{
469 struct GNUNET_JSON_Specification ret = {
470 .parser = &parse_u32,
471 .cleaner = NULL,
472 .cls = NULL,
473 .field = name,
474 .ptr = u32,
475 .ptr_size = sizeof (uint32_t),
476 .size_ptr = NULL
477 };
478 return ret;
479}
480
481
482/**
483 * Parse given JSON object to a uint8_t.
484 *
485 * @param cls closure, NULL
486 * @param root the json object representing data
487 * @param[out] spec where to write the data
488 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
489 */
490static int
491parse_u64 (void *cls,
492 json_t *root,
493 struct GNUNET_JSON_Specification *spec)
494{
495 json_int_t val;
496 uint64_t *up = spec->ptr;
497
498 if (! json_is_integer (root))
499 {
500 GNUNET_break_op (0);
501 return GNUNET_SYSERR;
502 }
503 val = json_integer_value (root);
504 *up = (uint64_t) val;
505 return GNUNET_OK;
506}
507
508
509/**
510 * 64-bit integer.
511 *
512 * @param name name of the JSON field
513 * @param[out] u64 where to store the integer found under @a name
514 */
515struct GNUNET_JSON_Specification
516GNUNET_JSON_spec_uint64 (const char *name,
517 uint64_t *u64)
518{
519 struct GNUNET_JSON_Specification ret = {
520 .parser = &parse_u64,
521 .cleaner = NULL,
522 .cls = NULL,
523 .field = name,
524 .ptr = u64,
525 .ptr_size = sizeof (uint64_t),
526 .size_ptr = NULL
527 };
528 return ret;
529}
530
531
532/* ************ GNUnet-specific parser specifications ******************* */
533
534/**
535 * Parse given JSON object to absolute time.
536 *
537 * @param cls closure, NULL
538 * @param root the json object representing data
539 * @param[out] spec where to write the data
540 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
541 */
542static int
543parse_abs_time (void *cls,
544 json_t *root,
545 struct GNUNET_JSON_Specification *spec)
546{
547 struct GNUNET_TIME_Absolute *abs = spec->ptr;
548 const char *val;
549 unsigned long long int tval;
550
551 val = json_string_value (root);
552 if (NULL == val)
553 {
554 GNUNET_break_op (0);
555 return GNUNET_SYSERR;
556 }
557 if ( (0 == strcasecmp (val,
558 "/forever/")) ||
559 (0 == strcasecmp (val,
560 "/end of time/")) ||
561 (0 == strcasecmp (val,
562 "/never/")) )
563 {
564 *abs = GNUNET_TIME_UNIT_FOREVER_ABS;
565 return GNUNET_OK;
566 }
567 if (1 != sscanf (val,
568 "/Date(%llu)/",
569 &tval))
570 {
571 GNUNET_break_op (0);
572 return GNUNET_SYSERR;
573 }
574 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
575 abs->abs_value_us = tval * 1000LL * 1000LL;
576 if ( (abs->abs_value_us) / 1000LL / 1000LL != tval)
577 {
578 /* Integer overflow */
579 GNUNET_break_op (0);
580 return GNUNET_SYSERR;
581 }
582 return GNUNET_OK;
583}
584
585
586/**
587 * Absolute time.
588 *
589 * @param name name of the JSON field
590 * @param[out] at where to store the absolute time found under @a name
591 */
592struct GNUNET_JSON_Specification
593GNUNET_JSON_spec_absolute_time (const char *name,
594 struct GNUNET_TIME_Absolute *at)
595{
596 struct GNUNET_JSON_Specification ret = {
597 .parser = &parse_abs_time,
598 .cleaner = NULL,
599 .cls = NULL,
600 .field = name,
601 .ptr = at,
602 .ptr_size = sizeof (uint64_t),
603 .size_ptr = NULL
604 };
605 return ret;
606}
607
608
609/**
610 * Parse given JSON object to relative time.
611 *
612 * @param cls closure, NULL
613 * @param root the json object representing data
614 * @param[out] spec where to write the data
615 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
616 */
617static int
618parse_rel_time (void *cls,
619 json_t *root,
620 struct GNUNET_JSON_Specification *spec)
621{
622 struct GNUNET_TIME_Relative *rel = spec->ptr;
623 const char *val;
624 unsigned long long int tval;
625
626 val = json_string_value (root);
627 if (NULL == val)
628 {
629 GNUNET_break_op (0);
630 return GNUNET_SYSERR;
631 }
632 if ( (0 == strcasecmp (val,
633 "/forever/")) )
634 {
635 *rel = GNUNET_TIME_UNIT_FOREVER_REL;
636 return GNUNET_OK;
637 }
638 if (1 != sscanf (val,
639 "/Delay(%llu)/",
640 &tval))
641 {
642 GNUNET_break_op (0);
643 return GNUNET_SYSERR;
644 }
645 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Relative */
646 rel->rel_value_us = tval * 1000LL * 1000LL;
647 if ( (rel->rel_value_us) / 1000LL / 1000LL != tval)
648 {
649 /* Integer overflow */
650 GNUNET_break_op (0);
651 return GNUNET_SYSERR;
652 }
653 return GNUNET_OK;
654}
655
656
657/**
658 * Relative time.
659 *
660 * @param name name of the JSON field
661 * @param[out] rt where to store the relative time found under @a name
662 */
663struct GNUNET_JSON_Specification
664GNUNET_JSON_spec_relative_time (const char *name,
665 struct GNUNET_TIME_Relative *rt)
666{
667 struct GNUNET_JSON_Specification ret = {
668 .parser = &parse_rel_time,
669 .cleaner = NULL,
670 .cls = NULL,
671 .field = name,
672 .ptr = rt,
673 .ptr_size = sizeof (uint64_t),
674 .size_ptr = NULL
675 };
676 return ret;
677}
678
679
680/**
681 * Parse given JSON object to RSA public key.
682 *
683 * @param cls closure, NULL
684 * @param root the json object representing data
685 * @param[out] spec where to write the data
686 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
687 */
688static int
689parse_rsa_public_key (void *cls,
690 json_t *root,
691 struct GNUNET_JSON_Specification *spec)
692{
693 struct GNUNET_CRYPTO_rsa_PublicKey **pk = spec->ptr;
694 const char *enc;
695 char *buf;
696 size_t len;
697 size_t buf_len;
698
699 if (NULL == (enc = json_string_value (root)))
700 {
701 GNUNET_break_op (0);
702 return GNUNET_SYSERR;
703 }
704 len = strlen (enc);
705 buf_len = (len * 5) / 8;
706 buf = GNUNET_malloc (buf_len);
707 if (GNUNET_OK !=
708 GNUNET_STRINGS_string_to_data (enc,
709 len,
710 buf,
711 buf_len))
712 {
713 GNUNET_break_op (0);
714 GNUNET_free (buf);
715 return GNUNET_SYSERR;
716 }
717 if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
718 buf_len)))
719 {
720 GNUNET_break_op (0);
721 GNUNET_free (buf);
722 return GNUNET_SYSERR;
723 }
724 GNUNET_free (buf);
725 return GNUNET_OK;
726}
727
728
729/**
730 * Cleanup data left from parsing RSA public key.
731 *
732 * @param cls closure, NULL
733 * @param[out] spec where to free the data
734 */
735static void
736clean_rsa_public_key (void *cls,
737 struct GNUNET_JSON_Specification *spec)
738{
739 struct GNUNET_CRYPTO_rsa_PublicKey **pk = spec->ptr;
740
741 if (NULL != *pk)
742 {
743 GNUNET_CRYPTO_rsa_public_key_free (*pk);
744 *pk = NULL;
745 }
746}
747
748
749/**
750 * Specification for parsing an RSA public key.
751 *
752 * @param name name of the JSON field
753 * @param pk where to store the RSA key found under @a name
754 */
755struct GNUNET_JSON_Specification
756GNUNET_JSON_spec_rsa_public_key (const char *name,
757 struct GNUNET_CRYPTO_rsa_PublicKey **pk)
758{
759 struct GNUNET_JSON_Specification ret = {
760 .parser = &parse_rsa_public_key,
761 .cleaner = &clean_rsa_public_key,
762 .cls = NULL,
763 .field = name,
764 .ptr = pk,
765 .ptr_size = 0,
766 .size_ptr = NULL
767 };
768 return ret;
769}
770
771
772/**
773 * Parse given JSON object to RSA signature.
774 *
775 * @param cls closure, NULL
776 * @param root the json object representing data
777 * @param[out] spec where to write the data
778 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
779 */
780static int
781parse_rsa_signature (void *cls,
782 json_t *root,
783 struct GNUNET_JSON_Specification *spec)
784{
785 struct GNUNET_CRYPTO_rsa_Signature **sig = spec->ptr;
786 size_t size;
787 const char *str;
788 int res;
789 void *buf;
790
791 str = json_string_value (root);
792 if (NULL == str)
793 {
794 GNUNET_break_op (0);
795 return GNUNET_SYSERR;
796 }
797 size = (strlen (str) * 5) / 8;
798 buf = GNUNET_malloc (size);
799 res = GNUNET_STRINGS_string_to_data (str,
800 strlen (str),
801 buf,
802 size);
803 if (GNUNET_OK != res)
804 {
805 GNUNET_free (buf);
806 GNUNET_break_op (0);
807 return GNUNET_SYSERR;
808 }
809 if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
810 size)))
811 {
812 GNUNET_break_op (0);
813 GNUNET_free (buf);
814 return GNUNET_SYSERR;
815 }
816 GNUNET_free (buf);
817 return GNUNET_OK;
818}
819
820
821/**
822 * Cleanup data left from parsing RSA signature.
823 *
824 * @param cls closure, NULL
825 * @param[out] spec where to free the data
826 */
827static void
828clean_rsa_signature (void *cls,
829 struct GNUNET_JSON_Specification *spec)
830{
831 struct GNUNET_CRYPTO_rsa_Signature **sig = spec->ptr;
832
833 if (NULL != *sig)
834 {
835 GNUNET_CRYPTO_rsa_signature_free (*sig);
836 *sig = NULL;
837 }
838}
839
840
841/**
842 * Specification for parsing an RSA signature.
843 *
844 * @param name name of the JSON field
845 * @param sig where to store the RSA signature found under @a name
846 */
847struct GNUNET_JSON_Specification
848GNUNET_JSON_spec_rsa_signature (const char *name,
849 struct GNUNET_CRYPTO_rsa_Signature **sig)
850{
851 struct GNUNET_JSON_Specification ret = {
852 .parser = &parse_rsa_signature,
853 .cleaner = &clean_rsa_signature,
854 .cls = NULL,
855 .field = name,
856 .ptr = sig,
857 .ptr_size = 0,
858 .size_ptr = NULL
859 };
860 return ret;
861}
862
863
864/* end of json_helper.c */
diff --git a/src/json/test_json.c b/src/json/test_json.c
new file mode 100644
index 000000000..a334bf599
--- /dev/null
+++ b/src/json/test_json.c
@@ -0,0 +1,217 @@
1/*
2 This file is part of GNUnet
3 (C) 2015, 2016 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file json/test_json.c
19 * @brief Tests for JSON conversion functions
20 * @author Christian Grothoff <christian@grothoff.org>
21 */
22#include "platform.h"
23#include "gnunet_util_lib.h"
24#include "gnunet_json_lib.h"
25
26
27/**
28 * Test absolute time conversion from/to JSON.
29 *
30 * @return 0 on success
31 */
32static int
33test_abs_time ()
34{
35 json_t *j;
36 struct GNUNET_TIME_Absolute a1;
37 struct GNUNET_TIME_Absolute a2;
38 struct GNUNET_JSON_Specification s1[] = {
39 GNUNET_JSON_spec_absolute_time (NULL, &a2),
40 GNUNET_JSON_spec_end()
41 };
42 struct GNUNET_JSON_Specification s2[] = {
43 GNUNET_JSON_spec_absolute_time (NULL, &a2),
44 GNUNET_JSON_spec_end()
45 };
46
47 a1 = GNUNET_TIME_absolute_get ();
48 GNUNET_TIME_round_abs (&a1);
49 j = GNUNET_JSON_from_time_abs (a1);
50 GNUNET_assert (NULL != j);
51 GNUNET_assert (GNUNET_OK ==
52 GNUNET_JSON_parse (j, s1, NULL, NULL));
53 GNUNET_assert (a1.abs_value_us ==
54 a2.abs_value_us);
55 json_decref (j);
56
57 a1 = GNUNET_TIME_UNIT_FOREVER_ABS;
58 j = GNUNET_JSON_from_time_abs (a1);
59 GNUNET_assert (NULL != j);
60 GNUNET_assert (GNUNET_OK ==
61 GNUNET_JSON_parse (j, s2, NULL, NULL));
62 GNUNET_assert (a1.abs_value_us ==
63 a2.abs_value_us);
64 json_decref (j);
65 return 0;
66}
67
68
69/**
70 * Test relative time conversion from/to JSON.
71 *
72 * @return 0 on success
73 */
74static int
75test_rel_time ()
76{
77 json_t *j;
78 struct GNUNET_TIME_Relative r1;
79 struct GNUNET_TIME_Relative r2;
80 struct GNUNET_JSON_Specification s1[] = {
81 GNUNET_JSON_spec_relative_time (NULL, &r2),
82 GNUNET_JSON_spec_end()
83 };
84 struct GNUNET_JSON_Specification s2[] = {
85 GNUNET_JSON_spec_relative_time (NULL, &r2),
86 GNUNET_JSON_spec_end()
87 };
88
89 r1 = GNUNET_TIME_UNIT_SECONDS;
90 j = GNUNET_JSON_from_time_rel (r1);
91 GNUNET_assert (NULL != j);
92 GNUNET_assert (GNUNET_OK ==
93 GNUNET_JSON_parse (j, s1, NULL, NULL));
94 GNUNET_assert (r1.rel_value_us ==
95 r2.rel_value_us);
96 json_decref (j);
97
98 r1 = GNUNET_TIME_UNIT_FOREVER_REL;
99 j = GNUNET_JSON_from_time_rel (r1);
100 GNUNET_assert (NULL != j);
101 GNUNET_assert (GNUNET_OK ==
102 GNUNET_JSON_parse (j, s2, NULL, NULL));
103 GNUNET_assert (r1.rel_value_us ==
104 r2.rel_value_us);
105 json_decref (j);
106 return 0;
107}
108
109
110/**
111 * Test raw (binary) conversion from/to JSON.
112 *
113 * @return 0 on success
114 */
115static int
116test_raw ()
117{
118 char blob[256];
119 unsigned int i;
120 json_t *j;
121
122 for (i=0;i<=256;i++)
123 {
124 char blob2[256];
125 struct GNUNET_JSON_Specification spec[] = {
126 GNUNET_JSON_spec_fixed (NULL, blob2, i),
127 GNUNET_JSON_spec_end()
128 };
129
130 memset (blob, i, i);
131 j = GNUNET_JSON_from_data (blob, i);
132 GNUNET_assert (NULL != j);
133 GNUNET_assert (GNUNET_OK ==
134 GNUNET_JSON_parse (j, spec,
135 NULL, NULL));
136 GNUNET_assert (0 ==
137 memcmp (blob,
138 blob2,
139 i));
140 }
141 return 0;
142}
143
144
145/**
146 * Test rsa conversions from/to JSON.
147 *
148 * @return 0 on success
149 */
150static int
151test_rsa ()
152{
153 struct GNUNET_CRYPTO_rsa_PublicKey *pub;
154 struct GNUNET_CRYPTO_rsa_PublicKey *pub2;
155 struct GNUNET_JSON_Specification pspec[] = {
156 GNUNET_JSON_spec_rsa_public_key (NULL, &pub2),
157 GNUNET_JSON_spec_end()
158 };
159 struct GNUNET_CRYPTO_rsa_Signature *sig;
160 struct GNUNET_CRYPTO_rsa_Signature *sig2;
161 struct GNUNET_JSON_Specification sspec[] = {
162 GNUNET_JSON_spec_rsa_signature (NULL, &sig2),
163 GNUNET_JSON_spec_end()
164 };
165 struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
166 char msg[] = "Hello";
167 json_t *jp;
168 json_t *js;
169
170 priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
171 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
172 sig = GNUNET_CRYPTO_rsa_sign (priv,
173 msg,
174 sizeof (msg));
175 GNUNET_assert (NULL != (jp = GNUNET_JSON_from_rsa_public_key (pub)));
176 GNUNET_assert (NULL != (js = GNUNET_JSON_from_rsa_signature (sig)));
177 GNUNET_assert (GNUNET_OK ==
178 GNUNET_JSON_parse (jp, pspec,
179 NULL, NULL));
180 GNUNET_assert (GNUNET_OK ==
181 GNUNET_JSON_parse (js, sspec,
182 NULL, NULL));
183 GNUNET_break (0 ==
184 GNUNET_CRYPTO_rsa_signature_cmp (sig,
185 sig2));
186 GNUNET_break (0 ==
187 GNUNET_CRYPTO_rsa_public_key_cmp (pub,
188 pub2));
189 GNUNET_CRYPTO_rsa_signature_free (sig);
190 GNUNET_CRYPTO_rsa_signature_free (sig2);
191 GNUNET_CRYPTO_rsa_private_key_free (priv);
192 GNUNET_CRYPTO_rsa_public_key_free (pub);
193 GNUNET_CRYPTO_rsa_public_key_free (pub2);
194 return 0;
195}
196
197
198int
199main(int argc,
200 const char *const argv[])
201{
202 GNUNET_log_setup ("test-json",
203 "WARNING",
204 NULL);
205 if (0 != test_abs_time ())
206 return 1;
207 if (0 != test_rel_time ())
208 return 1;
209 if (0 != test_raw ())
210 return 1;
211 if (0 != test_rsa ())
212 return 1;
213 /* FIXME: test EdDSA signature conversion... */
214 return 0;
215}
216
217/* end of test_json.c */
diff --git a/src/util/time.c b/src/util/time.c
index 4f3eaa7fb..654b567f0 100644
--- a/src/util/time.c
+++ b/src/util/time.c
@@ -59,6 +59,46 @@ GNUNET_TIME_get_offset ()
59 59
60 60
61/** 61/**
62 * Round a time value so that it is suitable for transmission
63 * via JSON encodings.
64 *
65 * @param at time to round
66 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
67 * it was just now rounded
68 */
69int
70GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
71{
72 if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
73 return GNUNET_OK;
74 if (0 == at->abs_value_us % 1000000)
75 return GNUNET_OK;
76 at->abs_value_us -= at->abs_value_us % 1000000;
77 return GNUNET_NO;
78}
79
80
81/**
82 * Round a time value so that it is suitable for transmission
83 * via JSON encodings.
84 *
85 * @param rt time to round
86 * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
87 * it was just now rounded
88 */
89int
90GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
91{
92 if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
93 return GNUNET_OK;
94 if (0 == rt->rel_value_us % 1000000)
95 return GNUNET_OK;
96 rt->rel_value_us -= rt->rel_value_us % 1000000;
97 return GNUNET_NO;
98}
99
100
101/**
62 * Get the current time (works just as "time", just that we use the 102 * Get the current time (works just as "time", just that we use the
63 * unit of time that the cron-jobs use (and is 64 bit)). 103 * unit of time that the cron-jobs use (and is 64 bit)).
64 * 104 *