aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-15 19:24:33 +0100
committerChristian Grothoff <christian@grothoff.org>2022-02-19 12:39:55 +0100
commitb0abdf7127f2403ff583d224e0d9d4e68c1c5bfc (patch)
tree47df762cdbcce501ec5536c8963b5c9ee55da31d
parent3a71153405e8fc26712807b4bdb5987fb3bf2b9e (diff)
downloadgnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.tar.gz
gnunet-b0abdf7127f2403ff583d224e0d9d4e68c1c5bfc.zip
-more work on DHTU integration
-rw-r--r--src/datacache/datacache.c86
-rw-r--r--src/datacache/plugin_datacache_heap.c8
-rw-r--r--src/datacache/plugin_datacache_postgres.c16
-rw-r--r--src/datacache/plugin_datacache_sqlite.c52
-rw-r--r--src/datacache/plugin_datacache_template.c2
-rw-r--r--src/dht/Makefile.am1
-rw-r--r--src/dht/dht_api.c11
-rw-r--r--src/dht/gnunet-service-dht.c149
-rw-r--r--src/dht/gnunet-service-dht.h60
-rw-r--r--src/dht/gnunet-service-dht_clients.c2
-rw-r--r--src/dht/gnunet-service-dht_datacache.c124
-rw-r--r--src/dht/gnunet-service-dht_datacache.h11
-rw-r--r--src/dht/gnunet-service-dht_hello.c154
-rw-r--r--src/dht/gnunet-service-dht_hello.h55
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c1108
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h17
-rw-r--r--src/dht/gnunet-service-dht_routing.c2
-rw-r--r--src/dhtu/plugin_dhtu_gnunet.c13
-rw-r--r--src/dhtu/plugin_dhtu_ip.c5
-rw-r--r--src/hello/hello-uri.c149
-rw-r--r--src/include/gnunet_datacache_lib.h2
-rw-r--r--src/include/gnunet_datacache_plugin.h2
-rw-r--r--src/include/gnunet_dht_service.h10
-rw-r--r--src/include/gnunet_dhtu_plugin.h5
-rw-r--r--src/include/gnunet_hello_uri_lib.h44
-rw-r--r--src/include/gnunet_protocols.h8
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,
114 h->utilization -= size; 114 h->utilization -= size;
115 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); 115 GNUNET_CONTAINER_bloomfilter_remove (h->filter, key);
116 GNUNET_STATISTICS_update (h->stats, 116 GNUNET_STATISTICS_update (h->stats,
117 gettext_noop ("# bytes stored"), 117 "# bytes stored",
118 -(long long) size, 118 -(long long) size,
119 GNUNET_NO); 119 GNUNET_NO);
120 GNUNET_STATISTICS_update (h->stats, 120 GNUNET_STATISTICS_update (h->stats,
121 gettext_noop ("# items stored"), 121 "# items stored",
122 -1, 122 -1,
123 GNUNET_NO); 123 GNUNET_NO);
124} 124}
@@ -136,15 +136,25 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
136 const struct GNUNET_OS_ProjectData *pd; 136 const struct GNUNET_OS_ProjectData *pd;
137 137
138 if (GNUNET_OK != 138 if (GNUNET_OK !=
139 GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", &quota)) 139 GNUNET_CONFIGURATION_get_value_size (cfg,
140 section,
141 "QUOTA",
142 &quota))
140 { 143 {
141 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "QUOTA"); 144 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
145 section,
146 "QUOTA");
142 return NULL; 147 return NULL;
143 } 148 }
144 if (GNUNET_OK != 149 if (GNUNET_OK !=
145 GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name)) 150 GNUNET_CONFIGURATION_get_value_string (cfg,
151 section,
152 "DATABASE",
153 &name))
146 { 154 {
147 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, "DATABASE"); 155 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
156 section,
157 "DATABASE");
148 return NULL; 158 return NULL;
149 } 159 }
150 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ 160 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,
152 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle); 162 ret = GNUNET_new (struct GNUNET_DATACACHE_Handle);
153 163
154 if (GNUNET_YES != 164 if (GNUNET_YES !=
155 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF")) 165 GNUNET_CONFIGURATION_get_value_yesno (cfg,
166 section,
167 "DISABLE_BF"))
156 { 168 {
157 if (GNUNET_YES != 169 if (GNUNET_YES !=
158 GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC")) 170 GNUNET_CONFIGURATION_get_value_yesno (cfg,
171 section,
172 "DISABLE_BF_RC"))
159 { 173 {
160 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom"); 174 ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom");
161 } 175 }
@@ -174,7 +188,8 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
174 5); /* approx. 3% false positives at max use */ 188 5); /* approx. 3% false positives at max use */
175 } 189 }
176 } 190 }
177 ret->stats = GNUNET_STATISTICS_create ("datacache", cfg); 191 ret->stats = GNUNET_STATISTICS_create ("datacache",
192 cfg);
178 ret->section = GNUNET_strdup (section); 193 ret->section = GNUNET_strdup (section);
179 ret->env.cfg = cfg; 194 ret->env.cfg = cfg;
180 ret->env.delete_notify = &env_delete_notify; 195 ret->env.delete_notify = &env_delete_notify;
@@ -182,25 +197,31 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
182 ret->env.cls = ret; 197 ret->env.cls = ret;
183 ret->env.delete_notify = &env_delete_notify; 198 ret->env.delete_notify = &env_delete_notify;
184 ret->env.quota = quota; 199 ret->env.quota = quota;
185 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' datacache plugin\n"), name); 200 LOG (GNUNET_ERROR_TYPE_INFO,
186 GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); 201 "Loading `%s' datacache plugin\n",
202 name);
203 GNUNET_asprintf (&libname,
204 "libgnunet_plugin_datacache_%s",
205 name);
187 ret->short_name = name; 206 ret->short_name = name;
188 ret->lib_name = libname; 207 ret->lib_name = libname;
189 /* Load the plugin within GNUnet's default context */ 208 /* Load the plugin within GNUnet's default context */
190 pd = GNUNET_OS_project_data_get (); 209 pd = GNUNET_OS_project_data_get ();
191 GNUNET_OS_init (GNUNET_OS_project_data_default ()); 210 GNUNET_OS_init (GNUNET_OS_project_data_default ());
192 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 211 ret->api = GNUNET_PLUGIN_load (libname,
212 &ret->env);
193 GNUNET_OS_init (pd); 213 GNUNET_OS_init (pd);
194 if (NULL == ret->api) 214 if (NULL == ret->api)
195 { 215 {
196 /* Try to load the plugin within the application's context 216 /* Try to load the plugin within the application's context
197 This normally happens when the application is not GNUnet itself but a 217 This normally happens when the application is not GNUnet itself but a
198 third party; inside GNUnet this is effectively a double failure. */ 218 third party; inside GNUnet this is effectively a double failure. */
199 ret->api = GNUNET_PLUGIN_load (libname, &ret->env); 219 ret->api = GNUNET_PLUGIN_load (libname,
220 &ret->env);
200 if (NULL == ret->api) 221 if (NULL == ret->api)
201 { 222 {
202 LOG (GNUNET_ERROR_TYPE_ERROR, 223 LOG (GNUNET_ERROR_TYPE_ERROR,
203 _ ("Failed to load datacache plugin for `%s'\n"), 224 "Failed to load datacache plugin for `%s'\n",
204 name); 225 name);
205 GNUNET_DATACACHE_destroy (ret); 226 GNUNET_DATACACHE_destroy (ret);
206 return NULL; 227 return NULL;
@@ -216,7 +237,9 @@ GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
216 if (NULL != h->filter) 237 if (NULL != h->filter)
217 GNUNET_CONTAINER_bloomfilter_free (h->filter); 238 GNUNET_CONTAINER_bloomfilter_free (h->filter);
218 if (NULL != h->api) 239 if (NULL != h->api)
219 GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api)); 240 GNUNET_break (NULL ==
241 GNUNET_PLUGIN_unload (h->lib_name,
242 h->api));
220 GNUNET_free (h->lib_name); 243 GNUNET_free (h->lib_name);
221 GNUNET_free (h->short_name); 244 GNUNET_free (h->short_name);
222 GNUNET_free (h->section); 245 GNUNET_free (h->section);
@@ -270,17 +293,19 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h,
270 "Stored data under key `%s' in cache\n", 293 "Stored data under key `%s' in cache\n",
271 GNUNET_h2s (key)); 294 GNUNET_h2s (key));
272 if (NULL != h->filter) 295 if (NULL != h->filter)
273 GNUNET_CONTAINER_bloomfilter_add (h->filter, key); 296 GNUNET_CONTAINER_bloomfilter_add (h->filter,
297 key);
274 GNUNET_STATISTICS_update (h->stats, 298 GNUNET_STATISTICS_update (h->stats,
275 gettext_noop ("# bytes stored"), 299 "# bytes stored",
276 used, 300 used,
277 GNUNET_NO); 301 GNUNET_NO);
278 GNUNET_STATISTICS_update (h->stats, 302 GNUNET_STATISTICS_update (h->stats,
279 gettext_noop ("# items stored"), 303 "# items stored",
280 1, 304 1,
281 GNUNET_NO); 305 GNUNET_NO);
282 while (h->utilization + used > h->env.quota) 306 while (h->utilization + used > h->env.quota)
283 GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); 307 GNUNET_assert (GNUNET_OK ==
308 h->api->del (h->api->cls));
284 h->utilization += used; 309 h->utilization += used;
285 return GNUNET_OK; 310 return GNUNET_OK;
286} 311}
@@ -294,18 +319,18 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
294 void *iter_cls) 319 void *iter_cls)
295{ 320{
296 GNUNET_STATISTICS_update (h->stats, 321 GNUNET_STATISTICS_update (h->stats,
297 gettext_noop ("# requests received"), 322 "# requests received",
298 1, 323 1,
299 GNUNET_NO); 324 GNUNET_NO);
300 LOG (GNUNET_ERROR_TYPE_DEBUG, 325 LOG (GNUNET_ERROR_TYPE_DEBUG,
301 "Processing request for key `%s'\n", 326 "Processing request for key `%s'\n",
302 GNUNET_h2s (key)); 327 GNUNET_h2s (key));
303 if ((NULL != h->filter) && 328 if ((NULL != h->filter) &&
304 (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key))) 329 (GNUNET_OK !=
330 GNUNET_CONTAINER_bloomfilter_test (h->filter, key)))
305 { 331 {
306 GNUNET_STATISTICS_update (h->stats, 332 GNUNET_STATISTICS_update (h->stats,
307 gettext_noop ( 333 "# requests filtered by bloom filter",
308 "# requests filtered by bloom filter"),
309 1, 334 1,
310 GNUNET_NO); 335 GNUNET_NO);
311 LOG (GNUNET_ERROR_TYPE_DEBUG, 336 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -313,26 +338,33 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
313 GNUNET_h2s (key)); 338 GNUNET_h2s (key));
314 return 0; /* can not be present */ 339 return 0; /* can not be present */
315 } 340 }
316 return h->api->get (h->api->cls, key, type, iter, iter_cls); 341 return h->api->get (h->api->cls,
342 key,
343 type,
344 iter, iter_cls);
317} 345}
318 346
319 347
320unsigned int 348unsigned int
321GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 349GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
322 const struct GNUNET_HashCode *key, 350 const struct GNUNET_HashCode *key,
351 enum GNUNET_BLOCK_Type type,
323 unsigned int num_results, 352 unsigned int num_results,
324 GNUNET_DATACACHE_Iterator iter, 353 GNUNET_DATACACHE_Iterator iter,
325 void *iter_cls) 354 void *iter_cls)
326{ 355{
327 GNUNET_STATISTICS_update (h->stats, 356 GNUNET_STATISTICS_update (h->stats,
328 gettext_noop ( 357 "# proximity search requests received",
329 "# proximity search requests received"),
330 1, 358 1,
331 GNUNET_NO); 359 GNUNET_NO);
332 LOG (GNUNET_ERROR_TYPE_DEBUG, 360 LOG (GNUNET_ERROR_TYPE_DEBUG,
333 "Processing proximity search at `%s'\n", 361 "Processing proximity search at `%s'\n",
334 GNUNET_h2s (key)); 362 GNUNET_h2s (key));
335 return h->api->get_closest (h->api->cls, key, num_results, iter, iter_cls); 363 return h->api->get_closest (h->api->cls,
364 key,
365 type,
366 num_results,
367 iter, iter_cls);
336} 368}
337 369
338 370
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
409{ 409{
410 struct Value **values; 410 struct Value **values;
411 411
412 enum GNUNET_BLOCK_Type type;
413
412 unsigned int num_results; 414 unsigned int num_results;
413 415
414 const struct GNUNET_HashCode *key; 416 const struct GNUNET_HashCode *key;
@@ -427,6 +429,9 @@ find_closest (void *cls,
427 if (1 != GNUNET_CRYPTO_hash_cmp (key, 429 if (1 != GNUNET_CRYPTO_hash_cmp (key,
428 gcc->key)) 430 gcc->key))
429 return GNUNET_OK; /* useless */ 431 return GNUNET_OK; /* useless */
432 if ( (val->type != gcc->type) &&
433 (GNUNET_BLOCK_TYPE_ANY != gcc->type) )
434 return GNUNET_OK; /* useless */
430 j = gcc->num_results; 435 j = gcc->num_results;
431 for (unsigned int i = 0; i < gcc->num_results; i++) 436 for (unsigned int i = 0; i < gcc->num_results; i++)
432 { 437 {
@@ -457,6 +462,7 @@ find_closest (void *cls,
457 * 462 *
458 * @param cls closure (internal context for the plugin) 463 * @param cls closure (internal context for the plugin)
459 * @param key area of the keyspace to look into 464 * @param key area of the keyspace to look into
465 * @param type desired block type for the replies
460 * @param num_results number of results that should be returned to @a iter 466 * @param num_results number of results that should be returned to @a iter
461 * @param iter maybe NULL (to just count) 467 * @param iter maybe NULL (to just count)
462 * @param iter_cls closure for @a iter 468 * @param iter_cls closure for @a iter
@@ -465,6 +471,7 @@ find_closest (void *cls,
465static unsigned int 471static unsigned int
466heap_plugin_get_closest (void *cls, 472heap_plugin_get_closest (void *cls,
467 const struct GNUNET_HashCode *key, 473 const struct GNUNET_HashCode *key,
474 enum GNUNET_BLOCK_Type type,
468 unsigned int num_results, 475 unsigned int num_results,
469 GNUNET_DATACACHE_Iterator iter, 476 GNUNET_DATACACHE_Iterator iter,
470 void *iter_cls) 477 void *iter_cls)
@@ -473,6 +480,7 @@ heap_plugin_get_closest (void *cls,
473 struct Value *values[num_results]; 480 struct Value *values[num_results];
474 struct GetClosestContext gcc = { 481 struct GetClosestContext gcc = {
475 .values = values, 482 .values = values,
483 .type = type,
476 .num_results = num_results, 484 .num_results = num_results,
477 .key = key 485 .key = key
478 }; 486 };
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 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018 GNUnet e.V. 3 Copyright (C) 2006, 2009, 2010, 2012, 2015, 2017, 2018, 2022 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published 6 under the terms of the GNU Affero General Public License as published
@@ -109,9 +109,13 @@ init_connection (struct Plugin *plugin)
109 " ORDER BY prox ASC, discard_time ASC LIMIT 1", 109 " ORDER BY prox ASC, discard_time ASC LIMIT 1",
110 0), 110 0),
111 GNUNET_PQ_make_prepare ("get_closest", 111 GNUNET_PQ_make_prepare ("get_closest",
112 "SELECT discard_time,type,value,path,key FROM gn011dc " 112 "SELECT discard_time,type,value,path,key FROM gn011dc"
113 "WHERE key>=$1 AND discard_time >= $2 ORDER BY key ASC LIMIT $3", 113 " WHERE key >= $1"
114 3), 114 " AND discard_time >= $2"
115 " AND ( (type = $3) OR ( 0 = $3) )"
116 " ORDER BY key ASC"
117 " LIMIT $4",
118 4),
115 GNUNET_PQ_make_prepare ("delrow", 119 GNUNET_PQ_make_prepare ("delrow",
116 "DELETE FROM gn011dc WHERE oid=$1", 120 "DELETE FROM gn011dc WHERE oid=$1",
117 1), 121 1),
@@ -511,6 +515,7 @@ extract_result_cb (void *cls,
511 * 515 *
512 * @param cls closure (internal context for the plugin) 516 * @param cls closure (internal context for the plugin)
513 * @param key area of the keyspace to look into 517 * @param key area of the keyspace to look into
518 * @param type desired block type for the replies
514 * @param num_results number of results that should be returned to @a iter 519 * @param num_results number of results that should be returned to @a iter
515 * @param iter maybe NULL (to just count) 520 * @param iter maybe NULL (to just count)
516 * @param iter_cls closure for @a iter 521 * @param iter_cls closure for @a iter
@@ -519,16 +524,19 @@ extract_result_cb (void *cls,
519static unsigned int 524static unsigned int
520postgres_plugin_get_closest (void *cls, 525postgres_plugin_get_closest (void *cls,
521 const struct GNUNET_HashCode *key, 526 const struct GNUNET_HashCode *key,
527 enum GNUNET_BLOCK_Type type,
522 unsigned int num_results, 528 unsigned int num_results,
523 GNUNET_DATACACHE_Iterator iter, 529 GNUNET_DATACACHE_Iterator iter,
524 void *iter_cls) 530 void *iter_cls)
525{ 531{
526 struct Plugin *plugin = cls; 532 struct Plugin *plugin = cls;
527 uint32_t num_results32 = (uint32_t) num_results; 533 uint32_t num_results32 = (uint32_t) num_results;
534 uint32_t type32 = (uint32_t) type;
528 struct GNUNET_TIME_Absolute now; 535 struct GNUNET_TIME_Absolute now;
529 struct GNUNET_PQ_QueryParam params[] = { 536 struct GNUNET_PQ_QueryParam params[] = {
530 GNUNET_PQ_query_param_auto_from_type (key), 537 GNUNET_PQ_query_param_auto_from_type (key),
531 GNUNET_PQ_query_param_absolute_time (&now), 538 GNUNET_PQ_query_param_absolute_time (&now),
539 GNUNET_PQ_query_param_uint32 (&type32),
532 GNUNET_PQ_query_param_uint32 (&num_results32), 540 GNUNET_PQ_query_param_uint32 (&num_results32),
533 GNUNET_PQ_query_param_end 541 GNUNET_PQ_query_param_end
534 }; 542 };
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)
454 * 454 *
455 * @param cls closure (internal context for the plugin) 455 * @param cls closure (internal context for the plugin)
456 * @param key area of the keyspace to look into 456 * @param key area of the keyspace to look into
457 * @param type desired block type for the replies
457 * @param num_results number of results that should be returned to @a iter 458 * @param num_results number of results that should be returned to @a iter
458 * @param iter maybe NULL (to just count) 459 * @param iter maybe NULL (to just count)
459 * @param iter_cls closure for @a iter 460 * @param iter_cls closure for @a iter
@@ -462,11 +463,13 @@ sqlite_plugin_del (void *cls)
462static unsigned int 463static unsigned int
463sqlite_plugin_get_closest (void *cls, 464sqlite_plugin_get_closest (void *cls,
464 const struct GNUNET_HashCode *key, 465 const struct GNUNET_HashCode *key,
466 enum GNUNET_BLOCK_Type type,
465 unsigned int num_results, 467 unsigned int num_results,
466 GNUNET_DATACACHE_Iterator iter, 468 GNUNET_DATACACHE_Iterator iter,
467 void *iter_cls) 469 void *iter_cls)
468{ 470{
469 struct Plugin *plugin = cls; 471 struct Plugin *plugin = cls;
472 uint32_t type32 = type;
470 uint32_t num_results32 = num_results; 473 uint32_t num_results32 = num_results;
471 struct GNUNET_TIME_Absolute now; 474 struct GNUNET_TIME_Absolute now;
472 struct GNUNET_TIME_Absolute exp; 475 struct GNUNET_TIME_Absolute exp;
@@ -474,38 +477,46 @@ sqlite_plugin_get_closest (void *cls,
474 void *dat; 477 void *dat;
475 unsigned int cnt; 478 unsigned int cnt;
476 size_t psize; 479 size_t psize;
477 uint32_t type; 480 uint32_t rtype;
478 struct GNUNET_HashCode hc; 481 struct GNUNET_HashCode hc;
479 struct GNUNET_DHT_PathElement *path; 482 struct GNUNET_DHT_PathElement *path;
480 struct GNUNET_SQ_QueryParam params[] = 483 struct GNUNET_SQ_QueryParam params[] = {
481 { GNUNET_SQ_query_param_auto_from_type (key), 484 GNUNET_SQ_query_param_auto_from_type (key),
482 GNUNET_SQ_query_param_absolute_time (&now), 485 GNUNET_SQ_query_param_absolute_time (&now),
486 GNUNET_SQ_query_param_uint32 (&type32),
483 GNUNET_SQ_query_param_uint32 (&num_results32), 487 GNUNET_SQ_query_param_uint32 (&num_results32),
484 GNUNET_SQ_query_param_end }; 488 GNUNET_SQ_query_param_end
485 struct GNUNET_SQ_ResultSpec rs[] = 489 };
486 { GNUNET_SQ_result_spec_variable_size (&dat, &size), 490 struct GNUNET_SQ_ResultSpec rs[] = {
491 GNUNET_SQ_result_spec_variable_size (&dat, &size),
487 GNUNET_SQ_result_spec_absolute_time (&exp), 492 GNUNET_SQ_result_spec_absolute_time (&exp),
488 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize), 493 GNUNET_SQ_result_spec_variable_size ((void **) &path, &psize),
489 GNUNET_SQ_result_spec_uint32 (&type), 494 GNUNET_SQ_result_spec_uint32 (&rtype),
490 GNUNET_SQ_result_spec_auto_from_type (&hc), 495 GNUNET_SQ_result_spec_auto_from_type (&hc),
491 GNUNET_SQ_result_spec_end }; 496 GNUNET_SQ_result_spec_end
497 };
492 498
493 now = GNUNET_TIME_absolute_get (); 499 now = GNUNET_TIME_absolute_get ();
494 LOG (GNUNET_ERROR_TYPE_DEBUG, 500 LOG (GNUNET_ERROR_TYPE_DEBUG,
495 "Processing GET_CLOSEST for key `%s'\n", 501 "Processing GET_CLOSEST for key `%s'\n",
496 GNUNET_h2s (key)); 502 GNUNET_h2s (key));
497 if (GNUNET_OK != GNUNET_SQ_bind (plugin->get_closest_stmt, params)) 503 if (GNUNET_OK !=
504 GNUNET_SQ_bind (plugin->get_closest_stmt,
505 params))
498 { 506 {
499 LOG_SQLITE (plugin->dbh, 507 LOG_SQLITE (plugin->dbh,
500 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, 508 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
501 "sqlite3_bind_xxx"); 509 "sqlite3_bind_xxx");
502 GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt); 510 GNUNET_SQ_reset (plugin->dbh,
511 plugin->get_closest_stmt);
503 return 0; 512 return 0;
504 } 513 }
505 cnt = 0; 514 cnt = 0;
506 while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt)) 515 while (SQLITE_ROW == sqlite3_step (plugin->get_closest_stmt))
507 { 516 {
508 if (GNUNET_OK != GNUNET_SQ_extract_result (plugin->get_closest_stmt, rs)) 517 if (GNUNET_OK !=
518 GNUNET_SQ_extract_result (plugin->get_closest_stmt,
519 rs))
509 { 520 {
510 GNUNET_break (0); 521 GNUNET_break (0);
511 break; 522 break;
@@ -522,14 +533,22 @@ sqlite_plugin_get_closest (void *cls,
522 "Found %u-byte result at %s when processing GET_CLOSE\n", 533 "Found %u-byte result at %s when processing GET_CLOSE\n",
523 (unsigned int) size, 534 (unsigned int) size,
524 GNUNET_h2s (&hc)); 535 GNUNET_h2s (&hc));
525 if (GNUNET_OK != iter (iter_cls, &hc, size, dat, type, exp, psize, path)) 536 if (GNUNET_OK != iter (iter_cls,
537 &hc,
538 size,
539 dat,
540 rtype,
541 exp,
542 psize,
543 path))
526 { 544 {
527 GNUNET_SQ_cleanup_result (rs); 545 GNUNET_SQ_cleanup_result (rs);
528 break; 546 break;
529 } 547 }
530 GNUNET_SQ_cleanup_result (rs); 548 GNUNET_SQ_cleanup_result (rs);
531 } 549 }
532 GNUNET_SQ_reset (plugin->dbh, plugin->get_closest_stmt); 550 GNUNET_SQ_reset (plugin->dbh,
551 plugin->get_closest_stmt);
533 return cnt; 552 return cnt;
534} 553}
535 554
@@ -620,7 +639,7 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
620 &plugin->get_stmt)) || 639 &plugin->get_stmt)) ||
621 (SQLITE_OK != sq_prepare (plugin->dbh, 640 (SQLITE_OK != sq_prepare (plugin->dbh,
622 "SELECT _ROWID_,key,value FROM ds091" 641 "SELECT _ROWID_,key,value FROM ds091"
623 " WHERE expire < ?" 642 " WHERE expire < ?1"
624 " ORDER BY expire ASC LIMIT 1", 643 " ORDER BY expire ASC LIMIT 1",
625 &plugin->del_expired_stmt)) || 644 &plugin->del_expired_stmt)) ||
626 (SQLITE_OK != sq_prepare (plugin->dbh, 645 (SQLITE_OK != sq_prepare (plugin->dbh,
@@ -633,7 +652,10 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
633 (SQLITE_OK != 652 (SQLITE_OK !=
634 sq_prepare (plugin->dbh, 653 sq_prepare (plugin->dbh,
635 "SELECT value,expire,path,type,key FROM ds091 " 654 "SELECT value,expire,path,type,key FROM ds091 "
636 "WHERE key>=? AND expire >= ? ORDER BY KEY ASC LIMIT ?", 655 " WHERE key>=?1 "
656 " AND expire >= ?2"
657 " AND ( (type=?3) or (0 == ?3) )"
658 " ORDER BY KEY ASC LIMIT ?4",
637 &plugin->get_closest_stmt))) 659 &plugin->get_closest_stmt)))
638 { 660 {
639 LOG_SQLITE (plugin->dbh, 661 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)
116 * 116 *
117 * @param cls closure (internal context for the plugin) 117 * @param cls closure (internal context for the plugin)
118 * @param key area of the keyspace to look into 118 * @param key area of the keyspace to look into
119 * @param type desired block type for the replies
119 * @param num_results number of results that should be returned to @a iter 120 * @param num_results number of results that should be returned to @a iter
120 * @param iter maybe NULL (to just count) 121 * @param iter maybe NULL (to just count)
121 * @param iter_cls closure for @a iter 122 * @param iter_cls closure for @a iter
@@ -124,6 +125,7 @@ template_plugin_del (void *cls)
124static unsigned int 125static unsigned int
125template_plugin_get_closest (void *cls, 126template_plugin_get_closest (void *cls,
126 const struct GNUNET_HashCode *key, 127 const struct GNUNET_HashCode *key,
128 enum GNUNET_BLOCK_Type type,
127 unsigned int num_results, 129 unsigned int num_results,
128 GNUNET_DATACACHE_Iterator iter, 130 GNUNET_DATACACHE_Iterator iter,
129 void *iter_cls) 131 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 = \
58gnunet_service_dht_SOURCES = \ 58gnunet_service_dht_SOURCES = \
59 gnunet-service-dht.c gnunet-service-dht.h \ 59 gnunet-service-dht.c gnunet-service-dht.h \
60 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \ 60 gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \
61 gnunet-service-dht_hello.c gnunet-service-dht_hello.h \
62 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \ 61 gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \
63 gnunet-service-dht_routing.c gnunet-service-dht_routing.h 62 gnunet-service-dht_routing.c gnunet-service-dht_routing.h
64gnunet_service_dht_LDADD = \ 63gnunet_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,
726 const struct GNUNET_DHT_ClientResultMessage *crm = cls; 726 const struct GNUNET_DHT_ClientResultMessage *crm = cls;
727 struct GNUNET_DHT_GetHandle *get_handle = value; 727 struct GNUNET_DHT_GetHandle *get_handle = value;
728 size_t msize = ntohs (crm->header.size) - sizeof(*crm); 728 size_t msize = ntohs (crm->header.size) - sizeof(*crm);
729 uint16_t type = ntohl (crm->type);
729 uint32_t put_path_length = ntohl (crm->put_path_length); 730 uint32_t put_path_length = ntohl (crm->put_path_length);
730 uint32_t get_path_length = ntohl (crm->get_path_length); 731 uint32_t get_path_length = ntohl (crm->get_path_length);
731 const struct GNUNET_DHT_PathElement *put_path; 732 const struct GNUNET_DHT_PathElement *put_path;
@@ -745,7 +746,13 @@ process_client_result (void *cls,
745 (unsigned long long) get_handle->unique_id); 746 (unsigned long long) get_handle->unique_id);
746 return GNUNET_YES; 747 return GNUNET_YES;
747 } 748 }
748 /* FIXME: might want to check that type matches */ 749 if ( (get_handle->type != GNUNET_BLOCK_TYPE_ANY) &&
750 (get_handle->type != type) )
751 {
752 /* type mismatch */
753 GNUNET_break (0);
754 return GNUNET_YES;
755 }
749 meta_length = 756 meta_length =
750 sizeof(struct GNUNET_DHT_PathElement) * (get_path_length + put_path_length); 757 sizeof(struct GNUNET_DHT_PathElement) * (get_path_length + put_path_length);
751 data_length = msize - meta_length; 758 data_length = msize - meta_length;
@@ -786,7 +793,7 @@ process_client_result (void *cls,
786 get_path_length, 793 get_path_length,
787 put_path, 794 put_path,
788 put_path_length, 795 put_path_length,
789 ntohl (crm->type), 796 type,
790 data_length, 797 data_length,
791 data); 798 data);
792 return GNUNET_YES; 799 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 @@
28#include "gnunet_block_lib.h" 28#include "gnunet_block_lib.h"
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h" 30#include "gnunet_hello_lib.h"
31#include "gnunet_hello_uri_lib.h"
31#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
32#include "gnunet_statistics_service.h" 33#include "gnunet_statistics_service.h"
33#include "gnunet-service-dht.h" 34#include "gnunet-service-dht.h"
34#include "gnunet-service-dht_datacache.h" 35#include "gnunet-service-dht_datacache.h"
35#include "gnunet-service-dht_hello.h"
36#include "gnunet-service-dht_neighbours.h" 36#include "gnunet-service-dht_neighbours.h"
37#include "gnunet-service-dht_routing.h" 37#include "gnunet-service-dht_routing.h"
38 38
39/**
40 * How often do we broadcast our HELLO to neighbours if
41 * nothing special happens?
42 */
43#define HELLO_FREQUENCY GNUNET_TIME_UNIT_HOURS
44
39 45
40/** 46/**
41 * Information we keep per underlay. 47 * Information we keep per underlay.
@@ -110,7 +116,27 @@ struct MyAddress
110/** 116/**
111 * Our HELLO 117 * Our HELLO
112 */ 118 */
113struct GNUNET_MessageHeader *GDS_my_hello; 119struct GNUNET_HELLO_Builder *GDS_my_hello;
120
121/**
122 * Identity of this peer.
123 */
124struct GNUNET_PeerIdentity GDS_my_identity;
125
126/**
127 * Hash of the identity of this peer.
128 */
129struct GNUNET_HashCode GDS_my_identity_hash;
130
131/**
132 * Our private key.
133 */
134struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
135
136/**
137 * Task broadcasting our HELLO.
138 */
139static struct GNUNET_SCHEDULER_Task *hello_task;
114 140
115/** 141/**
116 * Handles for the DHT underlays. 142 * Handles for the DHT underlays.
@@ -133,11 +159,6 @@ static struct MyAddress *a_head;
133static struct MyAddress *a_tail; 159static struct MyAddress *a_tail;
134 160
135/** 161/**
136 * Hello address expiration
137 */
138struct GNUNET_TIME_Relative hello_expiration;
139
140/**
141 * log of the current network size estimate, used as the point where 162 * log of the current network size estimate, used as the point where
142 * we switch between random and deterministic routing. 163 * we switch between random and deterministic routing.
143 */ 164 */
@@ -195,13 +216,29 @@ GDS_NSE_get (void)
195 216
196 217
197/** 218/**
198 * Update our HELLO with all of our our addresses. 219 * Task run periodically to broadcast our HELLO.
220 *
221 * @param cls NULL
199 */ 222 */
200static void 223static void
201update_hello (void) 224broadcast_hello (void *cls)
202{ 225{
203 GNUNET_free (GDS_my_hello); 226 struct GNUNET_MessageHeader *hello;
204 // FIXME: build new HELLO properly! 227
228 (void) cls;
229 /* TODO: randomize! */
230 hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_FREQUENCY,
231 &broadcast_hello,
232 NULL);
233 hello = GNUNET_HELLO_builder_to_dht_hello_msg (GDS_my_hello,
234 &GDS_my_private_key);
235 if (NULL == hello)
236 {
237 GNUNET_break (0);
238 return;
239 }
240 GDS_NEIGHBOURS_broadcast (hello);
241 GNUNET_free (hello);
205} 242}
206 243
207 244
@@ -231,7 +268,12 @@ u_address_add (void *cls,
231 a_tail, 268 a_tail,
232 a); 269 a);
233 *ctx = a; 270 *ctx = a;
234 update_hello (); 271 GNUNET_HELLO_builder_add_address (GDS_my_hello,
272 address);
273 if (NULL != hello_task)
274 GNUNET_SCHEDULER_cancel (hello_task);
275 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
276 NULL);
235} 277}
236 278
237 279
@@ -245,12 +287,47 @@ u_address_del (void *ctx)
245{ 287{
246 struct MyAddress *a = ctx; 288 struct MyAddress *a = ctx;
247 289
290 GNUNET_HELLO_builder_del_address (GDS_my_hello,
291 a->url);
248 GNUNET_CONTAINER_DLL_remove (a_head, 292 GNUNET_CONTAINER_DLL_remove (a_head,
249 a_tail, 293 a_tail,
250 a); 294 a);
251 GNUNET_free (a->url); 295 GNUNET_free (a->url);
252 GNUNET_free (a); 296 GNUNET_free (a);
253 update_hello (); 297 if (NULL != hello_task)
298 GNUNET_SCHEDULER_cancel (hello_task);
299 hello_task = GNUNET_SCHEDULER_add_now (&broadcast_hello,
300 NULL);
301}
302
303
304void
305GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
306 const char *address)
307{
308 for (struct Underlay *u = u_head;
309 NULL != u;
310 u = u->next)
311 u->dhtu->try_connect (u->dhtu->cls,
312 pid,
313 address);
314}
315
316
317void
318GDS_u_send (struct Underlay *u,
319 struct GNUNET_DHTU_Target *target,
320 const void *msg,
321 size_t msg_size,
322 GNUNET_SCHEDULER_TaskCallback finished_cb,
323 void *finished_cb_cls)
324{
325 u->dhtu->send (u->dhtu->cls,
326 target,
327 msg,
328 msg_size,
329 finished_cb,
330 finished_cb_cls);
254} 331}
255 332
256 333
@@ -265,7 +342,6 @@ shutdown_task (void *cls)
265 GDS_NEIGHBOURS_done (); 342 GDS_NEIGHBOURS_done ();
266 GDS_DATACACHE_done (); 343 GDS_DATACACHE_done ();
267 GDS_ROUTING_done (); 344 GDS_ROUTING_done ();
268 GDS_HELLO_done ();
269 if (NULL != GDS_block_context) 345 if (NULL != GDS_block_context)
270 { 346 {
271 GNUNET_BLOCK_context_destroy (GDS_block_context); 347 GNUNET_BLOCK_context_destroy (GDS_block_context);
@@ -277,7 +353,7 @@ shutdown_task (void *cls)
277 GNUNET_YES); 353 GNUNET_YES);
278 GDS_stats = NULL; 354 GDS_stats = NULL;
279 } 355 }
280 GNUNET_free (GDS_my_hello); 356 GNUNET_HELLO_builder_free (GDS_my_hello);
281 GDS_my_hello = NULL; 357 GDS_my_hello = NULL;
282 GDS_CLIENTS_stop (); 358 GDS_CLIENTS_stop ();
283} 359}
@@ -348,14 +424,39 @@ run (void *cls,
348{ 424{
349 GDS_cfg = c; 425 GDS_cfg = c;
350 GDS_service = service; 426 GDS_service = service;
351 if (GNUNET_OK !=
352 GNUNET_CONFIGURATION_get_value_time (c,
353 "transport",
354 "HELLO_EXPIRATION",
355 &hello_expiration))
356 { 427 {
357 hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; 428 char *keyfile;
429
430 if (GNUNET_OK !=
431 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
432 "PEER",
433 "PRIVATE_KEY",
434 &keyfile))
435 {
436 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
437 "PEER",
438 "PRIVATE_KEY");
439 GNUNET_SCHEDULER_shutdown ();
440 return;
441 }
442 if (GNUNET_SYSERR ==
443 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
444 GNUNET_YES,
445 &GDS_my_private_key))
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
448 "Failed to setup peer's private key\n");
449 GNUNET_free (keyfile);
450 GNUNET_SCHEDULER_shutdown ();
451 return;
452 }
453 GNUNET_free (keyfile);
358 } 454 }
455 GNUNET_CRYPTO_eddsa_key_get_public (&GDS_my_private_key,
456 &GDS_my_identity.public_key);
457 GNUNET_CRYPTO_hash (&GDS_my_identity,
458 sizeof(struct GNUNET_PeerIdentity),
459 &GDS_my_identity_hash);
359 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); 460 GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg);
360 GDS_stats = GNUNET_STATISTICS_create ("dht", 461 GDS_stats = GNUNET_STATISTICS_create ("dht",
361 GDS_cfg); 462 GDS_cfg);
@@ -364,6 +465,12 @@ run (void *cls,
364 GDS_DATACACHE_init (); 465 GDS_DATACACHE_init ();
365 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 466 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
366 NULL); 467 NULL);
468 if (GNUNET_OK !=
469 GDS_NEIGHBOURS_init ())
470 {
471 GNUNET_SCHEDULER_shutdown ();
472 return;
473 }
367 GNUNET_CONFIGURATION_iterate_sections (GDS_cfg, 474 GNUNET_CONFIGURATION_iterate_sections (GDS_cfg,
368 &load_underlay, 475 &load_underlay,
369 NULL); 476 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,6 +27,7 @@
27#define GNUNET_SERVICE_DHT_H 27#define GNUNET_SERVICE_DHT_H
28 28
29#include "gnunet-service-dht_datacache.h" 29#include "gnunet-service-dht_datacache.h"
30#include "gnunet-service-dht_neighbours.h"
30#include "gnunet_statistics_service.h" 31#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h" 32#include "gnunet_transport_service.h"
32 33
@@ -34,6 +35,11 @@
34#define DEBUG_DHT GNUNET_EXTRA_LOGGING 35#define DEBUG_DHT GNUNET_EXTRA_LOGGING
35 36
36/** 37/**
38 * Information we keep per underlay.
39 */
40struct Underlay;
41
42/**
37 * Configuration we use. 43 * Configuration we use.
38 */ 44 */
39extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; 45extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg;
@@ -54,9 +60,59 @@ extern struct GNUNET_BLOCK_Context *GDS_block_context;
54extern struct GNUNET_STATISTICS_Handle *GDS_stats; 60extern struct GNUNET_STATISTICS_Handle *GDS_stats;
55 61
56/** 62/**
57 * Our HELLO 63 * Our HELLO builder.
64 */
65extern struct GNUNET_HELLO_Builder *GDS_my_hello;
66
67/**
68 * Identity of this peer.
69 */
70extern struct GNUNET_PeerIdentity GDS_my_identity;
71
72/**
73 * Hash of the identity of this peer.
74 */
75extern struct GNUNET_HashCode GDS_my_identity_hash;
76
77/**
78 * Our private key.
58 */ 79 */
59extern struct GNUNET_MessageHeader *GDS_my_hello; 80extern struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key;
81
82
83/**
84 * Ask all underlays to connect to peer @a pid at @a address.
85 *
86 * @param pid identity of the peer we would connect to
87 * @param address an address of @a pid
88 */
89void
90GDS_u_try_connect (const struct GNUNET_PeerIdentity *pid,
91 const char *address);
92
93
94/**
95 * Send message to some other participant over the network. Note that
96 * sending is not guaranteeing that the other peer actually received the
97 * message. For any given @a target, the DHT must wait for the @a
98 * finished_cb to be called before calling send() again.
99 *
100 * @param u underlay to use for transmission
101 * @param target receiver identification
102 * @param msg message
103 * @param msg_size number of bytes in @a msg
104 * @param finished_cb function called once transmission is done
105 * (not called if @a target disconnects, then only the
106 * disconnect_cb is called).
107 * @param finished_cb_cls closure for @a finished_cb
108 */
109void
110GDS_u_send (struct Underlay *u,
111 struct GNUNET_DHTU_Target *target,
112 const void *msg,
113 size_t msg_size,
114 GNUNET_SCHEDULER_TaskCallback finished_cb,
115 void *finished_cb_cls);
60 116
61 117
62/** 118/**
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,
917 GNUNET_NO); 917 GNUNET_NO);
918 return GNUNET_YES; /* type mismatch */ 918 return GNUNET_YES; /* type mismatch */
919 } 919 }
920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) && 920 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
921 (0 != GNUNET_memcmp (&frc->bd->key, 921 (0 != GNUNET_memcmp (&frc->bd->key,
922 query_hash)) ) 922 query_hash)) )
923 { 923 {
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)
68 1, 68 1,
69 GNUNET_NO); 69 GNUNET_NO);
70 GNUNET_CRYPTO_hash_xor (&bd->key, 70 GNUNET_CRYPTO_hash_xor (&bd->key,
71 &my_identity_hash, 71 &GDS_my_identity_hash,
72 &xor); 72 &xor);
73 r = GNUNET_DATACACHE_put (datacache, 73 r = GNUNET_DATACACHE_put (datacache,
74 &bd->key, 74 &bd->key,
@@ -231,7 +231,15 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
231 GDS_DATACACHE_GetCallback gc, 231 GDS_DATACACHE_GetCallback gc,
232 void *gc_cls) 232 void *gc_cls)
233{ 233{
234 struct GetRequestContext ctx; 234 struct GetRequestContext ctx = {
235 .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
236 .key = *key,
237 .xquery = xquery,
238 .xquery_size = xquery_size,
239 .bg = bg,
240 .gc = gc,
241 .gc_cls = gc_cls
242 };
235 unsigned int r; 243 unsigned int r;
236 244
237 if (NULL == datacache) 245 if (NULL == datacache)
@@ -240,13 +248,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
240 "# GET requests given to datacache", 248 "# GET requests given to datacache",
241 1, 249 1,
242 GNUNET_NO); 250 GNUNET_NO);
243 ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
244 ctx.key = *key;
245 ctx.xquery = xquery;
246 ctx.xquery_size = xquery_size;
247 ctx.bg = bg;
248 ctx.gc = gc;
249 ctx.gc_cls = gc_cls;
250 r = GNUNET_DATACACHE_get (datacache, 251 r = GNUNET_DATACACHE_get (datacache,
251 key, 252 key,
252 type, 253 type,
@@ -261,85 +262,44 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
261} 262}
262 263
263 264
264/** 265enum GNUNET_BLOCK_EvaluationResult
265 * Closure for #datacache_get_successors_iterator().
266 */
267struct SuccContext
268{
269 /**
270 * Function to call on the result
271 */
272 GDS_DATACACHE_GetCallback cb;
273
274 /**
275 * Closure for @e cb.
276 */
277 void *cb_cls;
278
279};
280
281
282/**
283 * Iterator for local get request results,
284 *
285 * @param cls closure with the `struct GNUNET_HashCode *` with the trail ID
286 * @param key the key this data is stored under
287 * @param size the size of the data identified by key
288 * @param data the actual data
289 * @param type the type of the data
290 * @param exp when does this value expire?
291 * @param put_path_length number of peers in @a put_path
292 * @param put_path path the reply took on put
293 * @return #GNUNET_OK to continue iteration, anything else
294 * to stop iteration.
295 */
296static enum GNUNET_GenericReturnValue
297datacache_get_successors_iterator (void *cls,
298 const struct GNUNET_HashCode *key,
299 size_t size,
300 const char *data,
301 enum GNUNET_BLOCK_Type type,
302 struct GNUNET_TIME_Absolute exp,
303 unsigned int put_path_length,
304 const struct
305 GNUNET_DHT_PathElement *put_path)
306{
307 const struct SuccContext *sc = cls;
308 struct GDS_DATACACHE_BlockData bd = {
309 .key = *key,
310 .expiration_time = exp,
311 .put_path = put_path,
312 .data = data,
313 .data_size = size,
314 .put_path_length = put_path_length,
315 .type = type
316 };
317
318 /* NOTE: The datacache currently does not store the RO from
319 the original 'put', so we don't know the 'correct' option
320 at this point anymore. Thus, we conservatively assume
321 that recording is desired (for now). */
322 sc->cb (sc->cb_cls,
323 &bd);
324 return GNUNET_OK;
325}
326
327
328void
329GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 266GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
267 enum GNUNET_BLOCK_Type type,
268 const void *xquery,
269 size_t xquery_size,
270 struct GNUNET_BLOCK_Group *bg,
330 GDS_DATACACHE_GetCallback cb, 271 GDS_DATACACHE_GetCallback cb,
331 void *cb_cls) 272 void *cb_cls)
332{ 273{
333 struct SuccContext sc = { 274 struct GetRequestContext ctx = {
334 .cb = cb, 275 .eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID,
335 .cb_cls = cb_cls 276 .key = *key,
277 .xquery = xquery,
278 .xquery_size = xquery_size,
279 .bg = bg,
280 .gc = cb,
281 .gc_cls = cb_cls
336 }; 282 };
283 unsigned int r;
337 284
338 (void) GNUNET_DATACACHE_get_closest (datacache, 285 if (NULL == datacache)
339 key, 286 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
340 NUM_CLOSEST, 287 GNUNET_STATISTICS_update (GDS_stats,
341 &datacache_get_successors_iterator, 288 "# GET closest requests given to datacache",
342 &sc); 289 1,
290 GNUNET_NO);
291 r = GNUNET_DATACACHE_get_closest (datacache,
292 key,
293 type,
294 NUM_CLOSEST,
295 &datacache_get_iterator,
296 &ctx);
297 LOG (GNUNET_ERROR_TYPE_DEBUG,
298 "DATACACHE approximate GET for key %s completed (%d). %u results found.\n",
299 GNUNET_h2s (key),
300 ctx.eval,
301 r);
302 return ctx.eval;
343} 303}
344 304
345 305
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,
122 * another peer. 122 * another peer.
123 * 123 *
124 * @param key the location at which the peer is looking for data that is close 124 * @param key the location at which the peer is looking for data that is close
125 * @param type requested data type
126 * @param xquery extended query
127 * @param xquery_size number of bytes in xquery
128 * @param bg block group to use for evaluation of replies
125 * @param cb function to call with the result 129 * @param cb function to call with the result
126 * @param cb_cls closure for @a cb 130 * @param cb_cls closure for @a cb
131 * @return evaluation result for the local replies
127 */ 132 */
128void 133enum GNUNET_BLOCK_EvaluationResult
129GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key, 134GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
135 enum GNUNET_BLOCK_Type type,
136 const void *xquery,
137 size_t xquery_size,
138 struct GNUNET_BLOCK_Group *bg,
130 GDS_DATACACHE_GetCallback cb, 139 GDS_DATACACHE_GetCallback cb,
131 void *cb_cls); 140 void *cb_cls);
132 141
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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.c
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - consider adding mechanism to remove expired HELLOs
28 */
29#include "platform.h"
30#include "gnunet-service-dht.h"
31#include "gnunet-service-dht_hello.h"
32#include "gnunet_peerinfo_service.h"
33
34
35/**
36 * Handle for peerinfo notifications.
37 */
38static struct GNUNET_PEERINFO_NotifyContext *pnc;
39
40/**
41 * Hash map of peers to HELLOs.
42 */
43static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
44
45
46/**
47 * Obtain a peer's HELLO if available
48 *
49 * @param peer peer to look for a HELLO from
50 * @return HELLO for the given peer
51 */
52const struct GNUNET_HELLO_Message *
53GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{
55 if (NULL == peer_to_hello)
56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
58 peer);
59}
60
61
62/**
63 * Function called for each HELLO known to PEERINFO.
64 *
65 * @param cls closure
66 * @param peer id of the peer, NULL for last call
67 * @param hello hello message for the peer (can be NULL)
68 * @param err_msg error message (not used)
69 *
70 * FIXME this is called once per address. Merge instead of replacing?
71 */
72static void
73process_hello (void *cls,
74 const struct GNUNET_PeerIdentity *peer,
75 const struct GNUNET_HELLO_Message *hello,
76 const char *err_msg)
77{
78 struct GNUNET_TIME_Absolute ex;
79 struct GNUNET_HELLO_Message *hm;
80
81 if (NULL == hello)
82 return;
83 ex = GNUNET_HELLO_get_last_expiration (hello);
84 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
85 return;
86 GNUNET_STATISTICS_update (GDS_stats,
87 "# HELLOs obtained from peerinfo",
88 1,
89 GNUNET_NO);
90 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
91 peer);
92 GNUNET_free (hm);
93 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
94 GNUNET_memcpy (hm,
95 hello,
96 GNUNET_HELLO_size (hello));
97 GNUNET_assert (GNUNET_SYSERR !=
98 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
99 peer,
100 hm,
101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
102}
103
104
105/**
106 * Initialize HELLO subsystem.
107 */
108void
109GDS_HELLO_init ()
110{
111 pnc = GNUNET_PEERINFO_notify (GDS_cfg,
112 GNUNET_NO,
113 &process_hello,
114 NULL);
115 peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
116 GNUNET_NO);
117}
118
119
120/**
121 * Free memory occopied by the HELLO.
122 */
123static enum GNUNET_GenericReturnValue
124free_hello (void *cls,
125 const struct GNUNET_PeerIdentity *key,
126 void *hello)
127{
128 GNUNET_free (hello);
129 return GNUNET_OK;
130}
131
132
133/**
134 * Shutdown HELLO subsystem.
135 */
136void
137GDS_HELLO_done ()
138{
139 if (NULL != pnc)
140 {
141 GNUNET_PEERINFO_notify_cancel (pnc);
142 pnc = NULL;
143 }
144 if (NULL != peer_to_hello)
145 {
146 GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
147 &free_hello,
148 NULL);
149 GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
150 }
151}
152
153
154/* 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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file dht/gnunet-service-dht_hello.h
23 * @brief GNUnet DHT integration with peerinfo
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_DHT_HELLO_H
27#define GNUNET_SERVICE_DHT_HELLO_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_hello_lib.h"
31
32/**
33 * Obtain a peer's HELLO if available
34 *
35 * @param peer peer to look for a HELLO from
36 * @return HELLO for the given peer
37 */
38const struct GNUNET_HELLO_Message *
39GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer);
40
41
42/**
43 * Initialize HELLO subsystem.
44 */
45void
46GDS_HELLO_init (void);
47
48
49/**
50 * Shutdown HELLO subsystem.
51 */
52void
53GDS_HELLO_done (void);
54
55#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 @@
29#include "gnunet_protocols.h" 29#include "gnunet_protocols.h"
30#include "gnunet_signatures.h" 30#include "gnunet_signatures.h"
31#include "gnunet_hello_lib.h" 31#include "gnunet_hello_lib.h"
32#include "gnunet_hello_uri_lib.h"
32#include "gnunet-service-dht.h" 33#include "gnunet-service-dht.h"
33#include "gnunet-service-dht_hello.h"
34#include "gnunet-service-dht_neighbours.h" 34#include "gnunet-service-dht_neighbours.h"
35#include "gnunet-service-dht_routing.h" 35#include "gnunet-service-dht_routing.h"
36#include "dht.h" 36#include "dht.h"
@@ -88,11 +88,6 @@
88 */ 88 */
89#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) 89#define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
90 90
91/**
92 * Hello address expiration
93 */
94extern struct GNUNET_TIME_Relative hello_expiration;
95
96 91
97GNUNET_NETWORK_STRUCT_BEGIN 92GNUNET_NETWORK_STRUCT_BEGIN
98 93
@@ -260,81 +255,129 @@ GNUNET_NETWORK_STRUCT_END
260/** 255/**
261 * Entry for a peer in a bucket. 256 * Entry for a peer in a bucket.
262 */ 257 */
263struct PeerInfo 258struct PeerInfo;
259
260
261/**
262 * List of targets that we can use to reach this peer.
263 */
264struct Target
264{ 265{
265 /** 266 /**
266 * Next peer entry (DLL) 267 * Kept in a DLL.
267 */ 268 */
268 struct PeerInfo *next; 269 struct Target *next;
269 270
270 /** 271 /**
271 * Prev peer entry (DLL) 272 * Kept in a DLL.
272 */ 273 */
273 struct PeerInfo *prev; 274 struct Target *prev;
274 275
275 /** 276 /**
276 * Handle for sending messages to this peer. 277 * Handle for sending messages to this peer.
277 */ 278 */
278 struct GNUNET_DHTU_Target *target; 279 struct GNUNET_DHTU_Target *utarget;
279 280
280 /** 281 /**
281 * What is the identity of the peer? 282 * Underlay providing this target.
282 */ 283 */
283 struct GNUNET_PeerIdentity id; 284 struct Underlay *u;
284 285
285 /** 286 /**
286 * Hash of @e id. 287 * Peer this is a target for.
287 */ 288 */
288 struct GNUNET_HashCode phash; 289 struct PeerInfo *pi;
289 290
290 /** 291 /**
291 * Which bucket is this peer in? 292 * Set to number of messages are waiting for the transmission to finish.
292 */ 293 */
293 int peer_bucket; 294 unsigned int load;
295
296 /**
297 * Set to @a true if the target was dropped, but we could not clean
298 * up yet because @e busy was also true.
299 */
300 bool dropped;
301
294}; 302};
295 303
296 304
297/** 305/**
298 * Peers are grouped into buckets. 306 * Entry for a peer in a bucket.
299 */ 307 */
300struct PeerBucket 308struct PeerInfo
301{ 309{
302 /** 310 /**
303 * Head of DLL 311 * What is the identity of the peer?
304 */ 312 */
305 struct PeerInfo *head; 313 struct GNUNET_PeerIdentity id;
306 314
307 /** 315 /**
308 * Tail of DLL 316 * Hash of @e id.
309 */ 317 */
310 struct PeerInfo *tail; 318 struct GNUNET_HashCode phash;
311 319
312 /** 320 /**
313 * Number of peers in the bucket. 321 * When does our HELLO from this peer expire?
314 */ 322 */
315 unsigned int peers_size; 323 struct GNUNET_TIME_Absolute hello_expiration;
324
325 /**
326 * Next peer entry (DLL)
327 */
328 struct PeerInfo *next;
329
330 /**
331 * Prev peer entry (DLL)
332 */
333 struct PeerInfo *prev;
334
335 /**
336 * Head of DLL of targets for this peer.
337 */
338 struct Target *t_head;
339
340 /**
341 * Tail of DLL of targets for this peer.
342 */
343 struct Target *t_tail;
344
345 /**
346 * Block with a HELLO of this peer.
347 */
348 void *hello;
349
350 /**
351 * Number of bytes in @e hello.
352 */
353 size_t hello_size;
354
355 /**
356 * Which bucket is this peer in?
357 */
358 int peer_bucket;
316}; 359};
317 360
318 361
319/** 362/**
320 * Information about a peer that we would like to connect to. 363 * Peers are grouped into buckets.
321 */ 364 */
322struct ConnectInfo 365struct PeerBucket
323{ 366{
324 /** 367 /**
325 * Handle to active HELLO offer operation, or NULL. 368 * Head of DLL
326 */ 369 */
327 struct GNUNET_TRANSPORT_OfferHelloHandle *oh; 370 struct PeerInfo *head;
328 371
329 /** 372 /**
330 * Handle to active connectivity suggestion operation, or NULL. 373 * Tail of DLL
331 */ 374 */
332 struct GNUNET_DHTU_PreferenceHandle *ph; 375 struct PeerInfo *tail;
333 376
334 /** 377 /**
335 * How much would we like to connect to this peer? 378 * Number of peers in the bucket.
336 */ 379 */
337 uint32_t strength; 380 unsigned int peers_size;
338}; 381};
339 382
340 383
@@ -371,12 +414,6 @@ static struct PeerBucket k_buckets[MAX_BUCKETS];
371static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers; 414static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers;
372 415
373/** 416/**
374 * Hash map of all peers we would like to be connected to.
375 * Values are of type `struct ConnectInfo`.
376 */
377static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers;
378
379/**
380 * Maximum size for each bucket. 417 * Maximum size for each bucket.
381 */ 418 */
382static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; 419static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
@@ -386,20 +423,83 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE;
386 */ 423 */
387static struct GNUNET_SCHEDULER_Task *find_peer_task; 424static struct GNUNET_SCHEDULER_Task *find_peer_task;
388 425
389/**
390 * Identity of this peer.
391 */
392static struct GNUNET_PeerIdentity my_identity;
393 426
394/** 427/**
395 * Hash of the identity of this peer. 428 * Function called whenever we finished sending to a target.
429 * Marks the transmission as finished (and the target as ready
430 * for the next message).
431 *
432 * @param cls a `struct Target *`
396 */ 433 */
397struct GNUNET_HashCode my_identity_hash; 434static void
435send_done_cb (void *cls)
436{
437 struct Target *t = cls;
438 struct PeerInfo *pi = t->pi; /* NULL if t->dropped! */
439
440 GNUNET_assert (t->load > 0);
441 t->load--;
442 if (0 < t->load)
443 return;
444 if (t->dropped)
445 {
446 GNUNET_free (t);
447 return;
448 }
449 /* move target back to the front */
450 GNUNET_CONTAINER_DLL_remove (pi->t_head,
451 pi->t_tail,
452 t);
453 GNUNET_CONTAINER_DLL_insert (pi->t_head,
454 pi->t_tail,
455 t);
456}
457
398 458
399/** 459/**
400 * Our private key. 460 * Send @a msg to @a pi.
461 *
462 * @param pi where to send the message
463 * @param msg message to send
401 */ 464 */
402static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key; 465static void
466do_send (struct PeerInfo *pi,
467 const struct GNUNET_MessageHeader *msg)
468{
469 struct Target *t;
470
471 for (t = pi->t_head;
472 NULL != t;
473 t = t->next)
474 if (t->load < MAXIMUM_PENDING_PER_PEER)
475 break;
476 if (NULL == t)
477 {
478 /* all targets busy, drop message */
479 GNUNET_STATISTICS_update (GDS_stats,
480 "# messages dropped (underlays busy)",
481 1,
482 GNUNET_NO);
483 return;
484 }
485 t->load++;
486 /* rotate busy targets to the end */
487 if (MAXIMUM_PENDING_PER_PEER == t->load)
488 {
489 GNUNET_CONTAINER_DLL_remove (pi->t_head,
490 pi->t_tail,
491 t);
492 GNUNET_CONTAINER_DLL_insert_tail (pi->t_head,
493 pi->t_tail,
494 t);
495 }
496 GDS_u_send (t->u,
497 t->utarget,
498 msg,
499 ntohs (msg->size),
500 &send_done_cb,
501 t);
502}
403 503
404 504
405/** 505/**
@@ -436,7 +536,7 @@ sign_path (const struct GNUNET_HashCode *key,
436 GNUNET_CRYPTO_hash (data, 536 GNUNET_CRYPTO_hash (data,
437 data_size, 537 data_size,
438 &hs.h_data); 538 &hs.h_data);
439 GNUNET_CRYPTO_eddsa_sign (&my_private_key, 539 GNUNET_CRYPTO_eddsa_sign (&GDS_my_private_key,
440 &hs, 540 &hs,
441 sig); 541 sig);
442} 542}
@@ -456,7 +556,7 @@ find_bucket (const struct GNUNET_HashCode *hc)
456 unsigned int bits; 556 unsigned int bits;
457 557
458 GNUNET_CRYPTO_hash_xor (hc, 558 GNUNET_CRYPTO_hash_xor (hc,
459 &my_identity_hash, 559 &GDS_my_identity_hash,
460 &xor); 560 &xor);
461 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 561 bits = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
462 if (bits == MAX_BUCKETS) 562 if (bits == MAX_BUCKETS)
@@ -470,175 +570,6 @@ find_bucket (const struct GNUNET_HashCode *hc)
470 570
471 571
472/** 572/**
473 * Function called when #GNUNET_TRANSPORT_offer_hello() is done.
474 * Clean up the "oh" field in the @a cls
475 *
476 * @param cls a `struct ConnectInfo`
477 */
478static void
479offer_hello_done (void *cls)
480{
481 struct ConnectInfo *ci = cls;
482
483 ci->oh = NULL;
484}
485
486
487/**
488 * Function called for all entries in #all_desired_peers to clean up.
489 *
490 * @param cls NULL
491 * @param peer peer the entry is for
492 * @param value the value to remove
493 * @return #GNUNET_YES
494 */
495static enum GNUNET_GenericReturnValue
496free_connect_info (void *cls,
497 const struct GNUNET_PeerIdentity *peer,
498 void *value)
499{
500 struct ConnectInfo *ci = value;
501
502 (void) cls;
503 GNUNET_assert (GNUNET_YES ==
504 GNUNET_CONTAINER_multipeermap_remove (all_desired_peers,
505 peer,
506 ci));
507 if (NULL != ci->ph)
508 {
509 // ci->u->drop (ci->ph); // FIXME!
510 ci->ph = NULL;
511 }
512 if (NULL != ci->oh)
513 {
514 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
515 ci->oh = NULL;
516 }
517 GNUNET_free (ci);
518 return GNUNET_YES;
519}
520
521
522/**
523 * Consider if we want to connect to a given peer, and if so
524 * let ATS know. If applicable, the HELLO is offered to the
525 * TRANSPORT service.
526 *
527 * @param pid peer to consider connectivity requirements for
528 * @param h a HELLO message, or NULL
529 */
530static void
531try_connect (const struct GNUNET_PeerIdentity *pid,
532 const struct GNUNET_MessageHeader *h)
533{
534 int bucket_idx;
535 struct GNUNET_HashCode pid_hash;
536 struct ConnectInfo *ci;
537 uint32_t strength;
538 struct PeerBucket *bucket;
539
540 GNUNET_CRYPTO_hash (pid,
541 sizeof(struct GNUNET_PeerIdentity),
542 &pid_hash);
543 bucket_idx = find_bucket (&pid_hash);
544 if (bucket_idx < 0)
545 {
546 GNUNET_break (0);
547 return; /* self!? */
548 }
549 bucket = &k_buckets[bucket_idx];
550 ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers,
551 pid);
552 if (bucket->peers_size < bucket_size)
553 strength = (bucket_size - bucket->peers_size) * bucket_idx;
554 else
555 strength = 0;
556 if (GNUNET_YES ==
557 GNUNET_CONTAINER_multipeermap_contains (all_connected_peers,
558 pid))
559 strength *= 2; /* double for connected peers */
560 if ( (0 == strength) &&
561 (NULL != ci) )
562 {
563 /* release request */
564 GNUNET_assert (GNUNET_YES ==
565 free_connect_info (NULL,
566 pid,
567 ci));
568 return;
569 }
570 if (NULL == ci)
571 {
572 ci = GNUNET_new (struct ConnectInfo);
573 GNUNET_assert (GNUNET_OK ==
574 GNUNET_CONTAINER_multipeermap_put (all_desired_peers,
575 pid,
576 ci,
577 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
578 }
579 if ( (NULL != ci->oh) &&
580 (NULL != h) )
581 GNUNET_TRANSPORT_offer_hello_cancel (ci->oh);
582 if (NULL != h)
583 ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_cfg,
584 h,
585 &offer_hello_done,
586 ci);
587 if ( (NULL != ci->ph) &&
588 (ci->strength != strength) )
589 {
590 // ci->u_api->drop (ci->ph);
591 ci->ph = NULL;
592 }
593 if (ci->strength != strength)
594 {
595#if FIXME
596 ci->ph = ci->u_api->hold (ci->u_api->cls,
597 TARGET);
598#endif
599 ci->strength = strength;
600 }
601}
602
603
604/**
605 * Function called for each peer in #all_desired_peers during
606 * #update_connect_preferences() if we have reason to adjust
607 * the strength of our desire to keep connections to certain
608 * peers. Calls #try_connect() to update the calculations for
609 * the given @a pid.
610 *
611 * @param cls NULL
612 * @param pid peer to update
613 * @param value unused
614 * @return #GNUNET_YES (continue to iterate)
615 */
616static enum GNUNET_GenericReturnValue
617update_desire_strength (void *cls,
618 const struct GNUNET_PeerIdentity *pid,
619 void *value)
620{
621 (void) cls;
622 (void) value;
623 try_connect (pid,
624 NULL);
625 return GNUNET_YES;
626}
627
628
629/**
630 * Update our preferences for connectivity as given to ATS.
631 */
632static void
633update_connect_preferences (void)
634{
635 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
636 &update_desire_strength,
637 NULL);
638}
639
640
641/**
642 * Add each of the peers we already know to the Bloom filter of 573 * Add each of the peers we already know to the Bloom filter of
643 * the request so that we don't get duplicate HELLOs. 574 * the request so that we don't get duplicate HELLOs.
644 * 575 *
@@ -728,11 +659,11 @@ send_find_peer_message (void *cls)
728 GNUNET_CONSTANTS_BLOOMFILTER_K); 659 GNUNET_CONSTANTS_BLOOMFILTER_K);
729 if (GNUNET_OK != 660 if (GNUNET_OK !=
730 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO, 661 GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
731 GNUNET_DHT_RO_FIND_PEER 662 GNUNET_DHT_RO_FIND_APPROXIMATE
732 | GNUNET_DHT_RO_RECORD_ROUTE, 663 | GNUNET_DHT_RO_RECORD_ROUTE,
733 FIND_PEER_REPLICATION_LEVEL, 664 FIND_PEER_REPLICATION_LEVEL,
734 0, /* hop count */ 665 0, /* hop count */
735 &my_identity_hash, 666 &GDS_my_identity_hash,
736 NULL, 0, /* xquery */ 667 NULL, 0, /* xquery */
737 bg, 668 bg,
738 peer_bf)) 669 peer_bf))
@@ -761,106 +692,131 @@ GDS_u_connect (void *cls,
761 const struct GNUNET_PeerIdentity *pid, 692 const struct GNUNET_PeerIdentity *pid,
762 void **ctx) 693 void **ctx)
763{ 694{
695 struct Underlay *u = cls;
764 struct PeerInfo *pi; 696 struct PeerInfo *pi;
765 struct PeerBucket *bucket; 697 struct PeerBucket *bucket;
766 698
767 (void) cls;
768 /* Check for connect to self message */ 699 /* Check for connect to self message */
769 if (0 == GNUNET_memcmp (&my_identity, 700 if (0 == GNUNET_memcmp (&GDS_my_identity,
770 pid)) 701 pid))
771 return; 702 return;
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
773 "Connected to peer %s\n", 704 "Connected to peer %s\n",
774 GNUNET_i2s (pid)); 705 GNUNET_i2s (pid));
775 GNUNET_assert (NULL == 706 pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers,
776 GNUNET_CONTAINER_multipeermap_get (all_connected_peers, 707 pid);
777 pid)); 708 if (NULL == pi)
778 GNUNET_STATISTICS_update (GDS_stats,
779 "# peers connected",
780 1,
781 GNUNET_NO);
782 pi = GNUNET_new (struct PeerInfo);
783 pi->id = *pid;
784 pi->target = target;
785 GNUNET_CRYPTO_hash (pid,
786 sizeof(*pid),
787 &pi->phash);
788 pi->peer_bucket = find_bucket (&pi->phash);
789 GNUNET_assert ( (pi->peer_bucket >= 0) &&
790 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
791 bucket = &k_buckets[pi->peer_bucket];
792 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
793 bucket->tail,
794 pi);
795 bucket->peers_size++;
796 closest_bucket = GNUNET_MAX (closest_bucket,
797 (unsigned int) pi->peer_bucket + 1);
798 GNUNET_assert (GNUNET_OK ==
799 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
800 &pi->id,
801 pi,
802 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
803 if (bucket->peers_size <= bucket_size)
804 { 709 {
805 update_connect_preferences (); 710 GNUNET_STATISTICS_update (GDS_stats,
806 newly_found_peers++; 711 "# peers connected",
712 1,
713 GNUNET_NO);
714 pi = GNUNET_new (struct PeerInfo);
715 pi->id = *pid;
716 GNUNET_CRYPTO_hash (pid,
717 sizeof(*pid),
718 &pi->phash);
719 pi->peer_bucket = find_bucket (&pi->phash);
720 GNUNET_assert ( (pi->peer_bucket >= 0) &&
721 ((unsigned int) pi->peer_bucket < MAX_BUCKETS));
722 bucket = &k_buckets[pi->peer_bucket];
723 GNUNET_CONTAINER_DLL_insert_tail (bucket->head,
724 bucket->tail,
725 pi);
726 bucket->peers_size++;
727 closest_bucket = GNUNET_MAX (closest_bucket,
728 (unsigned int) pi->peer_bucket + 1);
729 GNUNET_assert (GNUNET_OK ==
730 GNUNET_CONTAINER_multipeermap_put (all_connected_peers,
731 &pi->id,
732 pi,
733 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
734 if (bucket->peers_size <= bucket_size)
735 {
736 newly_found_peers++;
737 // FIXME: call 'hold'!
738 }
739 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
740 (GNUNET_YES != disable_try_connect) )
741 {
742 /* got a first connection, good time to start with FIND PEER requests... */
743 GNUNET_assert (NULL == find_peer_task);
744 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message,
745 NULL);
746 }
807 } 747 }
808 if ( (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
809 (GNUNET_YES != disable_try_connect) )
810 { 748 {
811 /* got a first connection, good time to start with FIND PEER requests... */ 749 struct Target *t;
812 GNUNET_assert (NULL == find_peer_task); 750
813 find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, 751 t = GNUNET_new (struct Target);
814 NULL); 752 t->u = u;
753 t->utarget = target;
754 t->pi = pi;
755 GNUNET_CONTAINER_DLL_insert (pi->t_head,
756 pi->t_tail,
757 t);
758 *ctx = t;
759
815 } 760 }
816 *ctx = pi;
817} 761}
818 762
819 763
820/**
821 * Method called whenever a peer disconnects.
822 *
823 * @param ctx context
824 */
825void 764void
826GDS_u_disconnect (void *ctx) 765GDS_u_disconnect (void *ctx)
827{ 766{
828 struct PeerInfo *to_remove = ctx; 767 struct Target *t = ctx;
768 struct PeerInfo *pi;
829 struct PeerBucket *bucket; 769 struct PeerBucket *bucket;
830 770
831 /* Check for disconnect from self message (on shutdown) */ 771 /* Check for disconnect from self message (on shutdown) */
832 if (NULL == to_remove) 772 if (NULL == t)
833 return; 773 return;
774 pi = t->pi;
775 GNUNET_CONTAINER_DLL_remove (pi->t_head,
776 pi->t_tail,
777 t);
778 if (t->load > 0)
779 {
780 t->dropped = true;
781 t->pi = NULL;
782 }
783 else
784 {
785 GNUNET_free (t);
786 }
787 if (NULL != pi->t_head)
788 return; /* got other connections still */
834 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 789 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
835 "Disconnected from peer %s\n", 790 "Disconnected from peer %s\n",
836 GNUNET_i2s (&to_remove->id)); 791 GNUNET_i2s (&pi->id));
837 GNUNET_STATISTICS_update (GDS_stats, 792 GNUNET_STATISTICS_update (GDS_stats,
838 "# peers connected", 793 "# peers connected",
839 -1, 794 -1,
840 GNUNET_NO); 795 GNUNET_NO);
841 GNUNET_assert (GNUNET_YES == 796 GNUNET_assert (GNUNET_YES ==
842 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers, 797 GNUNET_CONTAINER_multipeermap_remove (all_connected_peers,
843 &to_remove->id, 798 &pi->id,
844 to_remove)); 799 pi));
845 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) && 800 if ( (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)) &&
846 (GNUNET_YES != disable_try_connect)) 801 (GNUNET_YES != disable_try_connect))
847 { 802 {
848 GNUNET_SCHEDULER_cancel (find_peer_task); 803 GNUNET_SCHEDULER_cancel (find_peer_task);
849 find_peer_task = NULL; 804 find_peer_task = NULL;
850 } 805 }
851 GNUNET_assert (to_remove->peer_bucket >= 0); 806 GNUNET_assert (pi->peer_bucket >= 0);
852 bucket = &k_buckets[to_remove->peer_bucket]; 807 bucket = &k_buckets[pi->peer_bucket];
853 GNUNET_CONTAINER_DLL_remove (bucket->head, 808 GNUNET_CONTAINER_DLL_remove (bucket->head,
854 bucket->tail, 809 bucket->tail,
855 to_remove); 810 pi);
856 GNUNET_assert (bucket->peers_size > 0); 811 GNUNET_assert (bucket->peers_size > 0);
857 bucket->peers_size--; 812 bucket->peers_size--;
813 // FIXME: check if this peer was in one of the first 'bucket_size'
814 // peers, and call 'hold' on the next peer if there is any!
858 while ( (closest_bucket > 0) && 815 while ( (closest_bucket > 0) &&
859 (0 == k_buckets[closest_bucket - 1].peers_size)) 816 (0 == k_buckets[closest_bucket - 1].peers_size))
860 closest_bucket--; 817 closest_bucket--;
861 if (bucket->peers_size < bucket_size) 818 GNUNET_free (pi->hello);
862 update_connect_preferences (); 819 GNUNET_free (pi);
863 GNUNET_free (to_remove);
864} 820}
865 821
866 822
@@ -935,7 +891,7 @@ enum GNUNET_GenericReturnValue
935GDS_am_closest_peer (const struct GNUNET_HashCode *key, 891GDS_am_closest_peer (const struct GNUNET_HashCode *key,
936 const struct GNUNET_CONTAINER_BloomFilter *bloom) 892 const struct GNUNET_CONTAINER_BloomFilter *bloom)
937{ 893{
938 if (0 == GNUNET_memcmp (&my_identity_hash, 894 if (0 == GNUNET_memcmp (&GDS_my_identity_hash,
939 key)) 895 key))
940 return GNUNET_YES; 896 return GNUNET_YES;
941 for (int bucket_num = find_bucket (key); 897 for (int bucket_num = find_bucket (key);
@@ -962,7 +918,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
962 because an unfiltered peer exists, we are not the 918 because an unfiltered peer exists, we are not the
963 closest. */ 919 closest. */
964 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash, 920 int delta = GNUNET_CRYPTO_hash_xorcmp (&pos->phash,
965 &my_identity_hash, 921 &GDS_my_identity_hash,
966 key); 922 key);
967 switch (delta) 923 switch (delta)
968 { 924 {
@@ -1026,7 +982,7 @@ select_peer (const struct GNUNET_HashCode *key,
1026 struct GNUNET_HashCode xor; 982 struct GNUNET_HashCode xor;
1027 983
1028 GNUNET_CRYPTO_hash_xor (key, 984 GNUNET_CRYPTO_hash_xor (key,
1029 &my_identity_hash, 985 &GDS_my_identity_hash,
1030 &xor); 986 &xor);
1031 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor); 987 best_bucket = GNUNET_CRYPTO_hash_count_leading_zeros (&xor);
1032 } 988 }
@@ -1046,9 +1002,10 @@ select_peer (const struct GNUNET_HashCode *key,
1046 if (count >= bucket_size) 1002 if (count >= bucket_size)
1047 break; /* we only consider first #bucket_size entries per bucket */ 1003 break; /* we only consider first #bucket_size entries per bucket */
1048 count++; 1004 count++;
1049 if (GNUNET_YES == 1005 if ( (NULL != bloom) &&
1050 GNUNET_CONTAINER_bloomfilter_test (bloom, 1006 (GNUNET_YES ==
1051 &pos->phash)) 1007 GNUNET_CONTAINER_bloomfilter_test (bloom,
1008 &pos->phash)) )
1052 { 1009 {
1053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1054 "Excluded peer `%s' due to BF match in greedy routing for %s\n", 1011 "Excluded peer `%s' due to BF match in greedy routing for %s\n",
@@ -1134,18 +1091,20 @@ select_peer (const struct GNUNET_HashCode *key,
1134 1091
1135 for (unsigned int bc = 0; bc < closest_bucket; bc++) 1092 for (unsigned int bc = 0; bc < closest_bucket; bc++)
1136 { 1093 {
1094 struct PeerBucket *bucket = &k_buckets[bc];
1137 unsigned int count = 0; 1095 unsigned int count = 0;
1138 1096
1139 for (struct PeerInfo *pos = k_buckets[bc].head; 1097 for (struct PeerInfo *pos = bucket->head;
1140 NULL != pos; 1098 NULL != pos;
1141 pos = pos->next) 1099 pos = pos->next)
1142 { 1100 {
1143 count++; 1101 count++;
1144 if (count > bucket_size) 1102 if (count > bucket_size)
1145 break; /* limits search to #bucket_size peers per bucket */ 1103 break; /* limits search to #bucket_size peers per bucket */
1146 if (GNUNET_YES == 1104 if ( (NULL != bloom) &&
1147 GNUNET_CONTAINER_bloomfilter_test (bloom, 1105 (GNUNET_YES ==
1148 &pos->phash)) 1106 GNUNET_CONTAINER_bloomfilter_test (bloom,
1107 &pos->phash)) )
1149 { 1108 {
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151 "Excluded peer `%s' due to BF match in random routing for %s\n", 1110 "Excluded peer `%s' due to BF match in random routing for %s\n",
@@ -1180,9 +1139,10 @@ select_peer (const struct GNUNET_HashCode *key,
1180 if (count > bucket_size) 1139 if (count > bucket_size)
1181 break; /* limits search to #bucket_size peers per bucket */ 1140 break; /* limits search to #bucket_size peers per bucket */
1182 1141
1183 if (GNUNET_YES == 1142 if ( (NULL != bloom) &&
1184 GNUNET_CONTAINER_bloomfilter_test (bloom, 1143 (GNUNET_YES ==
1185 &pos->phash)) 1144 GNUNET_CONTAINER_bloomfilter_test (bloom,
1145 &pos->phash)) )
1186 continue; /* Ignore bloomfiltered peers */ 1146 continue; /* Ignore bloomfiltered peers */
1187 if (0 == selected--) 1147 if (0 == selected--)
1188 { 1148 {
@@ -1296,7 +1256,7 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1296 bd->put_path, 1256 bd->put_path,
1297 bd->put_path_length, 1257 bd->put_path_length,
1298 NULL, 0, /* get_path */ 1258 NULL, 0, /* get_path */
1299 &my_identity)) 1259 &GDS_my_identity))
1300 { 1260 {
1301 GNUNET_break_op (0); 1261 GNUNET_break_op (0);
1302 put_path_length = 0; 1262 put_path_length = 0;
@@ -1304,10 +1264,10 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1304#endif 1264#endif
1305 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306 "Adding myself (%s) to PUT bloomfilter for %s\n", 1266 "Adding myself (%s) to PUT bloomfilter for %s\n",
1307 GNUNET_i2s (&my_identity), 1267 GNUNET_i2s (&GDS_my_identity),
1308 GNUNET_h2s (&bd->key)); 1268 GNUNET_h2s (&bd->key));
1309 GNUNET_CONTAINER_bloomfilter_add (bf, 1269 GNUNET_CONTAINER_bloomfilter_add (bf,
1310 &my_identity_hash); 1270 &GDS_my_identity_hash);
1311 GNUNET_STATISTICS_update (GDS_stats, 1271 GNUNET_STATISTICS_update (GDS_stats,
1312 "# PUT requests routed", 1272 "# PUT requests routed",
1313 1, 1273 1,
@@ -1324,7 +1284,7 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1324 "Routing PUT for %s terminates after %u hops at %s\n", 1284 "Routing PUT for %s terminates after %u hops at %s\n",
1325 GNUNET_h2s (&bd->key), 1285 GNUNET_h2s (&bd->key),
1326 (unsigned int) hop_count, 1286 (unsigned int) hop_count,
1327 GNUNET_i2s (&my_identity)); 1287 GNUNET_i2s (&GDS_my_identity));
1328 return GNUNET_NO; 1288 return GNUNET_NO;
1329 } 1289 }
1330 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement) 1290 msize = bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement)
@@ -1346,30 +1306,18 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1346 for (unsigned int i = 0; i < target_count; i++) 1306 for (unsigned int i = 0; i < target_count; i++)
1347 { 1307 {
1348 struct PeerInfo *target = targets[i]; 1308 struct PeerInfo *target = targets[i];
1349 struct GNUNET_MQ_Envelope *env;
1350 struct PeerPutMessage *ppm; 1309 struct PeerPutMessage *ppm;
1310 char buf[sizeof (*ppm) + msize] GNUNET_ALIGN;
1351 struct GNUNET_DHT_PathElement *pp; 1311 struct GNUNET_DHT_PathElement *pp;
1352 1312
1353#if FIXME_LEGACY
1354 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1355 {
1356 /* skip */
1357 GNUNET_STATISTICS_update (GDS_stats,
1358 "# P2P messages dropped due to full queue",
1359 1,
1360 GNUNET_NO);
1361 skip_count++;
1362 continue;
1363 }
1364#endif
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366 "Routing PUT for %s after %u hops to %s\n", 1314 "Routing PUT for %s after %u hops to %s\n",
1367 GNUNET_h2s (&bd->key), 1315 GNUNET_h2s (&bd->key),
1368 (unsigned int) hop_count, 1316 (unsigned int) hop_count,
1369 GNUNET_i2s (&target->id)); 1317 GNUNET_i2s (&target->id));
1370 env = GNUNET_MQ_msg_extra (ppm, 1318 ppm = (struct PeerPutMessage *) buf;
1371 msize, 1319 ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1372 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1320 ppm->header.size = htons (sizeof (buf));
1373 ppm->options = htonl (options); 1321 ppm->options = htonl (options);
1374 ppm->type = htonl (bd->type); 1322 ppm->type = htonl (bd->type);
1375 ppm->hop_count = htonl (hop_count + 1); 1323 ppm->hop_count = htonl (hop_count + 1);
@@ -1405,10 +1353,8 @@ GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1405 GNUNET_memcpy (&pp[put_path_length], 1353 GNUNET_memcpy (&pp[put_path_length],
1406 bd->data, 1354 bd->data,
1407 bd->data_size); 1355 bd->data_size);
1408#if FIXME 1356 do_send (target,
1409 GNUNET_MQ_send (target->mq, 1357 &ppm->header);
1410 env);
1411#endif
1412 } 1358 }
1413 GNUNET_free (targets); 1359 GNUNET_free (targets);
1414 GNUNET_STATISTICS_update (GDS_stats, 1360 GNUNET_STATISTICS_update (GDS_stats,
@@ -1450,17 +1396,17 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1450 &targets); 1396 &targets);
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1452 "Adding myself (%s) to GET bloomfilter for %s\n", 1398 "Adding myself (%s) to GET bloomfilter for %s\n",
1453 GNUNET_i2s (&my_identity), 1399 GNUNET_i2s (&GDS_my_identity),
1454 GNUNET_h2s (key)); 1400 GNUNET_h2s (key));
1455 GNUNET_CONTAINER_bloomfilter_add (peer_bf, 1401 GNUNET_CONTAINER_bloomfilter_add (peer_bf,
1456 &my_identity_hash); 1402 &GDS_my_identity_hash);
1457 if (0 == target_count) 1403 if (0 == target_count)
1458 { 1404 {
1459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460 "Routing GET for %s terminates after %u hops at %s\n", 1406 "Routing GET for %s terminates after %u hops at %s\n",
1461 GNUNET_h2s (key), 1407 GNUNET_h2s (key),
1462 (unsigned int) hop_count, 1408 (unsigned int) hop_count,
1463 GNUNET_i2s (&my_identity)); 1409 GNUNET_i2s (&GDS_my_identity));
1464 return GNUNET_NO; 1410 return GNUNET_NO;
1465 } 1411 }
1466 if (GNUNET_OK != 1412 if (GNUNET_OK !=
@@ -1487,30 +1433,18 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1487 for (unsigned int i = 0; i < target_count; i++) 1433 for (unsigned int i = 0; i < target_count; i++)
1488 { 1434 {
1489 struct PeerInfo *target = targets[i]; 1435 struct PeerInfo *target = targets[i];
1490 struct GNUNET_MQ_Envelope *env;
1491 struct PeerGetMessage *pgm; 1436 struct PeerGetMessage *pgm;
1437 char buf[sizeof (*pgm) + msize] GNUNET_ALIGN;
1492 char *xq; 1438 char *xq;
1493 1439
1494#if FIXME
1495 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
1496 {
1497 /* skip */
1498 GNUNET_STATISTICS_update (GDS_stats,
1499 "# P2P messages dropped due to full queue",
1500 1,
1501 GNUNET_NO);
1502 skip_count++;
1503 continue;
1504 }
1505#endif
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Routing GET for %s after %u hops to %s\n", 1441 "Routing GET for %s after %u hops to %s\n",
1508 GNUNET_h2s (key), 1442 GNUNET_h2s (key),
1509 (unsigned int) hop_count, 1443 (unsigned int) hop_count,
1510 GNUNET_i2s (&target->id)); 1444 GNUNET_i2s (&target->id));
1511 env = GNUNET_MQ_msg_extra (pgm, 1445 pgm = (struct PeerGetMessage *) buf;
1512 msize, 1446 pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET);
1513 GNUNET_MESSAGE_TYPE_DHT_P2P_GET); 1447 pgm->header.size = htons (sizeof (buf));
1514 pgm->options = htonl (options); 1448 pgm->options = htonl (options);
1515 pgm->type = htonl (type); 1449 pgm->type = htonl (type);
1516 pgm->hop_count = htonl (hop_count + 1); 1450 pgm->hop_count = htonl (hop_count + 1);
@@ -1532,10 +1466,8 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1532 GNUNET_memcpy (&xq[xquery_size], 1466 GNUNET_memcpy (&xq[xquery_size],
1533 reply_bf, 1467 reply_bf,
1534 reply_bf_size); 1468 reply_bf_size);
1535#if FIXME 1469 do_send (target,
1536 GNUNET_MQ_send (target->mq, 1470 &pgm->header);
1537 env);
1538#endif
1539 } 1471 }
1540 GNUNET_STATISTICS_update (GDS_stats, 1472 GNUNET_STATISTICS_update (GDS_stats,
1541 "# GET messages queued for transmission", 1473 "# GET messages queued for transmission",
@@ -1562,8 +1494,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1562 unsigned int get_path_length, 1494 unsigned int get_path_length,
1563 const struct GNUNET_DHT_PathElement *get_path) 1495 const struct GNUNET_DHT_PathElement *get_path)
1564{ 1496{
1565 struct GNUNET_MQ_Envelope *env;
1566 struct PeerResultMessage *prm;
1567 struct GNUNET_DHT_PathElement *paths; 1497 struct GNUNET_DHT_PathElement *paths;
1568 size_t msize; 1498 size_t msize;
1569 unsigned int ppl = bd->put_path_length; 1499 unsigned int ppl = bd->put_path_length;
@@ -1578,7 +1508,7 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1578 bd->put_path_length, 1508 bd->put_path_length,
1579 get_path, 1509 get_path,
1580 get_path_length, 1510 get_path_length,
1581 &my_identity)) 1511 &GDS_my_identity))
1582 { 1512 {
1583 GNUNET_break_op (0); 1513 GNUNET_break_op (0);
1584 get_path_length = 0; 1514 get_path_length = 0;
@@ -1609,20 +1539,6 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1609 GNUNET_break (0); 1539 GNUNET_break (0);
1610 return; 1540 return;
1611 } 1541 }
1612#if FIXME
1613 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
1614 {
1615 /* skip */
1616 GNUNET_STATISTICS_update (GDS_stats,
1617 "# P2P messages dropped due to full queue",
1618 1,
1619 GNUNET_NO);
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1621 "Peer queue full, ignoring reply for key %s\n",
1622 GNUNET_h2s (&bd->key));
1623 return;
1624 }
1625#endif
1626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1627 "Forwarding reply for key %s to peer %s\n", 1543 "Forwarding reply for key %s to peer %s\n",
1628 GNUNET_h2s (query_hash), 1544 GNUNET_h2s (query_hash),
@@ -1631,41 +1547,44 @@ GDS_NEIGHBOURS_handle_reply (struct PeerInfo *pi,
1631 "# RESULT messages queued for transmission", 1547 "# RESULT messages queued for transmission",
1632 1, 1548 1,
1633 GNUNET_NO); 1549 GNUNET_NO);
1634 env = GNUNET_MQ_msg_extra (prm,
1635 msize,
1636 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1637 prm->type = htonl (bd->type);
1638 prm->put_path_length = htonl (ppl);
1639 prm->get_path_length = htonl (get_path_length);
1640 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1641 prm->key = *query_hash;
1642 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1643 GNUNET_memcpy (paths,
1644 bd->put_path,
1645 ppl * sizeof(struct GNUNET_DHT_PathElement));
1646 GNUNET_memcpy (&paths[ppl],
1647 get_path,
1648 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1649 /* 0 == get_path_length means path is not being tracked */
1650 if (0 != get_path_length)
1651 { 1550 {
1652 /* Note that the signature in 'get_path' was not initialized before, 1551 struct PeerResultMessage *prm;
1653 so this is crucial to avoid sending garbage. */ 1552 char buf[sizeof (*prm) + msize] GNUNET_ALIGN;
1654 sign_path (&bd->key, 1553
1655 bd->data, 1554 prm = (struct PeerResultMessage *) buf;
1656 bd->data_size, 1555 prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1657 bd->expiration_time, 1556 prm->header.size = htons (sizeof (buf));
1658 &paths[ppl + get_path_length - 1].pred, 1557 prm->type = htonl (bd->type);
1659 &pi->id, 1558 prm->put_path_length = htonl (ppl);
1660 &paths[ppl + get_path_length - 1].sig); 1559 prm->get_path_length = htonl (get_path_length);
1661 } 1560 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1662 GNUNET_memcpy (&paths[ppl + get_path_length], 1561 prm->key = *query_hash;
1562 paths = (struct GNUNET_DHT_PathElement *) &prm[1];
1563 GNUNET_memcpy (paths,
1564 bd->put_path,
1565 ppl * sizeof(struct GNUNET_DHT_PathElement));
1566 GNUNET_memcpy (&paths[ppl],
1567 get_path,
1568 get_path_length * sizeof(struct GNUNET_DHT_PathElement));
1569 /* 0 == get_path_length means path is not being tracked */
1570 if (0 != get_path_length)
1571 {
1572 /* Note that the signature in 'get_path' was not initialized before,
1573 so this is crucial to avoid sending garbage. */
1574 sign_path (&bd->key,
1663 bd->data, 1575 bd->data,
1664 bd->data_size); 1576 bd->data_size,
1665#if FIXME 1577 bd->expiration_time,
1666 GNUNET_MQ_send (pi->mq, 1578 &paths[ppl + get_path_length - 1].pred,
1667 env); 1579 &pi->id,
1668#endif 1580 &paths[ppl + get_path_length - 1].sig);
1581 }
1582 GNUNET_memcpy (&paths[ppl + get_path_length],
1583 bd->data,
1584 bd->data_size);
1585 do_send (pi,
1586 &prm->header);
1587 }
1669} 1588}
1670 1589
1671 1590
@@ -1819,7 +1738,7 @@ handle_dht_p2p_put (void *cls,
1819 bd.put_path, 1738 bd.put_path,
1820 putlen, 1739 putlen,
1821 NULL, 0, /* get_path */ 1740 NULL, 0, /* get_path */
1822 &my_identity)) 1741 &GDS_my_identity))
1823 { 1742 {
1824 GNUNET_break_op (0); 1743 GNUNET_break_op (0);
1825 putlen = 0; 1744 putlen = 0;
@@ -1875,45 +1794,60 @@ handle_dht_p2p_put (void *cls,
1875 1794
1876 1795
1877/** 1796/**
1878 * We have received a FIND PEER request. Send matching 1797 * We have received a request for a HELLO. Sends our
1879 * HELLOs back. 1798 * HELLO back.
1880 * 1799 *
1881 * @param pi sender of the FIND PEER request 1800 * @param pi sender of the request
1882 * @param key peers close to this key are desired 1801 * @param key peers close to this key are desired
1883 * @param bg group for filtering peers 1802 * @param bg group for filtering peers
1884 */ 1803 */
1885static void 1804static void
1886handle_find_peer (struct PeerInfo *pi, 1805handle_find_my_hello (struct PeerInfo *pi,
1887 const struct GNUNET_HashCode *query_hash, 1806 const struct GNUNET_HashCode *query_hash,
1888 struct GNUNET_BLOCK_Group *bg) 1807 struct GNUNET_BLOCK_Group *bg)
1889{ 1808{
1890 int bucket_idx; 1809 size_t block_size = 0;
1891 struct PeerBucket *bucket; 1810
1892 struct PeerInfo *peer; 1811 /* TODO: consider caching our HELLO block for a bit, to
1893 unsigned int choice; 1812 avoid signing too often here... */
1894 struct GDS_DATACACHE_BlockData bd = { 1813 GNUNET_break (GNUNET_NO ==
1895 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO 1814 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1896 }; 1815 &GDS_my_private_key,
1897 1816 NULL,
1898 /* first, check about our own HELLO */ 1817 &block_size));
1899 if (NULL != GDS_my_hello)
1900 { 1818 {
1901 bd.expiration_time = GNUNET_TIME_relative_to_absolute ( 1819 char block[block_size];
1902 hello_expiration), 1820
1903 bd.key = my_identity_hash, 1821 if (GNUNET_OK !=
1904 bd.data = GDS_my_hello; 1822 GNUNET_HELLO_builder_to_block (GDS_my_hello,
1905 bd.data_size = GNUNET_HELLO_size ( 1823 &GDS_my_private_key,
1906 (const struct GNUNET_HELLO_Message *) GDS_my_hello); 1824 block,
1907 GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader)); 1825 &block_size))
1908 if (GNUNET_BLOCK_REPLY_OK_MORE ==
1909 GNUNET_BLOCK_check_reply (GDS_block_context,
1910 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1911 bg,
1912 &my_identity_hash,
1913 NULL, 0,
1914 bd.data,
1915 bd.data_size))
1916 { 1826 {
1827 GNUNET_STATISTICS_update (GDS_stats,
1828 "# FIND PEER requests ignored due to lack of HELLO",
1829 1,
1830 GNUNET_NO);
1831 }
1832 else if (GNUNET_BLOCK_REPLY_OK_MORE ==
1833 GNUNET_BLOCK_check_reply (GDS_block_context,
1834 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1835 bg,
1836 &GDS_my_identity_hash,
1837 NULL, 0,
1838 block,
1839 block_size))
1840 {
1841 struct GDS_DATACACHE_BlockData bd = {
1842 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1843 .expiration_time
1844 = GNUNET_TIME_relative_to_absolute (
1845 GNUNET_HELLO_ADDRESS_EXPIRATION),
1846 .key = GDS_my_identity_hash,
1847 .data = block,
1848 .data_size = block_size
1849 };
1850
1917 GDS_NEIGHBOURS_handle_reply (pi, 1851 GDS_NEIGHBOURS_handle_reply (pi,
1918 &bd, 1852 &bd,
1919 query_hash, 1853 query_hash,
@@ -1927,66 +1861,48 @@ handle_find_peer (struct PeerInfo *pi,
1927 GNUNET_NO); 1861 GNUNET_NO);
1928 } 1862 }
1929 } 1863 }
1930 else 1864}
1931 {
1932 GNUNET_STATISTICS_update (GDS_stats,
1933 "# FIND PEER requests ignored due to lack of HELLO",
1934 1,
1935 GNUNET_NO);
1936 }
1937 1865
1938 /* then, also consider sending a random HELLO from the closest bucket */
1939 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
1940 if (0 ==
1941 GNUNET_memcmp (&my_identity_hash,
1942 query_hash))
1943 bucket_idx = closest_bucket - 1;
1944 else
1945 bucket_idx = GNUNET_MIN ((int) closest_bucket - 1,
1946 find_bucket (query_hash));
1947 if (bucket_idx < 0)
1948 return;
1949 bucket = &k_buckets[bucket_idx];
1950 if (bucket->peers_size == 0)
1951 return;
1952 choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1953 bucket->peers_size);
1954 peer = bucket->head;
1955 while (choice > 0)
1956 {
1957 GNUNET_assert (NULL != peer);
1958 peer = peer->next;
1959 choice--;
1960 }
1961 choice = bucket->peers_size;
1962 1866
1867/**
1868 * We have received a request for nearby HELLOs. Sends matching
1869 * HELLOs back.
1870 *
1871 * @param pi sender of the request
1872 * @param key peers close to this key are desired
1873 * @param bg group for filtering peers
1874 */
1875static void
1876handle_find_local_hello (struct PeerInfo *pi,
1877 const struct GNUNET_HashCode *query_hash,
1878 struct GNUNET_BLOCK_Group *bg)
1879{
1880 /* Force non-random selection by hop count */
1881 struct PeerInfo *peer;
1882
1883 peer = select_peer (query_hash,
1884 NULL,
1885 GDS_NSE_get () + 1);
1886 if ( (NULL != peer->hello) &&
1887 (! GNUNET_TIME_absolute_is_past (peer->hello_expiration)) &&
1888 (GNUNET_BLOCK_REPLY_OK_MORE ==
1889 GNUNET_BLOCK_check_reply (
1890 GDS_block_context,
1891 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1892 bg,
1893 &peer->phash,
1894 NULL, 0, /* xquery */
1895 peer->hello,
1896 peer->hello_size)) )
1963 { 1897 {
1964 const struct GNUNET_HELLO_Message *hello; 1898 struct GDS_DATACACHE_BlockData bd = {
1965 size_t hello_size; 1899 .type = GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1900 .expiration_time = peer->hello_expiration,
1901 .key = peer->phash,
1902 .data = peer->hello,
1903 .data_size = peer->hello_size
1904 };
1966 1905
1967 do
1968 {
1969 peer = peer->next;
1970 if (0 == choice--)
1971 return; /* no non-masked peer available */
1972 if (NULL == peer)
1973 peer = bucket->head;
1974 hello = GDS_HELLO_get (&peer->id);
1975 } while ( (NULL == hello) ||
1976 (GNUNET_BLOCK_REPLY_OK_MORE !=
1977 GNUNET_BLOCK_check_reply (
1978 GDS_block_context,
1979 GNUNET_BLOCK_TYPE_DHT_URL_HELLO,
1980 bg,
1981 &peer->phash,
1982 NULL, 0, /* xquery */
1983 hello,
1984 (hello_size = GNUNET_HELLO_size (hello)))));
1985 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1986 GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
1987 bd.key = peer->phash;
1988 bd.data = hello;
1989 bd.data_size = hello_size;
1990 GDS_NEIGHBOURS_handle_reply (pi, 1906 GDS_NEIGHBOURS_handle_reply (pi,
1991 &bd, 1907 &bd,
1992 query_hash, 1908 query_hash,
@@ -2101,32 +2017,45 @@ handle_dht_p2p_get (void *cls,
2101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2102 "GET for %s at %s after %u hops\n", 2018 "GET for %s at %s after %u hops\n",
2103 GNUNET_h2s (&get->key), 2019 GNUNET_h2s (&get->key),
2104 GNUNET_i2s (&my_identity), 2020 GNUNET_i2s (&GDS_my_identity),
2105 (unsigned int) hop_count); 2021 (unsigned int) hop_count);
2106 /* local lookup (this may update the reply_bf) */ 2022 /* local lookup (this may update the bg) */
2107 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 2023 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
2108 (GDS_am_closest_peer (&get->key, 2024 (GDS_am_closest_peer (&get->key,
2109 peer_bf)) ) 2025 peer_bf)) )
2110 { 2026 {
2111 if ((0 != (options & GNUNET_DHT_RO_FIND_PEER))) 2027 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == type)
2112 { 2028 {
2113 GNUNET_STATISTICS_update (GDS_stats, 2029 GNUNET_STATISTICS_update (GDS_stats,
2114 "# P2P FIND PEER requests processed", 2030 "# P2P HELLO lookup requests processed",
2115 1, 2031 1,
2116 GNUNET_NO); 2032 GNUNET_NO);
2117 handle_find_peer (peer, 2033 handle_find_my_hello (peer,
2118 &get->key, 2034 &get->key,
2119 bg); 2035 bg);
2036 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2037 handle_find_local_hello (peer,
2038 &get->key,
2039 bg);
2120 } 2040 }
2121 else 2041 else
2122 { 2042 {
2123 eval = GDS_DATACACHE_handle_get (&get->key, 2043 if (0 != (options & GNUNET_DHT_RO_FIND_APPROXIMATE))
2124 type, 2044 eval = GDS_DATACACHE_get_closest (&get->key,
2125 xquery, 2045 type,
2126 xquery_size, 2046 xquery,
2127 bg, 2047 xquery_size,
2128 &handle_local_result, 2048 bg,
2129 peer); 2049 &handle_local_result,
2050 peer);
2051 else
2052 eval = GDS_DATACACHE_handle_get (&get->key,
2053 type,
2054 xquery,
2055 xquery_size,
2056 bg,
2057 &handle_local_result,
2058 peer);
2130 } 2059 }
2131 } 2060 }
2132 else 2061 else
@@ -2137,7 +2066,9 @@ handle_dht_p2p_get (void *cls,
2137 GNUNET_NO); 2066 GNUNET_NO);
2138 } 2067 }
2139 2068
2140 /* remember request for routing replies */ 2069 /* remember request for routing replies
2070 TODO: why should we do this if GNUNET_BLOCK_REPLY_OK_LAST == eval?
2071 */
2141 GDS_ROUTING_add (&peer->id, 2072 GDS_ROUTING_add (&peer->id,
2142 type, 2073 type,
2143 bg, /* bg now owned by routing, but valid at least until end of this function! */ 2074 bg, /* bg now owned by routing, but valid at least until end of this function! */
@@ -2260,6 +2191,52 @@ check_dht_p2p_result (void *cls,
2260 2191
2261 2192
2262/** 2193/**
2194 * Callback function used to extract URIs from a builder.
2195 * Called when we should consider connecting to a peer.
2196 *
2197 * @param cls closure pointing to a `struct GNUNET_PeerIdentity *`
2198 * @param uri one of the URIs
2199 */
2200static void
2201try_connect (void *cls,
2202 const char *uri)
2203{
2204 const struct GNUNET_PeerIdentity *pid = cls;
2205 struct GNUNET_HashCode phash;
2206 int peer_bucket;
2207 struct PeerBucket *bucket;
2208
2209 if (0 == GNUNET_memcmp (&GDS_my_identity,
2210 pid))
2211 return; /* that's us! */
2212 GNUNET_CRYPTO_hash (pid,
2213 sizeof(*pid),
2214 &phash);
2215 peer_bucket = find_bucket (&phash);
2216 GNUNET_assert ( (peer_bucket >= 0) &&
2217 ((unsigned int) peer_bucket < MAX_BUCKETS));
2218 bucket = &k_buckets[peer_bucket];
2219 if (bucket->peers_size >= bucket_size)
2220 return; /* do not care */
2221 for (struct PeerInfo *pi = bucket->head;
2222 NULL != pi;
2223 pi = pi->next)
2224 if (0 ==
2225 GNUNET_memcmp (&pi->id,
2226 pid))
2227 {
2228 /* already connected */
2229 /* TODO: maybe consider 'uri' anyway as an additional
2230 alternative address??? */
2231 return;
2232 }
2233 /* new peer that we like! */
2234 GDS_u_try_connect (pid,
2235 uri);
2236}
2237
2238
2239/**
2263 * Core handler for p2p result messages. 2240 * Core handler for p2p result messages.
2264 * 2241 *
2265 * @param cls closure 2242 * @param cls closure
@@ -2333,32 +2310,17 @@ handle_dht_p2p_result (void *cls,
2333 /* if we got a HELLO, consider it for our own routing table */ 2310 /* if we got a HELLO, consider it for our own routing table */
2334 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == bd.type) 2311 if (GNUNET_BLOCK_TYPE_DHT_URL_HELLO == bd.type)
2335 { 2312 {
2336 const struct GNUNET_MessageHeader *h = bd.data;
2337 struct GNUNET_PeerIdentity pid; 2313 struct GNUNET_PeerIdentity pid;
2338 2314 struct GNUNET_HELLO_Builder *b;
2339 /* Should be a HELLO, validate and consider using it! */ 2315
2340 if (bd.data_size < sizeof(struct GNUNET_HELLO_Message)) 2316 b = GNUNET_HELLO_builder_from_block (bd.data,
2341 { 2317 bd.data_size);
2342 GNUNET_break (0); 2318 if (GNUNET_YES != disable_try_connect)
2343 return; 2319 GNUNET_HELLO_builder_iterate (b,
2344 } 2320 &pid,
2345 if (bd.data_size != ntohs (h->size)) 2321 &try_connect,
2346 { 2322 &pid);
2347 GNUNET_break (0); 2323 GNUNET_HELLO_builder_free (b);
2348 return;
2349 }
2350 if (GNUNET_OK !=
2351 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h,
2352 &pid))
2353 {
2354 GNUNET_break_op (0);
2355 return;
2356 }
2357 if ( (GNUNET_YES != disable_try_connect) &&
2358 (0 != GNUNET_memcmp (&my_identity,
2359 &pid)) )
2360 try_connect (&pid,
2361 h);
2362 } 2324 }
2363 2325
2364 /* First, check if 'peer' is already on the path, and if 2326 /* First, check if 'peer' is already on the path, and if
@@ -2391,6 +2353,50 @@ handle_dht_p2p_result (void *cls,
2391} 2353}
2392 2354
2393 2355
2356/**
2357 * Check validity of a p2p hello message.
2358 *
2359 * @param cls closure
2360 * @param hello message
2361 * @return #GNUNET_YES if the message is well-formed
2362 */
2363static enum GNUNET_GenericReturnValue
2364check_dht_p2p_hello (void *cls,
2365 const struct GNUNET_MessageHeader *hello)
2366{
2367 struct GNUNET_HELLO_Builder *b;
2368 enum GNUNET_GenericReturnValue ret;
2369
2370 b = GNUNET_HELLO_builder_from_msg (hello);
2371 ret = (NULL == b) ? GNUNET_SYSERR : GNUNET_OK;
2372 GNUNET_HELLO_builder_free (b);
2373 return ret;
2374}
2375
2376
2377/**
2378 * Core handler for p2p HELLO messages.
2379 *
2380 * @param cls closure
2381 * @param message message
2382 */
2383static void
2384handle_dht_p2p_hello (void *cls,
2385 const struct GNUNET_MessageHeader *hello)
2386{
2387 struct PeerInfo *peer = cls;
2388
2389 GNUNET_free (peer->hello);
2390 peer->hello_size = 0;
2391 GNUNET_break (GNUNET_OK ==
2392 GNUNET_HELLO_dht_msg_to_block (hello,
2393 &peer->id,
2394 &peer->hello,
2395 &peer->hello_size,
2396 &peer->hello_expiration));
2397}
2398
2399
2394void 2400void
2395GDS_u_receive (void *cls, 2401GDS_u_receive (void *cls,
2396 void **tctx, 2402 void **tctx,
@@ -2412,6 +2418,10 @@ GDS_u_receive (void *cls,
2412 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 2418 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT,
2413 struct PeerResultMessage, 2419 struct PeerResultMessage,
2414 pi), 2420 pi),
2421 GNUNET_MQ_hd_var_size (dht_p2p_hello,
2422 GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO,
2423 struct GNUNET_MessageHeader,
2424 pi),
2415 GNUNET_MQ_handler_end () 2425 GNUNET_MQ_handler_end ()
2416 }; 2426 };
2417 const struct GNUNET_MessageHeader *mh = message; 2427 const struct GNUNET_MessageHeader *mh = message;
@@ -2438,6 +2448,34 @@ GDS_u_receive (void *cls,
2438} 2448}
2439 2449
2440 2450
2451/**
2452 * Send @a msg to all peers in our buckets.
2453 *
2454 * @param msg message to broadcast
2455 */
2456void
2457GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg)
2458{
2459 for (unsigned int bc = 0; bc<closest_bucket; bc++)
2460 {
2461 struct PeerBucket *bucket = &k_buckets[bc];
2462 unsigned int count = 0;
2463
2464 for (struct PeerInfo *pos = bucket->head;
2465 NULL != pos;
2466 pos = pos->next)
2467 {
2468 if (count >= bucket_size)
2469 break; /* we only consider first #bucket_size entries per bucket */
2470 count++;
2471 GNUNET_break (0);
2472 do_send (pos,
2473 msg);
2474 }
2475 }
2476}
2477
2478
2441enum GNUNET_GenericReturnValue 2479enum GNUNET_GenericReturnValue
2442GDS_NEIGHBOURS_init () 2480GDS_NEIGHBOURS_init ()
2443{ 2481{
@@ -2458,41 +2496,8 @@ GDS_NEIGHBOURS_init ()
2458 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, 2496 = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg,
2459 "DHT", 2497 "DHT",
2460 "CACHE_RESULTS"); 2498 "CACHE_RESULTS");
2461 {
2462 char *keyfile;
2463
2464 if (GNUNET_OK !=
2465 GNUNET_CONFIGURATION_get_value_filename (GDS_cfg,
2466 "PEER",
2467 "PRIVATE_KEY",
2468 &keyfile))
2469 {
2470 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2471 "Core service is lacking HOSTKEY configuration setting. Exiting.\n");
2472 return GNUNET_SYSERR;
2473 }
2474 if (GNUNET_SYSERR ==
2475 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
2476 GNUNET_YES,
2477 &my_private_key))
2478 {
2479 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2480 "Failed to setup peer's private key\n");
2481 GNUNET_free (keyfile);
2482 return GNUNET_SYSERR;
2483 }
2484 GNUNET_free (keyfile);
2485 }
2486 GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
2487 &my_identity.public_key);
2488 GNUNET_CRYPTO_hash (&my_identity,
2489 sizeof(struct GNUNET_PeerIdentity),
2490 &my_identity_hash);
2491
2492 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256, 2499 all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256,
2493 GNUNET_YES); 2500 GNUNET_YES);
2494 all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256,
2495 GNUNET_NO);
2496 return GNUNET_OK; 2501 return GNUNET_OK;
2497} 2502}
2498 2503
@@ -2506,11 +2511,6 @@ GDS_NEIGHBOURS_done ()
2506 GNUNET_CONTAINER_multipeermap_size (all_connected_peers)); 2511 GNUNET_CONTAINER_multipeermap_size (all_connected_peers));
2507 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers); 2512 GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers);
2508 all_connected_peers = NULL; 2513 all_connected_peers = NULL;
2509 GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers,
2510 &free_connect_info,
2511 NULL);
2512 GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers);
2513 all_desired_peers = NULL;
2514 GNUNET_assert (NULL == find_peer_task); 2514 GNUNET_assert (NULL == find_peer_task);
2515} 2515}
2516 2516
@@ -2518,7 +2518,7 @@ GDS_NEIGHBOURS_done ()
2518struct GNUNET_PeerIdentity * 2518struct GNUNET_PeerIdentity *
2519GDS_NEIGHBOURS_get_id () 2519GDS_NEIGHBOURS_get_id ()
2520{ 2520{
2521 return &my_identity; 2521 return &GDS_my_identity;
2522} 2522}
2523 2523
2524 2524
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 @@
33#include "gnunet_dhtu_plugin.h" 33#include "gnunet_dhtu_plugin.h"
34#include "gnunet-service-dht_datacache.h" 34#include "gnunet-service-dht_datacache.h"
35 35
36/**
37 * Hash of the identity of this peer.
38 */
39extern struct GNUNET_HashCode my_identity_hash;
40
41 36
42struct PeerInfo; 37struct PeerInfo;
43 38
@@ -141,7 +136,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
141 * Function to call when we connect to a peer and can henceforth transmit to 136 * Function to call when we connect to a peer and can henceforth transmit to
142 * that peer. 137 * that peer.
143 * 138 *
144 * @param cls the closure 139 * @param cls the closure, must be a `struct Underlay`
145 * @param target handle to the target, 140 * @param target handle to the target,
146 * pointer will remain valid until @e disconnect_cb is called 141 * pointer will remain valid until @e disconnect_cb is called
147 * @para pid peer identity, 142 * @para pid peer identity,
@@ -154,6 +149,7 @@ GDS_u_connect (void *cls,
154 const struct GNUNET_PeerIdentity *pid, 149 const struct GNUNET_PeerIdentity *pid,
155 void **ctx); 150 void **ctx);
156 151
152
157/** 153/**
158 * Function to call when we disconnected from a peer and can henceforth 154 * Function to call when we disconnected from a peer and can henceforth
159 * cannot transmit to that peer anymore. 155 * cannot transmit to that peer anymore.
@@ -183,6 +179,15 @@ GDS_u_receive (void *cls,
183 179
184 180
185/** 181/**
182 * Send @a msg to all peers in our buckets.
183 *
184 * @param msg message to broadcast
185 */
186void
187GDS_NEIGHBOURS_broadcast (const struct GNUNET_MessageHeader *msg);
188
189
190/**
186 * Initialize neighbours subsystem. 191 * Initialize neighbours subsystem.
187 * 192 *
188 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 193 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
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,
151 bdx.put_path_length = 0; 151 bdx.put_path_length = 0;
152 bdx.put_path = NULL; 152 bdx.put_path = NULL;
153 } 153 }
154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
155 (0 != GNUNET_memcmp (query_hash, 155 (0 != GNUNET_memcmp (query_hash,
156 &bdx.key)) ) 156 &bdx.key)) )
157 { 157 {
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)
235 */ 235 */
236static void 236static void
237ip_try_connect (void *cls, 237ip_try_connect (void *cls,
238 struct GNUNET_PeerIdentity *pid, 238 const struct GNUNET_PeerIdentity *pid,
239 const char *address) 239 const char *address)
240{ 240{
241 struct Plugin *plugin = cls; 241 struct Plugin *plugin = cls;
@@ -349,6 +349,17 @@ ip_send (void *cls,
349 struct GNUNET_MQ_Envelope *env; 349 struct GNUNET_MQ_Envelope *env;
350 struct GNUNET_MessageHeader *cmsg; 350 struct GNUNET_MessageHeader *cmsg;
351 351
352 if (GNUNET_MQ_get_length (target->mq) >= MAXIMUM_PENDING_PER_PEER)
353 {
354 /* skip */
355#if FIXME_STATS
356 GNUNET_STATISTICS_update (GDS_stats,
357 "# P2P messages dropped due to full queue",
358 1,
359 GNUNET_NO);
360#endif
361 return;
362 }
352 env = GNUNET_MQ_msg_extra (cmsg, 363 env = GNUNET_MQ_msg_extra (cmsg,
353 msg_size, 364 msg_size,
354 GNUNET_MESSAGE_TYPE_DHT_CORE); 365 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,
354 */ 354 */
355static void 355static void
356ip_try_connect (void *cls, 356ip_try_connect (void *cls,
357 struct GNUNET_PeerIdentity *pid, 357 const struct GNUNET_PeerIdentity *pid,
358 const char *address) 358 const char *address)
359{ 359{
360 struct Plugin *plugin = cls; 360 struct Plugin *plugin = cls;
@@ -365,7 +365,6 @@ ip_try_connect (void *cls,
365 .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV 365 .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
366 }; 366 };
367 struct addrinfo *result = NULL; 367 struct addrinfo *result = NULL;
368 char *epid;
369 368
370 if (0 != 369 if (0 !=
371 strncmp (address, 370 strncmp (address,
@@ -507,7 +506,6 @@ create_source (struct Plugin *plugin,
507 socklen_t addrlen) 506 socklen_t addrlen)
508{ 507{
509 struct GNUNET_DHTU_Source *src; 508 struct GNUNET_DHTU_Source *src;
510 char *pid;
511 509
512 src = GNUNET_new (struct GNUNET_DHTU_Source); 510 src = GNUNET_new (struct GNUNET_DHTU_Source);
513 src->addrlen = addrlen; 511 src->addrlen = addrlen;
@@ -549,7 +547,6 @@ create_source (struct Plugin *plugin,
549 break; 547 break;
550 default: 548 default:
551 GNUNET_break (0); 549 GNUNET_break (0);
552 GNUNET_free (pid);
553 GNUNET_free (src); 550 GNUNET_free (src);
554 return NULL; 551 return NULL;
555 } 552 }
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 @@
40#include "gnunet_protocols.h" 40#include "gnunet_protocols.h"
41#include "gnunet_util_lib.h" 41#include "gnunet_util_lib.h"
42 42
43/**
44 * For how long are HELLO signatures valid?
45 */
46#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
47 GNUNET_TIME_UNIT_DAYS, 2)
48
49 43
50GNUNET_NETWORK_STRUCT_BEGIN 44GNUNET_NETWORK_STRUCT_BEGIN
51 45
@@ -72,7 +66,7 @@ struct HelloSignaturePurpose
72}; 66};
73 67
74/** 68/**
75 * Binary block we sign when we sign an address. 69 * Message used when gossiping HELLOs between peers.
76 */ 70 */
77struct HelloUriMessage 71struct HelloUriMessage
78{ 72{
@@ -117,6 +111,42 @@ struct BlockHeader
117 111
118}; 112};
119 113
114
115/**
116 * Message used when a DHT provides its HELLO to direct
117 * neighbours.
118 */
119struct DhtHelloMessage
120{
121 /**
122 * Type must be #GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
123 */
124 struct GNUNET_MessageHeader header;
125
126 /**
127 * Reserved. 0.
128 */
129 uint16_t reserved GNUNET_PACKED;
130
131 /**
132 * Number of URLs encoded after the end of the struct, in NBO.
133 */
134 uint16_t url_counter GNUNET_PACKED;
135
136 /**
137 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
138 */
139 struct GNUNET_CRYPTO_EddsaSignature sig;
140
141 /**
142 * When does the HELLO expire?
143 */
144 struct GNUNET_TIME_AbsoluteNBO expiration_time;
145
146 /* followed by the serialized addresses of the 'block' */
147};
148
149
120GNUNET_NETWORK_STRUCT_END 150GNUNET_NETWORK_STRUCT_END
121 151
122 152
@@ -521,6 +551,11 @@ GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
521 struct HelloUriMessage *msg; 551 struct HelloUriMessage *msg;
522 size_t blen; 552 size_t blen;
523 553
554 if (builder->a_length > UINT16_MAX)
555 {
556 GNUNET_break (0);
557 return NULL;
558 }
524 blen = 0; 559 blen = 0;
525 GNUNET_assert (GNUNET_NO == 560 GNUNET_assert (GNUNET_NO ==
526 GNUNET_HELLO_builder_to_block (builder, 561 GNUNET_HELLO_builder_to_block (builder,
@@ -530,6 +565,7 @@ GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
530 env = GNUNET_MQ_msg_extra (msg, 565 env = GNUNET_MQ_msg_extra (msg,
531 blen, 566 blen,
532 GNUNET_MESSAGE_TYPE_HELLO_URI); 567 GNUNET_MESSAGE_TYPE_HELLO_URI);
568 msg->url_counter = htonl ((uint16_t) builder->a_length);
533 GNUNET_assert (GNUNET_OK == 569 GNUNET_assert (GNUNET_OK ==
534 GNUNET_HELLO_builder_to_block (builder, 570 GNUNET_HELLO_builder_to_block (builder,
535 priv, 571 priv,
@@ -539,6 +575,50 @@ GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
539} 575}
540 576
541 577
578struct GNUNET_MessageHeader *
579GNUNET_HELLO_builder_to_dht_hello_msg (
580 const struct GNUNET_HELLO_Builder *builder,
581 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
582{
583 struct DhtHelloMessage *msg;
584 size_t blen;
585
586 if (builder->a_length > UINT16_MAX)
587 {
588 GNUNET_break (0);
589 return NULL;
590 }
591 blen = 0;
592 GNUNET_assert (GNUNET_NO ==
593 GNUNET_HELLO_builder_to_block (builder,
594 priv,
595 NULL,
596 &blen));
597 GNUNET_assert (blen < UINT16_MAX);
598 GNUNET_assert (blen >= sizeof (struct BlockHeader));
599 {
600 char buf[blen] GNUNET_ALIGN;
601 const struct BlockHeader *block = (const struct BlockHeader *) buf;
602
603 GNUNET_assert (GNUNET_OK ==
604 GNUNET_HELLO_builder_to_block (builder,
605 priv,
606 buf,
607 &blen));
608 msg = GNUNET_malloc (sizeof (*msg) + blen);
609 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
610 msg->header.size = htons (sizeof (*msg) + blen);
611 memcpy (&msg[1],
612 &block[1],
613 blen - sizeof (*block));
614 msg->sig = block->sig;
615 msg->expiration_time = block->expiration_time;
616 }
617 msg->url_counter = htonl ((uint16_t) builder->a_length);
618 return &msg->header;
619}
620
621
542char * 622char *
543GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder, 623GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
544 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv) 624 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
@@ -550,7 +630,7 @@ GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
550 char *sigs; 630 char *sigs;
551 const char *sep = "?"; 631 const char *sep = "?";
552 632
553 et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION); 633 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
554 sign_hello (builder, 634 sign_hello (builder,
555 et, 635 et,
556 priv, 636 priv,
@@ -629,7 +709,7 @@ GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
629 return GNUNET_NO; 709 return GNUNET_NO;
630 } 710 }
631 bh.pid = builder->pid; 711 bh.pid = builder->pid;
632 et = GNUNET_TIME_relative_to_timestamp (HELLO_ADDRESS_EXPIRATION); 712 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
633 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time); 713 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
634 sign_hello (builder, 714 sign_hello (builder,
635 et, 715 et,
@@ -742,3 +822,54 @@ GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
742 a->uri); 822 a->uri);
743 } 823 }
744} 824}
825
826
827enum GNUNET_GenericReturnValue
828GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
829 const struct GNUNET_PeerIdentity *pid,
830 void **block,
831 size_t *block_size,
832 struct GNUNET_TIME_Absolute *block_expiration)
833{
834 const struct DhtHelloMessage *msg
835 = (const struct DhtHelloMessage *) hello;
836 uint16_t len = ntohs (hello->size);
837 struct BlockHeader *bh;
838 struct GNUNET_HELLO_Builder *b;
839 enum GNUNET_GenericReturnValue ret;
840
841 if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
842 {
843 GNUNET_break (0);
844 return GNUNET_SYSERR;
845 }
846 if (len < sizeof (*msg))
847 {
848 GNUNET_break (0);
849 return GNUNET_SYSERR;
850 }
851 len -= sizeof (*msg);
852 *block_size = len + sizeof (*bh);
853 *block = GNUNET_malloc (*block_size);
854 bh = *block;
855 bh->pid = *pid;
856 bh->sig = msg->sig;
857 bh->expiration_time = msg->expiration_time;
858 *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
859 memcpy (&bh[1],
860 &msg[1],
861 len);
862 b = GNUNET_HELLO_builder_from_block (*block,
863 *block_size);
864 ret = verify_hello (b,
865 *block_expiration,
866 &msg->sig);
867 GNUNET_HELLO_builder_free (b);
868 if (GNUNET_SYSERR == ret)
869 {
870 GNUNET_free (*block);
871 *block_size = 0;
872 return GNUNET_SYSERR;
873 }
874 return ret;
875}
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,
154 * 154 *
155 * @param h handle to the datacache 155 * @param h handle to the datacache
156 * @param key area of the keyspace to look into 156 * @param key area of the keyspace to look into
157 * @param type entries of which type are relevant?
157 * @param num_results number of results that should be returned to @a iter 158 * @param num_results number of results that should be returned to @a iter
158 * @param iter maybe NULL (to just count) 159 * @param iter maybe NULL (to just count)
159 * @param iter_cls closure for @a iter 160 * @param iter_cls closure for @a iter
@@ -162,6 +163,7 @@ GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h,
162unsigned int 163unsigned int
163GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h, 164GNUNET_DATACACHE_get_closest (struct GNUNET_DATACACHE_Handle *h,
164 const struct GNUNET_HashCode *key, 165 const struct GNUNET_HashCode *key,
166 enum GNUNET_BLOCK_Type type,
165 unsigned int num_results, 167 unsigned int num_results,
166 GNUNET_DATACACHE_Iterator iter, 168 GNUNET_DATACACHE_Iterator iter,
167 void *iter_cls); 169 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
165 * 165 *
166 * @param cls closure (internal context for the plugin) 166 * @param cls closure (internal context for the plugin)
167 * @param key area of the keyspace to look into 167 * @param key area of the keyspace to look into
168 * @param type desired block type for the replies
168 * @param num_results number of results that should be returned to @a iter 169 * @param num_results number of results that should be returned to @a iter
169 * @param iter maybe NULL (to just count) 170 * @param iter maybe NULL (to just count)
170 * @param iter_cls closure for @a iter 171 * @param iter_cls closure for @a iter
@@ -173,6 +174,7 @@ struct GNUNET_DATACACHE_PluginFunctions
173 unsigned int 174 unsigned int
174 (*get_closest) (void *cls, 175 (*get_closest) (void *cls,
175 const struct GNUNET_HashCode *key, 176 const struct GNUNET_HashCode *key,
177 enum GNUNET_BLOCK_Type type,
176 unsigned int num_results, 178 unsigned int num_results,
177 GNUNET_DATACACHE_Iterator iter, 179 GNUNET_DATACACHE_Iterator iter,
178 void *iter_cls); 180 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
101 GNUNET_DHT_RO_RECORD_ROUTE = 2, 101 GNUNET_DHT_RO_RECORD_ROUTE = 2,
102 102
103 /** 103 /**
104 * This is a 'FIND-PEER' request, so approximate results are fine. 104 * Approximate results are fine.
105 */ 105 */
106 GNUNET_DHT_RO_FIND_PEER = 4, 106 GNUNET_DHT_RO_FIND_APPROXIMATE = 4,
107 107
108 /** 108 /**
109 * Flag given to monitors if this was the last hop for a GET/PUT. 109 * Flag given to monitors if this was the last hop for a GET/PUT.
110 * This is only used for internal processing. 110 * This is only used for internal processing.
111 */ 111 */
112 GNUNET_DHT_RO_LAST_HOP = 65535 112 GNUNET_DHT_RO_LAST_HOP = 65535
113}; 113};
114 114
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
129 const struct GNUNET_PeerIdentity *pid, 129 const struct GNUNET_PeerIdentity *pid,
130 void **ctx); 130 void **ctx);
131 131
132
132 /** 133 /**
133 * Function to call when we disconnected from a peer and can henceforth 134 * Function to call when we disconnected from a peer and can henceforth
134 * cannot transmit to that peer anymore. 135 * cannot transmit to that peer anymore.
@@ -177,7 +178,7 @@ struct GNUNET_DHTU_PluginFunctions
177 */ 178 */
178 void 179 void
179 (*try_connect) (void *cls, 180 (*try_connect) (void *cls,
180 struct GNUNET_PeerIdentity *pid, 181 const struct GNUNET_PeerIdentity *pid,
181 const char *address); 182 const char *address);
182 183
183 184
@@ -194,7 +195,7 @@ struct GNUNET_DHTU_PluginFunctions
194 struct GNUNET_DHTU_Target *target); 195 struct GNUNET_DHTU_Target *target);
195 196
196 /** 197 /**
197 * Do no long request underlay to keep the connection alive. 198 * Do no longer request underlay to keep the connection alive.
198 * 199 *
199 * @param cls closure 200 * @param cls closure
200 * @param target connection to keep alive 201 * @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
@@ -49,6 +49,13 @@ struct GNUNET_HELLO_Builder;
49 49
50 50
51/** 51/**
52 * For how long are HELLO signatures valid?
53 */
54#define GNUNET_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply ( \
55 GNUNET_TIME_UNIT_DAYS, 2)
56
57
58/**
52 * Allocate builder. 59 * Allocate builder.
53 * 60 *
54 * @param pid peer the builder is for 61 * @param pid peer the builder is for
@@ -100,7 +107,8 @@ GNUNET_HELLO_builder_from_url (const char *url);
100 107
101 108
102/** 109/**
103 * Generate HELLO message from a @a builder 110 * Generate envelope with GNUnet HELLO message (including
111 * peer ID) from a @a builder
104 * 112 *
105 * @param builder builder to serialize 113 * @param builder builder to serialize
106 * @param priv private key to use to sign the result 114 * @param priv private key to use to sign the result
@@ -112,6 +120,19 @@ GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
112 120
113 121
114/** 122/**
123 * Generate DHT HELLO message (without peer ID) from a @a builder
124 *
125 * @param builder builder to serialize
126 * @param priv private key to use to sign the result
127 * @return HELLO message matching @a builder
128 */
129struct GNUNET_MessageHeader *
130GNUNET_HELLO_builder_to_dht_hello_msg (
131 const struct GNUNET_HELLO_Builder *builder,
132 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv);
133
134
135/**
115 * Generate GNUnet HELLO URI from a @a builder 136 * Generate GNUnet HELLO URI from a @a builder
116 * 137 *
117 * @param builder builder to serialize 138 * @param builder builder to serialize
@@ -191,6 +212,27 @@ GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
191 GNUNET_HELLO_UriCallback uc, 212 GNUNET_HELLO_UriCallback uc,
192 void *uc_cls); 213 void *uc_cls);
193 214
215
216/**
217 * Convert a DHT @a hello message to a HELLO @a block.
218 *
219 * @param hello the HELLO message
220 * @param pid peer that created the @a hello
221 * @param[out] block set to the HELLO block
222 * @param[out] block_size set to number of bytes in @a block
223 * @param[out] block_expiration set to expiration time of @a block
224 * @return #GNUNET_OK on success,
225 * #GNUNET_NO if the @a hello is expired (@a block is set!)
226 * #GNUNET_SYSERR if @a hello is invalid (@a block will be set to NULL)
227 */
228enum GNUNET_GenericReturnValue
229GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
230 const struct GNUNET_PeerIdentity *pid,
231 void **block,
232 size_t *block_size,
233 struct GNUNET_TIME_Absolute *block_expiration);
234
235
194#if 0 /* keep Emacsens' auto-indent happy */ 236#if 0 /* keep Emacsens' auto-indent happy */
195{ 237{
196#endif 238#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" {
660#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156 660#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156
661 661
662/** 662/**
663 * DHT wants to use CORE to transmit data. 663 * HELLO advertising a neighbours addresses.
664 */ 664 */
665#define GNUNET_MESSAGE_TYPE_DHT_CORE 143 665#define GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO 157
666 666
667/** 667/**
668 * Further X-VINE DHT messages continued from 880 668 * DHT wants to use CORE to transmit data.
669 */ 669 */
670#define GNUNET_MESSAGE_TYPE_DHT_CORE 143
671
670 672
671/******************************************************************************* 673/*******************************************************************************
672 * HOSTLIST message types 674 * HOSTLIST message types