- added mesh regex testcase, fixed bugs
[oweals/gnunet.git] / src / mesh / plugin_block_mesh.c
1 /*
2      This file is part of GNUnet
3      (C) 2012 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 mesh/plugin_block_mesh.c
23  * @brief blocks used for mesh peer discovery
24  * @author Bartlomiej Polot
25  */
26
27 #include "platform.h"
28 #include "gnunet_block_plugin.h"
29 #include "block_mesh.h"
30 #include "mesh_block_lib.h"
31
32 /**
33  * Number of bits we set per entry in the bloomfilter.
34  * Do not change!
35  */
36 #define BLOOMFILTER_K 16
37
38
39 /**
40  * Function called to validate a reply or a request.  For
41  * request evaluation, simply pass "NULL" for the reply_block.
42  * Note that it is assumed that the reply has already been
43  * matched to the key (and signatures checked) as it would
44  * be done with the "get_key" function.
45  *
46  * @param cls closure
47  * @param type block type
48  * @param query original query (hash)
49  * @param bf pointer to bloom filter associated with query; possibly updated (!)
50  * @param bf_mutator mutation value for bf
51  * @param xquery extrended query data (can be NULL, depending on type)
52  * @param xquery_size number of bytes in xquery
53  * @param reply_block response to validate
54  * @param reply_block_size number of bytes in reply block
55  * @return characterization of result
56  */
57 static enum GNUNET_BLOCK_EvaluationResult
58 block_plugin_mesh_evaluate (void *cls, enum GNUNET_BLOCK_Type type,
59                             const struct GNUNET_HashCode * query,
60                             struct GNUNET_CONTAINER_BloomFilter **bf,
61                             int32_t bf_mutator, const void *xquery,
62                             size_t xquery_size, const void *reply_block,
63                             size_t reply_block_size)
64 {
65   struct GNUNET_HashCode chash;
66   struct GNUNET_HashCode mhash;
67
68   switch (type)
69   {
70   case GNUNET_BLOCK_TYPE_MESH_PEER:
71     if (0 != xquery_size)
72     {
73       GNUNET_break_op (0);
74       return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
75     }
76     if (NULL == reply_block)
77       return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
78     if (sizeof (struct PBlock) != reply_block_size)  
79       return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;  
80     return GNUNET_BLOCK_EVALUATION_OK_LAST;
81   case GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE:
82     /* FIXME: have an xquery? not sure */
83     if (0 != xquery_size)
84     {
85       GNUNET_break_op (0);
86       return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
87     }
88     if (NULL == reply_block)
89       return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
90     if (sizeof (struct PBlock) != reply_block_size)  
91       return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;  
92     if (NULL != bf)
93     {
94       GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
95       GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
96       if (NULL != *bf)
97       {
98         if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
99           return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
100       }
101       else
102       {
103         *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K);
104       }
105       GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
106     }
107     return GNUNET_BLOCK_EVALUATION_OK_MORE;
108   case GNUNET_BLOCK_TYPE_MESH_REGEX:
109     if (0 != xquery_size)
110     {
111       GNUNET_break_op (0);
112       return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
113     }
114     if (NULL == reply_block)
115       return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
116     if (GNUNET_OK != GNUNET_MESH_regex_block_check (reply_block,
117                                                     reply_block_size))
118       return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
119     if (NULL != bf)
120     {
121       GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
122       GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
123       if (NULL != *bf)
124       {
125         if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
126           return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
127       }
128       else
129       {
130         *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K);
131       }
132       GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
133     }
134     return GNUNET_BLOCK_EVALUATION_OK_MORE;
135   case GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT:
136     if (0 != xquery_size)
137     {
138       GNUNET_break_op (0);
139       return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
140     }
141     if (NULL == reply_block)
142       return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
143     if (sizeof (struct MeshRegexAccept) != reply_block_size)  
144       return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
145     if (NULL != bf)
146     {
147       GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash);
148       GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash);
149       if (NULL != *bf)
150       {
151         if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash))
152           return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
153       }
154       else
155       {
156         *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K);
157       }
158       GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash);
159     }
160     return GNUNET_BLOCK_EVALUATION_OK_MORE;
161   default:
162     return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
163   }
164 }
165
166
167 /**
168  * Function called to obtain the key for a block.
169  *
170  * @param cls closure
171  * @param type block type
172  * @param block block to get the key for
173  * @param block_size number of bytes in block
174  * @param key set to the key (query) for the given block
175  * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported
176  *         (or if extracting a key from a block of this type does not work)
177  */
178 static int
179 block_plugin_mesh_get_key (void *cls, enum GNUNET_BLOCK_Type type,
180                            const void *block, size_t block_size,
181                            struct GNUNET_HashCode * key)
182 {
183   const struct PBlock *pb;
184   pb = block;
185
186   switch (type)
187   {
188   case GNUNET_BLOCK_TYPE_MESH_PEER:
189     if (sizeof (struct PBlock) != block_size)
190       return GNUNET_SYSERR;
191     *key = pb->id.hashPubKey;
192     return GNUNET_OK;
193   case GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE:
194     GNUNET_CRYPTO_hash (&pb->type, sizeof(GNUNET_MESH_ApplicationType), key);
195     return GNUNET_OK;
196   default:
197     return GNUNET_SYSERR;
198   }
199 }
200
201
202 /**
203  * Entry point for the plugin.
204  */
205 void *
206 libgnunet_plugin_block_mesh_init (void *cls)
207 {
208   static enum GNUNET_BLOCK_Type types[] =
209   {
210     GNUNET_BLOCK_TYPE_MESH_PEER,
211     GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
212     GNUNET_BLOCK_TYPE_MESH_REGEX,
213     GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT,
214     GNUNET_BLOCK_TYPE_ANY       /* end of list */
215   };
216   struct GNUNET_BLOCK_PluginFunctions *api;
217
218   api = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_PluginFunctions));
219   api->evaluate = &block_plugin_mesh_evaluate;
220   api->get_key = &block_plugin_mesh_get_key;
221   api->types = types;
222   return api;
223 }
224
225
226 /**
227  * Exit point from the plugin.
228  */
229 void *
230 libgnunet_plugin_block_mesh_done (void *cls)
231 {
232   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
233
234   GNUNET_free (api);
235   return NULL;
236 }
237
238 /* end of plugin_block_mesh.c */