#include "regex_block_lib.h"
#include "gnunet_dht_service.h"
#include "gnunet_statistics_service.h"
+#include "gnunet_constants.h"
+#include "gnunet_signatures.h"
+
#define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__)
#define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
#endif
-struct REGEX_ITERNAL_Announcement
+
+/**
+ * Handle to store cached data about a regex announce.
+ */
+struct REGEX_INTERNAL_Announcement
{
/**
* DHT handle to use, must be initialized externally.
/**
* Automaton representation of the regex (expensive to build).
*/
- struct REGEX_ITERNAL_Automaton* dfa;
+ struct REGEX_INTERNAL_Automaton* dfa;
/**
- * Identity under which to announce the regex.
+ * Our private key.
*/
- struct GNUNET_PeerIdentity id;
+ const struct GNUNET_CRYPTO_EccPrivateKey *priv;
/**
* Optional statistics handle to report usage. Can be NULL.
const char *proof,
int accepting,
unsigned int num_edges,
- const struct REGEX_ITERNAL_Edge *edges)
+ const struct REGEX_BLOCK_Edge *edges)
{
- struct REGEX_ITERNAL_Announcement *h = cls;
+ struct REGEX_INTERNAL_Announcement *h = cls;
struct RegexBlock *block;
- struct RegexEdge *block_edge;
size_t size;
- size_t len;
- unsigned int i;
- unsigned int offset;
- char *aux;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- " regex dht put for state %s\n",
- GNUNET_h2s (key));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " proof: %s\n", proof);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " num edges: %u\n", num_edges);
-
+ "DHT PUT for state %s with proof `%s' and %u edges\n",
+ GNUNET_h2s (key),
+ proof,
+ num_edges);
if (GNUNET_YES == accepting)
{
- struct RegexAccept block;
+ struct RegexAcceptBlock ab;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- " state %s is accepting, putting own id\n",
+ "State %s is accepting, putting own id\n",
GNUNET_h2s(key));
- size = sizeof (block);
- block.key = *key;
- block.id = h->id;
+ size = sizeof (struct RegexAcceptBlock);
+ ab.purpose.size = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
+ sizeof (struct GNUNET_TIME_AbsoluteNBO) +
+ sizeof (struct GNUNET_HashCode);
+ ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT);
+ ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION));
+ ab.key = *key;
+ GNUNET_CRYPTO_ecc_key_get_public (h->priv,
+ &ab.public_key);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_ecc_sign (h->priv,
+ &ab.purpose,
+ &ab.signature));
+
GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored",
1, GNUNET_NO);
GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored",
- sizeof (block), GNUNET_NO);
+ sizeof (struct RegexAcceptBlock), GNUNET_NO);
(void)
GNUNET_DHT_put (h->dht, key,
DHT_REPLICATION,
DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE,
GNUNET_BLOCK_TYPE_REGEX_ACCEPT,
size,
- (char *) &block,
+ &ab,
GNUNET_TIME_relative_to_absolute (DHT_TTL),
DHT_TTL,
NULL, NULL);
}
- len = strlen(proof);
- size = sizeof (struct RegexBlock) + len;
- block = GNUNET_malloc (size);
-
- block->key = *key;
- block->n_proof = htonl (len);
- block->n_edges = htonl (num_edges);
- block->accepting = htonl (accepting);
-
- /* Store the proof at the end of the block. */
- aux = (char *) &block[1];
- memcpy (aux, proof, len);
- aux = &aux[len];
-
- /* Store each edge in a variable length MeshEdge struct at the
- * very end of the MeshRegexBlock structure.
- */
- for (i = 0; i < num_edges; i++)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " edge %s towards %s\n",
- edges[i].label, GNUNET_h2s(&edges[i].destination));
-
- /* aux points at the end of the last block */
- len = strlen (edges[i].label);
- size += sizeof (struct RegexEdge) + len;
- // Calculate offset FIXME is this ok? use size instead?
- offset = aux - (char *) block;
- block = GNUNET_realloc (block, size);
- aux = &((char *) block)[offset];
- block_edge = (struct RegexEdge *) aux;
- block_edge->key = edges[i].destination;
- block_edge->n_token = htonl (len);
- aux = (char *) &block_edge[1];
- memcpy (aux, edges[i].label, len);
- aux = &aux[len];
- }
+ block = REGEX_BLOCK_create (proof,
+ num_edges, edges,
+ accepting,
+ &size);
(void)
GNUNET_DHT_put (h->dht, key,
DHT_REPLICATION,
DHT_OPT,
- GNUNET_BLOCK_TYPE_REGEX, size,
- (char *) block,
+ GNUNET_BLOCK_TYPE_REGEX,
+ size, block,
GNUNET_TIME_relative_to_absolute (DHT_TTL),
DHT_TTL,
NULL, NULL);
}
-struct REGEX_ITERNAL_Announcement *
-REGEX_ITERNAL_announce (struct GNUNET_DHT_Handle *dht,
- const struct GNUNET_PeerIdentity *id,
- const char *regex,
- uint16_t compression,
- struct GNUNET_STATISTICS_Handle *stats)
+/**
+ * Announce a regular expression: put all states of the automaton in the DHT.
+ * Does not free resources, must call REGEX_INTERNAL_announce_cancel for that.
+ *
+ * @param dht An existing and valid DHT service handle. CANNOT be NULL.
+ * @param priv our private key, must remain valid until the announcement is cancelled
+ * @param regex Regular expression to announce.
+ * @param compression How many characters per edge can we squeeze?
+ * @param stats Optional statistics handle to report usage. Can be NULL.
+ *
+ * @return Handle to reuse o free cached resources.
+ * Must be freed by calling REGEX_INTERNAL_announce_cancel.
+ */
+struct REGEX_INTERNAL_Announcement *
+REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht,
+ const struct GNUNET_CRYPTO_EccPrivateKey *priv,
+ const char *regex,
+ uint16_t compression,
+ struct GNUNET_STATISTICS_Handle *stats)
{
- struct REGEX_ITERNAL_Announcement *h;
+ struct REGEX_INTERNAL_Announcement *h;
GNUNET_assert (NULL != dht);
- h = GNUNET_malloc (sizeof (struct REGEX_ITERNAL_Announcement));
+ h = GNUNET_malloc (sizeof (struct REGEX_INTERNAL_Announcement));
h->regex = regex;
h->dht = dht;
h->stats = stats;
- h->id = *id;
- h->dfa = REGEX_ITERNAL_construct_dfa (regex,
+ h->priv = priv;
+ h->dfa = REGEX_INTERNAL_construct_dfa (regex,
strlen (regex),
compression);
- REGEX_ITERNAL_reannounce (h);
+ REGEX_INTERNAL_reannounce (h);
return h;
}
+/**
+ * Announce again a regular expression previously announced.
+ * Does use caching to speed up process.
+ *
+ * @param h Handle returned by a previous REGEX_INTERNAL_announce call.
+ */
void
-REGEX_ITERNAL_reannounce (struct REGEX_ITERNAL_Announcement *h)
+REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h)
{
GNUNET_assert (NULL != h->dfa); /* make sure to call announce first */
- LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_ITERNAL_reannounce: %.60s\n", h->regex);
+ LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_INTERNAL_reannounce: %.60s\n", h->regex);
LOG (GNUNET_ERROR_TYPE_DEBUG, " full: %s\n", h->regex);
- REGEX_ITERNAL_iterate_all_edges (h->dfa, ®ex_iterator, h);
+ REGEX_INTERNAL_iterate_all_edges (h->dfa, ®ex_iterator, h);
}
+
+/**
+ * Clear all cached data used by a regex announce.
+ * Does not close DHT connection.
+ *
+ * @param h Handle returned by a previous REGEX_INTERNAL_announce call.
+ */
void
-REGEX_ITERNAL_announce_cancel (struct REGEX_ITERNAL_Announcement *h)
+REGEX_INTERNAL_announce_cancel (struct REGEX_INTERNAL_Announcement *h)
{
- REGEX_ITERNAL_automaton_destroy (h->dfa);
+ REGEX_INTERNAL_automaton_destroy (h->dfa);
GNUNET_free (h);
}
*/
struct RegexSearchContext
{
- /**
- * Part of the description already consumed by
- * this particular search branch.
- */
+ /**
+ * Part of the description already consumed by
+ * this particular search branch.
+ */
size_t position;
- /**
- * Information about the search.
- */
- struct REGEX_ITERNAL_Search *info;
+ /**
+ * Information about the search.
+ */
+ struct REGEX_INTERNAL_Search *info;
- /**
- * We just want to look for one edge, the longer the better.
- * Keep its length.
- */
+ /**
+ * We just want to look for one edge, the longer the better.
+ * Keep its length.
+ */
unsigned int longest_match;
- /**
- * Destination hash of the longest match.
- */
+ /**
+ * Destination hash of the longest match.
+ */
struct GNUNET_HashCode hash;
};
* Struct to keep information of searches of services described by a regex
* using a user-provided string service description.
*/
-struct REGEX_ITERNAL_Search
+struct REGEX_INTERNAL_Search
{
/**
* DHT handle to use, must be initialized externally.
/**
* @param callback Callback for found peers.
*/
- REGEX_ITERNAL_Found callback;
+ REGEX_INTERNAL_Found callback;
/**
* @param callback_cls Closure for @c callback.
*/
static void
dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode * key,
+ const struct GNUNET_HashCode *key,
const struct GNUNET_PeerIdentity *get_path,
unsigned int get_path_length,
const struct GNUNET_PeerIdentity *put_path,
enum GNUNET_BLOCK_Type type,
size_t size, const void *data)
{
- const struct RegexAccept *block = data;
+ const struct RegexAcceptBlock *block = data;
struct RegexSearchContext *ctx = cls;
- struct REGEX_ITERNAL_Search *info = ctx->info;
+ struct REGEX_INTERNAL_Search *info = ctx->info;
+ struct GNUNET_PeerIdentity pid;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n");
LOG (GNUNET_ERROR_TYPE_INFO, " accept for %s (key %s)\n",
1, GNUNET_NO);
GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found",
size, GNUNET_NO);
-
+ GNUNET_CRYPTO_hash (&block->public_key,
+ sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded),
+ &pid.hashPubKey);
info->callback (info->callback_cls,
- &block->id,
+ &pid,
get_path, get_path_length,
put_path, put_path_length);
}
*/
static void
dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode * key,
+ const struct GNUNET_HashCode *key,
const struct GNUNET_PeerIdentity *get_path,
unsigned int get_path_length,
const struct GNUNET_PeerIdentity *put_path,
{
const struct RegexBlock *block = data;
struct RegexSearchContext *ctx = cls;
- struct REGEX_ITERNAL_Search *info = ctx->info;
+ struct REGEX_INTERNAL_Search *info = ctx->info;
void *copy;
size_t len;
char *datastore;
#if DEBUG_DHT
- if (NULL != put_path && 0 != put_path_length)
+ if ( (NULL != put_path) &&
+ (0 != put_path_length) )
{
datastore = GNUNET_strdup (GNUNET_i2s (&put_path[put_path_length - 1]));
}
GNUNET_free (datastore);
copy = GNUNET_malloc (size);
- memcpy (copy, data, size);
+ memcpy (copy, block, size);
GNUNET_break (
GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (info->dht_get_results,
- &((struct RegexBlock *)copy)->key, copy,
+ key, copy,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)
);
- len = ntohl (block->n_proof);
- {
- char proof[len + 1];
-
- memcpy (proof, &block[1], len);
- proof[len] = '\0';
- if (GNUNET_OK != REGEX_ITERNAL_check_proof (proof, key))
- {
- GNUNET_break_op (0);
- return;
- }
- }
len = strlen (info->description);
if (len == ctx->position) // String processed
{
- if (GNUNET_YES == ntohl (block->accepting))
+ if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block))
{
regex_find_path (key, ctx);
}
else
{
- LOG (GNUNET_ERROR_TYPE_INFO, " block not accepting!\n");
- // FIXME REGEX this block not successful, wait for more? start timeout?
+ LOG (GNUNET_ERROR_TYPE_INFO, "block not accepting!\n");
+ /* FIXME REGEX this block not successful, wait for more? start timeout? */
}
return;
}
struct RegexBlock *block = value;
struct RegexSearchContext *ctx = cls;
- if (GNUNET_YES == ntohl(block->accepting) &&
- ctx->position == strlen (ctx->info->description))
+ if ( (GNUNET_YES ==
+ GNUNET_BLOCK_is_accepting (block)) &&
+ (ctx->position == strlen (ctx->info->description)) )
{
LOG (GNUNET_ERROR_TYPE_INFO, " * Found accepting known block\n");
regex_find_path (key, ctx);
}
LOG (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n",
ctx->position, strlen(ctx->info->description),
- ntohl(block->accepting));
+ GNUNET_BLOCK_is_accepting (block));
regex_next_edge (block, SIZE_MAX, ctx);
const struct GNUNET_HashCode *key)
{
struct RegexSearchContext *ctx = cls;
- struct REGEX_ITERNAL_Search *info = ctx->info;
+ struct REGEX_INTERNAL_Search *info = ctx->info;
const char *current;
size_t current_len;
struct RegexSearchContext *ctx)
{
struct RegexSearchContext *new_ctx;
- struct REGEX_ITERNAL_Search *info = ctx->info;
+ struct REGEX_INTERNAL_Search *info = ctx->info;
struct GNUNET_DHT_GetHandle *get_h;
struct GNUNET_HashCode *hash;
const char *rest;
/* Find the longest match for the current string position,
* among tokens in the given block */
ctx->longest_match = 0;
- result = REGEX_ITERNAL_block_iterate (block, size,
+ result = REGEX_BLOCK_iterate (block, size,
®ex_edge_iterator, ctx);
GNUNET_break (GNUNET_OK == result);
}
-struct REGEX_ITERNAL_Search *
-REGEX_ITERNAL_search (struct GNUNET_DHT_Handle *dht,
+struct REGEX_INTERNAL_Search *
+REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht,
const char *string,
- REGEX_ITERNAL_Found callback,
+ REGEX_INTERNAL_Found callback,
void *callback_cls,
struct GNUNET_STATISTICS_Handle *stats)
{
- struct REGEX_ITERNAL_Search *h;
+ struct REGEX_INTERNAL_Search *h;
struct GNUNET_DHT_GetHandle *get_h;
struct RegexSearchContext *ctx;
struct GNUNET_HashCode key;
size_t len;
/* Initialize handle */
- LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_ITERNAL_search: %s\n", string);
+ LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_INTERNAL_search: %s\n", string);
GNUNET_assert (NULL != dht);
GNUNET_assert (NULL != callback);
- h = GNUNET_malloc (sizeof (struct REGEX_ITERNAL_Search));
+ h = GNUNET_malloc (sizeof (struct REGEX_INTERNAL_Search));
h->dht = dht;
h->description = GNUNET_strdup (string);
h->callback = callback;
h->callback_cls = callback_cls;
h->stats = stats;
h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
- h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
+ h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO);
/* Initialize context */
len = strlen (string);
- size = REGEX_ITERNAL_get_first_key (string, len, &key);
+ size = REGEX_INTERNAL_get_first_key (string, len, &key);
ctx = GNUNET_malloc (sizeof (struct RegexSearchContext));
ctx->position = size;
ctx->info = h;
const struct GNUNET_HashCode * key,
void *value)
{
-
GNUNET_free (value);
return GNUNET_YES;
}
/**
* Cancel an ongoing regex search in the DHT and free all resources.
*
- * @param ctx The search context.
+ * @param h the search context.
*/
-static void
-regex_cancel_search (struct REGEX_ITERNAL_Search *ctx)
+void
+REGEX_INTERNAL_search_cancel (struct REGEX_INTERNAL_Search *h)
{
- GNUNET_free (ctx->description);
- GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_handles,
+ unsigned int i;
+
+ GNUNET_free (h->description);
+ GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_handles,
®ex_cancel_dht_get, NULL);
- GNUNET_CONTAINER_multihashmap_iterate (ctx->dht_get_results,
+ GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_results,
®ex_free_result, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_results);
- GNUNET_CONTAINER_multihashmap_destroy (ctx->dht_get_handles);
- if (0 < ctx->n_contexts)
+ GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_results);
+ GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_handles);
+ if (0 < h->n_contexts)
{
- int i;
-
- for (i = 0; i < ctx->n_contexts; i++)
- {
- GNUNET_free (ctx->contexts[i]);
- }
- GNUNET_free (ctx->contexts);
+ for (i = 0; i < h->n_contexts; i++)
+ GNUNET_free (h->contexts[i]);
+ GNUNET_free (h->contexts);
}
-}
-
-void
-REGEX_ITERNAL_search_cancel (struct REGEX_ITERNAL_Search *h)
-{
- regex_cancel_search (h);
GNUNET_free (h);
}
-
-/* end of regex_dht.c */
+/* end of regex_internal_dht.c */