📄 search.c
字号:
/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors) 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 2, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//** * @file applications/fs/ecrs/search.c * @brief Helper functions for searching. * @author Christian Grothoff */#include "platform.h"#include "gnunet_protocols.h"#include "gnunet_fs_lib.h"#include "gnunet_ecrs_lib.h"#include "ecrs_core.h"#include "ecrs.h"#define DEBUG_SEARCH GNUNET_NO/** * Context for an individual search. Followed * by keyCount keys of type GNUNET_HashCode. */struct PendingSearch{ struct PendingSearch *next; struct GNUNET_ECRS_SearchContext *context; /** * The key (for decryption) */ GNUNET_HashCode decryptKey; unsigned int keyCount; /** * What type of query is it? */ unsigned int type;};/** * Context for search operation. */struct GNUNET_ECRS_SearchContext{ /** * Time when the cron-job was first started. */ GNUNET_CronTime start; /** * What is the global timeout? */ GNUNET_CronTime timeout; /** * Search context */ struct GNUNET_FS_SearchContext *sctx; /** * Active searches. */ struct PendingSearch *queries; GNUNET_ECRS_SearchResultProcessor spcb; void *spcbClosure; struct GNUNET_GE_Context *ectx; struct GNUNET_GC_Configuration *cfg; int aborted; int my_sctx; unsigned int anonymityLevel;};static intreceive_response_callback (const GNUNET_HashCode * key, const GNUNET_DatastoreValue * value, void *cls, unsigned long long uid);/** * Add a query to the SQC. */static voidadd_search (unsigned int type, unsigned int keyCount, const GNUNET_HashCode * keys, const GNUNET_HashCode * dkey, struct GNUNET_ECRS_SearchContext *sqc){ struct PendingSearch *ps; ps = GNUNET_malloc (sizeof (struct PendingSearch) + sizeof (GNUNET_HashCode) * keyCount); ps->type = type; ps->keyCount = keyCount; memcpy (&ps[1], keys, sizeof (GNUNET_HashCode) * keyCount); ps->decryptKey = *dkey; ps->context = sqc; ps->next = sqc->queries; sqc->queries = ps; GNUNET_FS_start_search (sqc->sctx, NULL, type, keyCount, keys, sqc->anonymityLevel, &receive_response_callback, ps);}/** * Add the query that corresponds to the given URI * to the SQC. */static voidadd_search_for_uri (const struct GNUNET_ECRS_URI *uri, struct GNUNET_ECRS_SearchContext *sqc){ struct GNUNET_GE_Context *ectx = sqc->ectx; switch (uri->type) { case chk: GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("CHK URI not allowed for search.\n")); break; case sks: { GNUNET_HashCode keys[2]; GNUNET_HashCode hk; /* hk = GNUNET_hash(identifier) */ GNUNET_HashCode hk2; /* hk2 = GNUNET_hash(hk) */ GNUNET_hash (uri->data.sks.identifier, strlen (uri->data.sks.identifier), &hk); GNUNET_hash (&hk, sizeof (GNUNET_HashCode), &hk2); /* compute routing key keys[0] = H(key) ^ namespace */ GNUNET_hash_xor (&hk2, &uri->data.sks.namespace, &keys[0]); keys[1] = uri->data.sks.namespace; add_search (GNUNET_ECRS_BLOCKTYPE_SIGNED, 2, &keys[0], &hk, sqc); break; } case ksk: { GNUNET_HashCode hc; GNUNET_HashCode query; struct GNUNET_RSA_PrivateKey *pk; GNUNET_RSA_PublicKey pub; int i; const char *keyword;#if DEBUG_SEARCH GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Computing queries (this may take a while).\n");#endif for (i = 0; i < uri->data.ksk.keywordCount; i++) { keyword = uri->data.ksk.keywords[i]; /* first character of the keyword is "+" or " " to indicate mandatory or not -- ignore for hashing! */ GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc); pk = GNUNET_RSA_create_key_from_hash (&hc); GNUNET_RSA_get_public_key (pk, &pub); GNUNET_hash (&pub, sizeof (GNUNET_RSA_PublicKey), &query); add_search (GNUNET_ECRS_BLOCKTYPE_ANY, /* GNUNET_ECRS_BLOCKTYPE_KEYWORD, GNUNET_ECRS_BLOCKTYPE_NAMESPACE or GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE ok */ 1, &query, &hc, sqc); GNUNET_RSA_free_key (pk); }#if DEBUG_SEARCH GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Queries ready.\n");#endif break; } case loc: GNUNET_GE_LOG (ectx, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER, _("LOC URI not allowed for search.\n")); break; default: GNUNET_GE_BREAK (ectx, 0); /* unknown URI type */ break; }}/** * We found an GNUNET_EC_SBlock. Decode the meta-data and call * the callback of the SQC with the root-URI for the namespace, * together with the namespace advertisement. Also, if this is * a result with updates, automatically start the search for * updates. */static intprocess_sblock_result (const GNUNET_EC_SBlock * sb, const GNUNET_HashCode * key, unsigned int size, struct GNUNET_ECRS_SearchContext *sqc){ static GNUNET_HashCode allZeros; struct GNUNET_GE_Context *ectx = sqc->ectx; GNUNET_ECRS_FileInfo fi; URI updateURI; int ret; const char *id; const char *uris; unsigned int len; unsigned int off; int isRoot; len = size - sizeof (GNUNET_EC_SBlock); off = GNUNET_string_buffer_tokenize ((const char *) &sb[1], len, 2, &id, &uris); if (off == 0) { GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */ return GNUNET_SYSERR; } fi.meta = GNUNET_meta_data_deserialize (ectx, &id[off], len - off); if (fi.meta == NULL) { GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */ return GNUNET_SYSERR; } isRoot = 0 == memcmp (&sb->identifier, &allZeros, sizeof (GNUNET_HashCode)); fi.uri = GNUNET_ECRS_string_to_uri (ectx, uris); if ((isRoot) && (fi.uri == NULL)) { fi.uri = GNUNET_malloc (sizeof (URI)); fi.uri->type = sks; GNUNET_hash (&sb->subspace, sizeof (GNUNET_RSA_PublicKey), &fi.uri->data.sks.namespace); fi.uri->data.sks.identifier = GNUNET_strdup (id); } if (fi.uri == NULL) { GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */ GNUNET_meta_data_destroy (fi.meta); return GNUNET_SYSERR; } if (sqc->spcb != NULL) { ret = sqc->spcb (&fi, key, isRoot, sqc->spcbClosure); if (ret == GNUNET_SYSERR) sqc->aborted = GNUNET_YES; } else ret = GNUNET_OK; if ((strlen (id) > 0) && (strlen (uris) > 0)) { updateURI.type = sks; GNUNET_hash (&sb->subspace, sizeof (GNUNET_RSA_PublicKey), &updateURI.data.sks.namespace); updateURI.data.sks.identifier = GNUNET_strdup (id); add_search_for_uri (&updateURI, sqc); GNUNET_free (updateURI.data.sks.identifier);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -