From a3882b58f1c5976677aa65b0af8a48e8e946b06e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 20 Feb 2017 15:09:00 +0100 Subject: [PATCH] first half of new BLOCK API to generalize duplicate detection beyond BFs --- src/block/Makefile.am | 15 ++- src/block/bg_bf.c | 173 +++++++++++++++++++++++++++ src/block/block.c | 72 +++++++++++ src/dht/Makefile.am | 1 + src/dht/plugin_block_dht.c | 36 +++++- src/dns/plugin_block_dns.c | 6 +- src/fs/Makefile.am | 1 + src/fs/plugin_block_fs.c | 48 +++++++- src/gns/Makefile.am | 1 + src/gns/plugin_block_gns.c | 45 ++++++- src/include/gnunet_block_group_lib.h | 82 +++++++++++++ src/include/gnunet_block_lib.h | 51 ++++++++ src/include/gnunet_block_plugin.h | 87 +++++++++++++- src/regex/Makefile.am | 1 + src/regex/plugin_block_regex.c | 37 +++++- 15 files changed, 645 insertions(+), 11 deletions(-) create mode 100644 src/block/bg_bf.c create mode 100644 src/include/gnunet_block_group_lib.h diff --git a/src/block/Makefile.am b/src/block/Makefile.am index c54a4c246..4a6d8e71e 100644 --- a/src/block/Makefile.am +++ b/src/block/Makefile.am @@ -11,7 +11,9 @@ if USE_COVERAGE AM_CFLAGS = --coverage endif -lib_LTLIBRARIES = libgnunetblock.la +lib_LTLIBRARIES = \ + libgnunetblock.la \ + libgnunetblockgroup.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_test.la @@ -49,3 +51,14 @@ libgnunetblock_la_DEPENDENCIES = \ libgnunetblock_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 + + +libgnunetblockgroup_la_SOURCES = \ + bg_bf.c +libgnunetblockgroup_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la +libgnunetblockgroup_la_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la +libgnunetblockgroup_la_LDFLAGS = \ + $(GN_LIB_LDFLAGS) \ + -version-info 0:0:0 diff --git a/src/block/bg_bf.c b/src/block/bg_bf.c new file mode 100644 index 000000000..f03ae5247 --- /dev/null +++ b/src/block/bg_bf.c @@ -0,0 +1,173 @@ +/* + This file is part of GNUnet + Copyright (C) 2017 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +/** + * @file block/bg_bf.c + * @brief implementation of a block group using a Bloom filter + * to drop duplicate blocks + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_block_group_lib.h" +#include "gnunet_block_plugin.h" + + +/** + * Internal data structure for a block group. + */ +struct BfGroupInternals +{ + /** + * A Bloom filter to weed out duplicate replies probabilistically. + */ + struct GNUNET_CONTAINER_BloomFilter *bf; + + /** + * Set from the nonce to mingle the hashes before going into the @e bf. + */ + uint32_t bf_mutator; + + /** + * Size of @a bf. + */ + uint32_t bf_size; + +}; + + +/** + * Serialize state of a block group. + * + * @param bg group to serialize + * @param[out] raw_data set to the serialized state + * @param[out] raw_data_size set to the number of bytes in @a raw_data + * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not + * supported, #GNUNET_SYSERR on error + */ +static int +bf_group_serialize_cb (struct GNUNET_BLOCK_Group *bg, + void **raw_data, + size_t *raw_data_size) +{ + struct BfGroupInternals *gi = bg->internal_cls; + char *raw; + + raw = GNUNET_malloc (gi->bf_size); + if (GNUNET_OK != + GNUNET_CONTAINER_bloomfilter_get_raw_data (gi->bf, + raw, + gi->bf_size)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + *raw_data = raw; + *raw_data_size = gi->bf_size; + return GNUNET_OK; +} + + +/** + * Destroy resources used by a block group. + * + * @param bg group to destroy, NULL is allowed + */ +static void +bf_group_destroy_cb (struct GNUNET_BLOCK_Group *bg) +{ + struct BfGroupInternals *gi = bg->internal_cls; + + GNUNET_CONTAINER_bloomfilter_free (gi->bf); + GNUNET_free (gi); + GNUNET_free (bg); +} + + +/** + * Create a new block group that filters duplicates using a Bloom filter. + * + * @param ctx block context in which the block group is created + * @param bf_size size of the Bloom filter + * @param bf_k K-value for the Bloom filter + * @param type block type + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +struct GNUNET_BLOCK_Group * +GNUNET_BLOCK_GROUP_bf_create (void *cls, + size_t bf_size, + unsigned int bf_k, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + struct BfGroupInternals *gi; + struct GNUNET_BLOCK_Group *bg; + + gi = GNUNET_new (struct BfGroupInternals); + gi->bf = GNUNET_CONTAINER_bloomfilter_init ((bf_size != raw_data_size) ? NULL : raw_data, + bf_size, + bf_k); + gi->bf_mutator = nonce; + gi->bf_size = bf_size; + bg = GNUNET_new (struct GNUNET_BLOCK_Group); + bg->type = type; + bg->serialize_cb = &bf_group_serialize_cb; + bg->destroy_cb = &bf_group_destroy_cb; + bg->internal_cls = gi; + return bg; +} + + +/** + * Test if @a hc is contained in the Bloom filter of @a bg. If so, + * return #GNUNET_YES. If not, add @a hc to the Bloom filter and + * return #GNUNET_NO. + * + * @param bg block group to use for testing + * @param hc hash of element to evaluate + * @return #GNUNET_YES if @a hc is (likely) a duplicate + * #GNUNET_NO if @a hc was definitively not in @bg (but now is) + */ +int +GNUNET_BLOCK_GROUP_bf_test_and_set (struct GNUNET_BLOCK_Group *bg, + const struct GNUNET_HashCode *hc) +{ + struct BfGroupInternals *gi = bg->internal_cls; + struct GNUNET_HashCode mhash; + + GNUNET_BLOCK_mingle_hash (hc, + gi->bf_mutator, + &mhash); + if (GNUNET_YES == + GNUNET_CONTAINER_bloomfilter_test (gi->bf, + &mhash)) + return GNUNET_YES; + GNUNET_CONTAINER_bloomfilter_add (gi->bf, + &mhash); + return GNUNET_NO; +} + + +/* end of bg_bf.c */ diff --git a/src/block/block.c b/src/block/block.c index c104f4bd1..d4f5462dd 100644 --- a/src/block/block.c +++ b/src/block/block.c @@ -158,6 +158,46 @@ GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx) } +/** + * Serialize state of a block group. + * + * @param bg group to serialize + * @param[out] raw_data set to the serialized state + * @param[out] raw_data_size set to the number of bytes in @a raw_data + * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not + * supported, #GNUNET_SYSERR on error + */ +int +GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg, + void **raw_data, + size_t *raw_data_size) +{ + *raw_data = NULL; + *raw_data_size = 0; + if (NULL == bg) + return GNUNET_NO; + if (NULL == bg->serialize_cb) + return GNUNET_NO; + return bg->serialize_cb (bg, + raw_data, + raw_data_size); +} + + +/** + * Destroy resources used by a block group. + * + * @param bg group to destroy, NULL is allowed + */ +void +GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg) +{ + if (NULL == bg) + return; + bg->destroy_cb (bg); +} + + /** * Find a plugin for the given type. * @@ -188,6 +228,38 @@ find_plugin (struct GNUNET_BLOCK_Context *ctx, } +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +struct GNUNET_BLOCK_Group * +GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + struct GNUNET_BLOCK_PluginFunctions *plugin; + + plugin = find_plugin (ctx, + type); + if (NULL == plugin->create_group) + return NULL; + return plugin->create_group (plugin->cls, + type, + nonce, + raw_data, + raw_data_size); +} + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am index 26beb300b..93dae9f6e 100644 --- a/src/dht/Makefile.am +++ b/src/dht/Makefile.am @@ -40,6 +40,7 @@ libgnunet_plugin_block_dht_la_SOURCES = \ libgnunet_plugin_block_dht_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/block/libgnunetblockgroup.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_dht_la_LDFLAGS = \ diff --git a/src/dht/plugin_block_dht.c b/src/dht/plugin_block_dht.c index 4256a0fe6..4c5f122a4 100644 --- a/src/dht/plugin_block_dht.c +++ b/src/dht/plugin_block_dht.c @@ -25,14 +25,47 @@ * DHT (see fs block plugin) * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_constants.h" #include "gnunet_hello_lib.h" #include "gnunet_block_plugin.h" +#include "gnunet_block_group_lib.h" #define DEBUG_DHT GNUNET_EXTRA_LOGGING +/** + * How big is the BF we use for DHT blocks? + */ +#define DHT_BF_SIZE 8 + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +static struct GNUNET_BLOCK_Group * +block_plugin_dht_create_group (void *cls, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + return GNUNET_BLOCK_GROUP_bf_create (cls, + DHT_BF_SIZE, + GNUNET_CONSTANTS_BLOOMFILTER_K, + type, + nonce, + raw_data, + raw_data_size); +} + /** * Function called to validate a reply or a request. For @@ -182,6 +215,7 @@ libgnunet_plugin_block_dht_init (void *cls) api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_dht_evaluate; api->get_key = &block_plugin_dht_get_key; + api->create_group = &block_plugin_dht_create_group; api->types = types; return api; } diff --git a/src/dns/plugin_block_dns.c b/src/dns/plugin_block_dns.c index 8c6ec93ee..e4bc9209c 100644 --- a/src/dns/plugin_block_dns.c +++ b/src/dns/plugin_block_dns.c @@ -96,9 +96,9 @@ block_plugin_dns_evaluate (void *cls, } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD, - &ad->purpose, - &ad->signature, - &ad->peer.public_key)) + &ad->purpose, + &ad->signature, + &ad->peer.public_key)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index 75451c7f6..4374d45ea 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -219,6 +219,7 @@ gnunet_unindex_LDADD = \ libgnunet_plugin_block_fs_la_SOURCES = \ plugin_block_fs.c libgnunet_plugin_block_fs_la_LIBADD = \ + $(top_builddir)/src/block/libgnunetblockgroup.la \ $(top_builddir)/src/block/libgnunetblock.la \ libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ diff --git a/src/fs/plugin_block_fs.c b/src/fs/plugin_block_fs.c index 415a2e3ed..038734082 100644 --- a/src/fs/plugin_block_fs.c +++ b/src/fs/plugin_block_fs.c @@ -23,12 +23,12 @@ * @brief blocks used for file-sharing * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_block_plugin.h" #include "gnunet_fs_service.h" #include "block_fs.h" #include "gnunet_signatures.h" +#include "gnunet_block_group_lib.h" /** @@ -37,6 +37,51 @@ */ #define BLOOMFILTER_K 16 +/** + * How big is the BF we use for FS blocks? + */ +#define FS_BF_SIZE 8 + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +static struct GNUNET_BLOCK_Group * +block_plugin_fs_create_group (void *cls, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + switch (type) + { + case GNUNET_BLOCK_TYPE_FS_DBLOCK: + return NULL; + case GNUNET_BLOCK_TYPE_FS_IBLOCK: + return NULL; + case GNUNET_BLOCK_TYPE_FS_UBLOCK: + return GNUNET_BLOCK_GROUP_bf_create (cls, + FS_BF_SIZE, + BLOOMFILTER_K, + type, + nonce, + raw_data, + raw_data_size); + default: + GNUNET_break (0); + return NULL; + } +} + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. @@ -214,6 +259,7 @@ libgnunet_plugin_block_fs_init (void *cls) api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_fs_evaluate; api->get_key = &block_plugin_fs_get_key; + api->create_group = &block_plugin_fs_create_group; api->types = types; return api; } diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 8f27890d7..d59908c0a 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am @@ -227,6 +227,7 @@ libgnunet_plugin_block_gns_la_SOURCES = \ libgnunet_plugin_block_gns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/block/libgnunetblockgroup.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunet_plugin_block_gns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) diff --git a/src/gns/plugin_block_gns.c b/src/gns/plugin_block_gns.c index f0e34a04b..8d3e84042 100644 --- a/src/gns/plugin_block_gns.c +++ b/src/gns/plugin_block_gns.c @@ -22,9 +22,11 @@ * @file gns/plugin_block_gns.c * @brief blocks used for GNS records * @author Martin Schanzenbach + * @author Christian Grothoff */ #include "platform.h" +#include "gnunet_block_group_lib.h" #include "gnunet_block_plugin.h" #include "gnunet_namestore_service.h" #include "gnunet_signatures.h" @@ -35,6 +37,40 @@ */ #define BLOOMFILTER_K 16 +/** + * How big is the BF we use for GNS blocks? + */ +#define GNS_BF_SIZE 8 + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +static struct GNUNET_BLOCK_Group * +block_plugin_gns_create_group (void *cls, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + return GNUNET_BLOCK_GROUP_bf_create (cls, + GNS_BF_SIZE, + BLOOMFILTER_K, + type, + nonce, + raw_data, + raw_data_size); +} + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. @@ -141,9 +177,11 @@ block_plugin_gns_evaluate (void *cls, * (or if extracting a key from a block of this type does not work) */ static int -block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type, - const void *reply_block, size_t reply_block_size, - struct GNUNET_HashCode *key) +block_plugin_gns_get_key (void *cls, + enum GNUNET_BLOCK_Type type, + const void *reply_block, + size_t reply_block_size, + struct GNUNET_HashCode *key) { const struct GNUNET_GNSRECORD_Block *block; @@ -178,6 +216,7 @@ libgnunet_plugin_block_gns_init (void *cls) api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_gns_evaluate; api->get_key = &block_plugin_gns_get_key; + api->create_group = &block_plugin_gns_create_group; api->types = types; return api; } diff --git a/src/include/gnunet_block_group_lib.h b/src/include/gnunet_block_group_lib.h new file mode 100644 index 000000000..5fa14ce00 --- /dev/null +++ b/src/include/gnunet_block_group_lib.h @@ -0,0 +1,82 @@ +/* + This file is part of GNUnet. + Copyright (C) 2010 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @author Christian Grothoff + * + * @file + * Library for creating block groups (to be used by block plugins) + * + * @defgroup block Block group library + * Library for data group management + * @{ + */ +#ifndef GNUNET_BLOCK_GROUP_LIB_H +#define GNUNET_BLOCK_GROUP_LIB_H + +#include "gnunet_util_lib.h" +#include "gnunet_block_lib.h" + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + + +/** + * Create a new block group that filters duplicates using a Bloom filter. + * + * @param ctx block context in which the block group is created + * @param bf_size size of the Bloom filter + * @param bf_k K-value for the Bloom filter + * @param type block type + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +struct GNUNET_BLOCK_Group * +GNUNET_BLOCK_GROUP_bf_create (void *cls, + size_t bf_size, + unsigned int bf_k, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size); + + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_BLOCK_GROUP_LIB_H */ +#endif + +/** @} */ /* end of group */ + +/* end of gnunet_block_group_lib.h */ diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h index b21b3496b..0f0fee499 100644 --- a/src/include/gnunet_block_lib.h +++ b/src/include/gnunet_block_lib.h @@ -229,6 +229,57 @@ void GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx); +/** + * Handle for a group of elements that will be evaluated together. + * They must all be of the same type. A block group allows the + * plugin to keep some state across individual evaluations. + */ +struct GNUNET_BLOCK_Group; + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +struct GNUNET_BLOCK_Group * +GNUNET_BLOCK_group_create (struct GNUNET_BLOCK_Context *ctx, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size); + + +/** + * Serialize state of a block group. + * + * @param bg group to serialize + * @param[out] raw_data set to the serialized state + * @param[out] raw_data_size set to the number of bytes in @a raw_data + * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not + * supported, #GNUNET_SYSERR on error + */ +int +GNUNET_BLOCK_group_serialize (struct GNUNET_BLOCK_Group *bg, + void **raw_data, + size_t *raw_data_size); + + +/** + * Destroy resources used by a block group. + * + * @param bg group to destroy, NULL is allowed + */ +void +GNUNET_BLOCK_group_destroy (struct GNUNET_BLOCK_Group *bg); + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the @a reply_block. diff --git a/src/include/gnunet_block_plugin.h b/src/include/gnunet_block_plugin.h index 5c320457e..d7454b5d5 100644 --- a/src/include/gnunet_block_plugin.h +++ b/src/include/gnunet_block_plugin.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet - Copyright (C) 2010,2013 GNUnet e.V. + Copyright (C) 2010,2013,2017 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -39,6 +39,86 @@ #include "gnunet_block_lib.h" +/** + * Serialize state of a block group. + * + * @param bg group to serialize + * @param[out] raw_data set to the serialized state + * @param[out] raw_data_size set to the number of bytes in @a raw_data + * @return #GNUNET_OK on success, #GNUNET_NO if serialization is not + * supported, #GNUNET_SYSERR on error + */ +typedef int +(*GNUNET_BLOCK_GroupSerializeFunction)(struct GNUNET_BLOCK_Group *bg, + void **raw_data, + size_t *raw_data_size); + + +/** + * Destroy resources used by a block group. + * + * @param bg group to destroy, NULL is allowed + */ +typedef void +(*GNUNET_BLOCK_GroupDestroyFunction)(struct GNUNET_BLOCK_Group *bg); + + +/** + * Block group data. The plugin must initialize the callbacks + * and can use the @e internal_cls as it likes. + */ +struct GNUNET_BLOCK_Group +{ + + /** + * Context owning the block group. Set by the main block library. + */ + struct GNUENT_BLOCK_Context *ctx; + + /** + * Type for the block group. Set by the main block library. + */ + enum GNUNET_BLOCK_Type type; + + /** + * Serialize the block group data, can be NULL if + * not supported. + */ + GNUNET_BLOCK_GroupSerializeFunction serialize_cb; + + /** + * Function to call to destroy the block group. + * Must not be NULL. + */ + GNUNET_BLOCK_GroupDestroyFunction destroy_cb; + + /** + * Internal data structure of the plugin. + */ + void *internal_cls; + +}; + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +typedef struct GNUNET_BLOCK_Group * +(*GNUNET_BLOCK_GroupCreateFunction)(void *cls, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size); + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the @a reply_block. @@ -121,6 +201,11 @@ struct GNUNET_BLOCK_PluginFunctions */ GNUNET_BLOCK_GetKeyFunction get_key; + /** + * Create a block group to process a bunch of blocks in a shared + * context (i.e. to detect duplicates). + */ + GNUNET_BLOCK_GroupCreateFunction create_group; }; #endif diff --git a/src/regex/Makefile.am b/src/regex/Makefile.am index 70f612485..80997db40 100644 --- a/src/regex/Makefile.am +++ b/src/regex/Makefile.am @@ -80,6 +80,7 @@ libgnunet_plugin_block_regex_la_SOURCES = \ libgnunet_plugin_block_regex_la_LIBADD = \ libgnunetregexblock.la \ $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/block/libgnunetblockgroup.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_block_regex_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) diff --git a/src/regex/plugin_block_regex.c b/src/regex/plugin_block_regex.c index 36926c25d..11511a71b 100644 --- a/src/regex/plugin_block_regex.c +++ b/src/regex/plugin_block_regex.c @@ -23,15 +23,49 @@ * @brief blocks used for regex storage and search * @author Bartlomiej Polot */ - #include "platform.h" #include "gnunet_block_plugin.h" +#include "gnunet_block_group_lib.h" #include "block_regex.h" #include "regex_block_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" +/** + * How big is the BF we use for REGEX blocks? + */ +#define REGEX_BF_SIZE 8 + + +/** + * Create a new block group. + * + * @param ctx block context in which the block group is created + * @param type type of the block for which we are creating the group + * @param nonce random value used to seed the group creation + * @param raw_data optional serialized prior state of the group, NULL if unavailable/fresh + * @param raw_data_size number of bytes in @a raw_data, 0 if unavailable/fresh + * @return block group handle, NULL if block groups are not supported + * by this @a type of block (this is not an error) + */ +static struct GNUNET_BLOCK_Group * +block_plugin_regex_create_group (void *cls, + enum GNUNET_BLOCK_Type type, + uint32_t nonce, + const void *raw_data, + size_t raw_data_size) +{ + return GNUNET_BLOCK_GROUP_bf_create (cls, + REGEX_BF_SIZE, + GNUNET_CONSTANTS_BLOOMFILTER_K, + type, + nonce, + raw_data, + raw_data_size); +} + + /** * Function called to validate a reply or a request of type * #GNUNET_BLOCK_TYPE_REGEX. @@ -346,6 +380,7 @@ libgnunet_plugin_block_regex_init (void *cls) api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_regex_evaluate; api->get_key = &block_plugin_regex_get_key; + api->create_group = &block_plugin_regex_create_group; api->types = types; return api; } -- 2.25.1