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