json_gnsrecord.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2009-2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file json/json_gnsrecord.c
  18. * @brief JSON handling of GNS record data
  19. * @author Philippe Buschmann
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_json_lib.h"
  24. #define GNUNET_JSON_GNSRECORD_VALUE "value"
  25. #define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
  26. #define GNUNET_JSON_GNSRECORD_TYPE "record_type"
  27. #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
  28. #define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "private"
  29. #define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "supplemental"
  30. #define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "relative_expiration"
  31. #define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "shadow"
  32. #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
  33. #define GNUNET_JSON_GNSRECORD_NEVER "never"
  34. struct GnsRecordInfo
  35. {
  36. char **name;
  37. unsigned int *rd_count;
  38. struct GNUNET_GNSRECORD_Data **rd;
  39. };
  40. static void
  41. cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
  42. {
  43. char *tmp;
  44. if (NULL != *(gnsrecord_info->rd))
  45. {
  46. for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
  47. {
  48. tmp = (char*) (*(gnsrecord_info->rd))[i].data;
  49. if (NULL != tmp)
  50. GNUNET_free (tmp);
  51. }
  52. GNUNET_free (*(gnsrecord_info->rd));
  53. *(gnsrecord_info->rd) = NULL;
  54. }
  55. if (NULL != *(gnsrecord_info->name))
  56. GNUNET_free (*(gnsrecord_info->name));
  57. *(gnsrecord_info->name) = NULL;
  58. }
  59. /**
  60. * Parse given JSON object to gns record
  61. *
  62. * @param cls closure, NULL
  63. * @param root the json object representing data
  64. * @param spec where to write the data
  65. * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  66. */
  67. static int
  68. parse_record (json_t *data, struct GNUNET_GNSRECORD_Data *rd)
  69. {
  70. struct GNUNET_TIME_Absolute abs_expiration_time;
  71. struct GNUNET_TIME_Relative rel_expiration_time;
  72. const char *value;
  73. const char *record_type;
  74. const char *expiration_time;
  75. int private;
  76. int supplemental;
  77. int rel_exp;
  78. int shadow;
  79. int unpack_state = 0;
  80. // interpret single gns record
  81. unpack_state = json_unpack (data,
  82. "{s:s, s:s, s:s, s:b, s:b, s:b, s:b}",
  83. GNUNET_JSON_GNSRECORD_VALUE,
  84. &value,
  85. GNUNET_JSON_GNSRECORD_TYPE,
  86. &record_type,
  87. GNUNET_JSON_GNSRECORD_EXPIRATION_TIME,
  88. &expiration_time,
  89. GNUNET_JSON_GNSRECORD_FLAG_PRIVATE,
  90. &private,
  91. GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL,
  92. &supplemental,
  93. GNUNET_JSON_GNSRECORD_FLAG_RELATIVE,
  94. &rel_exp,
  95. GNUNET_JSON_GNSRECORD_FLAG_SHADOW,
  96. &shadow);
  97. if (0 != unpack_state)
  98. {
  99. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  100. "Error gnsdata object has a wrong format!\n");
  101. return GNUNET_SYSERR;
  102. }
  103. rd->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
  104. if (UINT32_MAX == rd->record_type)
  105. {
  106. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
  107. return GNUNET_SYSERR;
  108. }
  109. if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (rd->record_type,
  110. value,
  111. (void **) &rd->data,
  112. &rd->data_size))
  113. {
  114. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
  115. return GNUNET_SYSERR;
  116. }
  117. if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
  118. {
  119. rd->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
  120. }
  121. else if ((1 != rel_exp) &&
  122. (GNUNET_OK ==
  123. GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
  124. &abs_expiration_time)))
  125. {
  126. rd->expiration_time = abs_expiration_time.abs_value_us;
  127. }
  128. else if (GNUNET_OK ==
  129. GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
  130. &rel_expiration_time))
  131. {
  132. rd->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
  133. rd->expiration_time = rel_expiration_time.rel_value_us;
  134. }
  135. else
  136. {
  137. GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
  138. return GNUNET_SYSERR;
  139. }
  140. if (1 == private)
  141. rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
  142. if (1 == supplemental)
  143. rd->flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
  144. if (1 == shadow)
  145. rd->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
  146. return GNUNET_OK;
  147. }
  148. /**
  149. * Parse given JSON object to gns record
  150. *
  151. * @param cls closure, NULL
  152. * @param root the json object representing data
  153. * @param spec where to write the data
  154. * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  155. */
  156. static int
  157. parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
  158. {
  159. GNUNET_assert (NULL != data);
  160. if (! json_is_array (data))
  161. {
  162. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  163. "Error gns record data JSON is not an array!\n");
  164. return GNUNET_SYSERR;
  165. }
  166. *(gnsrecord_info->rd_count) = json_array_size (data);
  167. *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
  168. * json_array_size (data));
  169. size_t index;
  170. json_t *value;
  171. json_array_foreach (data, index, value)
  172. {
  173. if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
  174. return GNUNET_SYSERR;
  175. }
  176. return GNUNET_OK;
  177. }
  178. static int
  179. parse_gnsrecordobject (void *cls,
  180. json_t *root,
  181. struct GNUNET_JSON_Specification *spec)
  182. {
  183. struct GnsRecordInfo *gnsrecord_info;
  184. int unpack_state = 0;
  185. const char *name;
  186. json_t *data;
  187. GNUNET_assert (NULL != root);
  188. if (! json_is_object (root))
  189. {
  190. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  191. "Error record JSON is not an object!\n");
  192. return GNUNET_SYSERR;
  193. }
  194. // interpret single gns record
  195. unpack_state = json_unpack (root,
  196. "{s:s, s:o!}",
  197. GNUNET_JSON_GNSRECORD_RECORD_NAME,
  198. &name,
  199. GNUNET_JSON_GNSRECORD_RECORD_DATA,
  200. &data);
  201. if (0 != unpack_state)
  202. {
  203. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  204. "Error namestore records object has a wrong format!\n");
  205. return GNUNET_SYSERR;
  206. }
  207. gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
  208. *(gnsrecord_info->name) = GNUNET_strdup (name);
  209. if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
  210. {
  211. cleanup_recordinfo (gnsrecord_info);
  212. return GNUNET_SYSERR;
  213. }
  214. return GNUNET_OK;
  215. }
  216. /**
  217. * Cleanup data left from parsing the record.
  218. *
  219. * @param cls closure, NULL
  220. * @param[out] spec where to free the data
  221. */
  222. static void
  223. clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
  224. {
  225. struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
  226. GNUNET_free (gnsrecord_info);
  227. }
  228. /**
  229. * JSON Specification for GNS Records.
  230. *
  231. * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill
  232. * @return JSON Specification
  233. */
  234. struct GNUNET_JSON_Specification
  235. GNUNET_JSON_spec_gnsrecord (struct GNUNET_GNSRECORD_Data **rd,
  236. unsigned int *rd_count,
  237. char **name)
  238. {
  239. struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
  240. gnsrecord_info->rd = rd;
  241. gnsrecord_info->name = name;
  242. gnsrecord_info->rd_count = rd_count;
  243. struct GNUNET_JSON_Specification ret = { .parser = &parse_gnsrecordobject,
  244. .cleaner = &clean_gnsrecordobject,
  245. .cls = NULL,
  246. .field = NULL,
  247. .ptr = (struct GnsRecordInfo *)
  248. gnsrecord_info,
  249. .ptr_size = 0,
  250. .size_ptr = NULL };
  251. return ret;
  252. }