GNUnet  0.21.0
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  }
147  else
148  {
149  rd->expiration_time = rel_exp.rel_value_us;
150  }
152  if (UINT32_MAX == rd->record_type)
153  {
154  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
155  return GNUNET_SYSERR;
156  }
158  value,
159  (void **) &rd->data,
160  &rd->data_size))
161  {
162  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
163  return GNUNET_SYSERR;
164  }
165 
166  if (is_rel_exp)
168  if (1 == private)
170  if (1 == supplemental)
172  if (1 == shadow)
174  return GNUNET_OK;
175 }
176 
177 
186 static int
187 parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
188 {
189  GNUNET_assert (NULL != data);
190  if (! json_is_array (data))
191  {
193  "Error gns record data JSON is not an array!\n");
194  return GNUNET_SYSERR;
195  }
196  *(gnsrecord_info->rd_count) = json_array_size (data);
197  *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
198  * json_array_size (data));
199  size_t index;
200  json_t *value;
201  json_array_foreach (data, index, value)
202  {
203  if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
204  return GNUNET_SYSERR;
205  }
206  return GNUNET_OK;
207 }
208 
209 
210 static int
212  json_t *root,
213  struct GNUNET_JSON_Specification *spec)
214 {
215  struct GnsRecordInfo *gnsrecord_info;
216  int unpack_state = 0;
217  const char *name;
218  json_t *data;
219 
220  GNUNET_assert (NULL != root);
221  if (! json_is_object (root))
222  {
224  "Error record JSON is not an object!\n");
225  return GNUNET_SYSERR;
226  }
227  // interpret single gns record
228  unpack_state = json_unpack (root,
229  "{s:s, s:o!}",
231  &name,
233  &data);
234  if (0 != unpack_state)
235  {
237  "Error namestore records object has a wrong format!\n");
238  return GNUNET_SYSERR;
239  }
240  gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
241  *(gnsrecord_info->name) = GNUNET_strdup (name);
242  if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
243  {
244  cleanup_recordinfo (gnsrecord_info);
245  return GNUNET_SYSERR;
246  }
247  return GNUNET_OK;
248 }
249 
250 
257 static void
259 {
260  struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
261 
262  GNUNET_free (gnsrecord_info);
263 }
264 
265 
274  unsigned int *rd_count,
275  char **name)
276 {
277  struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
278 
279  gnsrecord_info->rd = rd;
280  gnsrecord_info->name = name;
281  gnsrecord_info->rd_count = rd_count;
283  .cleaner = &clean_gnsrecordobject,
284  .cls = NULL,
285  .field = NULL,
286  .ptr = (struct GnsRecordInfo *)
287  gnsrecord_info,
288  .ptr_size = 0,
289  .size_ptr = NULL };
290  return ret;
291 }
292 
293 
301 json_t *
303  const struct GNUNET_GNSRECORD_Data *rd,
304  unsigned int rd_count)
305 {
306  const char *record_type_str;
307  char *value_str;
308  json_t *data;
309  json_t *record;
310  json_t *records;
311 
312  data = json_object ();
313  if (NULL == data)
314  {
315  GNUNET_break (0);
316  return NULL;
317  }
318  if (0 !=
319  json_object_set_new (data,
320  "record_name",
321  json_string (rname)))
322  {
323  GNUNET_break (0);
324  json_decref (data);
325  return NULL;
326  }
327  records = json_array ();
328  if (NULL == records)
329  {
330  GNUNET_break (0);
331  json_decref (data);
332  return NULL;
333  }
334  for (int i = 0; i < rd_count; i++)
335  {
336  value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
337  rd[i].data,
338  rd[i].data_size);
339  record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
341  "Packing %s %s %" PRIu64 " %d\n",
342  value_str, record_type_str, rd[i].expiration_time, rd[i].flags);
343  record = json_pack ("{s:s,s:s,s:I,s:b,s:b,s:b,s:b}",
345  value_str,
347  record_type_str,
348  (rd[i].flags
352  rd[i].expiration_time,
354  rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE,
360  rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW);
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 }
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
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
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
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.
@ 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.
#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
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