GNUnet  0.11.x
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_EXPIRATION_TIME "expiration_time"
35 #define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "private"
36 #define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "supplemental"
37 #define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "relative_expiration"
38 #define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "shadow"
39 #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
40 #define GNUNET_JSON_GNSRECORD_NEVER "never"
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_expiration_time;
86  struct GNUNET_TIME_Relative rel_expiration_time;
87  const char *value;
88  const char *record_type;
89  const char *expiration_time;
90  int private;
91  int supplemental;
92  int rel_exp;
93  int shadow;
94  int unpack_state = 0;
95 
96  // interpret single gns record
97  unpack_state = json_unpack (data,
98  "{s:s, s:s, s:s, s:b, s:b, s:b, s:b}",
100  &value,
102  &record_type,
104  &expiration_time,
106  &private,
108  &supplemental,
110  &rel_exp,
112  &shadow);
113  if (0 != unpack_state)
114  {
116  "Error gnsdata object has a wrong format!\n");
117  return GNUNET_SYSERR;
118  }
120  if (UINT32_MAX == rd->record_type)
121  {
122  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
123  return GNUNET_SYSERR;
124  }
126  value,
127  (void **) &rd->data,
128  &rd->data_size))
129  {
130  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
131  return GNUNET_SYSERR;
132  }
133 
134  if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
135  {
137  }
138  else if ((1 != rel_exp) &&
139  (GNUNET_OK ==
140  GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
141  &abs_expiration_time)))
142  {
143  rd->expiration_time = abs_expiration_time.abs_value_us;
144  }
145  else if (GNUNET_OK ==
146  GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
147  &rel_expiration_time))
148  {
150  rd->expiration_time = rel_expiration_time.rel_value_us;
151  }
152  else
153  {
154  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
155  return GNUNET_SYSERR;
156  }
157  if (1 == private)
159  if (1 == supplemental)
161  if (1 == shadow)
163  return GNUNET_OK;
164 }
165 
166 
175 static int
176 parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
177 {
178  GNUNET_assert (NULL != data);
179  if (! json_is_array (data))
180  {
182  "Error gns record data JSON is not an array!\n");
183  return GNUNET_SYSERR;
184  }
185  *(gnsrecord_info->rd_count) = json_array_size (data);
186  *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
187  * json_array_size (data));
188  size_t index;
189  json_t *value;
190  json_array_foreach (data, index, value)
191  {
192  if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
193  return GNUNET_SYSERR;
194  }
195  return GNUNET_OK;
196 }
197 
198 
199 static int
201  json_t *root,
202  struct GNUNET_JSON_Specification *spec)
203 {
204  struct GnsRecordInfo *gnsrecord_info;
205  int unpack_state = 0;
206  const char *name;
207  json_t *data;
208 
209  GNUNET_assert (NULL != root);
210  if (! json_is_object (root))
211  {
213  "Error record JSON is not an object!\n");
214  return GNUNET_SYSERR;
215  }
216  // interpret single gns record
217  unpack_state = json_unpack (root,
218  "{s:s, s:o!}",
220  &name,
222  &data);
223  if (0 != unpack_state)
224  {
226  "Error namestore records object has a wrong format!\n");
227  return GNUNET_SYSERR;
228  }
229  gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
230  *(gnsrecord_info->name) = GNUNET_strdup (name);
231  if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
232  {
233  cleanup_recordinfo (gnsrecord_info);
234  return GNUNET_SYSERR;
235  }
236  return GNUNET_OK;
237 }
238 
239 
246 static void
248 {
249  struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
250 
251  GNUNET_free (gnsrecord_info);
252 }
253 
254 
263  unsigned int *rd_count,
264  char **name)
265 {
266  struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
267 
268  gnsrecord_info->rd = rd;
269  gnsrecord_info->name = name;
270  gnsrecord_info->rd_count = rd_count;
272  .cleaner = &clean_gnsrecordobject,
273  .cls = NULL,
274  .field = NULL,
275  .ptr = (struct GnsRecordInfo *)
276  gnsrecord_info,
277  .ptr_size = 0,
278  .size_ptr = NULL };
279  return ret;
280 }
281 
282 
290 json_t *
292  const struct GNUNET_GNSRECORD_Data *rd,
293  unsigned int rd_count)
294 {
295  struct GNUNET_TIME_Absolute abs_exp;
296  struct GNUNET_TIME_Relative rel_exp;
297  const char *expiration_time_str;
298  const char *record_type_str;
299  char *value_str;
300  json_t *data;
301  json_t *record;
302  json_t *records;
303 
304  data = json_object ();
305  if (NULL == data)
306  {
307  GNUNET_break (0);
308  return NULL;
309  }
310  if (0 !=
311  json_object_set_new (data,
312  "record_name",
313  json_string (rname)))
314  {
315  GNUNET_break (0);
316  json_decref (data);
317  return NULL;
318  }
319  records = json_array ();
320  if (NULL == records)
321  {
322  GNUNET_break (0);
323  json_decref (data);
324  return NULL;
325  }
326  for (int i = 0; i < rd_count; i++)
327  {
328  value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
329  rd[i].data,
330  rd[i].data_size);
331  if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd[i].flags)
332  {
333  rel_exp.rel_value_us = rd[i].expiration_time;
334  expiration_time_str = GNUNET_STRINGS_relative_time_to_string (rel_exp,
335  GNUNET_NO);
336  }
337  else
338  {
339  abs_exp.abs_value_us = rd[i].expiration_time;
340  expiration_time_str = GNUNET_STRINGS_absolute_time_to_string (abs_exp);
341  }
342  record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
344  "Packing %s %s %s %d\n",
345  value_str, record_type_str, expiration_time_str, rd[i].flags);
346  record = json_pack ("{s:s,s:s,s:s,s:b,s:b,s:b,s:b}",
347  "value",
348  value_str,
349  "record_type",
350  record_type_str,
351  "expiration_time",
352  expiration_time_str,
353  "private",
354  rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE,
355  "relative_expiration",
357  "supplemental",
358  rd[i].flags & GNUNET_GNSRECORD_RF_SUPPLEMENTAL,
359  "shadow",
360  rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD);
361  GNUNET_free (value_str);
362  if (NULL == record)
363  {
364  GNUNET_break (0);
365  json_decref (records);
366  json_decref (data);
367  return NULL;
368  }
369  if (0 !=
370  json_array_append_new (records,
371  record))
372  {
373  GNUNET_break (0);
374  json_decref (records);
375  json_decref (data);
376  return NULL;
377  }
378  }
379  if (0 !=
380  json_object_set_new (data,
381  "data",
382  records))
383  {
384  GNUNET_break (0);
385  json_decref (data);
386  return NULL;
387  }
388  return data;
389 }
390 
391 
#define GNUNET_JSON_GNSRECORD_VALUE
#define GNUNET_JSON_GNSRECORD_RECORD_NAME
This record should not be used unless all (other) records with an absolute expiration time have expir...
#define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL
uint64_t rel_value_us
The actual value.
functions to parse JSON objects into GNUnet objects
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (i.e.
Definition: gnsrecord.c:220
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME
int GNUNET_STRINGS_fancy_time_to_relative(const char *fancy_time, struct GNUNET_TIME_Relative *rtime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:356
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
int GNUNET_STRINGS_fancy_time_to_absolute(const char *fancy_time, struct GNUNET_TIME_Absolute *atime)
Convert a given fancy human-readable time to our internal representation.
Definition: strings.c:407
This is a supplemental record.
static int parse_record_data(struct GnsRecordInfo *gnsrecord_info, json_t *data)
Parse given JSON object to gns record.
Entry in parser specification for GNUNET_JSON_parse().
size_t data_size
Number of bytes in data.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int records
Number of records we found.
static void cleanup_recordinfo(struct GnsRecordInfo *gnsrecord_info)
#define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE
static int parse_gnsrecordobject(void *cls, json_t *root, struct GNUNET_JSON_Specification *spec)
const void * data
Binary value stored in the DNS record.
static char * value
Value of the record to add/remove.
uint64_t expiration_time
Expiration time for the DNS record.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:702
This is a private record of this peer and it should thus not be handed out to other peers...
GNUNET_JSON_Parser parser
Function for how to parse this type of entry.
unsigned int * rd_count
int GNUNET_GNSRECORD_string_to_value(uint32_t type, const char *s, void **data, size_t *data_size)
Convert human-readable version of a &#39;value&#39; of a record to the binary representation.
Definition: gnsrecord.c:191
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.
void * ptr
Pointer, details specific to the parser.
#define GNUNET_JSON_GNSRECORD_TYPE
static int parse_record(json_t *data, struct GNUNET_GNSRECORD_Data *rd)
Parse given JSON object to gns record.
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.
uint32_t record_type
Type of the GNS/DNS record.
static void clean_gnsrecordobject(void *cls, struct GNUNET_JSON_Specification *spec)
Cleanup data left from parsing the record.
#define GNUNET_log(kind,...)
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_GNSRECORD_Data ** rd
#define GNUNET_JSON_GNSRECORD_NEVER
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This expiration time of the record is a relative time (not an absolute time).
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:758
#define GNUNET_JSON_GNSRECORD_RECORD_DATA
uint32_t data
The data value.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the &#39;value&#39; of a record to a string.
Definition: gnsrecord.c:159
const char * GNUNET_GNSRECORD_number_to_typename(uint32_t type)
Convert a type number (i.e.
Definition: gnsrecord.c:247
#define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
#define GNUNET_JSON_GNSRECORD_FLAG_SHADOW