GNUnet  0.19.2
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"
29 #include "gnunet_gnsrecord_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_PRIVATE "is_private"
37 #define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "is_supplemental"
38 #define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "is_relative_expiration"
39 #define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "is_shadow"
40 #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
41 
43 {
44  char **name;
45 
46  unsigned int *rd_count;
47 
49 };
50 
51 
52 static void
53 cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
54 {
55  char *tmp;
56 
57  if (NULL != *(gnsrecord_info->rd))
58  {
59  for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
60  {
61  tmp = (char*) (*(gnsrecord_info->rd))[i].data;
62  if (NULL != tmp)
63  GNUNET_free (tmp);
64  }
65  GNUNET_free (*(gnsrecord_info->rd));
66  *(gnsrecord_info->rd) = NULL;
67  }
68  if (NULL != *(gnsrecord_info->name))
69  GNUNET_free (*(gnsrecord_info->name));
70  *(gnsrecord_info->name) = NULL;
71 }
72 
73 
82 static int
84 {
85  struct GNUNET_TIME_Absolute abs_exp;
86  struct GNUNET_TIME_Relative rel_exp;
87  const char *value;
88  const char *record_type;
89  int private;
90  int supplemental;
91  int is_rel_exp;
92  int shadow;
93  int unpack_state = 0;
94  json_error_t err;
95 
96  // interpret single gns record
97  unpack_state = json_unpack_ex (data,
98  &err,
99  0,
100  "{s:s, s:s, s:I, s:b, s:b, s:b, s:b}",
102  &value,
104  &record_type,
106  &rel_exp.rel_value_us,
108  &private,
110  &supplemental,
112  &is_rel_exp,
114  &shadow);
115  if (0 != unpack_state)
116  {
118  "Error gnsdata object has a wrong format: `%s'!\n",
119  err.text);
120  unpack_state = json_unpack_ex (data,
121  &err,
122  0,
123  "{s:s, s:s, s:I, s:b, s:b, s:b, s:b}",
125  &value,
127  &record_type,
129  &abs_exp.abs_value_us,
131  &private,
133  &supplemental,
135  &is_rel_exp,
137  &shadow);
138  if ((0 != unpack_state) || (is_rel_exp))
139  {
141  "Error gnsdata object has a wrong format: `%s'!\n",
142  (is_rel_exp) ? "No relative expiration given" : err.text);
143  return GNUNET_SYSERR;
144  }
145  rd->expiration_time = abs_exp.abs_value_us;
146  } else {
147  rd->expiration_time = rel_exp.rel_value_us;
148  }
150  if (UINT32_MAX == rd->record_type)
151  {
152  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
153  return GNUNET_SYSERR;
154  }
156  value,
157  (void **) &rd->data,
158  &rd->data_size))
159  {
160  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
161  return GNUNET_SYSERR;
162  }
163 
164  if (is_rel_exp)
166  if (1 == private)
168  if (1 == supplemental)
170  if (1 == shadow)
172  return GNUNET_OK;
173 }
174 
175 
184 static int
185 parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
186 {
187  GNUNET_assert (NULL != data);
188  if (! json_is_array (data))
189  {
191  "Error gns record data JSON is not an array!\n");
192  return GNUNET_SYSERR;
193  }
194  *(gnsrecord_info->rd_count) = json_array_size (data);
195  *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
196  * json_array_size (data));
197  size_t index;
198  json_t *value;
199  json_array_foreach (data, index, value)
200  {
201  if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
202  return GNUNET_SYSERR;
203  }
204  return GNUNET_OK;
205 }
206 
207 
208 static int
210  json_t *root,
211  struct GNUNET_JSON_Specification *spec)
212 {
213  struct GnsRecordInfo *gnsrecord_info;
214  int unpack_state = 0;
215  const char *name;
216  json_t *data;
217 
218  GNUNET_assert (NULL != root);
219  if (! json_is_object (root))
220  {
222  "Error record JSON is not an object!\n");
223  return GNUNET_SYSERR;
224  }
225  // interpret single gns record
226  unpack_state = json_unpack (root,
227  "{s:s, s:o!}",
229  &name,
231  &data);
232  if (0 != unpack_state)
233  {
235  "Error namestore records object has a wrong format!\n");
236  return GNUNET_SYSERR;
237  }
238  gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
239  *(gnsrecord_info->name) = GNUNET_strdup (name);
240  if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
241  {
242  cleanup_recordinfo (gnsrecord_info);
243  return GNUNET_SYSERR;
244  }
245  return GNUNET_OK;
246 }
247 
248 
255 static void
257 {
258  struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
259 
260  GNUNET_free (gnsrecord_info);
261 }
262 
263 
272  unsigned int *rd_count,
273  char **name)
274 {
275  struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
276 
277  gnsrecord_info->rd = rd;
278  gnsrecord_info->name = name;
279  gnsrecord_info->rd_count = rd_count;
281  .cleaner = &clean_gnsrecordobject,
282  .cls = NULL,
283  .field = NULL,
284  .ptr = (struct GnsRecordInfo *)
285  gnsrecord_info,
286  .ptr_size = 0,
287  .size_ptr = NULL };
288  return ret;
289 }
290 
291 
299 json_t *
301  const struct GNUNET_GNSRECORD_Data *rd,
302  unsigned int rd_count)
303 {
304  const char *record_type_str;
305  char *value_str;
306  json_t *data;
307  json_t *record;
308  json_t *records;
309 
310  data = json_object ();
311  if (NULL == data)
312  {
313  GNUNET_break (0);
314  return NULL;
315  }
316  if (0 !=
317  json_object_set_new (data,
318  "record_name",
319  json_string (rname)))
320  {
321  GNUNET_break (0);
322  json_decref (data);
323  return NULL;
324  }
325  records = json_array ();
326  if (NULL == records)
327  {
328  GNUNET_break (0);
329  json_decref (data);
330  return NULL;
331  }
332  for (int i = 0; i < rd_count; i++)
333  {
334  value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
335  rd[i].data,
336  rd[i].data_size);
337  record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
339  "Packing %s %s %lu %d\n",
340  value_str, record_type_str, rd[i].expiration_time, rd[i].flags);
341  record = json_pack ("{s:s,s:s,s:I,s:b,s:b,s:b,s:b}",
343  value_str,
345  record_type_str,
348  rd[i].expiration_time,
350  rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE,
356  rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW);
357  GNUNET_free (value_str);
358  if (NULL == record)
359  {
360  GNUNET_break (0);
361  json_decref (records);
362  json_decref (data);
363  return NULL;
364  }
365  if (0 !=
366  json_array_append_new (records,
367  record))
368  {
369  GNUNET_break (0);
370  json_decref (records);
371  json_decref (data);
372  return NULL;
373  }
374  }
375  if (0 !=
376  json_object_set_new (data,
377  "data",
378  records))
379  {
380  GNUNET_break (0);
381  json_decref (data);
382  return NULL;
383  }
384  return data;
385 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
uint32_t data
The data value.
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 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
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
@ 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_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.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
Definition: gnsrecord.c:155
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.
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.
#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_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
const char * name
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