GNUnet 0.22.1
json_gnsrecord.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 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
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_json_lib.h"
31
32#define GNUNET_JSON_GNSRECORD_VALUE "value"
33#define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
34#define GNUNET_JSON_GNSRECORD_TYPE "record_type"
35#define GNUNET_JSON_GNSRECORD_RELATIVE_EXPIRATION_TIME "relative_expiration"
36#define GNUNET_JSON_GNSRECORD_ABSOLUTE_EXPIRATION_TIME "absolute_expiration"
37#define GNUNET_JSON_GNSRECORD_FLAG_MAINTENANCE "is_maintenance"
38#define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "is_private"
39#define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "is_supplemental"
40#define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "is_relative_expiration"
41#define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "is_shadow"
42#define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
43
45{
46 char **name;
47
48 unsigned int *rd_count;
49
51};
52
53
54static void
55cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
56{
57 char *tmp;
58
59 if (NULL != *(gnsrecord_info->rd))
60 {
61 for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
62 {
63 tmp = (char*) (*(gnsrecord_info->rd))[i].data;
64 if (NULL != tmp)
65 GNUNET_free (tmp);
66 }
67 GNUNET_free (*(gnsrecord_info->rd));
68 *(gnsrecord_info->rd) = NULL;
69 }
70 if (NULL != *(gnsrecord_info->name))
71 GNUNET_free (*(gnsrecord_info->name));
72 *(gnsrecord_info->name) = NULL;
73}
74
75
84static int
86{
87 struct GNUNET_TIME_Absolute abs_exp;
88 struct GNUNET_TIME_Relative rel_exp;
89 const char *value;
90 const char *record_type;
91 int maintenance;
92 int private;
93 int supplemental;
94 int is_rel_exp;
95 int shadow;
96 int unpack_state = 0;
97 json_error_t err;
98
99 // interpret single gns record
100 unpack_state = json_unpack_ex (data,
101 &err,
102 0,
103 "{s:s, s:s, s:I, s:b, s:b, s:b, s:b, s:b}",
105 &value,
107 &record_type,
109 &rel_exp.rel_value_us,
111 &maintenance,
113 &private,
115 &supplemental,
117 &is_rel_exp,
119 &shadow);
120 if (0 != unpack_state)
121 {
123 "Error gnsdata object has a wrong format: `%s'!\n",
124 err.text);
125 unpack_state = json_unpack_ex (data,
126 &err,
127 0,
128 "{s:s, s:s, s:I, s:b, s:b, s:b, s:b, s:b}",
130 &value,
132 &record_type,
134 &abs_exp.abs_value_us,
136 &maintenance,
138 &private,
140 &supplemental,
142 &is_rel_exp,
144 &shadow);
145 if ((0 != unpack_state) || (is_rel_exp))
146 {
148 "Error gnsdata object has a wrong format: `%s'!\n",
149 (is_rel_exp) ? "No relative expiration given" : err.text);
150 return GNUNET_SYSERR;
151 }
153 }
154 else
155 {
157 }
159 if (UINT32_MAX == rd->record_type)
160 {
161 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
162 return GNUNET_SYSERR;
163 }
165 value,
166 (void **) &rd->data,
167 &rd->data_size))
168 {
169 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
170 return GNUNET_SYSERR;
171 }
172
173 if (is_rel_exp)
175 if (1 == maintenance)
177 if (1 == private)
179 if (1 == supplemental)
181 if (1 == shadow)
183 return GNUNET_OK;
184}
185
186
195static int
196parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
197{
198 GNUNET_assert (NULL != data);
199 if (! json_is_array (data))
200 {
202 "Error gns record data JSON is not an array!\n");
203 return GNUNET_SYSERR;
204 }
205 *(gnsrecord_info->rd_count) = json_array_size (data);
206 *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
207 * json_array_size (data));
208 {
209 size_t index;
210 json_t *value;
211 json_array_foreach (data, index, value)
212 {
213 if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
214 return GNUNET_SYSERR;
215 }
216 }
217 return GNUNET_OK;
218}
219
220
221static int
223 json_t *root,
224 struct GNUNET_JSON_Specification *spec)
225{
226 struct GnsRecordInfo *gnsrecord_info;
227 int unpack_state = 0;
228 const char *name;
229 json_t *data;
230
231 GNUNET_assert (NULL != root);
232 if (! json_is_object (root))
233 {
235 "Error record JSON is not an object!\n");
236 return GNUNET_SYSERR;
237 }
238 // interpret single gns record
239 unpack_state = json_unpack (root,
240 "{s:s, s:o!}",
242 &name,
244 &data);
245 if (0 != unpack_state)
246 {
248 "Error namestore records object has a wrong format!\n");
249 return GNUNET_SYSERR;
250 }
251 gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
252 *(gnsrecord_info->name) = GNUNET_strdup (name);
253 if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
254 {
255 cleanup_recordinfo (gnsrecord_info);
256 return GNUNET_SYSERR;
257 }
258 return GNUNET_OK;
259}
260
261
268static void
270{
271 struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
272
273 GNUNET_free (gnsrecord_info);
274}
275
276
285 unsigned int *rd_count,
286 char **name)
287{
288 struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
290 .cleaner = &clean_gnsrecordobject,
291 .cls = NULL,
292 .field = NULL,
293 .ptr = (struct GnsRecordInfo *)
294 gnsrecord_info,
295 .ptr_size = 0,
296 .size_ptr = NULL };
297
298 gnsrecord_info->rd = rd;
299 gnsrecord_info->name = name;
300 gnsrecord_info->rd_count = rd_count;
301 return ret;
302}
303
304
312json_t *
314 const struct GNUNET_GNSRECORD_Data *rd,
315 unsigned int rd_count)
316{
317 const char *record_type_str;
318 char *value_str;
319 json_t *data;
320 json_t *record;
321 json_t *records;
322
323 data = json_object ();
324 if (NULL == data)
325 {
326 GNUNET_break (0);
327 return NULL;
328 }
329 if (0 !=
330 json_object_set_new (data,
331 "record_name",
332 json_string (rname)))
333 {
334 GNUNET_break (0);
335 json_decref (data);
336 return NULL;
337 }
338 records = json_array ();
339 if (NULL == records)
340 {
341 GNUNET_break (0);
342 json_decref (data);
343 return NULL;
344 }
345 for (int i = 0; i < rd_count; i++)
346 {
347 value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
348 rd[i].data,
349 rd[i].data_size);
350 record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
352 "Packing %s %s %" PRIu64 " %d\n",
353 value_str, record_type_str, rd[i].expiration_time, rd[i].flags);
354 record = json_pack (
355 "{s:s, s:s, s:I, s:b, s:b, s:b, s:b, s:b}",
357 GNUNET_JSON_GNSRECORD_TYPE, record_type_str,
361 rd[i].expiration_time,
371 rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW);
372 GNUNET_free (value_str);
373 if (NULL == record)
374 {
375 GNUNET_break (0);
376 json_decref (records);
377 json_decref (data);
378 return NULL;
379 }
380 if (0 !=
381 json_array_append_new (records,
382 record))
383 {
384 GNUNET_break (0);
385 json_decref (records);
386 json_decref (data);
387 return NULL;
388 }
389 }
390 if (0 !=
391 json_object_set_new (data,
392 "data",
393 records))
394 {
395 GNUNET_break (0);
396 json_decref (data);
397 return NULL;
398 }
399 return data;
400}
static int ret
Final status code.
Definition: gnunet-arm.c:93
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * data
The data to insert into the dht.
static char * name
Name (label) of the records to list.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char * value
Value of the record to add/remove.
static size_t data_size
Number of bytes in data.
static unsigned int records
Number of records we found.
API that can be used to manipulate JSON GNS record data.
API that can be used to manipulate GNS record data.
functions to parse JSON objects into GNUnet objects
json_t * GNUNET_GNSRECORD_JSON_from_gnsrecord(const char *rname, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Convert GNS record to JSON.
const char * GNUNET_GNSRECORD_number_to_typename(uint32_t type)
Convert a type number to the corresponding type string (e.g.
Definition: gnsrecord.c:227
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (e.g.
Definition: gnsrecord.c:200
int GNUNET_GNSRECORD_string_to_value(uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of the value s of a record of type type to the respective binary repre...
Definition: gnsrecord.c:177
struct GNUNET_JSON_Specification GNUNET_GNSRECORD_JSON_spec_gnsrecord(struct GNUNET_GNSRECORD_Data **rd, unsigned int *rd_count, char **name)
JSON Specification for GNS Records.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the binary value data of a record of type type to a human-readable string.
Definition: gnsrecord.c:155
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_SUPPLEMENTAL
This is a supplemental record.
@ GNUNET_GNSRECORD_RF_MAINTENANCE
Maintenance records.
@ GNUNET_GNSRECORD_RF_SHADOW
This record should not be used unless all (other) records in the set with an absolute expiration time...
@ GNUNET_GNSRECORD_RF_PRIVATE
This is a private record of this peer and it should thus not be published.
#define GNUNET_log(kind,...)
@ GNUNET_OK
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_JSON_GNSRECORD_FLAG_SHADOW
static int parse_record_data(struct GnsRecordInfo *gnsrecord_info, json_t *data)
Parse given JSON object to gns record.
#define GNUNET_JSON_GNSRECORD_VALUE
#define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE
#define GNUNET_JSON_GNSRECORD_FLAG_MAINTENANCE
#define GNUNET_JSON_GNSRECORD_ABSOLUTE_EXPIRATION_TIME
#define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL
static void clean_gnsrecordobject(void *cls, struct GNUNET_JSON_Specification *spec)
Cleanup data left from parsing the record.
#define GNUNET_JSON_GNSRECORD_RELATIVE_EXPIRATION_TIME
#define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE
static int parse_record(json_t *data, struct GNUNET_GNSRECORD_Data *rd)
Parse given JSON object to gns record.
#define GNUNET_JSON_GNSRECORD_RECORD_NAME
#define GNUNET_JSON_GNSRECORD_TYPE
static int parse_gnsrecordobject(void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
static void cleanup_recordinfo(struct GnsRecordInfo *gnsrecord_info)
#define GNUNET_JSON_GNSRECORD_RECORD_DATA
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
Entry in parser specification for GNUNET_JSON_parse().
void * ptr
Pointer, details specific to the parser.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
struct GNUNET_GNSRECORD_Data ** rd
unsigned int * rd_count