aboutsummaryrefslogtreecommitdiff
path: root/src/json
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:49:14 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:49:14 +0200
commit5b2527d8d81f92e00a0835e3039a0a2eee0ee566 (patch)
tree2e1ccc44f46ca7dc675f4938eab0e5e8efaad793 /src/json
parent84bbd6f1be6686b3c816ee5bb5c0c786ac193c6c (diff)
downloadgnunet-5b2527d8d81f92e00a0835e3039a0a2eee0ee566.tar.gz
gnunet-5b2527d8d81f92e00a0835e3039a0a2eee0ee566.zip
BUILD: Move json to lib
Diffstat (limited to 'src/json')
-rw-r--r--src/json/.gitignore2
-rw-r--r--src/json/Makefile.am57
-rw-r--r--src/json/json.c161
-rw-r--r--src/json/json_generator.c209
-rw-r--r--src/json/json_helper.c1182
-rw-r--r--src/json/json_mhd.c379
-rw-r--r--src/json/json_pack.c367
-rw-r--r--src/json/meson.build25
-rw-r--r--src/json/test_json.c247
-rw-r--r--src/json/test_json_mhd.c193
10 files changed, 0 insertions, 2822 deletions
diff --git a/src/json/.gitignore b/src/json/.gitignore
deleted file mode 100644
index 347bffd7b..000000000
--- a/src/json/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1test_json
2test_json_mhd
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
deleted file mode 100644
index c67824ee4..000000000
--- a/src/json/Makefile.am
+++ /dev/null
@@ -1,57 +0,0 @@
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 $(GN_LIBINTL) \
14 -version-info 0:0:0 \
15 -no-undefined
16libgnunetjson_la_CFLAGS = \
17 $(MHD_CFLAGS) \
18 $(AM_CFLAGS)
19libgnunetjson_la_SOURCES = \
20 json.c \
21 json_generator.c \
22 json_helper.c \
23 json_mhd.c \
24 json_pack.c
25libgnunetjson_la_LIBADD = \
26 $(top_builddir)/src/lib/util/libgnunetutil.la \
27 -ljansson \
28 $(MHD_LIBS) \
29 $(XLIB) \
30 $(Z_LIBS)
31
32check_PROGRAMS = \
33 test_json \
34 test_json_mhd
35
36TESTS = \
37 $(check_PROGRAMS)
38
39test_json_SOURCES = \
40 test_json.c
41test_json_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
42test_json_LDADD = \
43 libgnunetjson.la \
44 $(top_builddir)/src/lib/util/libgnunetutil.la \
45 -ljansson
46
47
48test_json_mhd_SOURCES = \
49 test_json_mhd.c
50test_json_mhd_LDADD = \
51 libgnunetjson.la \
52 $(top_builddir)/src/lib/util/libgnunetutil.la \
53 -ljansson \
54 $(MHD_LIBS) \
55 $(Z_LIBS) \
56 @LIBCURL@
57test_json_mhd_CFLAGS = $(MHD_CFLAGS) @LIBCURL_CPPFLAGS@ $(AM_CFLAGS)
diff --git a/src/json/json.c b/src/json/json.c
deleted file mode 100644
index 07ec158be..000000000
--- a/src/json/json.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014-2017, 2021, 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file json/json.c
22 * @brief functions to parse JSON snippets
23 * @author Florian Dold
24 * @author Benedikt Mueller
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_json_lib.h"
29
30
31enum GNUNET_GenericReturnValue
32GNUNET_JSON_parse (const json_t *root,
33 struct GNUNET_JSON_Specification *spec,
34 const char **error_json_name,
35 unsigned int *error_line)
36{
37 if (NULL == root)
38 return GNUNET_SYSERR;
39 for (unsigned int i = 0; NULL != spec[i].parser; i++)
40 {
41 json_t *pos;
42
43 if (NULL == spec[i].field)
44 pos = (json_t *) root;
45 else
46 pos = json_object_get (root,
47 spec[i].field);
48 if ( ( (NULL == pos) ||
49 (json_is_null (pos) ) ) &&
50 (spec[i].is_optional) )
51 {
52 if (NULL != spec[i].missing)
53 *spec[i].missing = true;
54 continue;
55 }
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 else
65 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
66 "Parsing failed for field `%s:%u`\n",
67 spec[i].field,
68 i);
69 if (NULL != error_line)
70 *error_line = i;
71 GNUNET_JSON_parse_free (spec);
72 return GNUNET_SYSERR;
73 }
74 if (NULL != spec[i].missing)
75 *spec[i].missing = false;
76 }
77 return GNUNET_OK; /* all OK! */
78}
79
80
81struct GNUNET_JSON_Specification
82GNUNET_JSON_spec_mark_optional (struct GNUNET_JSON_Specification spec,
83 bool *missing)
84{
85 struct GNUNET_JSON_Specification ret = spec;
86
87 ret.is_optional = true;
88 ret.missing = missing;
89 return ret;
90}
91
92
93void
94GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec)
95{
96 for (unsigned int i = 0; NULL != spec[i].parser; i++)
97 if (NULL != spec[i].cleaner)
98 spec[i].cleaner (spec[i].cls,
99 &spec[i]);
100}
101
102
103/**
104 * Set an option with a JSON value from the command line.
105 * A pointer to this function should be passed as part of the
106 * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
107 * of this type.
108 *
109 * @param ctx command line processing context
110 * @param scls additional closure (will point to the 'json_t *')
111 * @param option name of the option
112 * @param value actual value of the option as a string.
113 * @return #GNUNET_OK if parsing the value worked
114 */
115static enum GNUNET_GenericReturnValue
116set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
117 void *scls,
118 const char *option,
119 const char *value)
120{
121 json_t **json = scls;
122 json_error_t error;
123
124 *json = json_loads (value,
125 JSON_REJECT_DUPLICATES,
126 &error);
127 if (NULL == *json)
128 {
129 fprintf (stderr,
130 _ ("Failed to parse JSON in option `%s': %s (%s)\n"),
131 option,
132 error.text,
133 error.source);
134 return GNUNET_SYSERR;
135 }
136 return GNUNET_OK;
137}
138
139
140struct GNUNET_GETOPT_CommandLineOption
141GNUNET_JSON_getopt (char shortName,
142 const char *name,
143 const char *argumentHelp,
144 const char *description,
145 json_t **json)
146{
147 struct GNUNET_GETOPT_CommandLineOption clo = {
148 .shortName = shortName,
149 .name = name,
150 .argumentHelp = argumentHelp,
151 .description = description,
152 .require_argument = 1,
153 .processor = &set_json,
154 .scls = (void *) json
155 };
156
157 return clo;
158}
159
160
161/* end of json.c */
diff --git a/src/json/json_generator.c b/src/json/json_generator.c
deleted file mode 100644
index 4fda86e32..000000000
--- a/src/json/json_generator.c
+++ /dev/null
@@ -1,209 +0,0 @@
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
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file json/json_generator.c
22 * @brief helper functions for generating JSON from GNUnet data structures
23 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_json_lib.h"
28
29
30json_t *
31GNUNET_JSON_from_data (const void *data,
32 size_t size)
33{
34 char *buf;
35 json_t *json;
36
37 if ((size * 8 + 4) / 5 + 1 >=
38 GNUNET_MAX_MALLOC_CHECKED)
39 {
40 GNUNET_break (0);
41 return NULL;
42 }
43 buf = GNUNET_STRINGS_data_to_string_alloc (data,
44 size);
45 json = json_string (buf);
46 GNUNET_free (buf);
47 GNUNET_break (NULL != json);
48 return json;
49}
50
51
52json_t *
53GNUNET_JSON_from_data64 (const void *data,
54 size_t size)
55{
56 char *buf = NULL;
57 json_t *json;
58 size_t len;
59
60 if ((size * 8 + 5) / 6 + 1 >=
61 GNUNET_MAX_MALLOC_CHECKED)
62 {
63 GNUNET_break (0);
64 return NULL;
65 }
66 len = GNUNET_STRINGS_base64_encode (data,
67 size,
68 &buf);
69 if (NULL == buf)
70 {
71 GNUNET_break (0);
72 return NULL;
73 }
74 json = json_stringn (buf,
75 len);
76 GNUNET_free (buf);
77 GNUNET_break (NULL != json);
78 return json;
79}
80
81
82json_t *
83GNUNET_JSON_from_timestamp (struct GNUNET_TIME_Timestamp stamp)
84{
85 json_t *j;
86
87 j = json_object ();
88 if (NULL == j)
89 {
90 GNUNET_break (0);
91 return NULL;
92 }
93 if (GNUNET_TIME_absolute_is_never (stamp.abs_time))
94 {
95 if (0 !=
96 json_object_set_new (j,
97 "t_s",
98 json_string ("never")))
99 {
100 GNUNET_break (0);
101 json_decref (j);
102 return NULL;
103 }
104 return j;
105 }
106 GNUNET_assert (
107 0 ==
108 (stamp.abs_time.abs_value_us
109 % GNUNET_TIME_UNIT_SECONDS.rel_value_us));
110 if (0 !=
111 json_object_set_new (
112 j,
113 "t_s",
114 json_integer (
115 (json_int_t) (stamp.abs_time.abs_value_us
116 / GNUNET_TIME_UNIT_SECONDS.rel_value_us))))
117 {
118 GNUNET_break (0);
119 json_decref (j);
120 return NULL;
121 }
122 return j;
123}
124
125
126json_t *
127GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp)
128{
129 return GNUNET_JSON_from_timestamp (GNUNET_TIME_timestamp_ntoh (stamp));
130}
131
132
133json_t *
134GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
135{
136 json_t *j;
137
138 j = json_object ();
139 if (NULL == j)
140 {
141 GNUNET_break (0);
142 return NULL;
143 }
144 if (GNUNET_TIME_relative_is_forever (stamp))
145 {
146 if (0 !=
147 json_object_set_new (j,
148 "d_us",
149 json_string ("forever")))
150 {
151 GNUNET_break (0);
152 json_decref (j);
153 return NULL;
154 }
155 return j;
156 }
157 if (stamp.rel_value_us >= (1LLU << 53))
158 {
159 /* value is larger than allowed */
160 GNUNET_break (0);
161 return NULL;
162 }
163 if (0 !=
164 json_object_set_new (
165 j,
166 "d_us",
167 json_integer ((json_int_t) stamp.rel_value_us)))
168 {
169 GNUNET_break (0);
170 json_decref (j);
171 return NULL;
172 }
173 return j;
174}
175
176
177json_t *
178GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk)
179{
180 void *buf;
181 size_t buf_len;
182 json_t *ret;
183
184 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk,
185 &buf);
186 ret = GNUNET_JSON_from_data (buf,
187 buf_len);
188 GNUNET_free (buf);
189 return ret;
190}
191
192
193json_t *
194GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig)
195{
196 void *buf;
197 size_t buf_len;
198 json_t *ret;
199
200 buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig,
201 &buf);
202 ret = GNUNET_JSON_from_data (buf,
203 buf_len);
204 GNUNET_free (buf);
205 return ret;
206}
207
208
209/* End of json/json_generator.c */
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
deleted file mode 100644
index 4795285f4..000000000
--- a/src/json/json_helper.c
+++ /dev/null
@@ -1,1182 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014-2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file json/json_helper.c
22 * @brief functions to generate specifciations for JSON parsing
23 * @author Florian Dold
24 * @author Benedikt Mueller
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_json_lib.h"
29
30
31struct GNUNET_JSON_Specification
32GNUNET_JSON_spec_end ()
33{
34 struct GNUNET_JSON_Specification ret = {
35 .parser = NULL,
36 .cleaner = NULL,
37 .cls = NULL
38 };
39
40 return ret;
41}
42
43
44/**
45 * Parse given JSON object to fixed size data
46 *
47 * @param cls closure, NULL
48 * @param root the json object representing data
49 * @param[out] spec where to write the data
50 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
51 */
52static enum GNUNET_GenericReturnValue
53parse_fixed_data (void *cls,
54 json_t *root,
55 struct GNUNET_JSON_Specification *spec)
56{
57 const char *enc;
58 unsigned int len;
59
60 if (NULL == (enc = json_string_value (root)))
61 {
62 GNUNET_break_op (0);
63 return GNUNET_SYSERR;
64 }
65 len = strlen (enc);
66 if (((len * 5) / 8) != spec->ptr_size)
67 {
68 GNUNET_break_op (0);
69 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
70 "Field `%s' has wrong length\n",
71 spec->field);
72 return GNUNET_SYSERR;
73 }
74 if (GNUNET_OK !=
75 GNUNET_STRINGS_string_to_data (enc,
76 len,
77 spec->ptr,
78 spec->ptr_size))
79 {
80 GNUNET_break_op (0);
81 return GNUNET_SYSERR;
82 }
83 return GNUNET_OK;
84}
85
86
87struct GNUNET_JSON_Specification
88GNUNET_JSON_spec_fixed (const char *name,
89 void *obj,
90 size_t size)
91{
92 struct GNUNET_JSON_Specification ret = {
93 .parser = &parse_fixed_data,
94 .cleaner = NULL,
95 .cls = NULL,
96 .field = name,
97 .ptr = obj,
98 .ptr_size = size,
99 .size_ptr = NULL
100 };
101
102 return ret;
103}
104
105
106/**
107 * Parse given JSON object to fixed size data
108 *
109 * @param cls closure, NULL
110 * @param root the json object representing data
111 * @param[out] spec where to write the data
112 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
113 */
114static enum GNUNET_GenericReturnValue
115parse_fixed64_data (void *cls,
116 json_t *root,
117 struct GNUNET_JSON_Specification *spec)
118{
119 const char *enc;
120 unsigned int len;
121 void *output;
122 size_t olen;
123
124 if (NULL == (enc = json_string_value (root)))
125 {
126 GNUNET_break_op (0);
127 return GNUNET_SYSERR;
128 }
129 len = strlen (enc);
130 output = NULL;
131 olen = GNUNET_STRINGS_base64_decode (enc,
132 len,
133 &output);
134 if (olen != spec->ptr_size)
135 {
136 GNUNET_break_op (0);
137 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
138 "Field `%s' has wrong length\n",
139 spec->field);
140 GNUNET_free (output);
141 return GNUNET_SYSERR;
142 }
143 memcpy (spec->ptr,
144 output,
145 olen);
146 GNUNET_free (output);
147 return GNUNET_OK;
148}
149
150
151struct GNUNET_JSON_Specification
152GNUNET_JSON_spec_fixed64 (const char *name,
153 void *obj,
154 size_t size)
155{
156 struct GNUNET_JSON_Specification ret = {
157 .parser = &parse_fixed64_data,
158 .cleaner = NULL,
159 .cls = NULL,
160 .field = name,
161 .ptr = obj,
162 .ptr_size = size,
163 .size_ptr = NULL
164 };
165
166 return ret;
167}
168
169
170/**
171 * Parse given JSON object to variable size data
172 *
173 * @param cls closure, NULL
174 * @param root the json object representing data
175 * @param[out] spec where to write the data
176 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
177 */
178static enum GNUNET_GenericReturnValue
179parse_variable_data (void *cls,
180 json_t *root,
181 struct GNUNET_JSON_Specification *spec)
182{
183 const char *str;
184 size_t size;
185 void *data;
186
187 str = json_string_value (root);
188 if (NULL == str)
189 {
190 GNUNET_break_op (0);
191 return GNUNET_SYSERR;
192 }
193 if (GNUNET_OK !=
194 GNUNET_STRINGS_string_to_data_alloc (str,
195 strlen (str),
196 &data,
197 &size))
198 {
199 GNUNET_break_op (0);
200 return GNUNET_SYSERR;
201 }
202 *(void **) spec->ptr = data;
203 *spec->size_ptr = size;
204 return GNUNET_OK;
205}
206
207
208/**
209 * Cleanup data left from parsing variable size data
210 *
211 * @param cls closure, NULL
212 * @param[out] spec where to free the data
213 */
214static void
215clean_variable_data (void *cls,
216 struct GNUNET_JSON_Specification *spec)
217{
218 (void) cls;
219 if (0 != *spec->size_ptr)
220 {
221 GNUNET_free (*(void **) spec->ptr);
222 *(void **) spec->ptr = NULL;
223 *spec->size_ptr = 0;
224 }
225}
226
227
228struct GNUNET_JSON_Specification
229GNUNET_JSON_spec_varsize (const char *name,
230 void **obj,
231 size_t *size)
232{
233 struct GNUNET_JSON_Specification ret = {
234 .parser = &parse_variable_data,
235 .cleaner = &clean_variable_data,
236 .cls = NULL,
237 .field = name,
238 .ptr = obj,
239 .ptr_size = 0,
240 .size_ptr = size
241 };
242
243 *obj = NULL;
244 *size = 0;
245 return ret;
246}
247
248
249/**
250 * Parse given JSON object to string.
251 *
252 * @param cls closure, NULL
253 * @param root the json object representing data
254 * @param[out] spec where to write the data
255 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
256 */
257static enum GNUNET_GenericReturnValue
258parse_string (void *cls,
259 json_t *root,
260 struct GNUNET_JSON_Specification *spec)
261{
262 const char *str;
263
264 (void) cls;
265 str = json_string_value (root);
266 if (NULL == str)
267 {
268 GNUNET_break_op (0);
269 return GNUNET_SYSERR;
270 }
271 *(const char **) spec->ptr = str;
272 return GNUNET_OK;
273}
274
275
276struct GNUNET_JSON_Specification
277GNUNET_JSON_spec_string (const char *name,
278 const char **strptr)
279{
280 struct GNUNET_JSON_Specification ret = {
281 .parser = &parse_string,
282 .cleaner = NULL,
283 .cls = NULL,
284 .field = name,
285 .ptr = strptr,
286 .ptr_size = 0,
287 .size_ptr = NULL
288 };
289
290 *strptr = NULL;
291 return ret;
292}
293
294
295/**
296 * Parse given JSON object to a JSON object. (Yes, trivial.)
297 *
298 * @param cls closure, NULL
299 * @param root the json object representing data
300 * @param[out] spec where to write the data
301 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
302 */
303static enum GNUNET_GenericReturnValue
304parse_json (void *cls,
305 json_t *root,
306 struct GNUNET_JSON_Specification *spec)
307{
308 if (! (json_is_object (root) || json_is_array (root)))
309 {
310 GNUNET_break_op (0);
311 return GNUNET_SYSERR;
312 }
313 json_incref (root);
314 *(json_t **) spec->ptr = root;
315 return GNUNET_OK;
316}
317
318
319/**
320 * Cleanup data left from parsing JSON object.
321 *
322 * @param cls closure, NULL
323 * @param[out] spec where to free the data
324 */
325static void
326clean_json (void *cls,
327 struct GNUNET_JSON_Specification *spec)
328{
329 json_t **ptr = (json_t **) spec->ptr;
330
331 if (NULL != *ptr)
332 {
333 json_decref (*ptr);
334 *ptr = NULL;
335 }
336}
337
338
339struct GNUNET_JSON_Specification
340GNUNET_JSON_spec_json (const char *name,
341 json_t **jsonp)
342{
343 struct GNUNET_JSON_Specification ret = {
344 .parser = &parse_json,
345 .cleaner = &clean_json,
346 .cls = NULL,
347 .field = name,
348 .ptr = jsonp,
349 .ptr_size = 0,
350 .size_ptr = NULL
351 };
352
353 *jsonp = NULL;
354 return ret;
355}
356
357
358/**
359 * Parse given JSON object to a JSON object.
360 *
361 * @param cls closure, NULL
362 * @param root the json object representing data
363 * @param[out] spec where to write the data
364 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
365 */
366static enum GNUNET_GenericReturnValue
367parse_object_const (void *cls,
368 json_t *root,
369 struct GNUNET_JSON_Specification *spec)
370{
371 if (NULL == root)
372 return GNUNET_OK;
373 if (! json_is_object (root))
374 {
375 GNUNET_break_op (0);
376 return GNUNET_SYSERR;
377 }
378 *(const json_t **) spec->ptr = (const json_t *) root;
379 return GNUNET_OK;
380}
381
382
383struct GNUNET_JSON_Specification
384GNUNET_JSON_spec_object_const (const char *name,
385 const json_t **jsonp)
386{
387 struct GNUNET_JSON_Specification ret = {
388 .parser = &parse_object_const,
389 .cls = NULL,
390 .field = name,
391 .ptr = jsonp,
392 .ptr_size = 0,
393 .size_ptr = NULL
394 };
395
396 *jsonp = NULL;
397 return ret;
398}
399
400
401/**
402 * Parse given JSON to a JSON array.
403 *
404 * @param cls closure, NULL
405 * @param root the json object representing data
406 * @param[out] spec where to write the data
407 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
408 */
409static enum GNUNET_GenericReturnValue
410parse_array_const (void *cls,
411 json_t *root,
412 struct GNUNET_JSON_Specification *spec)
413{
414 if (NULL == root)
415 return GNUNET_OK;
416 if (! json_is_array (root))
417 {
418 GNUNET_break_op (0);
419 return GNUNET_SYSERR;
420 }
421 *(const json_t **) spec->ptr = (const json_t *) root;
422 return GNUNET_OK;
423}
424
425
426struct GNUNET_JSON_Specification
427GNUNET_JSON_spec_array_const (const char *name,
428 const json_t **jsonp)
429{
430 struct GNUNET_JSON_Specification ret = {
431 .parser = &parse_array_const,
432 .cls = NULL,
433 .field = name,
434 .ptr = jsonp,
435 .ptr_size = 0,
436 .size_ptr = NULL
437 };
438
439 *jsonp = NULL;
440 return ret;
441}
442
443
444/**
445 * Parse given JSON object to a bool.
446 *
447 * @param cls closure, NULL
448 * @param root the json object representing data
449 * @param[out] spec where to write the data
450 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
451 */
452static enum GNUNET_GenericReturnValue
453parse_bool (void *cls,
454 json_t *root,
455 struct GNUNET_JSON_Specification *spec)
456{
457 bool *b = spec->ptr;
458
459 if (json_true () == root)
460 {
461 *b = true;
462 return GNUNET_OK;
463 }
464 if (json_false () == root)
465 {
466 *b = false;
467 return GNUNET_OK;
468 }
469 GNUNET_break_op (0);
470 return GNUNET_SYSERR;
471}
472
473
474struct GNUNET_JSON_Specification
475GNUNET_JSON_spec_bool (const char *name,
476 bool *b)
477{
478 struct GNUNET_JSON_Specification ret = {
479 .parser = &parse_bool,
480 .cleaner = NULL,
481 .cls = NULL,
482 .field = name,
483 .ptr = b,
484 .ptr_size = sizeof(bool),
485 .size_ptr = NULL
486 };
487
488 return ret;
489}
490
491
492/**
493 * Parse given JSON object to a double.
494 *
495 * @param cls closure, NULL
496 * @param root the json object representing data
497 * @param[out] spec where to write the data
498 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
499 */
500static enum GNUNET_GenericReturnValue
501parse_double (void *cls,
502 json_t *root,
503 struct GNUNET_JSON_Specification *spec)
504{
505 double *f = spec->ptr;
506
507 if (! json_is_real (root))
508 {
509 GNUNET_break_op (0);
510 return GNUNET_SYSERR;
511 }
512 *f = json_real_value (root);
513 return GNUNET_OK;
514}
515
516
517struct GNUNET_JSON_Specification
518GNUNET_JSON_spec_double (const char *name,
519 double *f)
520{
521 struct GNUNET_JSON_Specification ret = {
522 .parser = &parse_double,
523 .cleaner = NULL,
524 .cls = NULL,
525 .field = name,
526 .ptr = f,
527 .ptr_size = sizeof(double),
528 .size_ptr = NULL
529 };
530
531 return ret;
532}
533
534
535/**
536 * Parse given JSON object to a uint8_t.
537 *
538 * @param cls closure, NULL
539 * @param root the json object representing data
540 * @param[out] spec where to write the data
541 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
542 */
543static enum GNUNET_GenericReturnValue
544parse_u8 (void *cls,
545 json_t *root,
546 struct GNUNET_JSON_Specification *spec)
547{
548 json_int_t val;
549 uint8_t *up = spec->ptr;
550
551 if (! json_is_integer (root))
552 {
553 GNUNET_break_op (0);
554 return GNUNET_SYSERR;
555 }
556 val = json_integer_value (root);
557 if ((0 > val) || (val > UINT8_MAX))
558 {
559 GNUNET_break_op (0);
560 return GNUNET_SYSERR;
561 }
562 *up = (uint8_t) val;
563 return GNUNET_OK;
564}
565
566
567struct GNUNET_JSON_Specification
568GNUNET_JSON_spec_uint8 (const char *name,
569 uint8_t *u8)
570{
571 struct GNUNET_JSON_Specification ret = {
572 .parser = &parse_u8,
573 .cleaner = NULL,
574 .cls = NULL,
575 .field = name,
576 .ptr = u8,
577 .ptr_size = sizeof(uint8_t),
578 .size_ptr = NULL
579 };
580
581 return ret;
582}
583
584
585/**
586 * Parse given JSON object to a uint16_t.
587 *
588 * @param cls closure, NULL
589 * @param root the json object representing data
590 * @param[out] spec where to write the data
591 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
592 */
593static enum GNUNET_GenericReturnValue
594parse_u16 (void *cls,
595 json_t *root,
596 struct GNUNET_JSON_Specification *spec)
597{
598 json_int_t val;
599 uint16_t *up = spec->ptr;
600
601 if (! json_is_integer (root))
602 {
603 GNUNET_break_op (0);
604 return GNUNET_SYSERR;
605 }
606 val = json_integer_value (root);
607 if ((0 > val) || (val > UINT16_MAX))
608 {
609 GNUNET_break_op (0);
610 return GNUNET_SYSERR;
611 }
612 *up = (uint16_t) val;
613 return GNUNET_OK;
614}
615
616
617struct GNUNET_JSON_Specification
618GNUNET_JSON_spec_uint16 (const char *name,
619 uint16_t *u16)
620{
621 struct GNUNET_JSON_Specification ret = {
622 .parser = &parse_u16,
623 .cleaner = NULL,
624 .cls = NULL,
625 .field = name,
626 .ptr = u16,
627 .ptr_size = sizeof(uint16_t),
628 .size_ptr = NULL
629 };
630
631 return ret;
632}
633
634
635/**
636 * Parse given JSON object to a uint32_t.
637 *
638 * @param cls closure, NULL
639 * @param root the json object representing data
640 * @param[out] spec where to write the data
641 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
642 */
643static enum GNUNET_GenericReturnValue
644parse_u32 (void *cls,
645 json_t *root,
646 struct GNUNET_JSON_Specification *spec)
647{
648 json_int_t val;
649 uint32_t *up = spec->ptr;
650
651 if (! json_is_integer (root))
652 {
653 GNUNET_break_op (0);
654 return GNUNET_SYSERR;
655 }
656 val = json_integer_value (root);
657 if ((0 > val) || (val > UINT32_MAX))
658 {
659 GNUNET_break_op (0);
660 return GNUNET_SYSERR;
661 }
662 *up = (uint32_t) val;
663 return GNUNET_OK;
664}
665
666
667struct GNUNET_JSON_Specification
668GNUNET_JSON_spec_uint32 (const char *name,
669 uint32_t *u32)
670{
671 struct GNUNET_JSON_Specification ret = {
672 .parser = &parse_u32,
673 .cleaner = NULL,
674 .cls = NULL,
675 .field = name,
676 .ptr = u32,
677 .ptr_size = sizeof(uint32_t),
678 .size_ptr = NULL
679 };
680
681 return ret;
682}
683
684
685/**
686 * Parse given JSON object to a uint64_t.
687 *
688 * @param cls closure, NULL
689 * @param root the json object representing data
690 * @param[out] spec where to write the data
691 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
692 */
693static enum GNUNET_GenericReturnValue
694parse_u64 (void *cls,
695 json_t *root,
696 struct GNUNET_JSON_Specification *spec)
697{
698 json_int_t val;
699 uint64_t *up = spec->ptr;
700
701 if (! json_is_integer (root))
702 {
703 GNUNET_break_op (0);
704 return GNUNET_SYSERR;
705 }
706 val = json_integer_value (root);
707 *up = (uint64_t) val;
708 return GNUNET_OK;
709}
710
711
712struct GNUNET_JSON_Specification
713GNUNET_JSON_spec_uint64 (const char *name,
714 uint64_t *u64)
715{
716 struct GNUNET_JSON_Specification ret = {
717 .parser = &parse_u64,
718 .cleaner = NULL,
719 .cls = NULL,
720 .field = name,
721 .ptr = u64,
722 .ptr_size = sizeof(uint64_t),
723 .size_ptr = NULL
724 };
725
726 return ret;
727}
728
729
730/**
731 * Parse given JSON object to a int64_t.
732 *
733 * @param cls closure, NULL
734 * @param root the json object representing data
735 * @param[out] spec where to write the data
736 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
737 */
738static enum GNUNET_GenericReturnValue
739parse_i64 (void *cls,
740 json_t *root,
741 struct GNUNET_JSON_Specification *spec)
742{
743 json_int_t val;
744 int64_t *up = spec->ptr;
745
746 if (! json_is_integer (root))
747 {
748 GNUNET_break_op (0);
749 return GNUNET_SYSERR;
750 }
751 val = json_integer_value (root);
752 *up = (int64_t) val;
753 return GNUNET_OK;
754}
755
756
757struct GNUNET_JSON_Specification
758GNUNET_JSON_spec_int64 (const char *name,
759 int64_t *i64)
760{
761 struct GNUNET_JSON_Specification ret = {
762 .parser = &parse_i64,
763 .cleaner = NULL,
764 .cls = NULL,
765 .field = name,
766 .ptr = i64,
767 .ptr_size = sizeof(int64_t),
768 .size_ptr = NULL
769 };
770
771 return ret;
772}
773
774
775/* ************ GNUnet-specific parser specifications ******************* */
776
777/**
778 * Parse given JSON object to a timestamp.
779 *
780 * @param cls closure, NULL
781 * @param root the json object representing data
782 * @param[out] spec where to write the data
783 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
784 */
785static enum GNUNET_GenericReturnValue
786parse_timestamp (void *cls,
787 json_t *root,
788 struct GNUNET_JSON_Specification *spec)
789{
790 struct GNUNET_TIME_Timestamp *ts = spec->ptr;
791 json_t *json_t_s;
792 unsigned long long int tval;
793
794 if (! json_is_object (root))
795 {
796 GNUNET_break_op (0);
797 return GNUNET_SYSERR;
798 }
799 json_t_s = json_object_get (root,
800 "t_s");
801 if (json_is_integer (json_t_s))
802 {
803 tval = json_integer_value (json_t_s);
804 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
805 ts->abs_time.abs_value_us
806 = tval * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
807 if (ts->abs_time.abs_value_us
808 / GNUNET_TIME_UNIT_SECONDS.rel_value_us
809 != tval)
810 {
811 /* Integer overflow */
812 GNUNET_break_op (0);
813 return GNUNET_SYSERR;
814 }
815 return GNUNET_OK;
816 }
817 if (json_is_string (json_t_s))
818 {
819 const char *val;
820
821 val = json_string_value (json_t_s);
822 if ((0 == strcasecmp (val,
823 "never")))
824 {
825 ts->abs_time = GNUNET_TIME_UNIT_FOREVER_ABS;
826 return GNUNET_OK;
827 }
828 GNUNET_break_op (0);
829 return GNUNET_SYSERR;
830 }
831 GNUNET_break_op (0);
832 return GNUNET_SYSERR;
833}
834
835
836struct GNUNET_JSON_Specification
837GNUNET_JSON_spec_timestamp (const char *name,
838 struct GNUNET_TIME_Timestamp *t)
839{
840 struct GNUNET_JSON_Specification ret = {
841 .parser = &parse_timestamp,
842 .field = name,
843 .ptr = t,
844 .ptr_size = sizeof(struct GNUNET_TIME_Timestamp)
845 };
846
847 return ret;
848}
849
850
851/**
852 * Parse given JSON object to absolute time.
853 *
854 * @param cls closure, NULL
855 * @param root the json object representing data
856 * @param[out] spec where to write the data
857 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
858 */
859static enum GNUNET_GenericReturnValue
860parse_timestamp_nbo (void *cls,
861 json_t *root,
862 struct GNUNET_JSON_Specification *spec)
863{
864 struct GNUNET_TIME_TimestampNBO *ts = spec->ptr;
865 struct GNUNET_TIME_Timestamp a;
866 struct GNUNET_JSON_Specification ispec;
867
868 ispec = *spec;
869 ispec.parser = &parse_timestamp;
870 ispec.ptr = &a;
871 if (GNUNET_OK !=
872 parse_timestamp (NULL,
873 root,
874 &ispec))
875 return GNUNET_SYSERR;
876 *ts = GNUNET_TIME_timestamp_hton (a);
877 return GNUNET_OK;
878}
879
880
881struct GNUNET_JSON_Specification
882GNUNET_JSON_spec_timestamp_nbo (const char *name,
883 struct GNUNET_TIME_TimestampNBO *at)
884{
885 struct GNUNET_JSON_Specification ret = {
886 .parser = &parse_timestamp_nbo,
887 .field = name,
888 .ptr = at,
889 .ptr_size = sizeof(struct GNUNET_TIME_TimestampNBO)
890 };
891
892 return ret;
893}
894
895
896/**
897 * Parse given JSON object to relative time.
898 *
899 * @param cls closure, NULL
900 * @param root the json object representing data
901 * @param[out] spec where to write the data
902 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
903 */
904static enum GNUNET_GenericReturnValue
905parse_rel_time (void *cls,
906 json_t *root,
907 struct GNUNET_JSON_Specification *spec)
908{
909 struct GNUNET_TIME_Relative *rel = spec->ptr;
910 json_t *json_d_us;
911 unsigned long long int tval;
912
913 if (! json_is_object (root))
914 {
915 GNUNET_break_op (0);
916 return GNUNET_SYSERR;
917 }
918 json_d_us = json_object_get (root,
919 "d_us");
920 if (json_is_integer (json_d_us))
921 {
922 tval = json_integer_value (json_d_us);
923 if (tval >= (1LLU << 53))
924 {
925 /* value is larger than allowed */
926 GNUNET_break_op (0);
927 return GNUNET_SYSERR;
928 }
929 rel->rel_value_us = tval;
930 return GNUNET_OK;
931 }
932 if (json_is_string (json_d_us))
933 {
934 const char *val;
935
936 val = json_string_value (json_d_us);
937 if ((0 == strcasecmp (val,
938 "forever")))
939 {
940 *rel = GNUNET_TIME_UNIT_FOREVER_REL;
941 return GNUNET_OK;
942 }
943 GNUNET_break_op (0);
944 return GNUNET_SYSERR;
945 }
946 GNUNET_break_op (0);
947 return GNUNET_SYSERR;
948}
949
950
951struct GNUNET_JSON_Specification
952GNUNET_JSON_spec_relative_time (const char *name,
953 struct GNUNET_TIME_Relative *rt)
954{
955 struct GNUNET_JSON_Specification ret = {
956 .parser = &parse_rel_time,
957 .field = name,
958 .ptr = rt,
959 .ptr_size = sizeof(struct GNUNET_TIME_Relative)
960 };
961
962 return ret;
963}
964
965
966/**
967 * Parse given JSON object to RSA public key.
968 *
969 * @param cls closure, NULL
970 * @param root the json object representing data
971 * @param[out] spec where to write the data
972 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
973 */
974static enum GNUNET_GenericReturnValue
975parse_rsa_public_key (void *cls,
976 json_t *root,
977 struct GNUNET_JSON_Specification *spec)
978{
979 struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
980 const char *enc;
981 char *buf;
982 size_t len;
983 size_t buf_len;
984
985 if (NULL == (enc = json_string_value (root)))
986 {
987 GNUNET_break_op (0);
988 return GNUNET_SYSERR;
989 }
990 len = strlen (enc);
991 buf_len = (len * 5) / 8;
992 buf = GNUNET_malloc (buf_len);
993 if (GNUNET_OK !=
994 GNUNET_STRINGS_string_to_data (enc,
995 len,
996 buf,
997 buf_len))
998 {
999 GNUNET_break_op (0);
1000 GNUNET_free (buf);
1001 return GNUNET_SYSERR;
1002 }
1003 if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
1004 buf_len)))
1005 {
1006 GNUNET_break_op (0);
1007 GNUNET_free (buf);
1008 return GNUNET_SYSERR;
1009 }
1010 GNUNET_free (buf);
1011 return GNUNET_OK;
1012}
1013
1014
1015/**
1016 * Cleanup data left from parsing RSA public key.
1017 *
1018 * @param cls closure, NULL
1019 * @param[out] spec where to free the data
1020 */
1021static void
1022clean_rsa_public_key (void *cls,
1023 struct GNUNET_JSON_Specification *spec)
1024{
1025 struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
1026
1027 if (NULL != *pk)
1028 {
1029 GNUNET_CRYPTO_rsa_public_key_free (*pk);
1030 *pk = NULL;
1031 }
1032}
1033
1034
1035struct GNUNET_JSON_Specification
1036GNUNET_JSON_spec_rsa_public_key (const char *name,
1037 struct GNUNET_CRYPTO_RsaPublicKey **pk)
1038{
1039 struct GNUNET_JSON_Specification ret = {
1040 .parser = &parse_rsa_public_key,
1041 .cleaner = &clean_rsa_public_key,
1042 .field = name,
1043 .ptr = pk
1044 };
1045
1046 *pk = NULL;
1047 return ret;
1048}
1049
1050
1051/**
1052 * Parse given JSON object to RSA signature.
1053 *
1054 * @param cls closure, NULL
1055 * @param root the json object representing data
1056 * @param[out] spec where to write the data
1057 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1058 */
1059static enum GNUNET_GenericReturnValue
1060parse_rsa_signature (void *cls,
1061 json_t *root,
1062 struct GNUNET_JSON_Specification *spec)
1063{
1064 struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
1065 size_t size;
1066 const char *str;
1067 int res;
1068 void *buf;
1069
1070 str = json_string_value (root);
1071 if (NULL == str)
1072 {
1073 GNUNET_break_op (0);
1074 return GNUNET_SYSERR;
1075 }
1076 size = (strlen (str) * 5) / 8;
1077 buf = GNUNET_malloc (size);
1078 res = GNUNET_STRINGS_string_to_data (str,
1079 strlen (str),
1080 buf,
1081 size);
1082 if (GNUNET_OK != res)
1083 {
1084 GNUNET_free (buf);
1085 GNUNET_break_op (0);
1086 return GNUNET_SYSERR;
1087 }
1088 if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
1089 size)))
1090 {
1091 GNUNET_break_op (0);
1092 GNUNET_free (buf);
1093 return GNUNET_SYSERR;
1094 }
1095 GNUNET_free (buf);
1096 return GNUNET_OK;
1097}
1098
1099
1100/**
1101 * Cleanup data left from parsing RSA signature.
1102 *
1103 * @param cls closure, NULL
1104 * @param[out] spec where to free the data
1105 */
1106static void
1107clean_rsa_signature (void *cls,
1108 struct GNUNET_JSON_Specification *spec)
1109{
1110 struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
1111
1112 if (NULL != *sig)
1113 {
1114 GNUNET_CRYPTO_rsa_signature_free (*sig);
1115 *sig = NULL;
1116 }
1117}
1118
1119
1120struct GNUNET_JSON_Specification
1121GNUNET_JSON_spec_rsa_signature (const char *name,
1122 struct GNUNET_CRYPTO_RsaSignature **sig)
1123{
1124 struct GNUNET_JSON_Specification ret = {
1125 .parser = &parse_rsa_signature,
1126 .cleaner = &clean_rsa_signature,
1127 .cls = NULL,
1128 .field = name,
1129 .ptr = sig,
1130 .ptr_size = 0,
1131 .size_ptr = NULL
1132 };
1133
1134 *sig = NULL;
1135 return ret;
1136}
1137
1138
1139/**
1140 * Parse given JSON object to an int as a boolean.
1141 *
1142 * @param cls closure, NULL
1143 * @param root the json object representing data
1144 * @param[out] spec where to write the data
1145 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
1146 */
1147static enum GNUNET_GenericReturnValue
1148parse_boolean (void *cls,
1149 json_t *root,
1150 struct GNUNET_JSON_Specification *spec)
1151{
1152 int *bp = spec->ptr;
1153
1154 if (! json_is_boolean (root))
1155 {
1156 GNUNET_break_op (0);
1157 return GNUNET_SYSERR;
1158 }
1159 *bp = json_boolean_value (root) ? GNUNET_YES : GNUNET_NO;
1160 return GNUNET_OK;
1161}
1162
1163
1164struct GNUNET_JSON_Specification
1165GNUNET_JSON_spec_boolean (const char *name,
1166 int *boolean)
1167{
1168 struct GNUNET_JSON_Specification ret = {
1169 .parser = &parse_boolean,
1170 .cleaner = NULL,
1171 .cls = NULL,
1172 .field = name,
1173 .ptr = boolean,
1174 .ptr_size = sizeof(int),
1175 .size_ptr = NULL
1176 };
1177
1178 return ret;
1179}
1180
1181
1182/* end of json_helper.c */
diff --git a/src/json/json_mhd.c b/src/json/json_mhd.c
deleted file mode 100644
index 0b0fa0538..000000000
--- a/src/json/json_mhd.c
+++ /dev/null
@@ -1,379 +0,0 @@
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
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file json/json_mhd.c
22 * @brief functions to parse JSON snippets we receive via MHD
23 * @author Florian Dold
24 * @author Benedikt Mueller
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_json_lib.h"
29#include <zlib.h>
30
31
32/**
33 * Initial size for POST request buffers. Should be big enough to
34 * usually not require a reallocation, but not so big that it hurts in
35 * terms of memory use.
36 */
37#define REQUEST_BUFFER_INITIAL (2 * 1024)
38
39
40/**
41 * Buffer for POST requests.
42 */
43struct Buffer
44{
45 /**
46 * Allocated memory
47 */
48 char *data;
49
50 /**
51 * Number of valid bytes in buffer.
52 */
53 size_t fill;
54
55 /**
56 * Number of allocated bytes in buffer.
57 */
58 size_t alloc;
59
60 /**
61 * Maximum buffer size allowed.
62 */
63 size_t max;
64};
65
66
67/**
68 * Initialize a buffer.
69 *
70 * @param buf the buffer to initialize
71 * @param data the initial data
72 * @param data_size size of the initial data
73 * @param alloc_size size of the buffer
74 * @param max_size maximum size that the buffer can grow to
75 * @return a GNUnet result code
76 */
77static int
78buffer_init (struct Buffer *buf,
79 const void *data,
80 size_t data_size,
81 size_t alloc_size,
82 size_t max_size)
83{
84 if ((data_size > max_size) || (alloc_size > max_size))
85 return GNUNET_SYSERR;
86 if (data_size > alloc_size)
87 alloc_size = data_size;
88 buf->data = GNUNET_malloc (alloc_size);
89 buf->alloc = alloc_size;
90 GNUNET_memcpy (buf->data, data, data_size);
91 buf->fill = data_size;
92 buf->max = max_size;
93 return GNUNET_OK;
94}
95
96
97/**
98 * Free the data in a buffer. Does *not* free
99 * the buffer object itself.
100 *
101 * @param buf buffer to de-initialize
102 */
103static void
104buffer_deinit (struct Buffer *buf)
105{
106 GNUNET_free (buf->data);
107 buf->data = NULL;
108}
109
110
111/**
112 * Append data to a buffer, growing the buffer if necessary.
113 *
114 * @param buf the buffer to append to
115 * @param data the data to append
116 * @param data_size the size of @a data
117 * @param max_size maximum size that the buffer can grow to
118 * @return #GNUNET_OK on success,
119 * #GNUNET_NO if the buffer can't accommodate for the new data
120 */
121static int
122buffer_append (struct Buffer *buf,
123 const void *data,
124 size_t data_size,
125 size_t max_size)
126{
127 if (buf->fill + data_size > max_size)
128 return GNUNET_NO;
129 if (buf->fill + data_size > buf->alloc)
130 {
131 char *new_buf;
132 size_t new_size = buf->alloc;
133 while (new_size < buf->fill + data_size)
134 new_size += 2;
135 if (new_size > max_size)
136 return GNUNET_NO;
137 new_buf = GNUNET_malloc (new_size);
138 GNUNET_memcpy (new_buf, buf->data, buf->fill);
139 GNUNET_free (buf->data);
140 buf->data = new_buf;
141 buf->alloc = new_size;
142 }
143 GNUNET_memcpy (buf->data + buf->fill, data, data_size);
144 buf->fill += data_size;
145 return GNUNET_OK;
146}
147
148
149/**
150 * Decompress data in @a buf.
151 *
152 * @param buf input data to inflate
153 * @return result code indicating the status of the operation
154 */
155static enum GNUNET_JSON_PostResult
156inflate_data (struct Buffer *buf)
157{
158 z_stream z;
159 char *tmp;
160 size_t tmp_size;
161 int ret;
162
163 memset (&z, 0, sizeof(z));
164 z.next_in = (Bytef *) buf->data;
165 z.avail_in = buf->fill;
166 tmp_size = GNUNET_MIN (buf->max, buf->fill * 4);
167 tmp = GNUNET_malloc (tmp_size);
168 z.next_out = (Bytef *) tmp;
169 z.avail_out = tmp_size;
170 ret = inflateInit (&z);
171 switch (ret)
172 {
173 case Z_MEM_ERROR:
174 GNUNET_break (0);
175 return GNUNET_JSON_PR_OUT_OF_MEMORY;
176
177 case Z_STREAM_ERROR:
178 GNUNET_break_op (0);
179 return GNUNET_JSON_PR_JSON_INVALID;
180
181 case Z_OK:
182 break;
183 }
184 while (1)
185 {
186 ret = inflate (&z, 0);
187 switch (ret)
188 {
189 case Z_BUF_ERROR:
190 GNUNET_break_op (0);
191 GNUNET_break (Z_OK == inflateEnd (&z));
192 GNUNET_free (tmp);
193 return GNUNET_JSON_PR_JSON_INVALID;
194 case Z_MEM_ERROR:
195 GNUNET_break (0);
196 GNUNET_break (Z_OK == inflateEnd (&z));
197 GNUNET_free (tmp);
198 return GNUNET_JSON_PR_OUT_OF_MEMORY;
199 case Z_DATA_ERROR:
200 GNUNET_break_op (0);
201 GNUNET_break (Z_OK == inflateEnd (&z));
202 GNUNET_free (tmp);
203 return GNUNET_JSON_PR_JSON_INVALID;
204 case Z_NEED_DICT:
205 GNUNET_break_op (0);
206 GNUNET_break (Z_OK == inflateEnd (&z));
207 GNUNET_free (tmp);
208 return GNUNET_JSON_PR_JSON_INVALID;
209 case Z_OK:
210 if ((0 < z.avail_out) && (0 == z.avail_in))
211 {
212 /* truncated input stream */
213 GNUNET_break (0);
214 GNUNET_break (Z_OK == inflateEnd (&z));
215 GNUNET_free (tmp);
216 return GNUNET_JSON_PR_JSON_INVALID;
217 }
218 if (0 < z.avail_out)
219 continue; /* just call it again */
220 /* output buffer full, can we grow it? */
221 if (tmp_size == buf->max)
222 {
223 /* already at max */
224 GNUNET_break (0);
225 GNUNET_break (Z_OK == inflateEnd (&z));
226 GNUNET_free (tmp);
227 return GNUNET_JSON_PR_OUT_OF_MEMORY;
228 }
229 if (tmp_size * 2 < tmp_size)
230 tmp_size = buf->max;
231 else
232 tmp_size = GNUNET_MIN (buf->max, tmp_size * 2);
233 tmp = GNUNET_realloc (tmp, tmp_size);
234 z.next_out = (Bytef *) &tmp[z.total_out];
235 continue;
236 case Z_STREAM_END:
237 /* decompression successful, make 'tmp' the new 'data' */
238 GNUNET_free (buf->data);
239 buf->data = tmp;
240 buf->alloc = tmp_size;
241 buf->fill = z.total_out;
242 GNUNET_break (Z_OK == inflateEnd (&z));
243 return GNUNET_JSON_PR_SUCCESS; /* at least for now */
244 }
245 } /* while (1) */
246}
247
248
249/**
250 * Process a POST request containing a JSON object. This function
251 * realizes an MHD POST processor that will (incrementally) process
252 * JSON data uploaded to the HTTP server. It will store the required
253 * state in the @a con_cls, which must be cleaned up using
254 * #GNUNET_JSON_post_parser_callback().
255 *
256 * @param buffer_max maximum allowed size for the buffer
257 * @param connection MHD connection handle (for meta data about the upload)
258 * @param con_cls the closure (will point to a `struct Buffer *`)
259 * @param upload_data the POST data
260 * @param upload_data_size number of bytes in @a upload_data
261 * @param json the JSON object for a completed request
262 * @return result code indicating the status of the operation
263 */
264enum GNUNET_JSON_PostResult
265GNUNET_JSON_post_parser (size_t buffer_max,
266 struct MHD_Connection *connection,
267 void **con_cls,
268 const char *upload_data,
269 size_t *upload_data_size,
270 json_t **json)
271{
272 struct Buffer *r = *con_cls;
273 const char *ce;
274 int ret;
275
276 *json = NULL;
277 if (NULL == *con_cls)
278 {
279 /* We are seeing a fresh POST request. */
280 r = GNUNET_new (struct Buffer);
281 if (GNUNET_OK != buffer_init (r,
282 upload_data,
283 *upload_data_size,
284 REQUEST_BUFFER_INITIAL,
285 buffer_max))
286 {
287 *con_cls = NULL;
288 buffer_deinit (r);
289 GNUNET_free (r);
290 return GNUNET_JSON_PR_OUT_OF_MEMORY;
291 }
292 /* everything OK, wait for more POST data */
293 *upload_data_size = 0;
294 *con_cls = r;
295 return GNUNET_JSON_PR_CONTINUE;
296 }
297 if (0 != *upload_data_size)
298 {
299 /* We are seeing an old request with more data available. */
300
301 if (GNUNET_OK !=
302 buffer_append (r, upload_data, *upload_data_size, buffer_max))
303 {
304 /* Request too long */
305 *con_cls = NULL;
306 buffer_deinit (r);
307 GNUNET_free (r);
308 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
309 }
310 /* everything OK, wait for more POST data */
311 *upload_data_size = 0;
312 return GNUNET_JSON_PR_CONTINUE;
313 }
314
315 /* We have seen the whole request. */
316 ce = MHD_lookup_connection_value (connection,
317 MHD_HEADER_KIND,
318 MHD_HTTP_HEADER_CONTENT_ENCODING);
319 if ((NULL != ce) && (0 == strcasecmp ("deflate", ce)))
320 {
321 ret = inflate_data (r);
322 if (GNUNET_JSON_PR_SUCCESS != ret)
323 {
324 buffer_deinit (r);
325 GNUNET_free (r);
326 *con_cls = NULL;
327 return ret;
328 }
329 }
330
331 {
332 json_error_t err;
333
334 *json = json_loadb (r->data,
335 r->fill,
336 0,
337 &err);
338 if (NULL == *json)
339 {
340 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
341 "Failed to parse JSON request body of %u byte at offset %d: %s\n",
342 (unsigned int) r->fill,
343 err.position,
344 err.text);
345 buffer_deinit (r);
346 GNUNET_free (r);
347 *con_cls = NULL;
348 return GNUNET_JSON_PR_JSON_INVALID;
349 }
350 }
351 buffer_deinit (r);
352 GNUNET_free (r);
353 *con_cls = NULL;
354
355 return GNUNET_JSON_PR_SUCCESS;
356}
357
358
359/**
360 * Function called whenever we are done with a request
361 * to clean up our state.
362 *
363 * @param con_cls value as it was left by
364 * #GNUNET_JSON_post_parser(), to be cleaned up
365 */
366void
367GNUNET_JSON_post_parser_cleanup (void *con_cls)
368{
369 struct Buffer *r = con_cls;
370
371 if (NULL != r)
372 {
373 buffer_deinit (r);
374 GNUNET_free (r);
375 }
376}
377
378
379/* end of mhd_json.c */
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
deleted file mode 100644
index 18487c3f4..000000000
--- a/src/json/json_pack.c
+++ /dev/null
@@ -1,367 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file json/json_pack.c
22 * @brief functions to pack JSON objects
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_json_lib.h"
27
28
29json_t *
30GNUNET_JSON_pack_ (struct GNUNET_JSON_PackSpec spec[])
31{
32 json_t *ret;
33
34 if (NULL == spec[0].field_name)
35 {
36 ret = spec[0].object;
37 spec[0].object = NULL;
38 return ret;
39 }
40 ret = json_object ();
41 GNUNET_assert (NULL != ret);
42 for (unsigned int i = 0;
43 NULL != spec[i].field_name;
44 i++)
45 {
46 if (NULL == spec[i].object)
47 {
48 if (! spec[i].allow_null)
49 {
50 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
51 "NULL not allowed for `%s'\n",
52 spec[i].field_name);
53 GNUNET_assert (0);
54 }
55 }
56 else
57 {
58 GNUNET_assert (0 ==
59 json_object_set_new (ret,
60 spec[i].field_name,
61 spec[i].object));
62 spec[i].object = NULL;
63 }
64 }
65 return ret;
66}
67
68
69struct GNUNET_JSON_PackSpec
70GNUNET_JSON_pack_end_ (void)
71{
72 struct GNUNET_JSON_PackSpec ps = {
73 .field_name = NULL
74 };
75
76 return ps;
77}
78
79
80struct GNUNET_JSON_PackSpec
81GNUNET_JSON_pack_allow_null (struct GNUNET_JSON_PackSpec in)
82{
83 in.allow_null = true;
84 return in;
85}
86
87
88struct GNUNET_JSON_PackSpec
89GNUNET_JSON_pack_bool (const char *name,
90 bool b)
91{
92 struct GNUNET_JSON_PackSpec ps = {
93 .field_name = name,
94 .object = json_boolean (b)
95 };
96
97 return ps;
98}
99
100
101struct GNUNET_JSON_PackSpec
102GNUNET_JSON_pack_double (const char *name,
103 double f)
104{
105 struct GNUNET_JSON_PackSpec ps = {
106 .field_name = name,
107 .object = json_real (f)
108 };
109
110 return ps;
111}
112
113
114struct GNUNET_JSON_PackSpec
115GNUNET_JSON_pack_string (const char *name,
116 const char *s)
117{
118 struct GNUNET_JSON_PackSpec ps = {
119 .field_name = name,
120 .object = json_string (s)
121 };
122
123 return ps;
124}
125
126
127struct GNUNET_JSON_PackSpec
128GNUNET_JSON_pack_uint64 (const char *name,
129 uint64_t num)
130{
131 struct GNUNET_JSON_PackSpec ps = {
132 .field_name = name,
133 .object = json_integer ((json_int_t) num)
134 };
135
136#if JSON_INTEGER_IS_LONG_LONG
137 GNUNET_assert (num <= LLONG_MAX);
138#else
139 GNUNET_assert (num <= LONG_MAX);
140#endif
141 return ps;
142}
143
144
145struct GNUNET_JSON_PackSpec
146GNUNET_JSON_pack_int64 (const char *name,
147 int64_t num)
148{
149 struct GNUNET_JSON_PackSpec ps = {
150 .field_name = name,
151 .object = json_integer ((json_int_t) num)
152 };
153
154#if JSON_INTEGER_IS_LONG_LONG
155 GNUNET_assert (num <= LLONG_MAX);
156 GNUNET_assert (num >= LLONG_MIN);
157#else
158 GNUNET_assert (num <= LONG_MAX);
159 GNUNET_assert (num >= LONG_MIN);
160#endif
161 return ps;
162}
163
164
165struct GNUNET_JSON_PackSpec
166GNUNET_JSON_pack_object_steal (const char *name,
167 json_t *o)
168{
169 struct GNUNET_JSON_PackSpec ps = {
170 .field_name = name,
171 .object = o
172 };
173
174 if (NULL == o)
175 return ps;
176 if (! json_is_object (o))
177 {
178 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
179 "Expected JSON object for field `%s'\n",
180 name);
181 GNUNET_assert (0);
182 }
183 return ps;
184}
185
186
187struct GNUNET_JSON_PackSpec
188GNUNET_JSON_pack_object_incref (const char *name,
189 json_t *o)
190{
191 struct GNUNET_JSON_PackSpec ps = {
192 .field_name = name,
193 .object = o
194 };
195
196 if (NULL == o)
197 return ps;
198 (void) json_incref (o);
199 if (! json_is_object (o))
200 {
201 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
202 "Expected JSON object for field `%s'\n",
203 name);
204 GNUNET_assert (0);
205 }
206 return ps;
207}
208
209
210struct GNUNET_JSON_PackSpec
211GNUNET_JSON_pack_array_steal (const char *name,
212 json_t *a)
213{
214 struct GNUNET_JSON_PackSpec ps = {
215 .field_name = name,
216 .object = a
217 };
218
219 if (NULL == a)
220 return ps;
221 if (! json_is_array (a))
222 {
223 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
224 "Expected JSON array for field `%s'\n",
225 name);
226 GNUNET_assert (0);
227 }
228 return ps;
229}
230
231
232struct GNUNET_JSON_PackSpec
233GNUNET_JSON_pack_array_incref (const char *name,
234 json_t *a)
235{
236 struct GNUNET_JSON_PackSpec ps = {
237 .field_name = name,
238 .object = a
239 };
240
241 if (NULL == a)
242 return ps;
243 (void) json_incref (a);
244 if (! json_is_array (a))
245 {
246 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
247 "Expected JSON array for field `%s'\n",
248 name);
249 GNUNET_assert (0);
250 }
251 return ps;
252}
253
254
255struct GNUNET_JSON_PackSpec
256GNUNET_JSON_pack_data_varsize (const char *name,
257 const void *blob,
258 size_t blob_size)
259{
260 struct GNUNET_JSON_PackSpec ps = {
261 .field_name = name,
262 .object = (NULL != blob)
263 ? GNUNET_JSON_from_data (blob,
264 blob_size)
265 : NULL
266 };
267
268 return ps;
269}
270
271
272struct GNUNET_JSON_PackSpec
273GNUNET_JSON_pack_data64_varsize (const char *name,
274 const void *blob,
275 size_t blob_size)
276{
277 struct GNUNET_JSON_PackSpec ps = {
278 .field_name = name,
279 .object = (NULL != blob)
280 ? GNUNET_JSON_from_data64 (blob,
281 blob_size)
282 : NULL
283 };
284
285 return ps;
286}
287
288
289struct GNUNET_JSON_PackSpec
290GNUNET_JSON_pack_timestamp (const char *name,
291 struct GNUNET_TIME_Timestamp t)
292{
293 struct GNUNET_JSON_PackSpec ps = {
294 .field_name = name
295 };
296
297 if (! GNUNET_TIME_absolute_is_zero (t.abs_time))
298 {
299 ps.object = GNUNET_JSON_from_timestamp (t);
300 GNUNET_assert (NULL != ps.object);
301 }
302 else
303 {
304 ps.object = NULL;
305 }
306 return ps;
307}
308
309
310struct GNUNET_JSON_PackSpec
311GNUNET_JSON_pack_timestamp_nbo (const char *name,
312 struct GNUNET_TIME_TimestampNBO at)
313{
314 return GNUNET_JSON_pack_timestamp (name,
315 GNUNET_TIME_timestamp_ntoh (at));
316}
317
318
319struct GNUNET_JSON_PackSpec
320GNUNET_JSON_pack_time_rel (const char *name,
321 struct GNUNET_TIME_Relative rt)
322{
323 json_t *json;
324
325 json = GNUNET_JSON_from_time_rel (rt);
326 GNUNET_assert (NULL != json);
327 return GNUNET_JSON_pack_object_steal (name,
328 json);
329}
330
331
332struct GNUNET_JSON_PackSpec
333GNUNET_JSON_pack_time_rel_nbo (const char *name,
334 struct GNUNET_TIME_RelativeNBO rt)
335{
336 return GNUNET_JSON_pack_time_rel (name,
337 GNUNET_TIME_relative_ntoh (rt));
338}
339
340
341struct GNUNET_JSON_PackSpec
342GNUNET_JSON_pack_rsa_public_key (const char *name,
343 const struct GNUNET_CRYPTO_RsaPublicKey *pk)
344{
345 struct GNUNET_JSON_PackSpec ps = {
346 .field_name = name,
347 .object = GNUNET_JSON_from_rsa_public_key (pk)
348 };
349
350 return ps;
351}
352
353
354struct GNUNET_JSON_PackSpec
355GNUNET_JSON_pack_rsa_signature (const char *name,
356 const struct GNUNET_CRYPTO_RsaSignature *sig)
357{
358 struct GNUNET_JSON_PackSpec ps = {
359 .field_name = name,
360 .object = GNUNET_JSON_from_rsa_signature (sig)
361 };
362
363 return ps;
364}
365
366
367/* end of json_pack.c */
diff --git a/src/json/meson.build b/src/json/meson.build
deleted file mode 100644
index 98385163e..000000000
--- a/src/json/meson.build
+++ /dev/null
@@ -1,25 +0,0 @@
1libgnunetjson_src = ['json.c',
2 'json_generator.c',
3 'json_helper.c',
4 'json_mhd.c',
5 'json_pack.c']
6
7if get_option('monolith')
8 foreach p : libgnunetjson_src
9 gnunet_src += 'json/' + p
10 endforeach
11 subdir_done()
12endif
13
14libgnunetjson = library('gnunetjson',
15 libgnunetjson_src,
16 soversion: '0',
17 version: '0.0.0',
18 dependencies: [libgnunetutil_dep, json_dep, mhd_dep, zlib_dep],
19 include_directories: [incdir, configuration_inc],
20 install: true,
21 install_dir: get_option('libdir'))
22libgnunetjson_dep = declare_dependency(link_with : libgnunetjson)
23pkg.generate(libgnunetjson, url: 'https://www.gnunet.org',
24 description : 'Library for JSON de/serialization')
25
diff --git a/src/json/test_json.c b/src/json/test_json.c
deleted file mode 100644
index db376d213..000000000
--- a/src/json/test_json.c
+++ /dev/null
@@ -1,247 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2015, 2016, 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file json/test_json.c
23 * @brief Tests for JSON conversion functions
24 * @author Christian Grothoff <christian@grothoff.org>
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_json_lib.h"
29
30
31/**
32 * Test absolute time conversion from/to JSON.
33 *
34 * @return 0 on success
35 */
36static int
37test_timestamp (void)
38{
39 json_t *j;
40 struct GNUNET_TIME_Absolute a1;
41 struct GNUNET_TIME_Timestamp t1;
42 struct GNUNET_TIME_Timestamp t2;
43 struct GNUNET_JSON_Specification s1[] = {
44 GNUNET_JSON_spec_timestamp (NULL,
45 &t2),
46 GNUNET_JSON_spec_end ()
47 };
48 struct GNUNET_JSON_Specification s2[] = {
49 GNUNET_JSON_spec_timestamp (NULL,
50 &t2),
51 GNUNET_JSON_spec_end ()
52 };
53
54 a1 = GNUNET_TIME_absolute_get ();
55 t1 = GNUNET_TIME_absolute_to_timestamp (a1);
56 j = GNUNET_JSON_from_timestamp (t1);
57 GNUNET_assert (NULL != j);
58 GNUNET_assert (GNUNET_OK ==
59 GNUNET_JSON_parse (j,
60 s1,
61 NULL,
62 NULL));
63 GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
64 json_decref (j);
65
66 a1 = GNUNET_TIME_UNIT_FOREVER_ABS;
67 j = GNUNET_JSON_from_timestamp (t1);
68 GNUNET_assert (NULL != j);
69 GNUNET_assert (GNUNET_OK ==
70 GNUNET_JSON_parse (j,
71 s2,
72 NULL,
73 NULL));
74 GNUNET_assert (GNUNET_TIME_timestamp_cmp (t1, ==, t2));
75 json_decref (j);
76 return 0;
77}
78
79
80/**
81 * Test relative time conversion from/to JSON.
82 *
83 * @return 0 on success
84 */
85static int
86test_rel_time (void)
87{
88 json_t *j;
89 struct GNUNET_TIME_Relative r1;
90 struct GNUNET_TIME_Relative r2;
91 struct GNUNET_JSON_Specification s1[] = {
92 GNUNET_JSON_spec_relative_time (NULL,
93 &r2),
94 GNUNET_JSON_spec_end ()
95 };
96 struct GNUNET_JSON_Specification s2[] = {
97 GNUNET_JSON_spec_relative_time (NULL,
98 &r2),
99 GNUNET_JSON_spec_end ()
100 };
101
102 r1 = GNUNET_TIME_UNIT_SECONDS;
103 j = GNUNET_JSON_from_time_rel (r1);
104 GNUNET_assert (NULL != j);
105 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s1, NULL, NULL));
106 GNUNET_assert (r1.rel_value_us == r2.rel_value_us);
107 json_decref (j);
108
109 r1 = GNUNET_TIME_UNIT_FOREVER_REL;
110 j = GNUNET_JSON_from_time_rel (r1);
111 GNUNET_assert (NULL != j);
112 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, s2, NULL, NULL));
113 GNUNET_assert (r1.rel_value_us == r2.rel_value_us);
114 json_decref (j);
115 return 0;
116}
117
118
119/**
120 * Test raw (binary) conversion from/to JSON.
121 *
122 * @return 0 on success
123 */
124static int
125test_raw ()
126{
127 char blob[256];
128 unsigned int i;
129 json_t *j;
130
131 for (i = 0; i <= 256; i++)
132 {
133 char blob2[256];
134 struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed (NULL,
135 blob2,
136 i),
137 GNUNET_JSON_spec_end () };
138
139 memset (blob, i, i);
140 j = GNUNET_JSON_from_data (blob, i);
141 GNUNET_assert (NULL != j);
142 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (j, spec, NULL, NULL));
143 GNUNET_assert (0 == memcmp (blob, blob2, i));
144 json_decref (j);
145 }
146 return 0;
147}
148
149
150/**
151 * Test rsa conversions from/to JSON.
152 *
153 * @return 0 on success
154 */
155static int
156test_rsa ()
157{
158 struct GNUNET_CRYPTO_RsaPublicKey *pub;
159 struct GNUNET_CRYPTO_RsaPublicKey *pub2;
160 struct GNUNET_JSON_Specification pspec[] =
161 { GNUNET_JSON_spec_rsa_public_key (NULL, &pub2), GNUNET_JSON_spec_end () };
162 struct GNUNET_CRYPTO_RsaSignature *sig;
163 struct GNUNET_CRYPTO_RsaSignature *sig2;
164 struct GNUNET_JSON_Specification sspec[] =
165 { GNUNET_JSON_spec_rsa_signature (NULL, &sig2), GNUNET_JSON_spec_end () };
166 struct GNUNET_CRYPTO_RsaPrivateKey *priv;
167 struct GNUNET_HashCode msg;
168 json_t *jp;
169 json_t *js;
170
171 priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
172 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
173 memset (&msg, 42, sizeof(msg));
174 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv, &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 == GNUNET_JSON_parse (jp, pspec, NULL, NULL));
178 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (js, sspec, NULL, NULL));
179 GNUNET_break (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig2));
180 GNUNET_break (0 == GNUNET_CRYPTO_rsa_public_key_cmp (pub, pub2));
181 json_decref (jp);
182 json_decref (js);
183 GNUNET_CRYPTO_rsa_signature_free (sig);
184 GNUNET_CRYPTO_rsa_signature_free (sig2);
185 GNUNET_CRYPTO_rsa_private_key_free (priv);
186 GNUNET_CRYPTO_rsa_public_key_free (pub);
187 GNUNET_CRYPTO_rsa_public_key_free (pub2);
188 return 0;
189}
190
191
192/**
193 * Test rsa conversions from/to JSON.
194 *
195 * @return 0 on success
196 */
197static int
198test_boolean ()
199{
200 int b1;
201 int b2;
202 json_t *json;
203 struct GNUNET_JSON_Specification pspec[] = { GNUNET_JSON_spec_boolean ("b1",
204 &b1),
205 GNUNET_JSON_spec_boolean ("b2",
206 &b2),
207 GNUNET_JSON_spec_end () };
208
209 json = json_object ();
210 json_object_set_new (json, "b1", json_true ());
211 json_object_set_new (json, "b2", json_false ());
212
213 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (json, pspec, NULL, NULL));
214
215 GNUNET_assert (GNUNET_YES == b1);
216 GNUNET_assert (GNUNET_NO == b2);
217
218 json_object_set_new (json, "b1", json_integer (42));
219
220 GNUNET_assert (GNUNET_OK != GNUNET_JSON_parse (json, pspec, NULL, NULL));
221
222 json_decref (json);
223
224 return 0;
225}
226
227
228int
229main (int argc, const char *const argv[])
230{
231 GNUNET_log_setup ("test-json", "WARNING", NULL);
232 if (0 != test_timestamp ())
233 return 1;
234 if (0 != test_rel_time ())
235 return 1;
236 if (0 != test_raw ())
237 return 1;
238 if (0 != test_rsa ())
239 return 1;
240 if (0 != test_boolean ())
241 return 1;
242 /* FIXME: test EdDSA signature conversion... */
243 return 0;
244}
245
246
247/* end of test_json.c */
diff --git a/src/json/test_json_mhd.c b/src/json/test_json_mhd.c
deleted file mode 100644
index 642715f25..000000000
--- a/src/json/test_json_mhd.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file json/test_json_mhd.c
23 * @brief Tests for JSON MHD integration functions
24 * @author Christian Grothoff <christian@grothoff.org>
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_json_lib.h"
29#include "gnunet_curl_lib.h"
30#include "gnunet_mhd_compat.h"
31#include <zlib.h>
32
33#define MAX_SIZE 1024 * 1024
34
35static json_t *bigj;
36
37static int global_ret;
38
39
40static MHD_RESULT
41access_handler_cb (void *cls,
42 struct MHD_Connection *connection,
43 const char *url,
44 const char *method,
45 const char *version,
46 const char *upload_data,
47 size_t *upload_data_size,
48 void **con_cls)
49{
50 int ret;
51 json_t *json;
52 struct MHD_Response *resp;
53
54 json = NULL;
55 ret = GNUNET_JSON_post_parser (MAX_SIZE,
56 connection,
57 con_cls,
58 upload_data,
59 upload_data_size,
60 &json);
61 switch (ret)
62 {
63 case GNUNET_JSON_PR_SUCCESS:
64 if (json_equal (bigj, json))
65 {
66 global_ret = 0;
67 }
68 else
69 {
70 GNUNET_break (0);
71 global_ret = 6;
72 }
73 json_decref (json);
74 resp = MHD_create_response_from_buffer (3, "OK\n", MHD_RESPMEM_PERSISTENT);
75 ret = MHD_queue_response (connection, MHD_HTTP_OK, resp);
76 MHD_destroy_response (resp);
77 return ret;
78
79 case GNUNET_JSON_PR_CONTINUE:
80 return MHD_YES;
81
82 case GNUNET_JSON_PR_OUT_OF_MEMORY:
83 GNUNET_break (0);
84 global_ret = 3;
85 break;
86
87 case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
88 GNUNET_break (0);
89 global_ret = 4;
90 break;
91
92 case GNUNET_JSON_PR_JSON_INVALID:
93 GNUNET_break (0);
94 global_ret = 5;
95 break;
96 }
97 GNUNET_break (0);
98 return MHD_NO;
99}
100
101
102int
103main (int argc, const char *const argv[])
104{
105 struct MHD_Daemon *daemon;
106 uint16_t port;
107 CURL *easy;
108 char *url;
109 char *str;
110 size_t slen;
111 long post_data_size;
112 void *post_data;
113 uLongf dlen;
114 struct curl_slist *json_header;
115
116 GNUNET_log_setup ("test-json-mhd", "WARNING", NULL);
117 global_ret = 2;
118 daemon = MHD_start_daemon (MHD_USE_DUAL_STACK | MHD_USE_AUTO_INTERNAL_THREAD,
119 0,
120 NULL,
121 NULL,
122 &access_handler_cb,
123 NULL,
124 MHD_OPTION_END);
125 if (NULL == daemon)
126 return 77;
127 bigj = json_object ();
128 json_object_set_new (bigj, "test", json_string ("value"));
129 for (unsigned int i = 0; i < 1000; i++)
130 {
131 char tmp[5];
132
133 GNUNET_snprintf (tmp, sizeof(tmp), "%u", i);
134 json_object_set_new (bigj, tmp, json_string (tmp));
135 }
136 str = json_dumps (bigj, JSON_INDENT (2));
137 slen = strlen (str);
138
139#ifdef compressBound
140 dlen = compressBound (slen);
141#else
142 dlen = slen + slen / 100 + 20;
143 /* documentation says 100.1% oldSize + 12 bytes, but we
144 * should be able to overshoot by more to be safe */
145#endif
146 post_data = GNUNET_malloc (dlen);
147 if (Z_OK !=
148 compress2 ((Bytef *) post_data, &dlen, (const Bytef *) str, slen, 9))
149 {
150 GNUNET_break (0);
151 MHD_stop_daemon (daemon);
152 json_decref (bigj);
153 GNUNET_free (post_data);
154 GNUNET_free (str);
155 return 1;
156 }
157 post_data_size = (long) dlen;
158 port = MHD_get_daemon_info (daemon, MHD_DAEMON_INFO_BIND_PORT)->port;
159 easy = curl_easy_init ();
160 GNUNET_asprintf (&url, "http://localhost:%u/", (unsigned int) port);
161 curl_easy_setopt (easy, CURLOPT_VERBOSE, 0);
162 curl_easy_setopt (easy, CURLOPT_URL, url);
163 curl_easy_setopt (easy, CURLOPT_POST, 1);
164 curl_easy_setopt (easy, CURLOPT_POSTFIELDS, post_data);
165 curl_easy_setopt (easy, CURLOPT_POSTFIELDSIZE, post_data_size);
166
167 json_header = curl_slist_append (NULL, "Content-Type: application/json");
168 json_header = curl_slist_append (json_header, "Content-Encoding: deflate");
169 curl_easy_setopt (easy, CURLOPT_HTTPHEADER, json_header);
170 if (0 != curl_easy_perform (easy))
171 {
172 GNUNET_break (0);
173 MHD_stop_daemon (daemon);
174 GNUNET_free (url);
175 json_decref (bigj);
176 GNUNET_free (post_data);
177 GNUNET_free (str);
178 curl_slist_free_all (json_header);
179 curl_easy_cleanup (easy);
180 return 1;
181 }
182 MHD_stop_daemon (daemon);
183 GNUNET_free (url);
184 json_decref (bigj);
185 GNUNET_free (post_data);
186 GNUNET_free (str);
187 curl_slist_free_all (json_header);
188 curl_easy_cleanup (easy);
189 return global_ret;
190}
191
192
193/* end of test_json_mhd.c */