RECLAIM: refactoring; cleanup
[oweals/gnunet.git] / src / reclaim-attribute / reclaim_attribute.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2010-2015 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
21 /**
22  * @file reclaim-attribute/reclaim_attribute.c
23  * @brief helper library to manage identity attributes
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "reclaim_attribute.h"
29 #include "gnunet_reclaim_attribute_plugin.h"
30
31 /**
32  * Handle for a plugin
33  */
34 struct Plugin
35 {
36   /**
37    * Name of the plugin
38    */
39   char *library_name;
40
41   /**
42    * Plugin API
43    */
44   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api;
45 };
46
47 /**
48  * Plugins
49  */
50 static struct Plugin **attr_plugins;
51
52 /**
53  * Number of plugins
54  */
55 static unsigned int num_plugins;
56
57 /**
58  * Init canary
59  */
60 static int initialized;
61
62 /**
63  * Add a plugin
64  */
65 static void
66 add_plugin (void* cls,
67             const char *library_name,
68             void *lib_ret)
69 {
70   struct GNUNET_RECLAIM_ATTRIBUTE_PluginFunctions *api = lib_ret;
71   struct Plugin *plugin;
72
73   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
74               "Loading attribute plugin `%s'\n",
75               library_name);
76   plugin = GNUNET_new (struct Plugin);
77   plugin->api = api;
78   plugin->library_name = GNUNET_strdup (library_name);
79   GNUNET_array_append (attr_plugins, num_plugins, plugin);
80 }
81
82 /**
83  * Load plugins
84  */
85 static void
86 init()
87 {
88   if (GNUNET_YES == initialized)
89     return;
90   initialized = GNUNET_YES;
91   GNUNET_PLUGIN_load_all ("libgnunet_plugin_reclaim_attribute_", NULL,
92                           &add_plugin, NULL);
93 }
94
95 /**
96  * Convert a type name to the corresponding number
97  *
98  * @param typename name to convert
99  * @return corresponding number, UINT32_MAX on error
100  */
101 uint32_t
102 GNUNET_RECLAIM_ATTRIBUTE_typename_to_number (const char *typename)
103 {
104   unsigned int i;
105   struct Plugin *plugin;
106   uint32_t ret;
107
108   init ();
109   for (i = 0; i < num_plugins; i++)
110   {
111     plugin = attr_plugins[i];
112     if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
113                                                               typename)))
114       return ret;
115   }
116   return UINT32_MAX;
117 }
118
119 /**
120  * Convert a type number to the corresponding type string
121  *
122  * @param type number of a type
123  * @return corresponding typestring, NULL on error
124  */
125 const char*
126 GNUNET_RECLAIM_ATTRIBUTE_number_to_typename (uint32_t type)
127 {
128   unsigned int i;
129   struct Plugin *plugin;
130   const char *ret;
131
132   init ();
133   for (i = 0; i < num_plugins; i++)
134   {
135     plugin = attr_plugins[i];
136     if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
137                                                         type)))
138       return ret;
139   }
140   return NULL;
141 }
142
143 /**
144  * Convert human-readable version of a 'claim' of an attribute to the binary
145  * representation
146  *
147  * @param type type of the claim
148  * @param s human-readable string
149  * @param data set to value in binary encoding (will be allocated)
150  * @param data_size set to number of bytes in @a data
151  * @return #GNUNET_OK on success
152  */
153 int
154 GNUNET_RECLAIM_ATTRIBUTE_string_to_value (uint32_t type,
155                                           const char *s,
156                                           void **data,
157                                           size_t *data_size)
158 {
159   unsigned int i;
160   struct Plugin *plugin;
161
162   init ();
163   for (i = 0; i < num_plugins; i++)
164   {
165     plugin = attr_plugins[i];
166     if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
167                                                    type,
168                                                    s,
169                                                    data,
170                                                    data_size))
171       return GNUNET_OK;
172   }
173   return GNUNET_SYSERR;
174 }
175
176 /**
177  * Convert the 'claim' of an attribute to a string
178  *
179  * @param type the type of attribute
180  * @param data claim in binary encoding
181  * @param data_size number of bytes in @a data
182  * @return NULL on error, otherwise human-readable representation of the claim
183  */
184 char *
185 GNUNET_RECLAIM_ATTRIBUTE_value_to_string (uint32_t type,
186                                           const void* data,
187                                           size_t data_size)
188 {
189   unsigned int i;
190   struct Plugin *plugin;
191   char *ret;
192
193   init();
194   for (i = 0; i < num_plugins; i++)
195   {
196     plugin = attr_plugins[i];
197     if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
198                                                      type,
199                                                      data,
200                                                      data_size)))
201       return ret;
202   }
203   return NULL;
204 }
205
206 /**
207  * Create a new attribute.
208  *
209  * @param attr_name the attribute name
210  * @param type the attribute type
211  * @param data the attribute value
212  * @param data_size the attribute value size
213  * @return the new attribute
214  */
215 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
216 GNUNET_RECLAIM_ATTRIBUTE_claim_new (const char* attr_name,
217                                     uint32_t type,
218                                     const void* data,
219                                     size_t data_size)
220 {
221   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
222   char *write_ptr;
223   char *attr_name_tmp = GNUNET_strdup (attr_name);
224
225   GNUNET_STRINGS_utf8_tolower (attr_name, attr_name_tmp);
226
227   attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim) +
228                         strlen (attr_name_tmp) + 1 +
229                         data_size);
230   attr->type = type;
231   attr->data_size = data_size;
232   attr->version = 0;
233   write_ptr = (char*)&attr[1];
234   GNUNET_memcpy (write_ptr,
235                  attr_name_tmp,
236                  strlen (attr_name_tmp) + 1);
237   attr->name = write_ptr;
238   write_ptr += strlen (attr->name) + 1;
239   GNUNET_memcpy (write_ptr,
240                  data,
241                  data_size);
242   attr->data = write_ptr;
243   GNUNET_free (attr_name_tmp);
244   return attr;
245 }
246
247 /**
248  * Add a new claim list entry.
249  *
250  * @param claim_list the attribute name
251  * @param attr_name the attribute name
252  * @param type the attribute type
253  * @param data the attribute value
254  * @param data_size the attribute value size
255  * @return
256  */
257 void
258 GNUNET_RECLAIM_ATTRIBUTE_list_add (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *claim_list,
259                                    const char* attr_name,
260                                    uint32_t type,
261                                    const void* data,
262                                    size_t data_size)
263 {
264   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
265   le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
266   le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (attr_name,
267                                                   type,
268                                                   data,
269                                                   data_size);
270   GNUNET_CONTAINER_DLL_insert (claim_list->list_head,
271                                claim_list->list_tail,
272                                le);
273 }
274
275 size_t
276 GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
277 {
278   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
279   size_t len = 0;
280   for (le = attrs->list_head; NULL != le; le = le->next)
281     len += GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
282   return len;
283 }
284
285 size_t
286 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
287                                          char *result)
288 {
289   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
290   size_t len;
291   size_t total_len;
292   char* write_ptr;
293
294   write_ptr = result;
295   total_len = 0;
296   for (le = attrs->list_head; NULL != le; le = le->next)
297   {
298     len = GNUNET_RECLAIM_ATTRIBUTE_serialize (le->claim,
299                                               write_ptr);
300     total_len += len;
301     write_ptr += len;
302   }
303   return total_len;
304 }
305
306 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *
307 GNUNET_RECLAIM_ATTRIBUTE_list_deserialize (const char* data,
308                                            size_t data_size)
309 {
310   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
311   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
312   size_t attr_len;
313   const char* read_ptr;
314
315   if (data_size < sizeof (struct Attribute))
316     return NULL;
317
318   attrs = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
319   read_ptr = data;
320   while (((data + data_size) - read_ptr) >= sizeof (struct Attribute))
321   {
322
323     le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
324     le->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize (read_ptr,
325                                                       data_size - (read_ptr - data));
326     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
327                 "Deserialized attribute %s\n", le->claim->name);
328     GNUNET_CONTAINER_DLL_insert (attrs->list_head,
329                                  attrs->list_tail,
330                                  le);
331     attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (le->claim);
332     read_ptr += attr_len;
333   }
334   return attrs;
335 }
336
337 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList*
338 GNUNET_RECLAIM_ATTRIBUTE_list_dup (const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
339 {
340   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
341   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *result_le;
342   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *result;
343
344   result = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList);
345   for (le = attrs->list_head; NULL != le; le = le->next)
346   {
347     result_le = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry);
348     result_le->claim = GNUNET_RECLAIM_ATTRIBUTE_claim_new (le->claim->name,
349                                                            le->claim->type,
350                                                            le->claim->data,
351                                                            le->claim->data_size);
352     result_le->claim->version = le->claim->version;
353     result_le->claim->id = le->claim->id;
354     GNUNET_CONTAINER_DLL_insert (result->list_head,
355                                  result->list_tail,
356                                  result_le);
357   }
358   return result;
359 }
360
361
362 void
363 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs)
364 {
365   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
366   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *tmp_le;
367
368   for (le = attrs->list_head; NULL != le;)
369   {
370     GNUNET_free (le->claim);
371     tmp_le = le;
372     le = le->next;
373     GNUNET_free (tmp_le);
374   }
375   GNUNET_free (attrs);
376
377 }
378
379 size_t
380 GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr)
381 {
382   return sizeof (struct Attribute)
383     + strlen (attr->name)
384     + attr->data_size;
385 }
386
387 size_t
388 GNUNET_RECLAIM_ATTRIBUTE_serialize (const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
389                                     char *result)
390 {
391   size_t data_len_ser;
392   size_t name_len;
393   struct Attribute *attr_ser;
394   char* write_ptr;
395
396   attr_ser = (struct Attribute*)result;
397   attr_ser->attribute_type = htons (attr->type);
398   attr_ser->attribute_version = htonl (attr->version);
399   attr_ser->attribute_id = GNUNET_htonll (attr->id);
400   name_len = strlen (attr->name);
401   attr_ser->name_len = htons (name_len);
402   write_ptr = (char*)&attr_ser[1];
403   GNUNET_memcpy (write_ptr, attr->name, name_len);
404   write_ptr += name_len;
405   //TODO plugin-ize
406   //data_len_ser = plugin->serialize_attribute_value (attr,
407   //                                                  &attr_ser[1]);
408   data_len_ser = attr->data_size;
409   GNUNET_memcpy (write_ptr, attr->data, attr->data_size);
410   attr_ser->data_size = htons (data_len_ser);
411
412   return sizeof (struct Attribute) + strlen (attr->name) + attr->data_size;
413 }
414
415 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *
416 GNUNET_RECLAIM_ATTRIBUTE_deserialize (const char* data,
417                                       size_t data_size)
418 {
419   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
420   struct Attribute *attr_ser;
421   size_t data_len;
422   size_t name_len;
423   char* write_ptr;
424
425   if (data_size < sizeof (struct Attribute))
426     return NULL;
427
428   attr_ser = (struct Attribute*)data;
429   data_len = ntohs (attr_ser->data_size);
430   name_len = ntohs (attr_ser->name_len);
431   attr = GNUNET_malloc (sizeof (struct GNUNET_RECLAIM_ATTRIBUTE_Claim)
432                         + data_len + name_len + 1);
433   attr->type = ntohs (attr_ser->attribute_type);
434   attr->version = ntohl (attr_ser->attribute_version);
435   attr->id = GNUNET_ntohll (attr_ser->attribute_id);
436   attr->data_size = ntohs (attr_ser->data_size);
437
438   write_ptr =  (char*)&attr[1];
439   GNUNET_memcpy (write_ptr,
440                  &attr_ser[1],
441                  name_len);
442   write_ptr[name_len] = '\0';
443   attr->name = write_ptr;
444
445   write_ptr += name_len + 1;
446   GNUNET_memcpy (write_ptr,
447                  (char*)&attr_ser[1] + name_len,
448                  attr->data_size);
449   attr->data = write_ptr;
450   return attr;
451
452 }
453
454 /* end of reclaim_attribute.c */