2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file json/json_gnsrecord.c
23 * @brief JSON handling of GNS record data
24 * @author Philippe Buschmann
27 #include "gnunet_util_lib.h"
28 #include "gnunet_json_lib.h"
30 #define GNUNET_JSON_GNSRECORD_VALUE "value"
31 #define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
32 #define GNUNET_JSON_GNSRECORD_TYPE "record_type"
33 #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
34 #define GNUNET_JSON_GNSRECORD_FLAG "flag"
35 #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
36 #define GNUNET_JSON_GNSRECORD_NEVER "never"
42 unsigned int *rd_count;
44 struct GNUNET_GNSRECORD_Data **rd;
49 cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
51 if (NULL != *(gnsrecord_info->rd))
53 for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
55 if (NULL != (*(gnsrecord_info->rd))[i].data)
56 GNUNET_free ((char *) (*(gnsrecord_info->rd))[i].data);
58 GNUNET_free (*(gnsrecord_info->rd));
59 *(gnsrecord_info->rd) = NULL;
61 if (NULL != *(gnsrecord_info->name))
62 GNUNET_free (*(gnsrecord_info->name));
63 *(gnsrecord_info->name) = NULL;
68 * Parse given JSON object to gns record
70 * @param cls closure, NULL
71 * @param root the json object representing data
72 * @param spec where to write the data
73 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
76 parse_record (json_t *data, struct GNUNET_GNSRECORD_Data *rd)
78 struct GNUNET_TIME_Absolute abs_expiration_time;
79 struct GNUNET_TIME_Relative rel_expiration_time;
81 const char *record_type;
82 const char *expiration_time;
86 // interpret single gns record
87 unpack_state = json_unpack (data,
88 "{s:s, s:s, s:s, s?:i!}",
89 GNUNET_JSON_GNSRECORD_VALUE,
91 GNUNET_JSON_GNSRECORD_TYPE,
93 GNUNET_JSON_GNSRECORD_EXPIRATION_TIME,
95 GNUNET_JSON_GNSRECORD_FLAG,
97 if (0 != unpack_state)
99 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
100 "Error gnsdata object has a wrong format!\n");
101 return GNUNET_SYSERR;
103 rd->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
104 if (UINT32_MAX == rd->record_type)
106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
107 return GNUNET_SYSERR;
109 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (rd->record_type,
114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
115 return GNUNET_SYSERR;
118 if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
120 rd->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
122 else if (GNUNET_OK ==
123 GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
124 &abs_expiration_time))
126 rd->expiration_time = abs_expiration_time.abs_value_us;
128 else if (GNUNET_OK ==
129 GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
130 &rel_expiration_time))
132 rd->expiration_time = rel_expiration_time.rel_value_us;
136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
137 return GNUNET_SYSERR;
139 rd->flags = (enum GNUNET_GNSRECORD_Flags) flag;
145 * Parse given JSON object to gns record
147 * @param cls closure, NULL
148 * @param root the json object representing data
149 * @param spec where to write the data
150 * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
153 parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
155 GNUNET_assert (NULL != data);
156 if (! json_is_array (data))
158 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
159 "Error gns record data JSON is not an array!\n");
160 return GNUNET_SYSERR;
162 *(gnsrecord_info->rd_count) = json_array_size (data);
163 *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
164 * json_array_size (data));
167 json_array_foreach (data, index, value)
169 if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
170 return GNUNET_SYSERR;
177 parse_gnsrecordobject (void *cls,
179 struct GNUNET_JSON_Specification *spec)
181 struct GnsRecordInfo *gnsrecord_info;
182 int unpack_state = 0;
186 GNUNET_assert (NULL != root);
187 if (! json_is_object (root))
189 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
190 "Error record JSON is not an object!\n");
191 return GNUNET_SYSERR;
193 // interpret single gns record
194 unpack_state = json_unpack (root,
196 GNUNET_JSON_GNSRECORD_RECORD_NAME,
198 GNUNET_JSON_GNSRECORD_RECORD_DATA,
200 if (0 != unpack_state)
202 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
203 "Error namestore records object has a wrong format!\n");
204 return GNUNET_SYSERR;
206 gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
207 *(gnsrecord_info->name) = GNUNET_strdup (name);
208 if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
210 cleanup_recordinfo (gnsrecord_info);
211 return GNUNET_SYSERR;
218 * Cleanup data left from parsing the record.
220 * @param cls closure, NULL
221 * @param[out] spec where to free the data
224 clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
226 struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
228 GNUNET_free (gnsrecord_info);
233 * JSON Specification for GNS Records.
235 * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill
236 * @return JSON Specification
238 struct GNUNET_JSON_Specification
239 GNUNET_JSON_spec_gnsrecord (struct GNUNET_GNSRECORD_Data **rd,
240 unsigned int *rd_count,
243 struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
245 gnsrecord_info->rd = rd;
246 gnsrecord_info->name = name;
247 gnsrecord_info->rd_count = rd_count;
248 struct GNUNET_JSON_Specification ret = { .parser = &parse_gnsrecordobject,
249 .cleaner = &clean_gnsrecordobject,
252 .ptr = (struct GnsRecordInfo *)