aboutsummaryrefslogtreecommitdiff
path: root/src/lib/json/json_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/json/json_helper.c')
-rw-r--r--src/lib/json/json_helper.c1182
1 files changed, 1182 insertions, 0 deletions
diff --git a/src/lib/json/json_helper.c b/src/lib/json/json_helper.c
new file mode 100644
index 000000000..4795285f4
--- /dev/null
+++ b/src/lib/json/json_helper.c
@@ -0,0 +1,1182 @@
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 */