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 
30 #define GNUNET_JSON_GNSRECORD_VALUE "value"
31 #define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
32 #define GNUNET_JSON_GNSRECORD_TYPE "record_type"
33 #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
34 #define GNUNET_JSON_GNSRECORD_FLAG_PRIVATE "private"
35 #define GNUNET_JSON_GNSRECORD_FLAG_SUPPLEMENTAL "supplemental"
36 #define GNUNET_JSON_GNSRECORD_FLAG_RELATIVE "relative_expiration"
37 #define GNUNET_JSON_GNSRECORD_FLAG_SHADOW "shadow"
38 #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
39 #define GNUNET_JSON_GNSRECORD_NEVER "never"
40 
42 {
43  char **name;
44 
45  unsigned int *rd_count;
46 
48 };
49 
50 
51 static void
52 cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
53 {
54  char *tmp;
55 
56  if (NULL != *(gnsrecord_info->rd))
57  {
58  for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
59  {
60  tmp = (char*) (*(gnsrecord_info->rd))[i].data;
61  if (NULL != tmp)
62  GNUNET_free (tmp);
63  }
64  GNUNET_free (*(gnsrecord_info->rd));
65  *(gnsrecord_info->rd) = NULL;
66  }
67  if (NULL != *(gnsrecord_info->name))
68  GNUNET_free (*(gnsrecord_info->name));
69  *(gnsrecord_info->name) = NULL;
70 }
71 
72 
81 static int
83 {
84  struct GNUNET_TIME_Absolute abs_expiration_time;
85  struct GNUNET_TIME_Relative rel_expiration_time;
86  const char *value;
87  const char *record_type;
88  const char *expiration_time;
89  int private;
90  int supplemental;
91  int rel_exp;
92  int shadow;
93  int unpack_state = 0;
94 
95  // interpret single gns record
96  unpack_state = json_unpack (data,
97  "{s:s, s:s, s:s, s:b, s:b, s:b, s:b}",
99  &value,
101  &record_type,
103  &expiration_time,
105  &private,
107  &supplemental,
109  &rel_exp,
111  &shadow);
112  if (0 != unpack_state)
113  {
115  "Error gnsdata object has a wrong format!\n");
116  return GNUNET_SYSERR;
117  }
119  if (UINT32_MAX == rd->record_type)
120  {
121  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
122  return GNUNET_SYSERR;
123  }
125  value,
126  (void **) &rd->data,
127  &rd->data_size))
128  {
129  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
130  return GNUNET_SYSERR;
131  }
132 
133  if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
134  {
136  }
137  else if ((1 != rel_exp) &&
138  (GNUNET_OK ==
139  GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
140  &abs_expiration_time)))
141  {
142  rd->expiration_time = abs_expiration_time.abs_value_us;
143  }
144  else if (GNUNET_OK ==
145  GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
146  &rel_expiration_time))
147  {
149  rd->expiration_time = rel_expiration_time.rel_value_us;
150  }
151  else
152  {
153  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
154  return GNUNET_SYSERR;
155  }
156  if (1 == private)
158  if (1 == supplemental)
160  if (1 == shadow)
162  return GNUNET_OK;
163 }
164 
165 
174 static int
175 parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
176 {
177  GNUNET_assert (NULL != data);
178  if (! json_is_array (data))
179  {
181  "Error gns record data JSON is not an array!\n");
182  return GNUNET_SYSERR;
183  }
184  *(gnsrecord_info->rd_count) = json_array_size (data);
185  *(gnsrecord_info->rd) = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Data)
186  * json_array_size (data));
187  size_t index;
188  json_t *value;
189  json_array_foreach (data, index, value)
190  {
191  if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
192  return GNUNET_SYSERR;
193  }
194  return GNUNET_OK;
195 }
196 
197 
198 static int
200  json_t *root,
201  struct GNUNET_JSON_Specification *spec)
202 {
203  struct GnsRecordInfo *gnsrecord_info;
204  int unpack_state = 0;
205  const char *name;
206  json_t *data;
207 
208  GNUNET_assert (NULL != root);
209  if (! json_is_object (root))
210  {
212  "Error record JSON is not an object!\n");
213  return GNUNET_SYSERR;
214  }
215  // interpret single gns record
216  unpack_state = json_unpack (root,
217  "{s:s, s:o!}",
219  &name,
221  &data);
222  if (0 != unpack_state)
223  {
225  "Error namestore records object has a wrong format!\n");
226  return GNUNET_SYSERR;
227  }
228  gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
229  *(gnsrecord_info->name) = GNUNET_strdup (name);
230  if (GNUNET_OK != parse_record_data (gnsrecord_info, data))
231  {
232  cleanup_recordinfo (gnsrecord_info);
233  return GNUNET_SYSERR;
234  }
235  return GNUNET_OK;
236 }
237 
238 
245 static void
247 {
248  struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
249 
250  GNUNET_free (gnsrecord_info);
251 }
252 
253 
262  unsigned int *rd_count,
263  char **name)
264 {
265  struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
266 
267  gnsrecord_info->rd = rd;
268  gnsrecord_info->name = name;
269  gnsrecord_info->rd_count = rd_count;
271  .cleaner = &clean_gnsrecordobject,
272  .cls = NULL,
273  .field = NULL,
274  .ptr = (struct GnsRecordInfo *)
275  gnsrecord_info,
276  .ptr_size = 0,
277  .size_ptr = NULL };
278  return ret;
279 }
#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
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (i.e.
Definition: gnsrecord.c:204
#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:355
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:406
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_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
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.
struct GNUNET_JSON_Specification GNUNET_JSON_spec_gnsrecord(struct GNUNET_GNSRECORD_Data **rd, unsigned int *rd_count, char **name)
JSON Specification for GNS Records.
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:175
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.
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,...)
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).
#define GNUNET_JSON_GNSRECORD_RECORD_DATA
uint32_t data
The data value.
#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