glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / gnsrecord / gnsrecord.c
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
16 /**
17  * @file gnsrecord/gnsrecord.c
18  * @brief API to access GNS record data
19  * @author Martin Schanzenbach
20  * @author Matthias Wachs
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25 #include "gnunet_constants.h"
26 #include "gnunet_gnsrecord_lib.h"
27 #include "gnunet_gnsrecord_plugin.h"
28 #include "gnunet_tun_lib.h"
29
30
31 #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
32
33
34 /**
35  * Handle for a plugin.
36  */
37 struct Plugin
38 {
39   /**
40    * Name of the shared library.
41    */
42   char *library_name;
43
44   /**
45    * Plugin API.
46    */
47   struct GNUNET_GNSRECORD_PluginFunctions *api;
48 };
49
50
51 /**
52  * Array of our plugins.
53  */
54 static struct Plugin **gns_plugins;
55
56 /**
57  * Size of the 'plugins' array.
58  */
59 static unsigned int num_plugins;
60
61 /**
62  * Global to mark if we've run the initialization.
63  */
64 static int once;
65
66
67 /**
68  * Add a plugin to the list managed by the block library.
69  *
70  * @param cls NULL
71  * @param library_name name of the plugin
72  * @param lib_ret the plugin API
73  */
74 static void
75 add_plugin (void *cls,
76             const char *library_name,
77             void *lib_ret)
78 {
79   struct GNUNET_GNSRECORD_PluginFunctions *api = lib_ret;
80   struct Plugin *plugin;
81
82   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83               "Loading block plugin `%s'\n",
84               library_name);
85   plugin = GNUNET_new (struct Plugin);
86   plugin->api = api;
87   plugin->library_name = GNUNET_strdup (library_name);
88   GNUNET_array_append (gns_plugins, num_plugins, plugin);
89 }
90
91
92 /**
93  * Loads all plugins (lazy initialization).
94  */
95 static void
96 init ()
97 {
98   if (1 == once)
99     return;
100   once = 1;
101   GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL,
102                           &add_plugin, NULL);
103 }
104
105
106 /**
107  * Dual function to #init().
108  */
109 void __attribute__ ((destructor))
110 GNSRECORD_fini ()
111 {
112   struct Plugin *plugin;
113
114   for (unsigned int i = 0; i < num_plugins; i++)
115   {
116     plugin = gns_plugins[i];
117     GNUNET_break (NULL ==
118                   GNUNET_PLUGIN_unload (plugin->library_name,
119                                         plugin->api));
120     GNUNET_free (plugin->library_name);
121     GNUNET_free (plugin);
122   }
123   GNUNET_free_non_null (gns_plugins);
124   gns_plugins = NULL;
125   once = 0;
126   num_plugins = 0;
127 }
128
129
130 /**
131  * Convert the 'value' of a record to a string.
132  *
133  * @param type type of the record
134  * @param data value in binary encoding
135  * @param data_size number of bytes in @a data
136  * @return NULL on error, otherwise human-readable representation of the value
137  */
138 char *
139 GNUNET_GNSRECORD_value_to_string (uint32_t type,
140                                   const void *data,
141                                   size_t data_size)
142 {
143   struct Plugin *plugin;
144   char *ret;
145
146   init ();
147   for (unsigned int i = 0; i < num_plugins; i++)
148   {
149     plugin = gns_plugins[i];
150     if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
151                                                      type,
152                                                      data,
153                                                      data_size)))
154       return ret;
155   }
156   return NULL;
157 }
158
159
160 /**
161  * Convert human-readable version of a 'value' of a record to the binary
162  * representation.
163  *
164  * @param type type of the record
165  * @param s human-readable string
166  * @param data set to value in binary encoding (will be allocated)
167  * @param data_size set to number of bytes in @a data
168  * @return #GNUNET_OK on success
169  */
170 int
171 GNUNET_GNSRECORD_string_to_value (uint32_t type,
172                                   const char *s,
173                                   void **data,
174                                   size_t *data_size)
175 {
176   struct Plugin *plugin;
177
178   init ();
179   for (unsigned int i = 0; i < num_plugins; i++)
180   {
181     plugin = gns_plugins[i];
182     if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
183                                                    type,
184                                                    s,
185                                                    data,
186                                                    data_size))
187       return GNUNET_OK;
188   }
189   return GNUNET_SYSERR;
190 }
191
192
193 /**
194  * Convert a type name (i.e. "AAAA") to the corresponding number.
195  *
196  * @param dns_typename name to convert
197  * @return corresponding number, UINT32_MAX on error
198  */
199 uint32_t
200 GNUNET_GNSRECORD_typename_to_number (const char *dns_typename)
201 {
202   struct Plugin *plugin;
203   uint32_t ret;
204
205   if (0 == strcasecmp (dns_typename,
206                        "ANY"))
207     return GNUNET_GNSRECORD_TYPE_ANY;
208   init ();
209   for (unsigned int i = 0; i < num_plugins; i++)
210   {
211     plugin = gns_plugins[i];
212     if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
213                                                               dns_typename)))
214       return ret;
215   }
216   return UINT32_MAX;
217 }
218
219
220 /**
221  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
222  *
223  * @param type number of a type to convert
224  * @return corresponding typestring, NULL on error
225  */
226 const char *
227 GNUNET_GNSRECORD_number_to_typename (uint32_t type)
228 {
229   struct Plugin *plugin;
230   const char * ret;
231
232   if (GNUNET_GNSRECORD_TYPE_ANY == type)
233     return "ANY";
234   init ();
235   for (unsigned int i = 0; i < num_plugins; i++)
236   {
237     plugin = gns_plugins[i];
238     if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
239                                                         type)))
240       return ret;
241   }
242   return NULL;
243 }
244
245
246 /* end of gnsrecord.c */