[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnunet] 07/20: -more work on DHTU integration
From: |
gnunet |
Subject: |
[gnunet] 07/20: -more work on DHTU integration |
Date: |
Sat, 19 Feb 2022 16:20:47 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository gnunet.
commit b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Jan 15 19:24:33 2022 +0100
-more work on DHTU integration
---
src/datacache/datacache.c | 86 ++-
src/datacache/plugin_datacache_heap.c | 8 +
src/datacache/plugin_datacache_postgres.c | 16 +-
src/datacache/plugin_datacache_sqlite.c | 52 +-
src/datacache/plugin_datacache_template.c | 2 +
src/dht/Makefile.am | 1 -
src/dht/dht_api.c | 11 +-
src/dht/gnunet-service-dht.c | 149 +++-
src/dht/gnunet-service-dht.h | 60 +-
src/dht/gnunet-service-dht_clients.c | 2 +-
src/dht/gnunet-service-dht_datacache.c | 124 ++--
src/dht/gnunet-service-dht_datacache.h | 11 +-
src/dht/gnunet-service-dht_hello.c | 154 ----
src/dht/gnunet-service-dht_hello.h | 55 --
src/dht/gnunet-service-dht_neighbours.c | 1108 ++++++++++++++---------------
src/dht/gnunet-service-dht_neighbours.h | 17 +-
src/dht/gnunet-service-dht_routing.c | 2 +-
src/dhtu/plugin_dhtu_gnunet.c | 13 +-
src/dhtu/plugin_dhtu_ip.c | 5 +-
src/hello/hello-uri.c | 149 +++-
src/include/gnunet_datacache_lib.h | 2 +
src/include/gnunet_datacache_plugin.h | 2 +
src/include/gnunet_dht_service.h | 10 +-
src/include/gnunet_dhtu_plugin.h | 5 +-
src/include/gnunet_hello_uri_lib.h | 44 +-
src/include/gnunet_protocols.h | 8 +-
26 files changed, 1145 insertions(+), 951 deletions(-)
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 944a99aad..761ab801f 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -114,11 +114,11 @@ env_delete_notify (void *cls,
h->utilization -= size;
GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# bytes stored"),
+ "# bytes stored",
-(long long) size,
GNUNET_NO);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# items stored"),
+ "# items stored",
-1,
GNUNET_NO);
}
@@ -136,15 +136,25 @@ GNUNET_DATACACHE_create (const struct
GNUNET_CONFIGURATION_Handle *cfg,
const struct GNUNET_OS_ProjectData *pd;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", "a))
+ GNUNET_CONFIGURATION_get_value_size (cfg,
+ section,
+ "QUOTA",
+ "a))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "QUOTA");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "QUOTA");
return NULL;
}
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name))
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "DATABASE",
+ &name))
{
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "DATABASE");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "DATABASE");
return NULL;
}
bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
@@ -152,10 +162,14 @@ GNUNET_DATACACHE_create (const struct
GNUNET_CONFIGURATION_Handle *cfg,
ret = GNUNET_new (struct GNUNET_DATACACHE_Handle);
if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF"))
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ section,
+ "DISABLE_BF"))
{
if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC"))
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ section,
+ "DISABLE_BF_RC"))
{
ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
}
@@ -174,7 +188,8 @@ GNUNET_DATACACHE_create (const struct
GNUNET_CONFIGURATION_Handle *cfg,
5); /* approx. 3% false
positives at max use */
}
}
- ret->stats = GNUNET_STATISTICS_create ("datacache", cfg);
+ ret->stats = GNUNET_STATISTICS_create ("datacache",
+ cfg);
ret->section = GNUNET_strdup (section);
ret->env.cfg = cfg;
ret->env.delete_notify = &env_delete_notify;
@@ -182,25 +197,31 @@ GNUNET_DATACACHE_create (const struct
GNUNET_CONFIGURATION_Handle *cfg,
ret->env.cls = ret;
ret->env.delete_notify = &env_delete_notify;
ret->env.quota = quota;
- LOG (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' datacache plugin\n"), name);
- GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name);
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ "Loading `%s' datacache plugin\n",
+ name);
+ GNUNET_asprintf (&libname,
+ "libgnunet_plugin_datacache_%s",
+ name);
ret->short_name = name;
ret->lib_name = libname;
/* Load the plugin within GNUnet's default context */
pd = GNUNET_OS_project_data_get ();
GNUNET_OS_init (GNUNET_OS_project_data_default ());
- ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
+ ret->api = GNUNET_PLUGIN_load (libname,
+ &ret->env);
GNUNET_OS_init (pd);
if (NULL == ret->api)
{
/* Try to load the plugin within the application's context
This normally happens when the application is not GNUnet itself but a
third party; inside GNUnet this is effectively a double failure. */
- ret->api = GNUNET_PLUGIN_load (libname, &ret->env);
+ ret->api = GNUNET_PLUGIN_load (libname,
+ &ret->env);
if (NULL == ret->api)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
- _ ("Failed to load datacache plugin for `%s'\n"),
+ "Failed to load datacache plugin for `%s'\n",
name);
GNUNET_DATACACHE_destroy (ret);
return NULL;
@@ -216,7 +237,9 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
if (NULL != h->filter)
GNUNET_CONTAINER_bloomfilter_free (h->filter);
if (NULL != h->api)
- GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api));
+ GNUNET_break (NULL ==
+ GNUNET_PLUGIN_unload (h->lib_name,
+ h->api));
GNUNET_free (h->lib_name);
GNUNET_free (h->short_name);
GNUNET_free (h->section);
@@ -270,17 +293,19 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
"Stored data under key `%s' in cache\n",
GNUNET_h2s (key));
if (NULL != h->filter)
- GNUNET_CONTAINER_bloomfilter_add (h->filter, key);
+ GNUNET_CONTAINER_bloomfilter_add (h->filter,
+ key);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# bytes stored"),
+ "# bytes stored",
used,
GNUNET_NO);
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# items stored"),
+ "# items stored",
1,
GNUNET_NO);
while (h->utilization + used > h->env.quota)
- GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls));
+ GNUNET_assert (GNUNET_OK ==
+ h->api->del (h->api->cls));
h->utilization += used;
return GNUNET_OK;
}
@@ -294,18 +319,18 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
void *iter_cls)
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop ("# requests received"),
+ "# requests received",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing request for key `%s'\n",
GNUNET_h2s (key));
if ((NULL != h->filter) &&
- (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
+ (GNUNET_OK !=
+ GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop (
- "# requests filtered by bloom filter"),
+ "# requests filtered by bloom filter",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -313,26 +338,33 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
GNUNET_h2s (key));
return 0; /* can not be present */
}
- return h->api->get (h->api->cls, key, type, iter, iter_cls);
+ return h->api->get (h->api->cls,
+ key,
+ type,
+ iter, iter_cls);
}
unsigned int
GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
GNUNET_STATISTICS_update (h->stats,
- gettext_noop (
- "# proximity search requests received"),
+ "# proximity search requests received",
1,
GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing proximity search at `%s'\n",
GNUNET_h2s (key));
- return h->api->get_closest (h->api->cls, key, num_results, iter, iter_cls);
+ return h->api->get_closest (h->api->cls,
+ key,
+ type,
+ num_results,
+ iter, iter_cls);
}
diff --git a/src/datacache/plugin_datacache_heap.c
b/src/datacache/plugin_datacache_heap.c
index fbd3aea9a..2756315fb 100644
--- a/src/datacache/plugin_datacache_heap.c
+++ b/src/datacache/plugin_datacache_heap.c
@@ -409,6 +409,8 @@ struct GetClosestContext
{
struct Value **values;
+ enum GNUNET_BLOCK_Type type;
+
unsigned int num_results;
const struct GNUNET_HashCode *key;
@@ -427,6 +429,9 @@ find_closest (void *cls,
if (1 != GNUNET_CRYPTO_hash_cmp (key,
gcc->key))
return GNUNET_OK; /* useless */
+ if ( (val->type != gcc->type) &&
+ (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
+ return GNUNET_OK; /* useless */
j = gcc->num_results;
for (unsigned int i = 0; i < gcc->num_results; i++)
{
@@ -457,6 +462,7 @@ find_closest (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -465,6 +471,7 @@ find_closest (void *cls,
static unsigned int
heap_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
@@ -473,6 +480,7 @@ heap_plugin_get_closest (void *cls,
struct Value *values[num_results];
struct GetClosestContext gcc = {
.values = values,
+ .type = type,
.num_results = num_results,
.key = key
};
diff --git a/src/datacache/plugin_datacache_postgres.c
b/src/datacache/plugin_datacache_postgres.c
index 6a44c44a5..61b699c8d 100644
--- a/src/datacache/plugin_datacache_postgres.c
+++ b/src/datacache/plugin_datacache_postgres.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018 GNUnet e.V.
+ Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018, 2022 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -109,9 +109,13 @@ init_connection (struct Plugin *plugin)
" ORDER BY prox ASC, discard_time ASC LIMIT 1",
0),
GNUNET_PQ_make_prepare ("get_closest",
- "SELECT discard_time,type,value,path,key FROM
gn011dc "
- "WHERE key>=$1 AND discard_time >= $2 ORDER BY key
ASC LIMIT $3",
- 3),
+ "SELECT discard_time,type,value,path,key FROM
gn011dc"
+ " WHERE key >= $1"
+ " AND discard_time >= $2"
+ " AND ( (type = $3) OR ( 0 = $3) )"
+ " ORDER BY key ASC"
+ " LIMIT $4",
+ 4),
GNUNET_PQ_make_prepare ("delrow",
"DELETE FROM gn011dc WHERE oid=$1",
1),
@@ -511,6 +515,7 @@ extract_result_cb (void *cls,
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -519,16 +524,19 @@ extract_result_cb (void *cls,
static unsigned int
postgres_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
struct Plugin *plugin = cls;
uint32_t num_results32 = (uint32_t) num_results;
+ uint32_t type32 = (uint32_t) type;
struct GNUNET_TIME_Absolute now;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (key),
GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_uint32 (&type32),
GNUNET_PQ_query_param_uint32 (&num_results32),
GNUNET_PQ_query_param_end
};
diff --git a/src/datacache/plugin_datacache_sqlite.c
b/src/datacache/plugin_datacache_sqlite.c
index d08b32caf..46ff66dce 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -454,6 +454,7 @@ sqlite_plugin_del (void *cls)
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -462,11 +463,13 @@ sqlite_plugin_del (void *cls)
static unsigned int
sqlite_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
{
struct Plugin *plugin = cls;
+ uint32_t type32 = type;
uint32_t num_results32 = num_results;
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute exp;
@@ -474,38 +477,46 @@ sqlite_plugin_get_closest (void *cls,
void *dat;
unsigned int cnt;
size_t psize;
- uint32_t type;
+ uint32_t rtype;
struct GNUNET_HashCode hc;
struct GNUNET_DHT_PathElement *path;
- struct GNUNET_SQ_QueryParam params[] =
- { GNUNET_SQ_query_param_auto_from_type (key),
+ struct GNUNET_SQ_QueryParam params[] = {
+ GNUNET_SQ_query_param_auto_from_type (key),
GNUNET_SQ_query_param_absolute_time (&now),
+ GNUNET_SQ_query_param_uint32 (&type32),
GNUNET_SQ_query_param_uint32 (&num_results32),
- GNUNET_SQ_query_param_end };
- struct GNUNET_SQ_ResultSpec rs[] =
- { GNUNET_SQ_result_spec_variable_size (&dat, &size),
+ GNUNET_SQ_query_param_end
+ };
+ struct GNUNET_SQ_ResultSpec rs[] = {
+ GNUNET_SQ_result_spec_variable_size (&dat, &size),
GNUNET_SQ_result_spec_absolute_time (&exp),
GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
- GNUNET_SQ_result_spec_uint32 (&type),
+ GNUNET_SQ_result_spec_uint32 (&rtype),
GNUNET_SQ_result_spec_auto_from_type (&hc),
- GNUNET_SQ_result_spec_end };
+ GNUNET_SQ_result_spec_end
+ };
now = GNUNET_TIME_absolute_get ();
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Processing GET_CLOSEST for key `%s'\n",
GNUNET_h2s (key));
- if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_closest_stmt, params))
+ if (GNUNET_OK !=
+ GNUNET_SQ_bind (plugin->get_closest_stmt,
+ params))
{
LOG_SQLITE (plugin->dbh,
GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"sqlite3_bind_xxx");
- GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
return 0;
}
cnt = 0;
while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
{
- if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_closest_stmt, rs))
+ if (GNUNET_OK !=
+ GNUNET_SQ_extract_result (plugin->get_closest_stmt,
+ rs))
{
GNUNET_break (0);
break;
@@ -522,14 +533,22 @@ sqlite_plugin_get_closest (void *cls,
"Found %u-byte result at %s when processing GET_CLOSE\n",
(unsigned int) size,
GNUNET_h2s (&hc));
- if (GNUNET_OK != iter (iter_cls, &hc, size, dat, type, exp, psize, path))
+ if (GNUNET_OK != iter (iter_cls,
+ &hc,
+ size,
+ dat,
+ rtype,
+ exp,
+ psize,
+ path))
{
GNUNET_SQ_cleanup_result (rs);
break;
}
GNUNET_SQ_cleanup_result (rs);
}
- GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt);
+ GNUNET_SQ_reset (plugin->dbh,
+ plugin->get_closest_stmt);
return cnt;
}
@@ -620,7 +639,7 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
&plugin->get_stmt)) ||
(SQLITE_OK != sq_prepare (plugin->dbh,
"SELECT _ROWID_,key,value FROM ds091"
- " WHERE expire < ?"
+ " WHERE expire < ?1"
" ORDER BY expire ASC LIMIT 1",
&plugin->del_expired_stmt)) ||
(SQLITE_OK != sq_prepare (plugin->dbh,
@@ -633,7 +652,10 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
(SQLITE_OK !=
sq_prepare (plugin->dbh,
"SELECT value,expire,path,type,key FROM ds091 "
- "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?",
+ " WHERE key>=?1 "
+ " AND expire >= ?2"
+ " AND ( (type=?3) or (0 == ?3) )"
+ " ORDER BY KEY ASC LIMIT ?4",
&plugin->get_closest_stmt)))
{
LOG_SQLITE (plugin->dbh,
diff --git a/src/datacache/plugin_datacache_template.c
b/src/datacache/plugin_datacache_template.c
index 231413ce9..2f7b41dbe 100644
--- a/src/datacache/plugin_datacache_template.c
+++ b/src/datacache/plugin_datacache_template.c
@@ -116,6 +116,7 @@ template_plugin_del (void *cls)
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -124,6 +125,7 @@ template_plugin_del (void *cls)
static unsigned int
template_plugin_get_closest (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls)
diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am
index 44439f66f..ab4ec1b3c 100644
--- a/src/dht/Makefile.am
+++ b/src/dht/Makefile.am
@@ -58,7 +58,6 @@ noinst_PROGRAMS = \
gnunet_service_dht_SOURCES = \
gnunet-service-dht.c gnunet-service-dht.h \
gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \
- gnunet-service-dht_hello.c gnunet-service-dht_hello.h \
gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \
gnunet-service-dht_routing.c gnunet-service-dht_routing.h
gnunet_service_dht_LDADD = \
diff --git a/src/dht/dht_api.c b/src/dht/dht_api.c
index 8389bbb95..a0c30d5e7 100644
--- a/src/dht/dht_api.c
+++ b/src/dht/dht_api.c
@@ -726,6 +726,7 @@ process_client_result (void *cls,
const struct GNUNET_DHT_ClientResultMessage *crm = cls;
struct GNUNET_DHT_GetHandle *get_handle = value;
size_t msize = ntohs (crm->header.size) - sizeof(*crm);
+ uint16_t type = ntohl (crm->type);
uint32_t put_path_length = ntohl (crm->put_path_length);
uint32_t get_path_length = ntohl (crm->get_path_length);
const struct GNUNET_DHT_PathElement *put_path;
@@ -745,7 +746,13 @@ process_client_result (void *cls,
(unsigned long long) get_handle->unique_id);
return GNUNET_YES;
}
- /* FIXME: might want to check that type matches */
+ if ( (get_handle->type != GNUNET_BLOCK_TYPE_ANY) &&
+ (get_handle->type != type) )
+ {
+ /* type mismatch */
+ GNUNET_break (0);
+ return GNUNET_YES;
+ }
meta_length =
sizeof(struct GNUNET_DHT_PathElement) * (get_path_length +
put_path_length);
data_length = msize - meta_length;
@@ -786,7 +793,7 @@ process_client_result (void *cls,
get_path_length,
put_path,
put_path_length,
- ntohl (crm->type),
+ type,
data_length,
data);
return GNUNET_YES;
diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c
index 6f2573d26..35e219926 100644
--- a/src/dht/gnunet-service-dht.c
+++ b/src/dht/gnunet-service-dht.c
@@ -28,14 +28,20 @@
#include "gnunet_block_lib.h"
#include "gnunet_util_lib.h"
#include "gnunet_hello_lib.h"
+#include "gnunet_hello_uri_lib.h"
#include "gnunet_dht_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet-service-dht.h"
#include "gnunet-service-dht_datacache.h"
-#include "gnunet-service-dht_hello.h"
#include "gnunet-service-dht_neighbours.h"
#include "gnunet-service-dht_routing.h"
+/**
+ * How often do we broadcast our HELLO to neighbours if
+ * nothing special happens?
+ */
+#define HELLO_FREQUENCY GNUNET_TIME_UNIT_HOURS
+
/**
* Information we keep per underlay.
@@ -110,7 +116,27 @@ struct MyAddress
/**
* Our HELLO
*/
-struct GNUNET_MessageHeader *GDS_my_hello;
+struct GNUNET_HELLO_Builder *GDS_my_hello;
+
+/**
+ * Identity of this peer.
+ */
+struct GNUNET_PeerIdentity GDS_my_identity;
+
+/**
+ * Hash of the identity of this peer.
+ */
+struct GNUNET_HashCode GDS_my_identity_hash;
+
+/**
+ * Our private key.
+ */
+struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
+
+/**
+ * Task broadcasting our HELLO.
+ */
+static struct GNUNET_SCHEDULER_Task *hello_task;
/**
* Handles for the DHT underlays.
@@ -132,11 +158,6 @@ static struct MyAddress *a_head;
*/
static struct MyAddress *a_tail;
-/**
- * Hello address expiration
- */
-struct GNUNET_TIME_Relative hello_expiration;
-
/**
* log of the current network size estimate, used as the point where
* we switch between random and deterministic routing.
@@ -195,13 +216,29 @@ GDS_NSE_get (void)
/**
- * Update our HELLO with all of our our addresses.
+ * Task run periodically to broadcast our HELLO.
+ *
+ * @param cls NULL
*/
static void
-update_hello (void)
+broadcast_hello (void *cls)
{
- GNUNET_free (GDS_my_hello);
- // FIXME: build new HELLO properly!
+ struct GNUNET_MessageHeader *hello;
+
+ (void) cls;
+ /* TODO: randomize! */
+ hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_FREQUENCY,
+ &broadcast_hello,
+ NULL);
+ hello = GNUNET_HELLO_builder_to_dht_hello_msg (GDS_my_hello,
+ &GDS_my_private_key);
+ if (NULL == hello)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GDS_NEIGHBOURS_broadcast (hello);
+ GNUNET_free (hello);
}
@@ -231,7 +268,12 @@ u_address_add (void *cls,
a_tail,
a);
*ctx = a;
- update_hello ();
+ GNUNET_HELLO_builder_add_address (GDS_my_hello,
+ address);
+ if (NULL != hello_task)
+ GNUNET_SCHEDULER_cancel (hello_task);
+ hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
+ NULL);
}
@@ -245,12 +287,47 @@ u_address_del (void *ctx)
{
struct MyAddress *a = ctx;
+ GNUNET_HELLO_builder_del_address (GDS_my_hello,
+ a->url);
GNUNET_CONTAINER_DLL_remove (a_head,
a_tail,
a);
GNUNET_free (a->url);
GNUNET_free (a);
- update_hello ();
+ if (NULL != hello_task)
+ GNUNET_SCHEDULER_cancel (hello_task);
+ hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
+ NULL);
+}
+
+
+void
+GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
+ const char *address)
+{
+ for (struct Underlay *u = u_head;
+ NULL != u;
+ u = u->next)
+ u->dhtu->try_connect (u->dhtu->cls,
+ pid,
+ address);
+}
+
+
+void
+GDS_u_send (struct Underlay *u,
+ struct GNUNET_DHTU_Target *target,
+ const void *msg,
+ size_t msg_size,
+ GNUNET_SCHEDULER_TaskCallback finished_cb,
+ void *finished_cb_cls)
+{
+ u->dhtu->send (u->dhtu->cls,
+ target,
+ msg,
+ msg_size,
+ finished_cb,
+ finished_cb_cls);
}
@@ -265,7 +342,6 @@ shutdown_task (void *cls)
GDS_NEIGHBOURS_done ();
GDS_DATACACHE_done ();
GDS_ROUTING_done ();
- GDS_HELLO_done ();
if (NULL != GDS_block_context)
{
GNUNET_BLOCK_context_destroy (GDS_block_context);
@@ -277,7 +353,7 @@ shutdown_task (void *cls)
GNUNET_YES);
GDS_stats = NULL;
}
- GNUNET_free (GDS_my_hello);
+ GNUNET_HELLO_builder_free (GDS_my_hello);
GDS_my_hello = NULL;
GDS_CLIENTS_stop ();
}
@@ -348,14 +424,39 @@ run (void *cls,
{
GDS_cfg = c;
GDS_service = service;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c,
- "transport",
- "HELLO_EXPIRATION",
- &hello_expiration))
{
- hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION;
+ char *keyfile;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
+ "PEER",
+ "PRIVATE_KEY",
+ &keyfile))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "PEER",
+ "PRIVATE_KEY");
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (GNUNET_SYSERR ==
+ GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
+ GNUNET_YES,
+ &GDS_my_private_key))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to setup peer's private key\n");
+ GNUNET_free (keyfile);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (keyfile);
}
+ GNUNET_CRYPTO_eddsa_key_get_public (&GDS_my_private_key,
+ &GDS_my_identity.public_key);
+ GNUNET_CRYPTO_hash (&GDS_my_identity,
+ sizeof(struct GNUNET_PeerIdentity),
+ &GDS_my_identity_hash);
GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
GDS_stats = GNUNET_STATISTICS_create ("dht",
GDS_cfg);
@@ -364,6 +465,12 @@ run (void *cls,
GDS_DATACACHE_init ();
GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
NULL);
+ if (GNUNET_OK !=
+ GDS_NEIGHBOURS_init ())
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
GNUNET_CONFIGURATION_iterate_sections (GDS_cfg,
&load_underlay,
NULL);
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 687e2d4d3..403b3f5a1 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -27,12 +27,18 @@
#define GNUNET_SERVICE_DHT_H
#include "gnunet-service-dht_datacache.h"
+#include "gnunet-service-dht_neighbours.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_service.h"
#define DEBUG_DHT GNUNET_EXTRA_LOGGING
+/**
+ * Information we keep per underlay.
+ */
+struct Underlay;
+
/**
* Configuration we use.
*/
@@ -54,9 +60,59 @@ extern struct GNUNET_BLOCK_Context *GDS_block_context;
extern struct GNUNET_STATISTICS_Handle *GDS_stats;
/**
- * Our HELLO
+ * Our HELLO builder.
+ */
+extern struct GNUNET_HELLO_Builder *GDS_my_hello;
+
+/**
+ * Identity of this peer.
+ */
+extern struct GNUNET_PeerIdentity GDS_my_identity;
+
+/**
+ * Hash of the identity of this peer.
+ */
+extern struct GNUNET_HashCode GDS_my_identity_hash;
+
+/**
+ * Our private key.
*/
-extern struct GNUNET_MessageHeader *GDS_my_hello;
+extern struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
+
+
+/**
+ * Ask all underlays to connect to peer @a pid at @a address.
+ *
+ * @param pid identity of the peer we would connect to
+ * @param address an address of @a pid
+ */
+void
+GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
+ const char *address);
+
+
+/**
+ * Send message to some other participant over the network. Note that
+ * sending is not guaranteeing that the other peer actually received the
+ * message. For any given @a target, the DHT must wait for the @a
+ * finished_cb to be called before calling send() again.
+ *
+ * @param u underlay to use for transmission
+ * @param target receiver identification
+ * @param msg message
+ * @param msg_size number of bytes in @a msg
+ * @param finished_cb function called once transmission is done
+ * (not called if @a target disconnects, then only the
+ * disconnect_cb is called).
+ * @param finished_cb_cls closure for @a finished_cb
+ */
+void
+GDS_u_send (struct Underlay *u,
+ struct GNUNET_DHTU_Target *target,
+ const void *msg,
+ size_t msg_size,
+ GNUNET_SCHEDULER_TaskCallback finished_cb,
+ void *finished_cb_cls);
/**
diff --git a/src/dht/gnunet-service-dht_clients.c
b/src/dht/gnunet-service-dht_clients.c
index a1c3024de..bc39e004a 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -917,7 +917,7 @@ forward_reply (void *cls,
GNUNET_NO);
return GNUNET_YES; /* type mismatch */
}
- if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) &&
+ if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
(0 != GNUNET_memcmp (&frc->bd->key,
query_hash)) )
{
diff --git a/src/dht/gnunet-service-dht_datacache.c
b/src/dht/gnunet-service-dht_datacache.c
index cb778717b..880c72cb2 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -68,7 +68,7 @@ GDS_DATACACHE_handle_put (const struct
GDS_DATACACHE_BlockData *bd)
1,
GNUNET_NO);
GNUNET_CRYPTO_hash_xor (&bd->key,
- &my_identity_hash,
+ &GDS_my_identity_hash,
&xor);
r = GNUNET_DATACACHE_put (datacache,
&bd->key,
@@ -231,7 +231,15 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode
*key,
GDS_DATACACHE_GetCallback gc,
void *gc_cls)
{
- struct GetRequestContext ctx;
+ struct GetRequestContext ctx = {
+ .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
+ .key = *key,
+ .xquery = xquery,
+ .xquery_size = xquery_size,
+ .bg = bg,
+ .gc = gc,
+ .gc_cls = gc_cls
+ };
unsigned int r;
if (NULL == datacache)
@@ -240,13 +248,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode
*key,
"# GET requests given to datacache",
1,
GNUNET_NO);
- ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
- ctx.key = *key;
- ctx.xquery = xquery;
- ctx.xquery_size = xquery_size;
- ctx.bg = bg;
- ctx.gc = gc;
- ctx.gc_cls = gc_cls;
r = GNUNET_DATACACHE_get (datacache,
key,
type,
@@ -261,85 +262,44 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode
*key,
}
-/**
- * Closure for #datacache_get_successors_iterator().
- */
-struct SuccContext
-{
- /**
- * Function to call on the result
- */
- GDS_DATACACHE_GetCallback cb;
-
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
-
-};
-
-
-/**
- * Iterator for local get request results,
- *
- * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
- * @param key the key this data is stored under
- * @param size the size of the data identified by key
- * @param data the actual data
- * @param type the type of the data
- * @param exp when does this value expire?
- * @param put_path_length number of peers in @a put_path
- * @param put_path path the reply took on put
- * @return #GNUNET_OK to continue iteration, anything else
- * to stop iteration.
- */
-static enum GNUNET_GenericReturnValue
-datacache_get_successors_iterator (void *cls,
- const struct GNUNET_HashCode *key,
- size_t size,
- const char *data,
- enum GNUNET_BLOCK_Type type,
- struct GNUNET_TIME_Absolute exp,
- unsigned int put_path_length,
- const struct
- GNUNET_DHT_PathElement *put_path)
-{
- const struct SuccContext *sc = cls;
- struct GDS_DATACACHE_BlockData bd = {
- .key = *key,
- .expiration_time = exp,
- .put_path = put_path,
- .data = data,
- .data_size = size,
- .put_path_length = put_path_length,
- .type = type
- };
-
- /* NOTE: The datacache currently does not store the RO from
- the original 'put', so we don't know the 'correct' option
- at this point anymore. Thus, we conservatively assume
- that recording is desired (for now). */
- sc->cb (sc->cb_cls,
- &bd);
- return GNUNET_OK;
-}
-
-
-void
+enum GNUNET_BLOCK_EvaluationResult
GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
+ const void *xquery,
+ size_t xquery_size,
+ struct GNUNET_BLOCK_Group *bg,
GDS_DATACACHE_GetCallback cb,
void *cb_cls)
{
- struct SuccContext sc = {
- .cb = cb,
- .cb_cls = cb_cls
+ struct GetRequestContext ctx = {
+ .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
+ .key = *key,
+ .xquery = xquery,
+ .xquery_size = xquery_size,
+ .bg = bg,
+ .gc = cb,
+ .gc_cls = cb_cls
};
+ unsigned int r;
- (void) GNUNET_DATACACHE_get_closest (datacache,
- key,
- NUM_CLOSEST,
- &datacache_get_successors_iterator,
- &sc);
+ if (NULL == datacache)
+ return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# GET closest requests given to datacache",
+ 1,
+ GNUNET_NO);
+ r = GNUNET_DATACACHE_get_closest (datacache,
+ key,
+ type,
+ NUM_CLOSEST,
+ &datacache_get_iterator,
+ &ctx);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "DATACACHE approximate GET for key %s completed (%d). %u results
found.\n",
+ GNUNET_h2s (key),
+ ctx.eval,
+ r);
+ return ctx.eval;
}
diff --git a/src/dht/gnunet-service-dht_datacache.h
b/src/dht/gnunet-service-dht_datacache.h
index 691a51e0e..69a18c605 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -122,11 +122,20 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode
*key,
* another peer.
*
* @param key the location at which the peer is looking for data that is close
+ * @param type requested data type
+ * @param xquery extended query
+ * @param xquery_size number of bytes in xquery
+ * @param bg block group to use for evaluation of replies
* @param cb function to call with the result
* @param cb_cls closure for @a cb
+ * @return evaluation result for the local replies
*/
-void
+enum GNUNET_BLOCK_EvaluationResult
GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
+ const void *xquery,
+ size_t xquery_size,
+ struct GNUNET_BLOCK_Group *bg,
GDS_DATACACHE_GetCallback cb,
void *cb_cls);
diff --git a/src/dht/gnunet-service-dht_hello.c
b/src/dht/gnunet-service-dht_hello.c
deleted file mode 100644
index 949456575..000000000
--- a/src/dht/gnunet-service-dht_hello.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2011 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-
-/**
- * @file dht/gnunet-service-dht_hello.c
- * @brief GNUnet DHT integration with peerinfo
- * @author Christian Grothoff
- *
- * TODO:
- * - consider adding mechanism to remove expired HELLOs
- */
-#include "platform.h"
-#include "gnunet-service-dht.h"
-#include "gnunet-service-dht_hello.h"
-#include "gnunet_peerinfo_service.h"
-
-
-/**
- * Handle for peerinfo notifications.
- */
-static struct GNUNET_PEERINFO_NotifyContext *pnc;
-
-/**
- * Hash map of peers to HELLOs.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
-
-
-/**
- * Obtain a peer's HELLO if available
- *
- * @param peer peer to look for a HELLO from
- * @return HELLO for the given peer
- */
-const struct GNUNET_HELLO_Message *
-GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
-{
- if (NULL == peer_to_hello)
- return NULL;
- return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
- peer);
-}
-
-
-/**
- * Function called for each HELLO known to PEERINFO.
- *
- * @param cls closure
- * @param peer id of the peer, NULL for last call
- * @param hello hello message for the peer (can be NULL)
- * @param err_msg error message (not used)
- *
- * FIXME this is called once per address. Merge instead of replacing?
- */
-static void
-process_hello (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Message *hello,
- const char *err_msg)
-{
- struct GNUNET_TIME_Absolute ex;
- struct GNUNET_HELLO_Message *hm;
-
- if (NULL == hello)
- return;
- ex = GNUNET_HELLO_get_last_expiration (hello);
- if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
- return;
- GNUNET_STATISTICS_update (GDS_stats,
- "# HELLOs obtained from peerinfo",
- 1,
- GNUNET_NO);
- hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
- peer);
- GNUNET_free (hm);
- hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
- GNUNET_memcpy (hm,
- hello,
- GNUNET_HELLO_size (hello));
- GNUNET_assert (GNUNET_SYSERR !=
- GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
- peer,
- hm,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
-}
-
-
-/**
- * Initialize HELLO subsystem.
- */
-void
-GDS_HELLO_init ()
-{
- pnc = GNUNET_PEERINFO_notify (GDS_cfg,
- GNUNET_NO,
- &process_hello,
- NULL);
- peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
- GNUNET_NO);
-}
-
-
-/**
- * Free memory occopied by the HELLO.
- */
-static enum GNUNET_GenericReturnValue
-free_hello (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *hello)
-{
- GNUNET_free (hello);
- return GNUNET_OK;
-}
-
-
-/**
- * Shutdown HELLO subsystem.
- */
-void
-GDS_HELLO_done ()
-{
- if (NULL != pnc)
- {
- GNUNET_PEERINFO_notify_cancel (pnc);
- pnc = NULL;
- }
- if (NULL != peer_to_hello)
- {
- GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
- &free_hello,
- NULL);
- GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
- }
-}
-
-
-/* end of gnunet-service-dht_hello.c */
diff --git a/src/dht/gnunet-service-dht_hello.h
b/src/dht/gnunet-service-dht_hello.h
deleted file mode 100644
index f8b90862d..000000000
--- a/src/dht/gnunet-service-dht_hello.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- This file is part of GNUnet.
- Copyright (C) 2011 GNUnet e.V.
-
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- 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
- Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- SPDX-License-Identifier: AGPL3.0-or-later
- */
-
-/**
- * @file dht/gnunet-service-dht_hello.h
- * @brief GNUnet DHT integration with peerinfo
- * @author Christian Grothoff
- */
-#ifndef GNUNET_SERVICE_DHT_HELLO_H
-#define GNUNET_SERVICE_DHT_HELLO_H
-
-#include "gnunet_util_lib.h"
-#include "gnunet_hello_lib.h"
-
-/**
- * Obtain a peer's HELLO if available
- *
- * @param peer peer to look for a HELLO from
- * @return HELLO for the given peer
- */
-const struct GNUNET_HELLO_Message *
-GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
-
-
-/**
- * Initialize HELLO subsystem.
- */
-void
-GDS_HELLO_init (void);
-
-
-/**
- * Shutdown HELLO subsystem.
- */
-void
-GDS_HELLO_done (void);
-
-#endif
diff --git a/src/dht/gnunet-service-dht_neighbours.c
b/src/dht/gnunet-service-dht_neighbours.c
index bc473df69..b7b5e8097 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -29,8 +29,8 @@
#include "gnunet_protocols.h"
#include "gnunet_signatures.h"
#include "gnunet_hello_lib.h"
+#include "gnunet_hello_uri_lib.h"
#include "gnunet-service-dht.h"
-#include "gnunet-service-dht_hello.h"
#include "gnunet-service-dht_neighbours.h"
#include "gnunet-service-dht_routing.h"
#include "dht.h"
@@ -88,11 +88,6 @@
*/
#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
-/**
- * Hello address expiration
- */
-extern struct GNUNET_TIME_Relative hello_expiration;
-
GNUNET_NETWORK_STRUCT_BEGIN
@@ -260,81 +255,129 @@ GNUNET_NETWORK_STRUCT_END
/**
* Entry for a peer in a bucket.
*/
-struct PeerInfo
+struct PeerInfo;
+
+
+/**
+ * List of targets that we can use to reach this peer.
+ */
+struct Target
{
/**
- * Next peer entry (DLL)
+ * Kept in a DLL.
*/
- struct PeerInfo *next;
+ struct Target *next;
/**
- * Prev peer entry (DLL)
+ * Kept in a DLL.
*/
- struct PeerInfo *prev;
+ struct Target *prev;
/**
* Handle for sending messages to this peer.
*/
- struct GNUNET_DHTU_Target *target;
+ struct GNUNET_DHTU_Target *utarget;
/**
- * What is the identity of the peer?
+ * Underlay providing this target.
*/
- struct GNUNET_PeerIdentity id;
+ struct Underlay *u;
/**
- * Hash of @e id.
+ * Peer this is a target for.
*/
- struct GNUNET_HashCode phash;
+ struct PeerInfo *pi;
/**
- * Which bucket is this peer in?
+ * Set to number of messages are waiting for the transmission to finish.
*/
- int peer_bucket;
+ unsigned int load;
+
+ /**
+ * Set to @a true if the target was dropped, but we could not clean
+ * up yet because @e busy was also true.
+ */
+ bool dropped;
+
};
/**
- * Peers are grouped into buckets.
+ * Entry for a peer in a bucket.
*/
-struct PeerBucket
+struct PeerInfo
{
/**
- * Head of DLL
+ * What is the identity of the peer?
*/
- struct PeerInfo *head;
+ struct GNUNET_PeerIdentity id;
/**
- * Tail of DLL
+ * Hash of @e id.
*/
- struct PeerInfo *tail;
+ struct GNUNET_HashCode phash;
/**
- * Number of peers in the bucket.
+ * When does our HELLO from this peer expire?
*/
- unsigned int peers_size;
+ struct GNUNET_TIME_Absolute hello_expiration;
+
+ /**
+ * Next peer entry (DLL)
+ */
+ struct PeerInfo *next;
+
+ /**
+ * Prev peer entry (DLL)
+ */
+ struct PeerInfo *prev;
+
+ /**
+ * Head of DLL of targets for this peer.
+ */
+ struct Target *t_head;
+
+ /**
+ * Tail of DLL of targets for this peer.
+ */
+ struct Target *t_tail;
+
+ /**
+ * Block with a HELLO of this peer.
+ */
+ void *hello;
+
+ /**
+ * Number of bytes in @e hello.
+ */
+ size_t hello_size;
+
+ /**
+ * Which bucket is this peer in?
+ */
+ int peer_bucket;
};
/**
- * Information about a peer that we would like to connect to.
+ * Peers are grouped into buckets.
*/
-struct ConnectInfo
+struct PeerBucket
{
/**
- * Handle to active HELLO offer operation, or NULL.
+ * Head of DLL
*/
- struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
+ struct PeerInfo *head;
/**
- * Handle to active connectivity suggestion operation, or NULL.
+ * Tail of DLL
*/
- struct GNUNET_DHTU_PreferenceHandle *ph;
+ struct PeerInfo *tail;
/**
- * How much would we like to connect to this peer?
+ * Number of peers in the bucket.
*/
- uint32_t strength;
+ unsigned int peers_size;
};
@@ -370,12 +413,6 @@ static struct PeerBucket k_buckets[MAX_BUCKETS];
*/
static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers;
-/**
- * Hash map of all peers we would like to be connected to.
- * Values are of type `struct ConnectInfo`.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers;
-
/**
* Maximum size for each bucket.
*/
@@ -386,20 +423,83 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
*/
static struct GNUNET_SCHEDULER_Task *find_peer_task;
-/**
- * Identity of this peer.
- */
-static struct GNUNET_PeerIdentity my_identity;
/**
- * Hash of the identity of this peer.
+ * Function called whenever we finished sending to a target.
+ * Marks the transmission as finished (and the target as ready
+ * for the next message).
+ *
+ * @param cls a `struct Target *`
*/
-struct GNUNET_HashCode my_identity_hash;
+static void
+send_done_cb (void *cls)
+{
+ struct Target *t = cls;
+ struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
+
+ GNUNET_assert (t->load > 0);
+ t->load--;
+ if (0 < t->load)
+ return;
+ if (t->dropped)
+ {
+ GNUNET_free (t);
+ return;
+ }
+ /* move target back to the front */
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ GNUNET_CONTAINER_DLL_insert (pi->t_head,
+ pi->t_tail,
+ t);
+}
+
/**
- * Our private key.
+ * Send @a msg to @a pi.
+ *
+ * @param pi where to send the message
+ * @param msg message to send
*/
-static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key;
+static void
+do_send (struct PeerInfo *pi,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct Target *t;
+
+ for (t = pi->t_head;
+ NULL != t;
+ t = t->next)
+ if (t->load < MAXIMUM_PENDING_PER_PEER)
+ break;
+ if (NULL == t)
+ {
+ /* all targets busy, drop message */
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# messages dropped (underlays busy)",
+ 1,
+ GNUNET_NO);
+ return;
+ }
+ t->load++;
+ /* rotate busy targets to the end */
+ if (MAXIMUM_PENDING_PER_PEER == t->load)
+ {
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ GNUNET_CONTAINER_DLL_insert_tail (pi->t_head,
+ pi->t_tail,
+ t);
+ }
+ GDS_u_send (t->u,
+ t->utarget,
+ msg,
+ ntohs (msg->size),
+ &send_done_cb,
+ t);
+}
/**
@@ -436,7 +536,7 @@ sign_path (const struct GNUNET_HashCode *key,
GNUNET_CRYPTO_hash (data,
data_size,
&hs.h_data);
- GNUNET_CRYPTO_eddsa_sign (&my_private_key,
+ GNUNET_CRYPTO_eddsa_sign (&GDS_my_private_key,
&hs,
sig);
}
@@ -456,7 +556,7 @@ find_bucket (const struct GNUNET_HashCode *hc)
unsigned int bits;
GNUNET_CRYPTO_hash_xor (hc,
- &my_identity_hash,
+ &GDS_my_identity_hash,
&xor);
bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
if (bits == MAX_BUCKETS)
@@ -469,175 +569,6 @@ find_bucket (const struct GNUNET_HashCode *hc)
}
-/**
- * Function called when #GNUNET_TRANSPORT_offer_hello() is done.
- * Clean up the "oh" field in the @a cls
- *
- * @param cls a `struct ConnectInfo`
- */
-static void
-offer_hello_done (void *cls)
-{
- struct ConnectInfo *ci = cls;
-
- ci->oh = NULL;
-}
-
-
-/**
- * Function called for all entries in #all_desired_peers to clean up.
- *
- * @param cls NULL
- * @param peer peer the entry is for
- * @param value the value to remove
- * @return #GNUNET_YES
- */
-static enum GNUNET_GenericReturnValue
-free_connect_info (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *value)
-{
- struct ConnectInfo *ci = value;
-
- (void) cls;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
- peer,
- ci));
- if (NULL != ci->ph)
- {
- // ci->u->drop (ci->ph); // FIXME!
- ci->ph = NULL;
- }
- if (NULL != ci->oh)
- {
- GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
- ci->oh = NULL;
- }
- GNUNET_free (ci);
- return GNUNET_YES;
-}
-
-
-/**
- * Consider if we want to connect to a given peer, and if so
- * let ATS know. If applicable, the HELLO is offered to the
- * TRANSPORT service.
- *
- * @param pid peer to consider connectivity requirements for
- * @param h a HELLO message, or NULL
- */
-static void
-try_connect (const struct GNUNET_PeerIdentity *pid,
- const struct GNUNET_MessageHeader *h)
-{
- int bucket_idx;
- struct GNUNET_HashCode pid_hash;
- struct ConnectInfo *ci;
- uint32_t strength;
- struct PeerBucket *bucket;
-
- GNUNET_CRYPTO_hash (pid,
- sizeof(struct GNUNET_PeerIdentity),
- &pid_hash);
- bucket_idx = find_bucket (&pid_hash);
- if (bucket_idx < 0)
- {
- GNUNET_break (0);
- return; /* self!? */
- }
- bucket = &k_buckets[bucket_idx];
- ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
- pid);
- if (bucket->peers_size < bucket_size)
- strength = (bucket_size - bucket->peers_size) * bucket_idx;
- else
- strength = 0;
- if (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
- pid))
- strength *= 2; /* double for connected peers */
- if ( (0 == strength) &&
- (NULL != ci) )
- {
- /* release request */
- GNUNET_assert (GNUNET_YES ==
- free_connect_info (NULL,
- pid,
- ci));
- return;
- }
- if (NULL == ci)
- {
- ci = GNUNET_new (struct ConnectInfo);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
- pid,
- ci,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
- if ( (NULL != ci->oh) &&
- (NULL != h) )
- GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
- if (NULL != h)
- ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
- h,
- &offer_hello_done,
- ci);
- if ( (NULL != ci->ph) &&
- (ci->strength != strength) )
- {
- // ci->u_api->drop (ci->ph);
- ci->ph = NULL;
- }
- if (ci->strength != strength)
- {
-#if FIXME
- ci->ph = ci->u_api->hold (ci->u_api->cls,
- TARGET);
-#endif
- ci->strength = strength;
- }
-}
-
-
-/**
- * Function called for each peer in #all_desired_peers during
- * #update_connect_preferences() if we have reason to adjust
- * the strength of our desire to keep connections to certain
- * peers. Calls #try_connect() to update the calculations for
- * the given @a pid.
- *
- * @param cls NULL
- * @param pid peer to update
- * @param value unused
- * @return #GNUNET_YES (continue to iterate)
- */
-static enum GNUNET_GenericReturnValue
-update_desire_strength (void *cls,
- const struct GNUNET_PeerIdentity *pid,
- void *value)
-{
- (void) cls;
- (void) value;
- try_connect (pid,
- NULL);
- return GNUNET_YES;
-}
-
-
-/**
- * Update our preferences for connectivity as given to ATS.
- */
-static void
-update_connect_preferences (void)
-{
- GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
- &update_desire_strength,
- NULL);
-}
-
-
/**
* Add each of the peers we already know to the Bloom filter of
* the request so that we don't get duplicate HELLOs.
@@ -728,11 +659,11 @@ send_find_peer_message (void *cls)
GNUNET_CONSTANTS_BLOOMFILTER_K);
if (GNUNET_OK !=
GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
- GNUNET_DHT_RO_FIND_PEER
+ GNUNET_DHT_RO_FIND_APPROXIMATE
| GNUNET_DHT_RO_RECORD_ROUTE,
FIND_PEER_REPLICATION_LEVEL,
0, /* hop count */
- &my_identity_hash,
+ &GDS_my_identity_hash,
NULL, 0, /* xquery */
bg,
peer_bf))
@@ -761,106 +692,131 @@ GDS_u_connect (void *cls,
const struct GNUNET_PeerIdentity *pid,
void **ctx)
{
+ struct Underlay *u = cls;
struct PeerInfo *pi;
struct PeerBucket *bucket;
- (void) cls;
/* Check for connect to self message */
- if (0 == GNUNET_memcmp (&my_identity,
+ if (0 == GNUNET_memcmp (&GDS_my_identity,
pid))
return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Connected to peer %s\n",
GNUNET_i2s (pid));
- GNUNET_assert (NULL ==
- GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
- pid));
- GNUNET_STATISTICS_update (GDS_stats,
- "# peers connected",
- 1,
- GNUNET_NO);
- pi = GNUNET_new (struct PeerInfo);
- pi->id = *pid;
- pi->target = target;
- GNUNET_CRYPTO_hash (pid,
- sizeof(*pid),
- &pi->phash);
- pi->peer_bucket = find_bucket (&pi->phash);
- GNUNET_assert ( (pi->peer_bucket >= 0) &&
- ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
- bucket = &k_buckets[pi->peer_bucket];
- GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
- bucket->tail,
- pi);
- bucket->peers_size++;
- closest_bucket = GNUNET_MAX (closest_bucket,
- (unsigned int) pi->peer_bucket + 1);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
- &pi->id,
- pi,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- if (bucket->peers_size <= bucket_size)
+ pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
+ pid);
+ if (NULL == pi)
{
- update_connect_preferences ();
- newly_found_peers++;
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# peers connected",
+ 1,
+ GNUNET_NO);
+ pi = GNUNET_new (struct PeerInfo);
+ pi->id = *pid;
+ GNUNET_CRYPTO_hash (pid,
+ sizeof(*pid),
+ &pi->phash);
+ pi->peer_bucket = find_bucket (&pi->phash);
+ GNUNET_assert ( (pi->peer_bucket >= 0) &&
+ ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
+ bucket = &k_buckets[pi->peer_bucket];
+ GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
+ bucket->tail,
+ pi);
+ bucket->peers_size++;
+ closest_bucket = GNUNET_MAX (closest_bucket,
+ (unsigned int) pi->peer_bucket + 1);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
+ &pi->id,
+ pi,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ if (bucket->peers_size <= bucket_size)
+ {
+ newly_found_peers++;
+ // FIXME: call 'hold'!
+ }
+ if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
+ (GNUNET_YES != disable_try_connect) )
+ {
+ /* got a first connection, good time to start with FIND PEER requests...
*/
+ GNUNET_assert (NULL == find_peer_task);
+ find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
+ NULL);
+ }
}
- if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
- (GNUNET_YES != disable_try_connect) )
{
- /* got a first connection, good time to start with FIND PEER requests... */
- GNUNET_assert (NULL == find_peer_task);
- find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
- NULL);
+ struct Target *t;
+
+ t = GNUNET_new (struct Target);
+ t->u = u;
+ t->utarget = target;
+ t->pi = pi;
+ GNUNET_CONTAINER_DLL_insert (pi->t_head,
+ pi->t_tail,
+ t);
+ *ctx = t;
+
}
- *ctx = pi;
}
-/**
- * Method called whenever a peer disconnects.
- *
- * @param ctx context
- */
void
GDS_u_disconnect (void *ctx)
{
- struct PeerInfo *to_remove = ctx;
+ struct Target *t = ctx;
+ struct PeerInfo *pi;
struct PeerBucket *bucket;
/* Check for disconnect from self message (on shutdown) */
- if (NULL == to_remove)
+ if (NULL == t)
return;
+ pi = t->pi;
+ GNUNET_CONTAINER_DLL_remove (pi->t_head,
+ pi->t_tail,
+ t);
+ if (t->load > 0)
+ {
+ t->dropped = true;
+ t->pi = NULL;
+ }
+ else
+ {
+ GNUNET_free (t);
+ }
+ if (NULL != pi->t_head)
+ return; /* got other connections still */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Disconnected from peer %s\n",
- GNUNET_i2s (&to_remove->id));
+ GNUNET_i2s (&pi->id));
GNUNET_STATISTICS_update (GDS_stats,
"# peers connected",
-1,
GNUNET_NO);
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
- &to_remove->id,
- to_remove));
+ &pi->id,
+ pi));
if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
(GNUNET_YES != disable_try_connect))
{
GNUNET_SCHEDULER_cancel (find_peer_task);
find_peer_task = NULL;
}
- GNUNET_assert (to_remove->peer_bucket >= 0);
- bucket = &k_buckets[to_remove->peer_bucket];
+ GNUNET_assert (pi->peer_bucket >= 0);
+ bucket = &k_buckets[pi->peer_bucket];
GNUNET_CONTAINER_DLL_remove (bucket->head,
bucket->tail,
- to_remove);
+ pi);
GNUNET_assert (bucket->peers_size > 0);
bucket->peers_size--;
+ // FIXME: check if this peer was in one of the first 'bucket_size'
+ // peers, and call 'hold' on the next peer if there is any!
while ( (closest_bucket > 0) &&
(0 == k_buckets[closest_bucket - 1].peers_size))
closest_bucket--;
- if (bucket->peers_size < bucket_size)
- update_connect_preferences ();
- GNUNET_free (to_remove);
+ GNUNET_free (pi->hello);
+ GNUNET_free (pi);
}
@@ -935,7 +891,7 @@ enum GNUNET_GenericReturnValue
GDS_am_closest_peer (const struct GNUNET_HashCode *key,
const struct GNUNET_CONTAINER_BloomFilter *bloom)
{
- if (0 == GNUNET_memcmp (&my_identity_hash,
+ if (0 == GNUNET_memcmp (&GDS_my_identity_hash,
key))
return GNUNET_YES;
for (int bucket_num = find_bucket (key);
@@ -962,7 +918,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
because an unfiltered peer exists, we are not the
closest. */
int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
- &my_identity_hash,
+ &GDS_my_identity_hash,
key);
switch (delta)
{
@@ -1026,7 +982,7 @@ select_peer (const struct GNUNET_HashCode *key,
struct GNUNET_HashCode xor;
GNUNET_CRYPTO_hash_xor (key,
- &my_identity_hash,
+ &GDS_my_identity_hash,
&xor);
best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
}
@@ -1046,9 +1002,10 @@ select_peer (const struct GNUNET_HashCode *key,
if (count >= bucket_size)
break; /* we only consider first #bucket_size entries per bucket */
count++;
- if (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash))
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Excluded peer `%s' due to BF match in greedy routing
for %s\n",
@@ -1134,18 +1091,20 @@ select_peer (const struct GNUNET_HashCode *key,
for (unsigned int bc = 0; bc < closest_bucket; bc++)
{
+ struct PeerBucket *bucket = &k_buckets[bc];
unsigned int count = 0;
- for (struct PeerInfo *pos = k_buckets[bc].head;
+ for (struct PeerInfo *pos = bucket->head;
NULL != pos;
pos = pos->next)
{
count++;
if (count > bucket_size)
break; /* limits search to #bucket_size peers per bucket */
- if (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash))
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Excluded peer `%s' due to BF match in random routing
for %s\n",
@@ -1180,9 +1139,10 @@ select_peer (const struct GNUNET_HashCode *key,
if (count > bucket_size)
break; /* limits search to #bucket_size peers per bucket */
- if (GNUNET_YES ==
- GNUNET_CONTAINER_bloomfilter_test (bloom,
- &pos->phash))
+ if ( (NULL != bloom) &&
+ (GNUNET_YES ==
+ GNUNET_CONTAINER_bloomfilter_test (bloom,
+ &pos->phash)) )
continue; /* Ignore bloomfiltered peers */
if (0 == selected--)
{
@@ -1296,7 +1256,7 @@ GDS_NEIGHBOURS_handle_put (const struct
GDS_DATACACHE_BlockData *bd,
bd->put_path,
bd->put_path_length,
NULL, 0, /* get_path */
- &my_identity))
+ &GDS_my_identity))
{
GNUNET_break_op (0);
put_path_length = 0;
@@ -1304,10 +1264,10 @@ GDS_NEIGHBOURS_handle_put (const struct
GDS_DATACACHE_BlockData *bd,
#endif
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Adding myself (%s) to PUT bloomfilter for %s\n",
- GNUNET_i2s (&my_identity),
+ GNUNET_i2s (&GDS_my_identity),
GNUNET_h2s (&bd->key));
GNUNET_CONTAINER_bloomfilter_add (bf,
- &my_identity_hash);
+ &GDS_my_identity_hash);
GNUNET_STATISTICS_update (GDS_stats,
"# PUT requests routed",
1,
@@ -1324,7 +1284,7 @@ GDS_NEIGHBOURS_handle_put (const struct
GDS_DATACACHE_BlockData *bd,
"Routing PUT for %s terminates after %u hops at %s\n",
GNUNET_h2s (&bd->key),
(unsigned int) hop_count,
- GNUNET_i2s (&my_identity));
+ GNUNET_i2s (&GDS_my_identity));
return GNUNET_NO;
}
msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)
@@ -1346,30 +1306,18 @@ GDS_NEIGHBOURS_handle_put (const struct
GDS_DATACACHE_BlockData *bd,
for (unsigned int i = 0; i < target_count; i++)
{
struct PeerInfo *target = targets[i];
- struct GNUNET_MQ_Envelope *env;
struct PeerPutMessage *ppm;
+ char buf[sizeof (*ppm) + msize] GNUNET_ALIGN;
struct GNUNET_DHT_PathElement *pp;
-#if FIXME_LEGACY
- if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
- {
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- "# P2P messages dropped due to full queue",
- 1,
- GNUNET_NO);
- skip_count++;
- continue;
- }
-#endif
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing PUT for %s after %u hops to %s\n",
GNUNET_h2s (&bd->key),
(unsigned int) hop_count,
GNUNET_i2s (&target->id));
- env = GNUNET_MQ_msg_extra (ppm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
+ ppm = (struct PeerPutMessage *) buf;
+ ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
+ ppm->header.size = htons (sizeof (buf));
ppm->options = htonl (options);
ppm->type = htonl (bd->type);
ppm->hop_count = htonl (hop_count + 1);
@@ -1405,10 +1353,8 @@ GDS_NEIGHBOURS_handle_put (const struct
GDS_DATACACHE_BlockData *bd,
GNUNET_memcpy (&pp[put_path_length],
bd->data,
bd->data_size);
-#if FIXME
- GNUNET_MQ_send (target->mq,
- env);
-#endif
+ do_send (target,
+ &ppm->header);
}
GNUNET_free (targets);
GNUNET_STATISTICS_update (GDS_stats,
@@ -1450,17 +1396,17 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
&targets);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Adding myself (%s) to GET bloomfilter for %s\n",
- GNUNET_i2s (&my_identity),
+ GNUNET_i2s (&GDS_my_identity),
GNUNET_h2s (key));
GNUNET_CONTAINER_bloomfilter_add (peer_bf,
- &my_identity_hash);
+ &GDS_my_identity_hash);
if (0 == target_count)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing GET for %s terminates after %u hops at %s\n",
GNUNET_h2s (key),
(unsigned int) hop_count,
- GNUNET_i2s (&my_identity));
+ GNUNET_i2s (&GDS_my_identity));
return GNUNET_NO;
}
if (GNUNET_OK !=
@@ -1487,30 +1433,18 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
for (unsigned int i = 0; i < target_count; i++)
{
struct PeerInfo *target = targets[i];
- struct GNUNET_MQ_Envelope *env;
struct PeerGetMessage *pgm;
+ char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
char *xq;
-#if FIXME
- if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
- {
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- "# P2P messages dropped due to full queue",
- 1,
- GNUNET_NO);
- skip_count++;
- continue;
- }
-#endif
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Routing GET for %s after %u hops to %s\n",
GNUNET_h2s (key),
(unsigned int) hop_count,
GNUNET_i2s (&target->id));
- env = GNUNET_MQ_msg_extra (pgm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
+ pgm = (struct PeerGetMessage *) buf;
+ pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
+ pgm->header.size = htons (sizeof (buf));
pgm->options = htonl (options);
pgm->type = htonl (type);
pgm->hop_count = htonl (hop_count + 1);
@@ -1532,10 +1466,8 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
GNUNET_memcpy (&xq[xquery_size],
reply_bf,
reply_bf_size);
-#if FIXME
- GNUNET_MQ_send (target->mq,
- env);
-#endif
+ do_send (target,
+ &pgm->header);
}
GNUNET_STATISTICS_update (GDS_stats,
"# GET messages queued for transmission",
@@ -1562,8 +1494,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
unsigned int get_path_length,
const struct GNUNET_DHT_PathElement *get_path)
{
- struct GNUNET_MQ_Envelope *env;
- struct PeerResultMessage *prm;
struct GNUNET_DHT_PathElement *paths;
size_t msize;
unsigned int ppl = bd->put_path_length;
@@ -1578,7 +1508,7 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
bd->put_path_length,
get_path,
get_path_length,
- &my_identity))
+ &GDS_my_identity))
{
GNUNET_break_op (0);
get_path_length = 0;
@@ -1609,20 +1539,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
GNUNET_break (0);
return;
}
-#if FIXME
- if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
- {
- /* skip */
- GNUNET_STATISTICS_update (GDS_stats,
- "# P2P messages dropped due to full queue",
- 1,
- GNUNET_NO);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Peer queue full, ignoring reply for key %s\n",
- GNUNET_h2s (&bd->key));
- return;
- }
-#endif
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Forwarding reply for key %s to peer %s\n",
GNUNET_h2s (query_hash),
@@ -1631,41 +1547,44 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
"# RESULT messages queued for transmission",
1,
GNUNET_NO);
- env = GNUNET_MQ_msg_extra (prm,
- msize,
- GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
- prm->type = htonl (bd->type);
- prm->put_path_length = htonl (ppl);
- prm->get_path_length = htonl (get_path_length);
- prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
- prm->key = *query_hash;
- paths = (struct GNUNET_DHT_PathElement *) &prm[1];
- GNUNET_memcpy (paths,
- bd->put_path,
- ppl * sizeof(struct GNUNET_DHT_PathElement));
- GNUNET_memcpy (&paths[ppl],
- get_path,
- get_path_length * sizeof(struct GNUNET_DHT_PathElement));
- /* 0 == get_path_length means path is not being tracked */
- if (0 != get_path_length)
{
- /* Note that the signature in 'get_path' was not initialized before,
- so this is crucial to avoid sending garbage. */
- sign_path (&bd->key,
- bd->data,
- bd->data_size,
- bd->expiration_time,
- &paths[ppl + get_path_length - 1].pred,
- &pi->id,
- &paths[ppl + get_path_length - 1].sig);
- }
- GNUNET_memcpy (&paths[ppl + get_path_length],
+ struct PeerResultMessage *prm;
+ char buf[sizeof (*prm) + msize] GNUNET_ALIGN;
+
+ prm = (struct PeerResultMessage *) buf;
+ prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
+ prm->header.size = htons (sizeof (buf));
+ prm->type = htonl (bd->type);
+ prm->put_path_length = htonl (ppl);
+ prm->get_path_length = htonl (get_path_length);
+ prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
+ prm->key = *query_hash;
+ paths = (struct GNUNET_DHT_PathElement *) &prm[1];
+ GNUNET_memcpy (paths,
+ bd->put_path,
+ ppl * sizeof(struct GNUNET_DHT_PathElement));
+ GNUNET_memcpy (&paths[ppl],
+ get_path,
+ get_path_length * sizeof(struct GNUNET_DHT_PathElement));
+ /* 0 == get_path_length means path is not being tracked */
+ if (0 != get_path_length)
+ {
+ /* Note that the signature in 'get_path' was not initialized before,
+ so this is crucial to avoid sending garbage. */
+ sign_path (&bd->key,
bd->data,
- bd->data_size);
-#if FIXME
- GNUNET_MQ_send (pi->mq,
- env);
-#endif
+ bd->data_size,
+ bd->expiration_time,
+ &paths[ppl + get_path_length - 1].pred,
+ &pi->id,
+ &paths[ppl + get_path_length - 1].sig);
+ }
+ GNUNET_memcpy (&paths[ppl + get_path_length],
+ bd->data,
+ bd->data_size);
+ do_send (pi,
+ &prm->header);
+ }
}
@@ -1819,7 +1738,7 @@ handle_dht_p2p_put (void *cls,
bd.put_path,
putlen,
NULL, 0, /* get_path */
- &my_identity))
+ &GDS_my_identity))
{
GNUNET_break_op (0);
putlen = 0;
@@ -1875,45 +1794,60 @@ handle_dht_p2p_put (void *cls,
/**
- * We have received a FIND PEER request. Send matching
- * HELLOs back.
+ * We have received a request for a HELLO. Sends our
+ * HELLO back.
*
- * @param pi sender of the FIND PEER request
+ * @param pi sender of the request
* @param key peers close to this key are desired
* @param bg group for filtering peers
*/
static void
-handle_find_peer (struct PeerInfo *pi,
- const struct GNUNET_HashCode *query_hash,
- struct GNUNET_BLOCK_Group *bg)
+handle_find_my_hello (struct PeerInfo *pi,
+ const struct GNUNET_HashCode *query_hash,
+ struct GNUNET_BLOCK_Group *bg)
{
- int bucket_idx;
- struct PeerBucket *bucket;
- struct PeerInfo *peer;
- unsigned int choice;
- struct GDS_DATACACHE_BlockData bd = {
- .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO
- };
-
- /* first, check about our own HELLO */
- if (NULL != GDS_my_hello)
+ size_t block_size = 0;
+
+ /* TODO: consider caching our HELLO block for a bit, to
+ avoid signing too often here... */
+ GNUNET_break (GNUNET_NO ==
+ GNUNET_HELLO_builder_to_block (GDS_my_hello,
+ &GDS_my_private_key,
+ NULL,
+ &block_size));
{
- bd.expiration_time = GNUNET_TIME_relative_to_absolute (
- hello_expiration),
- bd.key = my_identity_hash,
- bd.data = GDS_my_hello;
- bd.data_size = GNUNET_HELLO_size (
- (const struct GNUNET_HELLO_Message *) GDS_my_hello);
- GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader));
- if (GNUNET_BLOCK_REPLY_OK_MORE ==
- GNUNET_BLOCK_check_reply (GDS_block_context,
- GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
- bg,
- &my_identity_hash,
- NULL, 0,
- bd.data,
- bd.data_size))
+ char block[block_size];
+
+ if (GNUNET_OK !=
+ GNUNET_HELLO_builder_to_block (GDS_my_hello,
+ &GDS_my_private_key,
+ block,
+ &block_size))
{
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# FIND PEER requests ignored due to lack of
HELLO",
+ 1,
+ GNUNET_NO);
+ }
+ else if (GNUNET_BLOCK_REPLY_OK_MORE ==
+ GNUNET_BLOCK_check_reply (GDS_block_context,
+ GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ bg,
+ &GDS_my_identity_hash,
+ NULL, 0,
+ block,
+ block_size))
+ {
+ struct GDS_DATACACHE_BlockData bd = {
+ .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ .expiration_time
+ = GNUNET_TIME_relative_to_absolute (
+ GNUNET_HELLO_ADDRESS_EXPIRATION),
+ .key = GDS_my_identity_hash,
+ .data = block,
+ .data_size = block_size
+ };
+
GDS_NEIGHBOURS_handle_reply (pi,
&bd,
query_hash,
@@ -1927,66 +1861,48 @@ handle_find_peer (struct PeerInfo *pi,
GNUNET_NO);
}
}
- else
- {
- GNUNET_STATISTICS_update (GDS_stats,
- "# FIND PEER requests ignored due to lack of
HELLO",
- 1,
- GNUNET_NO);
- }
+}
- /* then, also consider sending a random HELLO from the closest bucket */
- /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
- if (0 ==
- GNUNET_memcmp (&my_identity_hash,
- query_hash))
- bucket_idx = closest_bucket - 1;
- else
- bucket_idx = GNUNET_MIN ((int) closest_bucket - 1,
- find_bucket (query_hash));
- if (bucket_idx < 0)
- return;
- bucket = &k_buckets[bucket_idx];
- if (bucket->peers_size == 0)
- return;
- choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- bucket->peers_size);
- peer = bucket->head;
- while (choice > 0)
- {
- GNUNET_assert (NULL != peer);
- peer = peer->next;
- choice--;
- }
- choice = bucket->peers_size;
+/**
+ * We have received a request for nearby HELLOs. Sends matching
+ * HELLOs back.
+ *
+ * @param pi sender of the request
+ * @param key peers close to this key are desired
+ * @param bg group for filtering peers
+ */
+static void
+handle_find_local_hello (struct PeerInfo *pi,
+ const struct GNUNET_HashCode *query_hash,
+ struct GNUNET_BLOCK_Group *bg)
+{
+ /* Force non-random selection by hop count */
+ struct PeerInfo *peer;
+
+ peer = select_peer (query_hash,
+ NULL,
+ GDS_NSE_get () + 1);
+ if ( (NULL != peer->hello) &&
+ (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
+ (GNUNET_BLOCK_REPLY_OK_MORE ==
+ GNUNET_BLOCK_check_reply (
+ GDS_block_context,
+ GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ bg,
+ &peer->phash,
+ NULL, 0, /* xquery */
+ peer->hello,
+ peer->hello_size)) )
{
- const struct GNUNET_HELLO_Message *hello;
- size_t hello_size;
+ struct GDS_DATACACHE_BlockData bd = {
+ .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
+ .expiration_time = peer->hello_expiration,
+ .key = peer->phash,
+ .data = peer->hello,
+ .data_size = peer->hello_size
+ };
- do
- {
- peer = peer->next;
- if (0 == choice--)
- return; /* no non-masked peer available */
- if (NULL == peer)
- peer = bucket->head;
- hello = GDS_HELLO_get (&peer->id);
- } while ( (NULL == hello) ||
- (GNUNET_BLOCK_REPLY_OK_MORE !=
- GNUNET_BLOCK_check_reply (
- GDS_block_context,
- GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
- bg,
- &peer->phash,
- NULL, 0, /* xquery */
- hello,
- (hello_size = GNUNET_HELLO_size (hello)))));
- bd.expiration_time = GNUNET_TIME_relative_to_absolute (
- GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
- bd.key = peer->phash;
- bd.data = hello;
- bd.data_size = hello_size;
GDS_NEIGHBOURS_handle_reply (pi,
&bd,
query_hash,
@@ -2101,32 +2017,45 @@ handle_dht_p2p_get (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"GET for %s at %s after %u hops\n",
GNUNET_h2s (&get->key),
- GNUNET_i2s (&my_identity),
+ GNUNET_i2s (&GDS_my_identity),
(unsigned int) hop_count);
- /* local lookup (this may update the reply_bf) */
+ /* local lookup (this may update the bg) */
if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
(GDS_am_closest_peer (&get->key,
peer_bf)) )
{
- if ((0 != (options & GNUNET_DHT_RO_FIND_PEER)))
+ if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == type)
{
GNUNET_STATISTICS_update (GDS_stats,
- "# P2P FIND PEER requests processed",
+ "# P2P HELLO lookup requests processed",
1,
GNUNET_NO);
- handle_find_peer (peer,
- &get->key,
- bg);
+ handle_find_my_hello (peer,
+ &get->key,
+ bg);
+ if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
+ handle_find_local_hello (peer,
+ &get->key,
+ bg);
}
else
{
- eval = GDS_DATACACHE_handle_get (&get->key,
- type,
- xquery,
- xquery_size,
- bg,
- &handle_local_result,
- peer);
+ if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
+ eval = GDS_DATACACHE_get_closest (&get->key,
+ type,
+ xquery,
+ xquery_size,
+ bg,
+ &handle_local_result,
+ peer);
+ else
+ eval = GDS_DATACACHE_handle_get (&get->key,
+ type,
+ xquery,
+ xquery_size,
+ bg,
+ &handle_local_result,
+ peer);
}
}
else
@@ -2137,7 +2066,9 @@ handle_dht_p2p_get (void *cls,
GNUNET_NO);
}
- /* remember request for routing replies */
+ /* remember request for routing replies
+ TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
+ */
GDS_ROUTING_add (&peer->id,
type,
bg, /* bg now owned by routing, but valid at least
until end of this function! */
@@ -2259,6 +2190,52 @@ check_dht_p2p_result (void *cls,
}
+/**
+ * Callback function used to extract URIs from a builder.
+ * Called when we should consider connecting to a peer.
+ *
+ * @param cls closure pointing to a `struct GNUNET_PeerIdentity *`
+ * @param uri one of the URIs
+ */
+static void
+try_connect (void *cls,
+ const char *uri)
+{
+ const struct GNUNET_PeerIdentity *pid = cls;
+ struct GNUNET_HashCode phash;
+ int peer_bucket;
+ struct PeerBucket *bucket;
+
+ if (0 == GNUNET_memcmp (&GDS_my_identity,
+ pid))
+ return; /* that's us! */
+ GNUNET_CRYPTO_hash (pid,
+ sizeof(*pid),
+ &phash);
+ peer_bucket = find_bucket (&phash);
+ GNUNET_assert ( (peer_bucket >= 0) &&
+ ((unsigned int) peer_bucket < MAX_BUCKETS));
+ bucket = &k_buckets[peer_bucket];
+ if (bucket->peers_size >= bucket_size)
+ return; /* do not care */
+ for (struct PeerInfo *pi = bucket->head;
+ NULL != pi;
+ pi = pi->next)
+ if (0 ==
+ GNUNET_memcmp (&pi->id,
+ pid))
+ {
+ /* already connected */
+ /* TODO: maybe consider 'uri' anyway as an additional
+ alternative address??? */
+ return;
+ }
+ /* new peer that we like! */
+ GDS_u_try_connect (pid,
+ uri);
+}
+
+
/**
* Core handler for p2p result messages.
*
@@ -2333,32 +2310,17 @@ handle_dht_p2p_result (void *cls,
/* if we got a HELLO, consider it for our own routing table */
if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == bd.type)
{
- const struct GNUNET_MessageHeader *h = bd.data;
struct GNUNET_PeerIdentity pid;
-
- /* Should be a HELLO, validate and consider using it! */
- if (bd.data_size < sizeof(struct GNUNET_HELLO_Message))
- {
- GNUNET_break (0);
- return;
- }
- if (bd.data_size != ntohs (h->size))
- {
- GNUNET_break (0);
- return;
- }
- if (GNUNET_OK !=
- GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
- &pid))
- {
- GNUNET_break_op (0);
- return;
- }
- if ( (GNUNET_YES != disable_try_connect) &&
- (0 != GNUNET_memcmp (&my_identity,
- &pid)) )
- try_connect (&pid,
- h);
+ struct GNUNET_HELLO_Builder *b;
+
+ b = GNUNET_HELLO_builder_from_block (bd.data,
+ bd.data_size);
+ if (GNUNET_YES != disable_try_connect)
+ GNUNET_HELLO_builder_iterate (b,
+ &pid,
+ &try_connect,
+ &pid);
+ GNUNET_HELLO_builder_free (b);
}
/* First, check if 'peer' is already on the path, and if
@@ -2391,6 +2353,50 @@ handle_dht_p2p_result (void *cls,
}
+/**
+ * Check validity of a p2p hello message.
+ *
+ * @param cls closure
+ * @param hello message
+ * @return #GNUNET_YES if the message is well-formed
+ */
+static enum GNUNET_GenericReturnValue
+check_dht_p2p_hello (void *cls,
+ const struct GNUNET_MessageHeader *hello)
+{
+ struct GNUNET_HELLO_Builder *b;
+ enum GNUNET_GenericReturnValue ret;
+
+ b = GNUNET_HELLO_builder_from_msg (hello);
+ ret = (NULL == b) ? GNUNET_SYSERR : GNUNET_OK;
+ GNUNET_HELLO_builder_free (b);
+ return ret;
+}
+
+
+/**
+ * Core handler for p2p HELLO messages.
+ *
+ * @param cls closure
+ * @param message message
+ */
+static void
+handle_dht_p2p_hello (void *cls,
+ const struct GNUNET_MessageHeader *hello)
+{
+ struct PeerInfo *peer = cls;
+
+ GNUNET_free (peer->hello);
+ peer->hello_size = 0;
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_HELLO_dht_msg_to_block (hello,
+ &peer->id,
+ &peer->hello,
+ &peer->hello_size,
+ &peer->hello_expiration));
+}
+
+
void
GDS_u_receive (void *cls,
void **tctx,
@@ -2412,6 +2418,10 @@ GDS_u_receive (void *cls,
GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT,
struct PeerResultMessage,
pi),
+ GNUNET_MQ_hd_var_size (dht_p2p_hello,
+ GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO,
+ struct GNUNET_MessageHeader,
+ pi),
GNUNET_MQ_handler_end ()
};
const struct GNUNET_MessageHeader *mh = message;
@@ -2438,6 +2448,34 @@ GDS_u_receive (void *cls,
}
+/**
+ * Send @a msg to all peers in our buckets.
+ *
+ * @param msg message to broadcast
+ */
+void
+GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg)
+{
+ for (unsigned int bc = 0; bc<closest_bucket; bc++)
+ {
+ struct PeerBucket *bucket = &k_buckets[bc];
+ unsigned int count = 0;
+
+ for (struct PeerInfo *pos = bucket->head;
+ NULL != pos;
+ pos = pos->next)
+ {
+ if (count >= bucket_size)
+ break; /* we only consider first #bucket_size entries per bucket */
+ count++;
+ GNUNET_break (0);
+ do_send (pos,
+ msg);
+ }
+ }
+}
+
+
enum GNUNET_GenericReturnValue
GDS_NEIGHBOURS_init ()
{
@@ -2458,41 +2496,8 @@ GDS_NEIGHBOURS_init ()
= GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
"DHT",
"CACHE_RESULTS");
- {
- char *keyfile;
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
- "PEER",
- "PRIVATE_KEY",
- &keyfile))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Core service is lacking HOSTKEY configuration setting.
Exiting.\n");
- return GNUNET_SYSERR;
- }
- if (GNUNET_SYSERR ==
- GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
- GNUNET_YES,
- &my_private_key))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to setup peer's private key\n");
- GNUNET_free (keyfile);
- return GNUNET_SYSERR;
- }
- GNUNET_free (keyfile);
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
- &my_identity.public_key);
- GNUNET_CRYPTO_hash (&my_identity,
- sizeof(struct GNUNET_PeerIdentity),
- &my_identity_hash);
-
all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
GNUNET_YES);
- all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
- GNUNET_NO);
return GNUNET_OK;
}
@@ -2506,11 +2511,6 @@ GDS_NEIGHBOURS_done ()
GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
all_connected_peers = NULL;
- GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
- &free_connect_info,
- NULL);
- GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
- all_desired_peers = NULL;
GNUNET_assert (NULL == find_peer_task);
}
@@ -2518,7 +2518,7 @@ GDS_NEIGHBOURS_done ()
struct GNUNET_PeerIdentity *
GDS_NEIGHBOURS_get_id ()
{
- return &my_identity;
+ return &GDS_my_identity;
}
diff --git a/src/dht/gnunet-service-dht_neighbours.h
b/src/dht/gnunet-service-dht_neighbours.h
index e1a553f06..5a4c8c620 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -33,11 +33,6 @@
#include "gnunet_dhtu_plugin.h"
#include "gnunet-service-dht_datacache.h"
-/**
- * Hash of the identity of this peer.
- */
-extern struct GNUNET_HashCode my_identity_hash;
-
struct PeerInfo;
@@ -141,7 +136,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
* Function to call when we connect to a peer and can henceforth transmit to
* that peer.
*
- * @param cls the closure
+ * @param cls the closure, must be a `struct Underlay`
* @param target handle to the target,
* pointer will remain valid until @e disconnect_cb is called
* @para pid peer identity,
@@ -154,6 +149,7 @@ GDS_u_connect (void *cls,
const struct GNUNET_PeerIdentity *pid,
void **ctx);
+
/**
* Function to call when we disconnected from a peer and can henceforth
* cannot transmit to that peer anymore.
@@ -182,6 +178,15 @@ GDS_u_receive (void *cls,
size_t message_size);
+/**
+ * Send @a msg to all peers in our buckets.
+ *
+ * @param msg message to broadcast
+ */
+void
+GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg);
+
+
/**
* Initialize neighbours subsystem.
*
diff --git a/src/dht/gnunet-service-dht_routing.c
b/src/dht/gnunet-service-dht_routing.c
index e7b5c3571..ec3f5b46f 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -151,7 +151,7 @@ process (void *cls,
bdx.put_path_length = 0;
bdx.put_path = NULL;
}
- if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
+ if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
(0 != GNUNET_memcmp (query_hash,
&bdx.key)) )
{
diff --git a/src/dhtu/plugin_dhtu_gnunet.c b/src/dhtu/plugin_dhtu_gnunet.c
index a75c47ce3..5cf47a850 100644
--- a/src/dhtu/plugin_dhtu_gnunet.c
+++ b/src/dhtu/plugin_dhtu_gnunet.c
@@ -235,7 +235,7 @@ hello_offered_cb (void *cls)
*/
static void
ip_try_connect (void *cls,
- struct GNUNET_PeerIdentity *pid,
+ const struct GNUNET_PeerIdentity *pid,
const char *address)
{
struct Plugin *plugin = cls;
@@ -349,6 +349,17 @@ ip_send (void *cls,
struct GNUNET_MQ_Envelope *env;
struct GNUNET_MessageHeader *cmsg;
+ if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
+ {
+ /* skip */
+#if FIXME_STATS
+ GNUNET_STATISTICS_update (GDS_stats,
+ "# P2P messages dropped due to full queue",
+ 1,
+ GNUNET_NO);
+#endif
+ return;
+ }
env = GNUNET_MQ_msg_extra (cmsg,
msg_size,
GNUNET_MESSAGE_TYPE_DHT_CORE);
diff --git a/src/dhtu/plugin_dhtu_ip.c b/src/dhtu/plugin_dhtu_ip.c
index 7c01e5baf..998a7903b 100644
--- a/src/dhtu/plugin_dhtu_ip.c
+++ b/src/dhtu/plugin_dhtu_ip.c
@@ -354,7 +354,7 @@ find_target (struct Plugin *plugin,
*/
static void
ip_try_connect (void *cls,
- struct GNUNET_PeerIdentity *pid,
+ const struct GNUNET_PeerIdentity *pid,
const char *address)
{
struct Plugin *plugin = cls;
@@ -365,7 +365,6 @@ ip_try_connect (void *cls,
.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
};
struct addrinfo *result = NULL;
- char *epid;
if (0 !=
strncmp (address,
@@ -507,7 +506,6 @@ create_source (struct Plugin *plugin,
socklen_t addrlen)
{
struct GNUNET_DHTU_Source *src;
- char *pid;
src = GNUNET_new (struct GNUNET_DHTU_Source);
src->addrlen = addrlen;
@@ -549,7 +547,6 @@ create_source (struct Plugin *plugin,
break;
default:
GNUNET_break (0);
- GNUNET_free (pid);
GNUNET_free (src);
return NULL;
}
diff --git a/src/hello/hello-uri.c b/src/hello/hello-uri.c
index 49e4f6ed3..355443455 100644
--- a/src/hello/hello-uri.c
+++ b/src/hello/hello-uri.c
@@ -40,12 +40,6 @@
#include "gnunet_protocols.h"
#include "gnunet_util_lib.h"
-/**
- * For how long are HELLO signatures valid?
- */
-#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
- GNUNET_TIME_UNIT_DAYS, 2)
-
GNUNET_NETWORK_STRUCT_BEGIN
@@ -72,7 +66,7 @@ struct HelloSignaturePurpose
};
/**
- * Binary block we sign when we sign an address.
+ * Message used when gossiping HELLOs between peers.
*/
struct HelloUriMessage
{
@@ -117,6 +111,42 @@ struct BlockHeader
};
+
+/**
+ * Message used when a DHT provides its HELLO to direct
+ * neighbours.
+ */
+struct DhtHelloMessage
+{
+ /**
+ * Type must be #GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Reserved. 0.
+ */
+ uint16_t reserved GNUNET_PACKED;
+
+ /**
+ * Number of URLs encoded after the end of the struct, in NBO.
+ */
+ uint16_t url_counter GNUNET_PACKED;
+
+ /**
+ * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
+ */
+ struct GNUNET_CRYPTO_EddsaSignature sig;
+
+ /**
+ * When does the HELLO expire?
+ */
+ struct GNUNET_TIME_AbsoluteNBO expiration_time;
+
+ /* followed by the serialized addresses of the 'block' */
+};
+
+
GNUNET_NETWORK_STRUCT_END
@@ -521,6 +551,11 @@ GNUNET_HELLO_builder_to_env (const struct
GNUNET_HELLO_Builder *builder,
struct HelloUriMessage *msg;
size_t blen;
+ if (builder->a_length > UINT16_MAX)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
blen = 0;
GNUNET_assert (GNUNET_NO ==
GNUNET_HELLO_builder_to_block (builder,
@@ -530,6 +565,7 @@ GNUNET_HELLO_builder_to_env (const struct
GNUNET_HELLO_Builder *builder,
env = GNUNET_MQ_msg_extra (msg,
blen,
GNUNET_MESSAGE_TYPE_HELLO_URI);
+ msg->url_counter = htonl ((uint16_t) builder->a_length);
GNUNET_assert (GNUNET_OK ==
GNUNET_HELLO_builder_to_block (builder,
priv,
@@ -539,6 +575,50 @@ GNUNET_HELLO_builder_to_env (const struct
GNUNET_HELLO_Builder *builder,
}
+struct GNUNET_MessageHeader *
+GNUNET_HELLO_builder_to_dht_hello_msg (
+ const struct GNUNET_HELLO_Builder *builder,
+ const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
+{
+ struct DhtHelloMessage *msg;
+ size_t blen;
+
+ if (builder->a_length > UINT16_MAX)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ blen = 0;
+ GNUNET_assert (GNUNET_NO ==
+ GNUNET_HELLO_builder_to_block (builder,
+ priv,
+ NULL,
+ &blen));
+ GNUNET_assert (blen < UINT16_MAX);
+ GNUNET_assert (blen >= sizeof (struct BlockHeader));
+ {
+ char buf[blen] GNUNET_ALIGN;
+ const struct BlockHeader *block = (const struct BlockHeader *) buf;
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_HELLO_builder_to_block (builder,
+ priv,
+ buf,
+ &blen));
+ msg = GNUNET_malloc (sizeof (*msg) + blen);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
+ msg->header.size = htons (sizeof (*msg) + blen);
+ memcpy (&msg[1],
+ &block[1],
+ blen - sizeof (*block));
+ msg->sig = block->sig;
+ msg->expiration_time = block->expiration_time;
+ }
+ msg->url_counter = htonl ((uint16_t) builder->a_length);
+ return &msg->header;
+}
+
+
char *
GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
@@ -550,7 +630,7 @@ GNUNET_HELLO_builder_to_url (const struct
GNUNET_HELLO_Builder *builder,
char *sigs;
const char *sep = "?";
- et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION);
+ et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
sign_hello (builder,
et,
priv,
@@ -629,7 +709,7 @@ GNUNET_HELLO_builder_to_block (const struct
GNUNET_HELLO_Builder *builder,
return GNUNET_NO;
}
bh.pid = builder->pid;
- et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION);
+ et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
sign_hello (builder,
et,
@@ -742,3 +822,54 @@ GNUNET_HELLO_builder_iterate (const struct
GNUNET_HELLO_Builder *builder,
a->uri);
}
}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
+ const struct GNUNET_PeerIdentity *pid,
+ void **block,
+ size_t *block_size,
+ struct GNUNET_TIME_Absolute *block_expiration)
+{
+ const struct DhtHelloMessage *msg
+ = (const struct DhtHelloMessage *) hello;
+ uint16_t len = ntohs (hello->size);
+ struct BlockHeader *bh;
+ struct GNUNET_HELLO_Builder *b;
+ enum GNUNET_GenericReturnValue ret;
+
+ if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (len < sizeof (*msg))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ len -= sizeof (*msg);
+ *block_size = len + sizeof (*bh);
+ *block = GNUNET_malloc (*block_size);
+ bh = *block;
+ bh->pid = *pid;
+ bh->sig = msg->sig;
+ bh->expiration_time = msg->expiration_time;
+ *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
+ memcpy (&bh[1],
+ &msg[1],
+ len);
+ b = GNUNET_HELLO_builder_from_block (*block,
+ *block_size);
+ ret = verify_hello (b,
+ *block_expiration,
+ &msg->sig);
+ GNUNET_HELLO_builder_free (b);
+ if (GNUNET_SYSERR == ret)
+ {
+ GNUNET_free (*block);
+ *block_size = 0;
+ return GNUNET_SYSERR;
+ }
+ return ret;
+}
diff --git a/src/include/gnunet_datacache_lib.h
b/src/include/gnunet_datacache_lib.h
index 11076e3e7..737a5c845 100644
--- a/src/include/gnunet_datacache_lib.h
+++ b/src/include/gnunet_datacache_lib.h
@@ -154,6 +154,7 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
*
* @param h handle to the datacache
* @param key area of the keyspace to look into
+ * @param type entries of which type are relevant?
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -162,6 +163,7 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
unsigned int
GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls);
diff --git a/src/include/gnunet_datacache_plugin.h
b/src/include/gnunet_datacache_plugin.h
index 24570be72..914aaf15c 100644
--- a/src/include/gnunet_datacache_plugin.h
+++ b/src/include/gnunet_datacache_plugin.h
@@ -165,6 +165,7 @@ struct GNUNET_DATACACHE_PluginFunctions
*
* @param cls closure (internal context for the plugin)
* @param key area of the keyspace to look into
+ * @param type desired block type for the replies
* @param num_results number of results that should be returned to @a iter
* @param iter maybe NULL (to just count)
* @param iter_cls closure for @a iter
@@ -173,6 +174,7 @@ struct GNUNET_DATACACHE_PluginFunctions
unsigned int
(*get_closest) (void *cls,
const struct GNUNET_HashCode *key,
+ enum GNUNET_BLOCK_Type type,
unsigned int num_results,
GNUNET_DATACACHE_Iterator iter,
void *iter_cls);
diff --git a/src/include/gnunet_dht_service.h b/src/include/gnunet_dht_service.h
index 768b19fb1..abe5a03e4 100644
--- a/src/include/gnunet_dht_service.h
+++ b/src/include/gnunet_dht_service.h
@@ -101,14 +101,14 @@ enum GNUNET_DHT_RouteOption
GNUNET_DHT_RO_RECORD_ROUTE = 2,
/**
- * This is a 'FIND-PEER' request, so approximate results are fine.
+ * Approximate results are fine.
*/
- GNUNET_DHT_RO_FIND_PEER = 4,
+ GNUNET_DHT_RO_FIND_APPROXIMATE = 4,
/**
- * Flag given to monitors if this was the last hop for a GET/PUT.
- * This is only used for internal processing.
- */
+ * Flag given to monitors if this was the last hop for a GET/PUT.
+ * This is only used for internal processing.
+ */
GNUNET_DHT_RO_LAST_HOP = 65535
};
diff --git a/src/include/gnunet_dhtu_plugin.h b/src/include/gnunet_dhtu_plugin.h
index b709ce9ae..fa0b5f667 100644
--- a/src/include/gnunet_dhtu_plugin.h
+++ b/src/include/gnunet_dhtu_plugin.h
@@ -129,6 +129,7 @@ struct GNUNET_DHTU_PluginEnvironment
const struct GNUNET_PeerIdentity *pid,
void **ctx);
+
/**
* Function to call when we disconnected from a peer and can henceforth
* cannot transmit to that peer anymore.
@@ -177,7 +178,7 @@ struct GNUNET_DHTU_PluginFunctions
*/
void
(*try_connect) (void *cls,
- struct GNUNET_PeerIdentity *pid,
+ const struct GNUNET_PeerIdentity *pid,
const char *address);
@@ -194,7 +195,7 @@ struct GNUNET_DHTU_PluginFunctions
struct GNUNET_DHTU_Target *target);
/**
- * Do no long request underlay to keep the connection alive.
+ * Do no longer request underlay to keep the connection alive.
*
* @param cls closure
* @param target connection to keep alive
diff --git a/src/include/gnunet_hello_uri_lib.h
b/src/include/gnunet_hello_uri_lib.h
index ec9cdfa5e..c109a151a 100644
--- a/src/include/gnunet_hello_uri_lib.h
+++ b/src/include/gnunet_hello_uri_lib.h
@@ -48,6 +48,13 @@ extern "C" {
struct GNUNET_HELLO_Builder;
+/**
+ * For how long are HELLO signatures valid?
+ */
+#define GNUNET_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
+ GNUNET_TIME_UNIT_DAYS, 2)
+
+
/**
* Allocate builder.
*
@@ -100,7 +107,8 @@ GNUNET_HELLO_builder_from_url (const char *url);
/**
- * Generate HELLO message from a @a builder
+ * Generate envelope with GNUnet HELLO message (including
+ * peer ID) from a @a builder
*
* @param builder builder to serialize
* @param priv private key to use to sign the result
@@ -111,6 +119,19 @@ GNUNET_HELLO_builder_to_env (const struct
GNUNET_HELLO_Builder *builder,
const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
+/**
+ * Generate DHT HELLO message (without peer ID) from a @a builder
+ *
+ * @param builder builder to serialize
+ * @param priv private key to use to sign the result
+ * @return HELLO message matching @a builder
+ */
+struct GNUNET_MessageHeader *
+GNUNET_HELLO_builder_to_dht_hello_msg (
+ const struct GNUNET_HELLO_Builder *builder,
+ const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
+
+
/**
* Generate GNUnet HELLO URI from a @a builder
*
@@ -191,6 +212,27 @@ GNUNET_HELLO_builder_iterate (const struct
GNUNET_HELLO_Builder *builder,
GNUNET_HELLO_UriCallback uc,
void *uc_cls);
+
+/**
+ * Convert a DHT @a hello message to a HELLO @a block.
+ *
+ * @param hello the HELLO message
+ * @param pid peer that created the @a hello
+ * @param[out] block set to the HELLO block
+ * @param[out] block_size set to number of bytes in @a block
+ * @param[out] block_expiration set to expiration time of @a block
+ * @return #GNUNET_OK on success,
+ * #GNUNET_NO if the @a hello is expired (@a block is set!)
+ * #GNUNET_SYSERR if @a hello is invalid (@a block will be set to NULL)
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
+ const struct GNUNET_PeerIdentity *pid,
+ void **block,
+ size_t *block_size,
+ struct GNUNET_TIME_Absolute *block_expiration);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index f5ccd2971..cddacc8a6 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -660,13 +660,15 @@ extern "C" {
#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156
/**
- * DHT wants to use CORE to transmit data.
+ * HELLO advertising a neighbours addresses.
*/
-#define GNUNET_MESSAGE_TYPE_DHT_CORE 143
+#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO 157
/**
- * Further X-VINE DHT messages continued from 880
+ * DHT wants to use CORE to transmit data.
*/
+#define GNUNET_MESSAGE_TYPE_DHT_CORE 143
+
/*******************************************************************************
* HOSTLIST message types
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [gnunet] branch master updated (25ef40ef7 -> d68731944), gnunet, 2022/02/19
- [gnunet] 02/20: -also add serialization from/to block, gnunet, 2022/02/19
- [gnunet] 03/20: incomplete first hack of new hello-uri lib, gnunet, 2022/02/19
- [gnunet] 01/20: first steps towards usable dhtu, gnunet, 2022/02/19
- [gnunet] 04/20: -conclude hello-uri implementation and test, gnunet, 2022/02/19
- [gnunet] 09/20: -DHT now takes care of queue size limit, gnunet, 2022/02/19
- [gnunet] 07/20: -more work on DHTU integration,
gnunet <=
- [gnunet] 08/20: rebase, gnunet, 2022/02/19
- [gnunet] 13/20: -fix port initialization in addr, gnunet, 2022/02/19
- [gnunet] 11/20: -DHT: add gnunet-dht-hello for bootstrapping, gnunet, 2022/02/19
- [gnunet] 16/20: -got basics to work with dhtu and udp+ip underlay, gnunet, 2022/02/19
- [gnunet] 18/20: -fix merge issues, gnunet, 2022/02/19
- [gnunet] 20/20: -fix assertion, fix key initialization, gnunet, 2022/02/19
- [gnunet] 17/20: -try to make static analysis happy, gnunet, 2022/02/19
- [gnunet] 15/20: -adding logging, minor dthu bugfixes, gnunet, 2022/02/19
- [gnunet] 19/20: -fix htons/htonl bug introduced by message format change, gnunet, 2022/02/19
- [gnunet] 12/20: -fix crashes on new DHT load/shutdown, gnunet, 2022/02/19