aboutsummaryrefslogtreecommitdiff
path: root/src/json
diff options
context:
space:
mode:
Diffstat (limited to 'src/json')
-rw-r--r--src/json/.gitignore2
-rw-r--r--src/json/Makefile.am68
-rw-r--r--src/json/json.c161
-rw-r--r--src/json/json_generator.c179
-rw-r--r--src/json/json_helper.c989
-rw-r--r--src/json/json_mhd.c379
-rw-r--r--src/json/json_pack.c331
-rw-r--r--src/json/test_json.c242
-rw-r--r--src/json/test_json_mhd.c193
9 files changed, 0 insertions, 2544 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 2e97cecb9..000000000
--- a/src/json/Makefile.am
+++ /dev/null
@@ -1,68 +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/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/util/libgnunetutil.la \
45 -ljansson
46
47
48if HAVE_LIBGNURL
49LIB_GNURL=@LIBGNURL@
50CPP_GNURL=@LIBGNURL_CPPFLAGS@
51else
52if HAVE_LIBCURL
53LIB_GNURL=@LIBCURL@
54CPP_GNURL=@LIBCURL_CPPFLAGS@
55endif
56endif
57
58
59test_json_mhd_SOURCES = \
60 test_json_mhd.c
61test_json_mhd_LDADD = \
62 libgnunetjson.la \
63 $(top_builddir)/src/util/libgnunetutil.la \
64 -ljansson \
65 $(MHD_LIBS) \
66 $(Z_LIBS) \
67 $(LIB_GNURL)
68test_json_mhd_CFLAGS = $(MHD_CFLAGS) $(CPP_GNURL) $(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 eb275712c..000000000
--- a/src/json/json_generator.c
+++ /dev/null
@@ -1,179 +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_timestamp (struct GNUNET_TIME_Timestamp stamp)
54{
55 json_t *j;
56
57 j = json_object ();
58 if (NULL == j)
59 {
60 GNUNET_break (0);
61 return NULL;
62 }
63 if (GNUNET_TIME_absolute_is_never (stamp.abs_time))
64 {
65 if (0 !=
66 json_object_set_new (j,
67 "t_s",
68 json_string ("never")))
69 {
70 GNUNET_break (0);
71 json_decref (j);
72 return NULL;
73 }
74 return j;
75 }
76 GNUNET_assert (
77 0 ==
78 (stamp.abs_time.abs_value_us
79 % GNUNET_TIME_UNIT_SECONDS.rel_value_us));
80 if (0 !=
81 json_object_set_new (
82 j,
83 "t_s",
84 json_integer (
85 (json_int_t) (stamp.abs_time.abs_value_us
86 / GNUNET_TIME_UNIT_SECONDS.rel_value_us))))
87 {
88 GNUNET_break (0);
89 json_decref (j);
90 return NULL;
91 }
92 return j;
93}
94
95
96json_t *
97GNUNET_JSON_from_timestamp_nbo (struct GNUNET_TIME_TimestampNBO stamp)
98{
99 return GNUNET_JSON_from_timestamp (GNUNET_TIME_timestamp_ntoh (stamp));
100}
101
102
103json_t *
104GNUNET_JSON_from_time_rel (struct GNUNET_TIME_Relative stamp)
105{
106 json_t *j;
107
108 j = json_object ();
109 if (NULL == j)
110 {
111 GNUNET_break (0);
112 return NULL;
113 }
114 if (GNUNET_TIME_relative_is_forever (stamp))
115 {
116 if (0 !=
117 json_object_set_new (j,
118 "d_us",
119 json_string ("forever")))
120 {
121 GNUNET_break (0);
122 json_decref (j);
123 return NULL;
124 }
125 return j;
126 }
127 if (stamp.rel_value_us >= (1LLU << 53))
128 {
129 /* value is larger than allowed */
130 GNUNET_break (0);
131 return NULL;
132 }
133 if (0 !=
134 json_object_set_new (
135 j,
136 "d_us",
137 json_integer ((json_int_t) stamp.rel_value_us)))
138 {
139 GNUNET_break (0);
140 json_decref (j);
141 return NULL;
142 }
143 return j;
144}
145
146
147json_t *
148GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk)
149{
150 void *buf;
151 size_t buf_len;
152 json_t *ret;
153
154 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk,
155 &buf);
156 ret = GNUNET_JSON_from_data (buf,
157 buf_len);
158 GNUNET_free (buf);
159 return ret;
160}
161
162
163json_t *
164GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig)
165{
166 void *buf;
167 size_t buf_len;
168 json_t *ret;
169
170 buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig,
171 &buf);
172 ret = GNUNET_JSON_from_data (buf,
173 buf_len);
174 GNUNET_free (buf);
175 return ret;
176}
177
178
179/* 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 a15dc74c0..000000000
--- a/src/json/json_helper.c
+++ /dev/null
@@ -1,989 +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_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 variable 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_variable_data (void *cls,
116 json_t *root,
117 struct GNUNET_JSON_Specification *spec)
118{
119 const char *str;
120 size_t size;
121 void *data;
122
123 str = json_string_value (root);
124 if (NULL == str)
125 {
126 GNUNET_break_op (0);
127 return GNUNET_SYSERR;
128 }
129 if (GNUNET_OK !=
130 GNUNET_STRINGS_string_to_data_alloc (str,
131 strlen (str),
132 &data,
133 &size))
134 {
135 GNUNET_break_op (0);
136 return GNUNET_SYSERR;
137 }
138 *(void **) spec->ptr = data;
139 *spec->size_ptr = size;
140 return GNUNET_OK;
141}
142
143
144/**
145 * Cleanup data left from parsing variable size data
146 *
147 * @param cls closure, NULL
148 * @param[out] spec where to free the data
149 */
150static void
151clean_variable_data (void *cls,
152 struct GNUNET_JSON_Specification *spec)
153{
154 (void) cls;
155 if (0 != *spec->size_ptr)
156 {
157 GNUNET_free (*(void **) spec->ptr);
158 *(void **) spec->ptr = NULL;
159 *spec->size_ptr = 0;
160 }
161}
162
163
164struct GNUNET_JSON_Specification
165GNUNET_JSON_spec_varsize (const char *name,
166 void **obj,
167 size_t *size)
168{
169 struct GNUNET_JSON_Specification ret = {
170 .parser = &parse_variable_data,
171 .cleaner = &clean_variable_data,
172 .cls = NULL,
173 .field = name,
174 .ptr = obj,
175 .ptr_size = 0,
176 .size_ptr = size
177 };
178
179 *obj = NULL;
180 *size = 0;
181 return ret;
182}
183
184
185/**
186 * Parse given JSON object to string.
187 *
188 * @param cls closure, NULL
189 * @param root the json object representing data
190 * @param[out] spec where to write the data
191 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
192 */
193static enum GNUNET_GenericReturnValue
194parse_string (void *cls,
195 json_t *root,
196 struct GNUNET_JSON_Specification *spec)
197{
198 const char *str;
199
200 (void) cls;
201 str = json_string_value (root);
202 if (NULL == str)
203 {
204 GNUNET_break_op (0);
205 return GNUNET_SYSERR;
206 }
207 *(const char **) spec->ptr = str;
208 return GNUNET_OK;
209}
210
211
212struct GNUNET_JSON_Specification
213GNUNET_JSON_spec_string (const char *name,
214 const char **strptr)
215{
216 struct GNUNET_JSON_Specification ret = {
217 .parser = &parse_string,
218 .cleaner = NULL,
219 .cls = NULL,
220 .field = name,
221 .ptr = strptr,
222 .ptr_size = 0,
223 .size_ptr = NULL
224 };
225
226 *strptr = NULL;
227 return ret;
228}
229
230
231/**
232 * Parse given JSON object to a JSON object. (Yes, trivial.)
233 *
234 * @param cls closure, NULL
235 * @param root the json object representing data
236 * @param[out] spec where to write the data
237 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
238 */
239static enum GNUNET_GenericReturnValue
240parse_object (void *cls,
241 json_t *root,
242 struct GNUNET_JSON_Specification *spec)
243{
244 if (! (json_is_object (root) || json_is_array (root)))
245 {
246 GNUNET_break_op (0);
247 return GNUNET_SYSERR;
248 }
249 json_incref (root);
250 *(json_t **) spec->ptr = root;
251 return GNUNET_OK;
252}
253
254
255/**
256 * Cleanup data left from parsing JSON object.
257 *
258 * @param cls closure, NULL
259 * @param[out] spec where to free the data
260 */
261static void
262clean_object (void *cls,
263 struct GNUNET_JSON_Specification *spec)
264{
265 json_t **ptr = (json_t **) spec->ptr;
266
267 if (NULL != *ptr)
268 {
269 json_decref (*ptr);
270 *ptr = NULL;
271 }
272}
273
274
275struct GNUNET_JSON_Specification
276GNUNET_JSON_spec_json (const char *name,
277 json_t **jsonp)
278{
279 struct GNUNET_JSON_Specification ret = {
280 .parser = &parse_object,
281 .cleaner = &clean_object,
282 .cls = NULL,
283 .field = name,
284 .ptr = jsonp,
285 .ptr_size = 0,
286 .size_ptr = NULL
287 };
288
289 *jsonp = NULL;
290 return ret;
291}
292
293
294/**
295 * Parse given JSON object to a bool.
296 *
297 * @param cls closure, NULL
298 * @param root the json object representing data
299 * @param[out] spec where to write the data
300 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
301 */
302static enum GNUNET_GenericReturnValue
303parse_bool (void *cls,
304 json_t *root,
305 struct GNUNET_JSON_Specification *spec)
306{
307 bool *b = spec->ptr;
308
309 if (json_true () == root)
310 {
311 *b = true;
312 return GNUNET_OK;
313 }
314 if (json_false () == root)
315 {
316 *b = false;
317 return GNUNET_OK;
318 }
319 GNUNET_break_op (0);
320 return GNUNET_SYSERR;
321}
322
323
324struct GNUNET_JSON_Specification
325GNUNET_JSON_spec_bool (const char *name,
326 bool *b)
327{
328 struct GNUNET_JSON_Specification ret = {
329 .parser = &parse_bool,
330 .cleaner = NULL,
331 .cls = NULL,
332 .field = name,
333 .ptr = b,
334 .ptr_size = sizeof(bool),
335 .size_ptr = NULL
336 };
337
338 return ret;
339}
340
341
342/**
343 * Parse given JSON object to a uint8_t.
344 *
345 * @param cls closure, NULL
346 * @param root the json object representing data
347 * @param[out] spec where to write the data
348 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
349 */
350static enum GNUNET_GenericReturnValue
351parse_u8 (void *cls,
352 json_t *root,
353 struct GNUNET_JSON_Specification *spec)
354{
355 json_int_t val;
356 uint8_t *up = spec->ptr;
357
358 if (! json_is_integer (root))
359 {
360 GNUNET_break_op (0);
361 return GNUNET_SYSERR;
362 }
363 val = json_integer_value (root);
364 if ((0 > val) || (val > UINT8_MAX))
365 {
366 GNUNET_break_op (0);
367 return GNUNET_SYSERR;
368 }
369 *up = (uint8_t) val;
370 return GNUNET_OK;
371}
372
373
374struct GNUNET_JSON_Specification
375GNUNET_JSON_spec_uint8 (const char *name,
376 uint8_t *u8)
377{
378 struct GNUNET_JSON_Specification ret = {
379 .parser = &parse_u8,
380 .cleaner = NULL,
381 .cls = NULL,
382 .field = name,
383 .ptr = u8,
384 .ptr_size = sizeof(uint8_t),
385 .size_ptr = NULL
386 };
387
388 return ret;
389}
390
391
392/**
393 * Parse given JSON object to a uint16_t.
394 *
395 * @param cls closure, NULL
396 * @param root the json object representing data
397 * @param[out] spec where to write the data
398 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
399 */
400static enum GNUNET_GenericReturnValue
401parse_u16 (void *cls,
402 json_t *root,
403 struct GNUNET_JSON_Specification *spec)
404{
405 json_int_t val;
406 uint16_t *up = spec->ptr;
407
408 if (! json_is_integer (root))
409 {
410 GNUNET_break_op (0);
411 return GNUNET_SYSERR;
412 }
413 val = json_integer_value (root);
414 if ((0 > val) || (val > UINT16_MAX))
415 {
416 GNUNET_break_op (0);
417 return GNUNET_SYSERR;
418 }
419 *up = (uint16_t) val;
420 return GNUNET_OK;
421}
422
423
424struct GNUNET_JSON_Specification
425GNUNET_JSON_spec_uint16 (const char *name,
426 uint16_t *u16)
427{
428 struct GNUNET_JSON_Specification ret = {
429 .parser = &parse_u16,
430 .cleaner = NULL,
431 .cls = NULL,
432 .field = name,
433 .ptr = u16,
434 .ptr_size = sizeof(uint16_t),
435 .size_ptr = NULL
436 };
437
438 return ret;
439}
440
441
442/**
443 * Parse given JSON object to a uint32_t.
444 *
445 * @param cls closure, NULL
446 * @param root the json object representing data
447 * @param[out] spec where to write the data
448 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
449 */
450static enum GNUNET_GenericReturnValue
451parse_u32 (void *cls,
452 json_t *root,
453 struct GNUNET_JSON_Specification *spec)
454{
455 json_int_t val;
456 uint32_t *up = spec->ptr;
457
458 if (! json_is_integer (root))
459 {
460 GNUNET_break_op (0);
461 return GNUNET_SYSERR;
462 }
463 val = json_integer_value (root);
464 if ((0 > val) || (val > UINT32_MAX))
465 {
466 GNUNET_break_op (0);
467 return GNUNET_SYSERR;
468 }
469 *up = (uint32_t) val;
470 return GNUNET_OK;
471}
472
473
474struct GNUNET_JSON_Specification
475GNUNET_JSON_spec_uint32 (const char *name,
476 uint32_t *u32)
477{
478 struct GNUNET_JSON_Specification ret = {
479 .parser = &parse_u32,
480 .cleaner = NULL,
481 .cls = NULL,
482 .field = name,
483 .ptr = u32,
484 .ptr_size = sizeof(uint32_t),
485 .size_ptr = NULL
486 };
487
488 return ret;
489}
490
491
492/**
493 * Parse given JSON object to a uint64_t.
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_u64 (void *cls,
502 json_t *root,
503 struct GNUNET_JSON_Specification *spec)
504{
505 json_int_t val;
506 uint64_t *up = spec->ptr;
507
508 if (! json_is_integer (root))
509 {
510 GNUNET_break_op (0);
511 return GNUNET_SYSERR;
512 }
513 val = json_integer_value (root);
514 *up = (uint64_t) val;
515 return GNUNET_OK;
516}
517
518
519struct GNUNET_JSON_Specification
520GNUNET_JSON_spec_uint64 (const char *name,
521 uint64_t *u64)
522{
523 struct GNUNET_JSON_Specification ret = {
524 .parser = &parse_u64,
525 .cleaner = NULL,
526 .cls = NULL,
527 .field = name,
528 .ptr = u64,
529 .ptr_size = sizeof(uint64_t),
530 .size_ptr = NULL
531 };
532
533 return ret;
534}
535
536
537/**
538 * Parse given JSON object to a int64_t.
539 *
540 * @param cls closure, NULL
541 * @param root the json object representing data
542 * @param[out] spec where to write the data
543 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
544 */
545static enum GNUNET_GenericReturnValue
546parse_i64 (void *cls,
547 json_t *root,
548 struct GNUNET_JSON_Specification *spec)
549{
550 json_int_t val;
551 int64_t *up = spec->ptr;
552
553 if (! json_is_integer (root))
554 {
555 GNUNET_break_op (0);
556 return GNUNET_SYSERR;
557 }
558 val = json_integer_value (root);
559 *up = (int64_t) val;
560 return GNUNET_OK;
561}
562
563
564struct GNUNET_JSON_Specification
565GNUNET_JSON_spec_int64 (const char *name,
566 int64_t *i64)
567{
568 struct GNUNET_JSON_Specification ret = {
569 .parser = &parse_i64,
570 .cleaner = NULL,
571 .cls = NULL,
572 .field = name,
573 .ptr = i64,
574 .ptr_size = sizeof(int64_t),
575 .size_ptr = NULL
576 };
577
578 return ret;
579}
580
581
582/* ************ GNUnet-specific parser specifications ******************* */
583
584/**
585 * Parse given JSON object to a timestamp.
586 *
587 * @param cls closure, NULL
588 * @param root the json object representing data
589 * @param[out] spec where to write the data
590 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
591 */
592static enum GNUNET_GenericReturnValue
593parse_timestamp (void *cls,
594 json_t *root,
595 struct GNUNET_JSON_Specification *spec)
596{
597 struct GNUNET_TIME_Timestamp *ts = spec->ptr;
598 json_t *json_t_s;
599 unsigned long long int tval;
600
601 if (! json_is_object (root))
602 {
603 GNUNET_break_op (0);
604 return GNUNET_SYSERR;
605 }
606 json_t_s = json_object_get (root,
607 "t_s");
608 if (json_is_integer (json_t_s))
609 {
610 tval = json_integer_value (json_t_s);
611 /* Time is in seconds in JSON, but in microseconds in GNUNET_TIME_Absolute */
612 ts->abs_time.abs_value_us
613 = tval * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
614 if (ts->abs_time.abs_value_us
615 / GNUNET_TIME_UNIT_SECONDS.rel_value_us
616 != tval)
617 {
618 /* Integer overflow */
619 GNUNET_break_op (0);
620 return GNUNET_SYSERR;
621 }
622 return GNUNET_OK;
623 }
624 if (json_is_string (json_t_s))
625 {
626 const char *val;
627
628 val = json_string_value (json_t_s);
629 if ((0 == strcasecmp (val,
630 "never")))
631 {
632 ts->abs_time = GNUNET_TIME_UNIT_FOREVER_ABS;
633 return GNUNET_OK;
634 }
635 GNUNET_break_op (0);
636 return GNUNET_SYSERR;
637 }
638 GNUNET_break_op (0);
639 return GNUNET_SYSERR;
640}
641
642
643struct GNUNET_JSON_Specification
644GNUNET_JSON_spec_timestamp (const char *name,
645 struct GNUNET_TIME_Timestamp *t)
646{
647 struct GNUNET_JSON_Specification ret = {
648 .parser = &parse_timestamp,
649 .field = name,
650 .ptr = t,
651 .ptr_size = sizeof(struct GNUNET_TIME_Timestamp)
652 };
653
654 return ret;
655}
656
657
658/**
659 * Parse given JSON object to absolute time.
660 *
661 * @param cls closure, NULL
662 * @param root the json object representing data
663 * @param[out] spec where to write the data
664 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
665 */
666static enum GNUNET_GenericReturnValue
667parse_timestamp_nbo (void *cls,
668 json_t *root,
669 struct GNUNET_JSON_Specification *spec)
670{
671 struct GNUNET_TIME_TimestampNBO *ts = spec->ptr;
672 struct GNUNET_TIME_Timestamp a;
673 struct GNUNET_JSON_Specification ispec;
674
675 ispec = *spec;
676 ispec.parser = &parse_timestamp;
677 ispec.ptr = &a;
678 if (GNUNET_OK !=
679 parse_timestamp (NULL,
680 root,
681 &ispec))
682 return GNUNET_SYSERR;
683 *ts = GNUNET_TIME_timestamp_hton (a);
684 return GNUNET_OK;
685}
686
687
688struct GNUNET_JSON_Specification
689GNUNET_JSON_spec_timestamp_nbo (const char *name,
690 struct GNUNET_TIME_TimestampNBO *at)
691{
692 struct GNUNET_JSON_Specification ret = {
693 .parser = &parse_timestamp_nbo,
694 .field = name,
695 .ptr = at,
696 .ptr_size = sizeof(struct GNUNET_TIME_TimestampNBO)
697 };
698
699 return ret;
700}
701
702
703/**
704 * Parse given JSON object to relative time.
705 *
706 * @param cls closure, NULL
707 * @param root the json object representing data
708 * @param[out] spec where to write the data
709 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
710 */
711static enum GNUNET_GenericReturnValue
712parse_rel_time (void *cls,
713 json_t *root,
714 struct GNUNET_JSON_Specification *spec)
715{
716 struct GNUNET_TIME_Relative *rel = spec->ptr;
717 json_t *json_d_us;
718 unsigned long long int tval;
719
720 if (! json_is_object (root))
721 {
722 GNUNET_break_op (0);
723 return GNUNET_SYSERR;
724 }
725 json_d_us = json_object_get (root,
726 "d_us");
727 if (json_is_integer (json_d_us))
728 {
729 tval = json_integer_value (json_d_us);
730 if (tval >= (1LLU << 53))
731 {
732 /* value is larger than allowed */
733 GNUNET_break_op (0);
734 return GNUNET_SYSERR;
735 }
736 rel->rel_value_us = tval;
737 return GNUNET_OK;
738 }
739 if (json_is_string (json_d_us))
740 {
741 const char *val;
742
743 val = json_string_value (json_d_us);
744 if ((0 == strcasecmp (val,
745 "forever")))
746 {
747 *rel = GNUNET_TIME_UNIT_FOREVER_REL;
748 return GNUNET_OK;
749 }
750 GNUNET_break_op (0);
751 return GNUNET_SYSERR;
752 }
753 GNUNET_break_op (0);
754 return GNUNET_SYSERR;
755}
756
757
758struct GNUNET_JSON_Specification
759GNUNET_JSON_spec_relative_time (const char *name,
760 struct GNUNET_TIME_Relative *rt)
761{
762 struct GNUNET_JSON_Specification ret = {
763 .parser = &parse_rel_time,
764 .field = name,
765 .ptr = rt,
766 .ptr_size = sizeof(struct GNUNET_TIME_Relative)
767 };
768
769 return ret;
770}
771
772
773/**
774 * Parse given JSON object to RSA public key.
775 *
776 * @param cls closure, NULL
777 * @param root the json object representing data
778 * @param[out] spec where to write the data
779 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
780 */
781static enum GNUNET_GenericReturnValue
782parse_rsa_public_key (void *cls,
783 json_t *root,
784 struct GNUNET_JSON_Specification *spec)
785{
786 struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
787 const char *enc;
788 char *buf;
789 size_t len;
790 size_t buf_len;
791
792 if (NULL == (enc = json_string_value (root)))
793 {
794 GNUNET_break_op (0);
795 return GNUNET_SYSERR;
796 }
797 len = strlen (enc);
798 buf_len = (len * 5) / 8;
799 buf = GNUNET_malloc (buf_len);
800 if (GNUNET_OK !=
801 GNUNET_STRINGS_string_to_data (enc,
802 len,
803 buf,
804 buf_len))
805 {
806 GNUNET_break_op (0);
807 GNUNET_free (buf);
808 return GNUNET_SYSERR;
809 }
810 if (NULL == (*pk = GNUNET_CRYPTO_rsa_public_key_decode (buf,
811 buf_len)))
812 {
813 GNUNET_break_op (0);
814 GNUNET_free (buf);
815 return GNUNET_SYSERR;
816 }
817 GNUNET_free (buf);
818 return GNUNET_OK;
819}
820
821
822/**
823 * Cleanup data left from parsing RSA public key.
824 *
825 * @param cls closure, NULL
826 * @param[out] spec where to free the data
827 */
828static void
829clean_rsa_public_key (void *cls,
830 struct GNUNET_JSON_Specification *spec)
831{
832 struct GNUNET_CRYPTO_RsaPublicKey **pk = spec->ptr;
833
834 if (NULL != *pk)
835 {
836 GNUNET_CRYPTO_rsa_public_key_free (*pk);
837 *pk = NULL;
838 }
839}
840
841
842struct GNUNET_JSON_Specification
843GNUNET_JSON_spec_rsa_public_key (const char *name,
844 struct GNUNET_CRYPTO_RsaPublicKey **pk)
845{
846 struct GNUNET_JSON_Specification ret = {
847 .parser = &parse_rsa_public_key,
848 .cleaner = &clean_rsa_public_key,
849 .field = name,
850 .ptr = pk
851 };
852
853 *pk = NULL;
854 return ret;
855}
856
857
858/**
859 * Parse given JSON object to RSA signature.
860 *
861 * @param cls closure, NULL
862 * @param root the json object representing data
863 * @param[out] spec where to write the data
864 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
865 */
866static enum GNUNET_GenericReturnValue
867parse_rsa_signature (void *cls,
868 json_t *root,
869 struct GNUNET_JSON_Specification *spec)
870{
871 struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
872 size_t size;
873 const char *str;
874 int res;
875 void *buf;
876
877 str = json_string_value (root);
878 if (NULL == str)
879 {
880 GNUNET_break_op (0);
881 return GNUNET_SYSERR;
882 }
883 size = (strlen (str) * 5) / 8;
884 buf = GNUNET_malloc (size);
885 res = GNUNET_STRINGS_string_to_data (str,
886 strlen (str),
887 buf,
888 size);
889 if (GNUNET_OK != res)
890 {
891 GNUNET_free (buf);
892 GNUNET_break_op (0);
893 return GNUNET_SYSERR;
894 }
895 if (NULL == (*sig = GNUNET_CRYPTO_rsa_signature_decode (buf,
896 size)))
897 {
898 GNUNET_break_op (0);
899 GNUNET_free (buf);
900 return GNUNET_SYSERR;
901 }
902 GNUNET_free (buf);
903 return GNUNET_OK;
904}
905
906
907/**
908 * Cleanup data left from parsing RSA signature.
909 *
910 * @param cls closure, NULL
911 * @param[out] spec where to free the data
912 */
913static void
914clean_rsa_signature (void *cls,
915 struct GNUNET_JSON_Specification *spec)
916{
917 struct GNUNET_CRYPTO_RsaSignature **sig = spec->ptr;
918
919 if (NULL != *sig)
920 {
921 GNUNET_CRYPTO_rsa_signature_free (*sig);
922 *sig = NULL;
923 }
924}
925
926
927struct GNUNET_JSON_Specification
928GNUNET_JSON_spec_rsa_signature (const char *name,
929 struct GNUNET_CRYPTO_RsaSignature **sig)
930{
931 struct GNUNET_JSON_Specification ret = {
932 .parser = &parse_rsa_signature,
933 .cleaner = &clean_rsa_signature,
934 .cls = NULL,
935 .field = name,
936 .ptr = sig,
937 .ptr_size = 0,
938 .size_ptr = NULL
939 };
940
941 *sig = NULL;
942 return ret;
943}
944
945
946/**
947 * Parse given JSON object to an int as a boolean.
948 *
949 * @param cls closure, NULL
950 * @param root the json object representing data
951 * @param[out] spec where to write the data
952 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
953 */
954static enum GNUNET_GenericReturnValue
955parse_boolean (void *cls,
956 json_t *root,
957 struct GNUNET_JSON_Specification *spec)
958{
959 int *bp = spec->ptr;
960
961 if (! json_is_boolean (root))
962 {
963 GNUNET_break_op (0);
964 return GNUNET_SYSERR;
965 }
966 *bp = json_boolean_value (root) ? GNUNET_YES : GNUNET_NO;
967 return GNUNET_OK;
968}
969
970
971struct GNUNET_JSON_Specification
972GNUNET_JSON_spec_boolean (const char *name,
973 int *boolean)
974{
975 struct GNUNET_JSON_Specification ret = {
976 .parser = &parse_boolean,
977 .cleaner = NULL,
978 .cls = NULL,
979 .field = name,
980 .ptr = boolean,
981 .ptr_size = sizeof(int),
982 .size_ptr = NULL
983 };
984
985 return ret;
986}
987
988
989/* 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 cc1ca3e97..000000000
--- a/src/json/json_pack.c
+++ /dev/null
@@ -1,331 +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 GNUNET_assert (spec[i].allow_null);
49 }
50 else
51 {
52 GNUNET_assert (0 ==
53 json_object_set_new (ret,
54 spec[i].field_name,
55 spec[i].object));
56 spec[i].object = NULL;
57 }
58 }
59 return ret;
60}
61
62
63struct GNUNET_JSON_PackSpec
64GNUNET_JSON_pack_end_ (void)
65{
66 struct GNUNET_JSON_PackSpec ps = {
67 .field_name = NULL
68 };
69
70 return ps;
71}
72
73
74struct GNUNET_JSON_PackSpec
75GNUNET_JSON_pack_allow_null (struct GNUNET_JSON_PackSpec in)
76{
77 in.allow_null = true;
78 return in;
79}
80
81
82struct GNUNET_JSON_PackSpec
83GNUNET_JSON_pack_bool (const char *name,
84 bool b)
85{
86 struct GNUNET_JSON_PackSpec ps = {
87 .field_name = name,
88 .object = json_boolean (b)
89 };
90
91 return ps;
92}
93
94
95struct GNUNET_JSON_PackSpec
96GNUNET_JSON_pack_string (const char *name,
97 const char *s)
98{
99 struct GNUNET_JSON_PackSpec ps = {
100 .field_name = name,
101 .object = json_string (s)
102 };
103
104 return ps;
105}
106
107
108struct GNUNET_JSON_PackSpec
109GNUNET_JSON_pack_uint64 (const char *name,
110 uint64_t num)
111{
112 struct GNUNET_JSON_PackSpec ps = {
113 .field_name = name,
114 .object = json_integer ((json_int_t) num)
115 };
116
117#if JSON_INTEGER_IS_LONG_LONG
118 GNUNET_assert (num <= LLONG_MAX);
119#else
120 GNUNET_assert (num <= LONG_MAX);
121#endif
122 return ps;
123}
124
125
126struct GNUNET_JSON_PackSpec
127GNUNET_JSON_pack_int64 (const char *name,
128 int64_t num)
129{
130 struct GNUNET_JSON_PackSpec ps = {
131 .field_name = name,
132 .object = json_integer ((json_int_t) num)
133 };
134
135#if JSON_INTEGER_IS_LONG_LONG
136 GNUNET_assert (num <= LLONG_MAX);
137 GNUNET_assert (num >= LLONG_MIN);
138#else
139 GNUNET_assert (num <= LONG_MAX);
140 GNUNET_assert (num >= LONG_MIN);
141#endif
142 return ps;
143}
144
145
146struct GNUNET_JSON_PackSpec
147GNUNET_JSON_pack_object_steal (const char *name,
148 json_t *o)
149{
150 struct GNUNET_JSON_PackSpec ps = {
151 .field_name = name,
152 .object = o
153 };
154
155 if (NULL == o)
156 return ps;
157 if (! json_is_object (o))
158 {
159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
160 "Expected JSON object for field `%s'\n",
161 name);
162 GNUNET_assert (0);
163 }
164 return ps;
165}
166
167
168struct GNUNET_JSON_PackSpec
169GNUNET_JSON_pack_object_incref (const char *name,
170 json_t *o)
171{
172 struct GNUNET_JSON_PackSpec ps = {
173 .field_name = name,
174 .object = o
175 };
176
177 if (NULL == o)
178 return ps;
179 (void) json_incref (o);
180 if (! json_is_object (o))
181 {
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
183 "Expected JSON object for field `%s'\n",
184 name);
185 GNUNET_assert (0);
186 }
187 return ps;
188}
189
190
191struct GNUNET_JSON_PackSpec
192GNUNET_JSON_pack_array_steal (const char *name,
193 json_t *a)
194{
195 struct GNUNET_JSON_PackSpec ps = {
196 .field_name = name,
197 .object = a
198 };
199
200 if (NULL == a)
201 return ps;
202 if (! json_is_array (a))
203 {
204 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
205 "Expected JSON array for field `%s'\n",
206 name);
207 GNUNET_assert (0);
208 }
209 return ps;
210}
211
212
213struct GNUNET_JSON_PackSpec
214GNUNET_JSON_pack_array_incref (const char *name,
215 json_t *a)
216{
217 struct GNUNET_JSON_PackSpec ps = {
218 .field_name = name,
219 .object = a
220 };
221
222 if (NULL == a)
223 return ps;
224 (void) json_incref (a);
225 if (! json_is_array (a))
226 {
227 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
228 "Expected JSON array for field `%s'\n",
229 name);
230 GNUNET_assert (0);
231 }
232 return ps;
233}
234
235
236struct GNUNET_JSON_PackSpec
237GNUNET_JSON_pack_data_varsize (const char *name,
238 const void *blob,
239 size_t blob_size)
240{
241 struct GNUNET_JSON_PackSpec ps = {
242 .field_name = name,
243 .object = (NULL != blob)
244 ? GNUNET_JSON_from_data (blob,
245 blob_size)
246 : NULL
247 };
248
249 return ps;
250}
251
252
253struct GNUNET_JSON_PackSpec
254GNUNET_JSON_pack_timestamp (const char *name,
255 struct GNUNET_TIME_Timestamp t)
256{
257 struct GNUNET_JSON_PackSpec ps = {
258 .field_name = name
259 };
260
261 if (! GNUNET_TIME_absolute_is_zero (t.abs_time))
262 {
263 ps.object = GNUNET_JSON_from_timestamp (t);
264 GNUNET_assert (NULL != ps.object);
265 }
266 else
267 {
268 ps.object = NULL;
269 }
270 return ps;
271}
272
273
274struct GNUNET_JSON_PackSpec
275GNUNET_JSON_pack_timestamp_nbo (const char *name,
276 struct GNUNET_TIME_TimestampNBO at)
277{
278 return GNUNET_JSON_pack_timestamp (name,
279 GNUNET_TIME_timestamp_ntoh (at));
280}
281
282
283struct GNUNET_JSON_PackSpec
284GNUNET_JSON_pack_time_rel (const char *name,
285 struct GNUNET_TIME_Relative rt)
286{
287 json_t *json;
288
289 json = GNUNET_JSON_from_time_rel (rt);
290 GNUNET_assert (NULL != json);
291 return GNUNET_JSON_pack_object_steal (name,
292 json);
293}
294
295
296struct GNUNET_JSON_PackSpec
297GNUNET_JSON_pack_time_rel_nbo (const char *name,
298 struct GNUNET_TIME_RelativeNBO rt)
299{
300 return GNUNET_JSON_pack_time_rel (name,
301 GNUNET_TIME_relative_ntoh (rt));
302}
303
304
305struct GNUNET_JSON_PackSpec
306GNUNET_JSON_pack_rsa_public_key (const char *name,
307 const struct GNUNET_CRYPTO_RsaPublicKey *pk)
308{
309 struct GNUNET_JSON_PackSpec ps = {
310 .field_name = name,
311 .object = GNUNET_JSON_from_rsa_public_key (pk)
312 };
313
314 return ps;
315}
316
317
318struct GNUNET_JSON_PackSpec
319GNUNET_JSON_pack_rsa_signature (const char *name,
320 const struct GNUNET_CRYPTO_RsaSignature *sig)
321{
322 struct GNUNET_JSON_PackSpec ps = {
323 .field_name = name,
324 .object = GNUNET_JSON_from_rsa_signature (sig)
325 };
326
327 return ps;
328}
329
330
331/* end of json_pack.c */
diff --git a/src/json/test_json.c b/src/json/test_json.c
deleted file mode 100644
index d6c372cf3..000000000
--- a/src/json/test_json.c
+++ /dev/null
@@ -1,242 +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 }
145 return 0;
146}
147
148
149/**
150 * Test rsa conversions from/to JSON.
151 *
152 * @return 0 on success
153 */
154static int
155test_rsa ()
156{
157 struct GNUNET_CRYPTO_RsaPublicKey *pub;
158 struct GNUNET_CRYPTO_RsaPublicKey *pub2;
159 struct GNUNET_JSON_Specification pspec[] =
160 { GNUNET_JSON_spec_rsa_public_key (NULL, &pub2), GNUNET_JSON_spec_end () };
161 struct GNUNET_CRYPTO_RsaSignature *sig;
162 struct GNUNET_CRYPTO_RsaSignature *sig2;
163 struct GNUNET_JSON_Specification sspec[] =
164 { GNUNET_JSON_spec_rsa_signature (NULL, &sig2), GNUNET_JSON_spec_end () };
165 struct GNUNET_CRYPTO_RsaPrivateKey *priv;
166 struct GNUNET_HashCode msg;
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 memset (&msg, 42, sizeof(msg));
173 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv, &msg);
174 GNUNET_assert (NULL != (jp = GNUNET_JSON_from_rsa_public_key (pub)));
175 GNUNET_assert (NULL != (js = GNUNET_JSON_from_rsa_signature (sig)));
176 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (jp, pspec, NULL, NULL));
177 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (js, sspec, NULL, NULL));
178 GNUNET_break (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig2));
179 GNUNET_break (0 == GNUNET_CRYPTO_rsa_public_key_cmp (pub, pub2));
180 GNUNET_CRYPTO_rsa_signature_free (sig);
181 GNUNET_CRYPTO_rsa_signature_free (sig2);
182 GNUNET_CRYPTO_rsa_private_key_free (priv);
183 GNUNET_CRYPTO_rsa_public_key_free (pub);
184 GNUNET_CRYPTO_rsa_public_key_free (pub2);
185 return 0;
186}
187
188
189/**
190 * Test rsa conversions from/to JSON.
191 *
192 * @return 0 on success
193 */
194static int
195test_boolean ()
196{
197 int b1;
198 int b2;
199 json_t *json;
200 struct GNUNET_JSON_Specification pspec[] = { GNUNET_JSON_spec_boolean ("b1",
201 &b1),
202 GNUNET_JSON_spec_boolean ("b2",
203 &b2),
204 GNUNET_JSON_spec_end () };
205
206 json = json_object ();
207 json_object_set_new (json, "b1", json_true ());
208 json_object_set_new (json, "b2", json_false ());
209
210 GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (json, pspec, NULL, NULL));
211
212 GNUNET_assert (GNUNET_YES == b1);
213 GNUNET_assert (GNUNET_NO == b2);
214
215 json_object_set_new (json, "b1", json_integer (42));
216
217 GNUNET_assert (GNUNET_OK != GNUNET_JSON_parse (json, pspec, NULL, NULL));
218
219 return 0;
220}
221
222
223int
224main (int argc, const char *const argv[])
225{
226 GNUNET_log_setup ("test-json", "WARNING", NULL);
227 if (0 != test_timestamp ())
228 return 1;
229 if (0 != test_rel_time ())
230 return 1;
231 if (0 != test_raw ())
232 return 1;
233 if (0 != test_rsa ())
234 return 1;
235 if (0 != test_boolean ())
236 return 1;
237 /* FIXME: test EdDSA signature conversion... */
238 return 0;
239}
240
241
242/* 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 */