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