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