documentation for new parameters
[oweals/gnunet.git] / src / block / block.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file block/block.c
23  * @brief library for data block manipulation
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_signatures.h"
29 #include "gnunet_block_lib.h"
30 #include "plugin_block.h"
31
32
33 /**
34  * Handle for a plugin.
35  */
36 struct Plugin
37 {
38   /**
39    * Name of the shared library.
40    */ 
41   char *library_name;
42   
43   /**
44    * Plugin API.
45    */
46   struct GNUNET_BLOCK_PluginFunctions *api;
47 };
48
49 /**
50  * Handle to an initialized block library.
51  */
52 struct GNUNET_BLOCK_Context
53 {
54   /**
55    * NULL-terminated array of our plugins.
56    */
57   struct Plugin **plugins;
58
59   /**
60    * Our configuration.
61    */ 
62   const struct GNUNET_CONFIGURATION_Handle *cfg;
63 };
64
65
66 /**
67  * Create a block context.  Loads the block plugins.
68  *
69  * @param cfg configuration to use
70  * @return NULL on error
71  */
72 struct GNUNET_BLOCK_Context *
73 GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg)
74 {
75   struct GNUNET_BLOCK_Context *ctx;
76   struct GNUNET_BLOCK_PluginFunctions *api;
77   struct Plugin *plugin;
78   unsigned int num_plugins;
79   char *plugs;
80   char *pos;
81   char *libname;
82
83   ctx = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_Context));
84   ctx->cfg = cfg;
85   num_plugins = 0;
86   if (GNUNET_OK ==
87       GNUNET_CONFIGURATION_get_value_string (cfg,
88                                              "block", "PLUGINS", &plugs))
89     {
90       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
91                   _("Loading block plugins `%s'\n"), plugs);
92       pos = strtok (plugs, " ");
93       while (pos != NULL)
94         {
95           GNUNET_asprintf (&libname, "libgnunet_plugin_block_%s", pos);
96           api = GNUNET_PLUGIN_load (libname, NULL);
97           if (api == NULL)
98             {
99               GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
100                           _("Failed to load block plugin `%s'\n"),
101                           pos);
102               GNUNET_free (libname);
103             }
104           else
105             {
106               plugin = GNUNET_malloc (sizeof (struct Plugin));
107               plugin->api = api;
108               plugin->library_name = libname;
109               GNUNET_array_append (ctx->plugins,
110                                    num_plugins,
111                                    plugin);
112             }
113           pos = strtok (NULL, " ");
114         }
115       GNUNET_free (plugs);
116     }
117   GNUNET_array_append (ctx->plugins,
118                        num_plugins,
119                        NULL);
120   return ctx;
121 }
122
123
124 /**
125  * Destroy the block context.
126  *
127  * @param ctx context to destroy
128  */
129 void
130 GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx)
131 {
132   unsigned int i;
133   struct Plugin *plugin;
134
135   i = 0;
136   while (NULL != (plugin = ctx->plugins[i]))
137     {
138       GNUNET_break (NULL == 
139                     GNUNET_PLUGIN_unload (plugin->library_name,
140                                           plugin->api));
141       GNUNET_free (plugin->library_name);
142       GNUNET_free (plugin);
143       i++;
144     }
145   GNUNET_free (ctx->plugins);
146   GNUNET_free (ctx);
147 }
148
149
150 /**
151  * Find a plugin for the given type.
152  *
153  * @param ctx context to search
154  * @param type type to look for
155  * @return NULL if no matching plugin exists
156  */
157 static struct GNUNET_BLOCK_PluginFunctions *
158 find_plugin (struct GNUNET_BLOCK_Context *ctx,
159              enum GNUNET_BLOCK_Type type)
160 {
161   struct Plugin *plugin;
162   unsigned int i;
163   unsigned int j;
164
165   i = 0;
166   while (NULL != (plugin = ctx->plugins[i]))
167     {
168       j = 0;
169       while (0 != (plugin->api->types[j]))
170         {
171           if (type == plugin->api->types[j])
172             return plugin->api;
173           j++;
174         }
175       i++;
176     }
177   return NULL;
178 }
179
180
181 /**
182  * Function called to validate a reply or a request.  For
183  * request evaluation, simply pass "NULL" for the reply_block.
184  * Note that it is assumed that the reply has already been 
185  * matched to the key (and signatures checked) as it would
186  * be done with the "get_key" function.
187  *
188  * @param ctx block contxt
189  * @param type block type
190  * @param query original query (hash)
191  * @param bf pointer to bloom filter associated with query; possibly updated (!)
192  * @param bf_mutator mutation value for bf
193  * @param xquery extrended query data (can be NULL, depending on type)
194  * @param xquery_size number of bytes in xquery
195  * @param reply_block response to validate
196  * @param reply_block_size number of bytes in reply block
197  * @return characterization of result
198  */
199 enum GNUNET_BLOCK_EvaluationResult
200 GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx,
201                        enum GNUNET_BLOCK_Type type,
202                        const GNUNET_HashCode *query,
203                        struct GNUNET_CONTAINER_BloomFilter **bf,
204                        int32_t bf_mutator,
205                        const void *xquery,
206                        size_t xquery_size,
207                        const void *reply_block,
208                        size_t reply_block_size)
209 {
210   struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type);
211
212   if (plugin == NULL)
213     return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
214   return plugin->evaluate (plugin->cls,
215                            type, query, bf, bf_mutator,
216                            xquery, xquery_size, reply_block, reply_block_size);
217 }
218
219
220 /**
221  * Function called to obtain the key for a block.
222  *
223  * @param ctx block context
224  * @param type block type
225  * @param block block to get the key for
226  * @param block_size number of bytes in block
227  * @param key set to the key (query) for the given block
228  * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported
229  *         (or if extracting a key from a block of this type does not work)
230  */
231 int
232 GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx,
233                       enum GNUNET_BLOCK_Type type,
234                       const void *block,
235                       size_t block_size,
236                       GNUNET_HashCode *key)
237 {
238   struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type);
239
240   if (plugin == NULL)
241     return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
242   return plugin->get_key (plugin->cls,
243                           type, block, block_size, key);
244 }
245
246
247 /* end of block.c */