GNUnet 0.21.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"
30
31#define GNUNET_JSON_GNSRECORD_VALUE "value"
32#define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
33#define GNUNET_JSON_GNSRECORD_TYPE "record_type"
34#define GNUNET_JSON_GNSRECORD_RELATIVE_EXPIRATION_TIME "relative_expiration"
35#define GNUNET_JSON_GNSRECORD_ABSOLUTE_EXPIRATION_TIME "absolute_expiration"
36#define GNUNET_JSON_GNSRECORD_FLAG_MAINTENANCE "is_maintenance"
37#define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "is_private"
38#define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "is_supplemental"
39#define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "is_relative_expiration"
40#define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "is_shadow"
41#define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
42
44{
45 char **name;
46
47 unsigned int *rd_count;
48
50};
51
52
53static void
54cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
55{
56 char *tmp;
57
58 if (NULL != *(gnsrecord_info->rd))
59 {
60 for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
61 {
62 tmp = (char*) (*(gnsrecord_info->rd))[i].data;
63 if (NULL != tmp)
64 GNUNET_free (tmp);
65 }
66 GNUNET_free (*(gnsrecord_info->rd));
67 *(gnsrecord_info->rd) = NULL;
68 }
69 if (NULL != *(gnsrecord_info->name))
70 GNUNET_free (*(gnsrecord_info->name));
71 *(gnsrecord_info->name) = NULL;
72}
73
74
83static int
85{
86 struct GNUNET_TIME_Absolute abs_exp;
87 struct GNUNET_TIME_Relative rel_exp;
88 const char *value;
89 const char *record_type;
90 int maintenance;
91 int private;
92 int supplemental;
93 int is_rel_exp;
94 int shadow;
95 int unpack_state = 0;
96 json_error_t err;
97
98 // interpret single gns record
99 unpack_state = json_unpack_ex (data,
100 &err,
101 0,
102 "{s:s, s:s, s:I, s:b, s:b, s:b, s:b}",
104 &value,
106 &record_type,
108 &rel_exp.rel_value_us,
110 &maintenance,
112 &private,
114 &supplemental,
116 &is_rel_exp,
118 &shadow);
119 if (0 != unpack_state)
120 {
122 "Error gnsdata object has a wrong format: `%s'!\n",
123 err.text);
124 unpack_state = json_unpack_ex (data,
125 &err,
126 0,
127 "{s:s, s:s, s:I, s:b, s:b, s:b, s:b}",
129 &value,
131 &record_type,
133 &abs_exp.abs_value_us,
135 &maintenance,
137 &private,
139 &supplemental,
141 &is_rel_exp,
143 &shadow);
144 if ((0 != unpack_state) || (is_rel_exp))
145 {
147 "Error gnsdata object has a wrong format: `%s'!\n",
148 (is_rel_exp) ? "No relative expiration given" : err.text);
149 return GNUNET_SYSERR;
150 }
152 }
153 else
154 {
156 }
158 if (UINT32_MAX == rd->record_type)
159 {
160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
161 return GNUNET_SYSERR;
162 }
164 value,
165 (void **) &rd->data,
166 &rd->data_size))
167 {
168 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
169 return GNUNET_SYSERR;
170 }
171
172 if (is_rel_exp)
174 if (1 == maintenance)
176 if (1 == private)
178 if (1 == supplemental)
180 if (1 == shadow)
182 return GNUNET_OK;
183}
184
185
194static int
195parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
196{
197 GNUNET_assert (NULL != data);
198 if (! json_is_array (data))
199 {
201 "Error gns record data JSON is not an array!\n");
202 return GNUNET_SYSERR;
203 }
204 *(gnsrecord_info->rd_count) = json_array_size (data);
205 *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
206 * json_array_size (data));
207 size_t index;
208 json_t *value;
209 json_array_foreach (data, index, value)
210 {
211 if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
212 return GNUNET_SYSERR;
213 }
214 return GNUNET_OK;
215}
216
217
218static int
220 json_t *root,
221 struct GNUNET_JSON_Specification *spec)
222{
223 struct GnsRecordInfo *gnsrecord_info;
224 int unpack_state = 0;
225 const char *name;
226 json_t *data;
227
228 GNUNET_assert (NULL != root);
229 if (! json_is_object (root))
230 {
232 "Error record JSON is not an object!\n");
233 return GNUNET_SYSERR;
234 }
235 // interpret single gns record
236 unpack_state = json_unpack (root,
237 "{s:s, s:o!}",
239 &name,
241 &data);
242 if (0 != unpack_state)
243 {
245 "Error namestore records object has a wrong format!\n");
246 return GNUNET_SYSERR;
247 }
248 gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
249 *(gnsrecord_info->name) = GNUNET_strdup (name);
250 if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
251 {
252 cleanup_recordinfo (gnsrecord_info);
253 return GNUNET_SYSERR;
254 }
255 return GNUNET_OK;
256}
257
258
265static void
267{
268 struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
269
270 GNUNET_free (gnsrecord_info);
271}
272
273
282 unsigned int *rd_count,
283 char **name)
284{
285 struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
286
287 gnsrecord_info->rd = rd;
288 gnsrecord_info->name = name;
289 gnsrecord_info->rd_count = rd_count;
291 .cleaner = &clean_gnsrecordobject,
292 .cls = NULL,
293 .field = NULL,
294 .ptr = (struct GnsRecordInfo *)
295 gnsrecord_info,
296 .ptr_size = 0,
297 .size_ptr = NULL };
298 return ret;
299}
300
301
309json_t *
311 const struct GNUNET_GNSRECORD_Data *rd,
312 unsigned int rd_count)
313{
314 const char *record_type_str;
315 char *value_str;
316 json_t *data;
317 json_t *record;
318 json_t *records;
319
320 data = json_object ();
321 if (NULL == data)
322 {
323 GNUNET_break (0);
324 return NULL;
325 }
326 if (0 !=
327 json_object_set_new (data,
328 "record_name",
329 json_string (rname)))
330 {
331 GNUNET_break (0);
332 json_decref (data);
333 return NULL;
334 }
335 records = json_array ();
336 if (NULL == records)
337 {
338 GNUNET_break (0);
339 json_decref (data);
340 return NULL;
341 }
342 for (int i = 0; i < rd_count; i++)
343 {
344 value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
345 rd[i].data,
346 rd[i].data_size);
347 record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
349 "Packing %s %s %" PRIu64 " %d\n",
350 value_str, record_type_str, rd[i].expiration_time, rd[i].flags);
351 record = json_pack (
352 "{s:s,s:s,s:I,s:b,s:b,s:b,s:b, s:b}",
354 GNUNET_JSON_GNSRECORD_TYPE, record_type_str,
358 rd[i].expiration_time,
368 rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW);
369 GNUNET_free (value_str);
370 if (NULL == record)
371 {
372 GNUNET_break (0);
373 json_decref (records);
374 json_decref (data);
375 return NULL;
376 }
377 if (0 !=
378 json_array_append_new (records,
379 record))
380 {
381 GNUNET_break (0);
382 json_decref (records);
383 json_decref (data);
384 return NULL;
385 }
386 }
387 if (0 !=
388 json_object_set_new (data,
389 "data",
390 records))
391 {
392 GNUNET_break (0);
393 json_decref (data);
394 return NULL;
395 }
396 return data;
397}
static int ret
Final status code.
Definition: gnunet-arm.c:94
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 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