X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ffs%2Fplugin_block_fs.c;h=bea6b148c423242af39de9189ffd1079255d7043;hb=4ba0fa6ba9f9be044c8c96ddd4d909e7d84403b5;hp=9b73f2497cde31a15c5d52254805f054078e0241;hpb=7860a8fa9e6cca9f59efbfee307a01545578f59f;p=oweals%2Fgnunet.git diff --git a/src/fs/plugin_block_fs.c b/src/fs/plugin_block_fs.c index 9b73f2497..bea6b148c 100644 --- a/src/fs/plugin_block_fs.c +++ b/src/fs/plugin_block_fs.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2010 Christian Grothoff (and other contributing authors) + Copyright (C) 2010, 2013 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 @@ -14,8 +14,8 @@ 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., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -23,13 +23,13 @@ * @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" -#define DEBUG_FS_BLOCK GNUNET_EXTRA_LOGGING /** * Number of bits we set per entry in the bloomfilter. @@ -37,115 +37,193 @@ */ #define BLOOMFILTER_K 16 + +/** + * How many bytes should a bloomfilter be if we have already seen + * entry_count responses? Note that #GNUNET_CONSTANTS_BLOOMFILTER_K + * gives us the number of bits set per entry. Furthermore, we should + * not re-size the filter too often (to keep it cheap). + * + * Since other peers will also add entries but not resize the filter, + * we should generally pick a slightly larger size than what the + * strict math would suggest. + * + * @param entry_count expected number of entries in the Bloom filter + * @return must be a power of two and smaller or equal to 2^15. + */ +static size_t +compute_bloomfilter_size (unsigned int entry_count) +{ + size_t size; + unsigned int ideal = (entry_count * BLOOMFILTER_K) / 4; + uint16_t max = 1 << 15; + + if (entry_count > max) + return max; + size = 8; + while ((size < max) && (size < ideal)) + size *= 2; + if (size > max) + return max; + return size; +} + + +/** + * 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 + * @param va variable arguments specific to @a type + * @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, + va_list va) +{ + unsigned int size; + const char *guard; + + switch (type) + { + case GNUNET_BLOCK_TYPE_FS_DBLOCK: + GNUNET_break (NULL == va_arg (va, const char *)); + return NULL; + case GNUNET_BLOCK_TYPE_FS_IBLOCK: + GNUNET_break (NULL == va_arg (va, const char *)); + return NULL; + case GNUNET_BLOCK_TYPE_FS_UBLOCK: + guard = va_arg (va, const char *); + if (0 != memcmp (guard, + "seen-set-size", + strlen ("seen-set-size"))) + { + /* va-args invalid! bad bug, complain! */ + GNUNET_break (0); + size = 8; + } + else + { + size = compute_bloomfilter_size (va_arg (va, unsigned int)); + } + if (0 == size) + size = raw_data_size; /* not for us to determine, use what we got! */ + GNUNET_break (NULL == va_arg (va, const char *)); + return GNUNET_BLOCK_GROUP_bf_create (cls, + size, + BLOOMFILTER_K, + type, + nonce, + raw_data, + raw_data_size); + default: + GNUNET_break (NULL == va_arg (va, const char *)); + GNUNET_break (0); + return NULL; + } +} + + /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would - * be done with the "get_key" function. + * be done with the #GNUNET_BLOCK_get_key() function. * * @param cls closure * @param type block type + * @param bg group to use for evaluation + * @param eo control flags * @param query original query (hash) - * @param bf pointer to bloom filter associated with query; possibly updated (!) - * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) - * @param xquery_size number of bytes in xquery + * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate - * @param reply_block_size number of bytes in reply block + * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult -block_plugin_fs_evaluate (void *cls, enum GNUNET_BLOCK_Type type, - const GNUNET_HashCode * query, - struct GNUNET_CONTAINER_BloomFilter **bf, - int32_t bf_mutator, const void *xquery, - size_t xquery_size, const void *reply_block, +block_plugin_fs_evaluate (void *cls, + enum GNUNET_BLOCK_Type type, + struct GNUNET_BLOCK_Group *bg, + enum GNUNET_BLOCK_EvaluationOptions eo, + const struct GNUNET_HashCode *query, + const void *xquery, + size_t xquery_size, + const void *reply_block, size_t reply_block_size) { - const struct SBlock *sb; - GNUNET_HashCode chash; - GNUNET_HashCode mhash; - const GNUNET_HashCode *nsid; - GNUNET_HashCode sh; + const struct UBlock *ub; + struct GNUNET_HashCode hc; + struct GNUNET_HashCode chash; switch (type) { case GNUNET_BLOCK_TYPE_FS_DBLOCK: case GNUNET_BLOCK_TYPE_FS_IBLOCK: - if (xquery_size != 0) + if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } - if (reply_block == NULL) + if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; return GNUNET_BLOCK_EVALUATION_OK_LAST; - case GNUNET_BLOCK_TYPE_FS_KBLOCK: - case GNUNET_BLOCK_TYPE_FS_NBLOCK: - if (xquery_size != 0) + case GNUNET_BLOCK_TYPE_FS_UBLOCK: + if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } - if (reply_block == NULL) + if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; - if (NULL != bf) - { - GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); - GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); - if (NULL != *bf) - { - if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) - return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; - } - else - { - *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); - } - GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); - } - return GNUNET_BLOCK_EVALUATION_OK_MORE; - case GNUNET_BLOCK_TYPE_FS_SBLOCK: - if (xquery_size != sizeof (GNUNET_HashCode)) + + if (reply_block_size < sizeof (struct UBlock)) { GNUNET_break_op (0); - return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; + return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - if (reply_block == NULL) - return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; - nsid = xquery; - if (reply_block_size < sizeof (struct SBlock)) + ub = reply_block; + GNUNET_CRYPTO_hash (&ub->verification_key, + sizeof (ub->verification_key), + &hc); + if (0 != memcmp (&hc, + query, + sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - sb = reply_block; - GNUNET_CRYPTO_hash (&sb->subspace, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &sh); - if (0 != memcmp (nsid, &sh, sizeof (GNUNET_HashCode))) + if (reply_block_size != ntohl (ub->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) { - GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "block-fs", - _ - ("Reply mismatched in terms of namespace. Discarded.\n")); + GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - if (NULL != bf) + if ( (0 == (eo & GNUNET_BLOCK_EO_LOCAL_SKIP_CRYPTO)) && + (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK, + &ub->purpose, + &ub->signature, + &ub->verification_key)) ) { - GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); - GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); - if (NULL != *bf) - { - if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) - return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; - } - else - { - *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); - } - GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); + GNUNET_break_op (0); + return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } + GNUNET_CRYPTO_hash (reply_block, + reply_block_size, + &chash); + if (GNUNET_YES == + GNUNET_BLOCK_GROUP_bf_test_and_set (bg, + &chash)) + return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; return GNUNET_BLOCK_EVALUATION_OK_MORE; default: return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; @@ -159,19 +237,19 @@ block_plugin_fs_evaluate (void *cls, enum GNUNET_BLOCK_Type type, * @param cls closure * @param type block type * @param block block to get the key for - * @param block_size number of bytes in block + * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block - * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported + * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int -block_plugin_fs_get_key (void *cls, enum GNUNET_BLOCK_Type type, - const void *block, size_t block_size, - GNUNET_HashCode * key) +block_plugin_fs_get_key (void *cls, + enum GNUNET_BLOCK_Type type, + const void *block, + size_t block_size, + struct GNUNET_HashCode *key) { - const struct KBlock *kb; - const struct SBlock *sb; - const struct NBlock *nb; + const struct UBlock *ub; switch (type) { @@ -179,104 +257,19 @@ block_plugin_fs_get_key (void *cls, enum GNUNET_BLOCK_Type type, case GNUNET_BLOCK_TYPE_FS_IBLOCK: GNUNET_CRYPTO_hash (block, block_size, key); return GNUNET_OK; - case GNUNET_BLOCK_TYPE_FS_KBLOCK: - if (block_size < sizeof (struct KBlock)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - kb = block; - if (block_size - sizeof (struct KBlock) != - ntohl (kb->purpose.size) - - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) - - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK, - &kb->purpose, &kb->signature, &kb->keyspace)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (key != NULL) - GNUNET_CRYPTO_hash (&kb->keyspace, - sizeof (struct - GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - key); - return GNUNET_OK; - case GNUNET_BLOCK_TYPE_FS_SBLOCK: - if (block_size < sizeof (struct SBlock)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - sb = block; - if (block_size != - ntohl (sb->purpose.size) + sizeof (struct GNUNET_CRYPTO_RsaSignature)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK, - &sb->purpose, &sb->signature, &sb->subspace)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (key != NULL) - *key = sb->identifier; - return GNUNET_OK; - case GNUNET_BLOCK_TYPE_FS_NBLOCK: - if (block_size < sizeof (struct NBlock)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - nb = block; - if (block_size - sizeof (struct NBlock) != - ntohl (nb->ns_purpose.size) - - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) - - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (block_size != - ntohl (nb->ksk_purpose.size) + - sizeof (struct GNUNET_CRYPTO_RsaSignature)) - { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG, - &nb->ksk_purpose, &nb->ksk_signature, - &nb->keyspace)) + case GNUNET_BLOCK_TYPE_FS_UBLOCK: + if (block_size < sizeof (struct UBlock)) { - GNUNET_break_op (0); - return GNUNET_NO; - } - if (GNUNET_OK != - GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK, - &nb->ns_purpose, &nb->ns_signature, - &nb->subspace)) - { - GNUNET_break_op (0); - return GNUNET_NO; + GNUNET_break (0); + return GNUNET_SYSERR; } - /* FIXME: we used to xor ID with NSID, - * why not here? */ - if (key != NULL) - GNUNET_CRYPTO_hash (&nb->keyspace, - sizeof (struct - GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - key); + ub = block; + GNUNET_CRYPTO_hash (&ub->verification_key, + sizeof (ub->verification_key), + key); return GNUNET_OK; default: + GNUNET_break (0); return GNUNET_SYSERR; } } @@ -292,16 +285,15 @@ libgnunet_plugin_block_fs_init (void *cls) { GNUNET_BLOCK_TYPE_FS_DBLOCK, GNUNET_BLOCK_TYPE_FS_IBLOCK, - GNUNET_BLOCK_TYPE_FS_KBLOCK, - GNUNET_BLOCK_TYPE_FS_SBLOCK, - GNUNET_BLOCK_TYPE_FS_NBLOCK, + GNUNET_BLOCK_TYPE_FS_UBLOCK, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; - api = GNUNET_malloc (sizeof (struct GNUNET_BLOCK_PluginFunctions)); + 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; }