aboutsummaryrefslogtreecommitdiff
path: root/src/dht
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-01-02 20:24:02 +0100
committerChristian Grothoff <christian@grothoff.org>2022-01-02 20:24:02 +0100
commite3ff017054eb35dedd95ae4fe66c82b88e3bbdc3 (patch)
treeabb821d63f09d0982d6f6802ec1c55234dcc0f5c /src/dht
parent329f0458fa1fce45ce1c31e86771ffefb22e941e (diff)
downloadgnunet-e3ff017054eb35dedd95ae4fe66c82b88e3bbdc3.tar.gz
gnunet-e3ff017054eb35dedd95ae4fe66c82b88e3bbdc3.zip
-non-trivial refactoring/cleanup of the DHT code
Diffstat (limited to 'src/dht')
-rw-r--r--src/dht/gnunet-service-dht.h68
-rw-r--r--src/dht/gnunet-service-dht_clients.c340
-rw-r--r--src/dht/gnunet-service-dht_datacache.c200
-rw-r--r--src/dht/gnunet-service-dht_datacache.h124
-rw-r--r--src/dht/gnunet-service-dht_hello.c18
-rw-r--r--src/dht/gnunet-service-dht_neighbours.c695
-rw-r--r--src/dht/gnunet-service-dht_neighbours.h47
-rw-r--r--src/dht/gnunet-service-dht_nse.c30
-rw-r--r--src/dht/gnunet-service-dht_routing.c200
-rw-r--r--src/dht/gnunet-service-dht_routing.h24
10 files changed, 626 insertions, 1120 deletions
diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h
index 2854131c5..d520cc905 100644
--- a/src/dht/gnunet-service-dht.h
+++ b/src/dht/gnunet-service-dht.h
@@ -26,10 +26,10 @@
26#ifndef GNUNET_SERVICE_DHT_H 26#ifndef GNUNET_SERVICE_DHT_H
27#define GNUNET_SERVICE_DHT_H 27#define GNUNET_SERVICE_DHT_H
28 28
29#include "gnunet_util_lib.h" 29#include "gnunet-service-dht_datacache.h"
30#include "gnunet_statistics_service.h" 30#include "gnunet_statistics_service.h"
31#include "gnunet_transport_service.h" 31#include "gnunet_transport_service.h"
32#include "gnunet_block_lib.h" 32
33 33
34#define DEBUG_DHT GNUNET_EXTRA_LOGGING 34#define DEBUG_DHT GNUNET_EXTRA_LOGGING
35 35
@@ -64,28 +64,16 @@ extern struct GNUNET_MessageHeader *GDS_my_hello;
64 * matches any of our pending queries, forward it to the respective 64 * matches any of our pending queries, forward it to the respective
65 * client(s). 65 * client(s).
66 * 66 *
67 * @param expiration when will the reply expire 67 * @param bd block details
68 * @param key the key of the query that triggered the reply 68 * @param query_hash hash of the original query, might not match key in @a bd
69 * @param query_hash the query hash of the response 69 * @param get_path_length number of entries in @a get_path
70 * @param get_path_length number of peers in @a get_path 70 * @param get_path path the reply has taken
71 * @param get_path path the reply took on get
72 * @param put_path_length number of peers in @a put_path
73 * @param put_path path the reply took on put
74 * @param type type of the reply
75 * @param data_size number of bytes in @a data
76 * @param data application payload data
77 */ 71 */
78void 72void
79GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, 73GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
80 const struct GNUNET_HashCode *key,
81 const struct GNUNET_HashCode *query_hash, 74 const struct GNUNET_HashCode *query_hash,
82 unsigned int get_path_length, 75 unsigned int get_path_length,
83 const struct GNUNET_PeerIdentity *get_path, 76 const struct GNUNET_PeerIdentity *get_path);
84 unsigned int put_path_length,
85 const struct GNUNET_PeerIdentity *put_path,
86 enum GNUNET_BLOCK_Type type,
87 size_t data_size,
88 const void *data);
89 77
90 78
91/** 79/**
@@ -114,26 +102,14 @@ GDS_CLIENTS_process_get (uint32_t options,
114 * Check if some client is monitoring GET RESP messages and notify 102 * Check if some client is monitoring GET RESP messages and notify
115 * them in that case. 103 * them in that case.
116 * 104 *
117 * @param type The type of data in the result. 105 * @param bd block details
118 * @param get_path Peers on GET path (or NULL if not recorded). 106 * @param get_path Peers on GET path (or NULL if not recorded).
119 * @param get_path_length number of entries in @a get_path. 107 * @param get_path_length number of entries in @a get_path.
120 * @param put_path peers on the PUT path (or NULL if not recorded).
121 * @param put_path_length number of entries in @a get_path.
122 * @param exp Expiration time of the data.
123 * @param key Key of the @a data.
124 * @param data Pointer to the result data.
125 * @param size Number of bytes in @a data.
126 */ 108 */
127void 109void
128GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, 110GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
129 const struct GNUNET_PeerIdentity *get_path, 111 const struct GNUNET_PeerIdentity *get_path,
130 unsigned int get_path_length, 112 unsigned int get_path_length);
131 const struct GNUNET_PeerIdentity *put_path,
132 unsigned int put_path_length,
133 struct GNUNET_TIME_Absolute exp,
134 const struct GNUNET_HashCode *key,
135 const void *data,
136 size_t size);
137 113
138 114
139/** 115/**
@@ -141,27 +117,15 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
141 * them in that case. The @a path should include our own 117 * them in that case. The @a path should include our own
142 * peer ID (if recorded). 118 * peer ID (if recorded).
143 * 119 *
144 * @param options Options, for instance RecordRoute, DemultiplexEverywhere. 120 * @param options routing options to apply
145 * @param type The type of data in the request. 121 * @param bd details about the block
146 * @param hop_count Hop count so far. 122 * @param hop_count Hop count so far.
147 * @param path_length number of entries in path (or 0 if not recorded).
148 * @param path peers on the PUT path (or NULL if not recorded).
149 * @param desired_replication_level Desired replication level. 123 * @param desired_replication_level Desired replication level.
150 * @param exp Expiration time of the data.
151 * @param key Key under which data is to be stored.
152 * @param data Pointer to the data carried.
153 * @param size Number of bytes in data.
154 */ 124 */
155void 125void
156GDS_CLIENTS_process_put (uint32_t options, 126GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
157 enum GNUNET_BLOCK_Type type, 127 const struct GDS_DATACACHE_BlockData *bd,
158 uint32_t hop_count, 128 uint32_t hop_count,
159 uint32_t desired_replication_level, 129 uint32_t desired_replication_level);
160 unsigned int path_length,
161 const struct GNUNET_PeerIdentity *path,
162 struct GNUNET_TIME_Absolute exp,
163 const struct GNUNET_HashCode *key,
164 const void *data,
165 size_t size);
166 130
167#endif 131#endif
diff --git a/src/dht/gnunet-service-dht_clients.c b/src/dht/gnunet-service-dht_clients.c
index aa41f519c..b520cda41 100644
--- a/src/dht/gnunet-service-dht_clients.c
+++ b/src/dht/gnunet-service-dht_clients.c
@@ -425,6 +425,7 @@ transmit_next_request_task (void *cls)
425{ 425{
426 struct ClientQueryRecord *cqr; 426 struct ClientQueryRecord *cqr;
427 427
428 (void) cls;
428 retry_task = NULL; 429 retry_task = NULL;
429 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap))) 430 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
430 { 431 {
@@ -486,19 +487,23 @@ handle_dht_local_put (void *cls,
486{ 487{
487 struct ClientHandle *ch = cls; 488 struct ClientHandle *ch = cls;
488 uint16_t size = ntohs (dht_msg->header.size); 489 uint16_t size = ntohs (dht_msg->header.size);
489 uint32_t type = ntohl (dht_msg->type);
490 struct GNUNET_TIME_Absolute expiration
491 = GNUNET_TIME_absolute_ntoh (dht_msg->expiration);
492 enum GNUNET_DHT_RouteOption options 490 enum GNUNET_DHT_RouteOption options
493 = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options); 491 = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options);
494 uint32_t replication_level 492 uint32_t replication_level
495 = ntohl (dht_msg->desired_replication_level); 493 = ntohl (dht_msg->desired_replication_level);
494 struct GDS_DATACACHE_BlockData bd = {
495 .key = dht_msg->key,
496 .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
497 .data = &dht_msg[1],
498 .data_size = size - sizeof (*dht_msg),
499 .type = ntohl (dht_msg->type)
500 };
496 501
497 LOG (GNUNET_ERROR_TYPE_DEBUG, 502 LOG (GNUNET_ERROR_TYPE_DEBUG,
498 "Handling local PUT of %lu-bytes for query %s of type %u\n", 503 "Handling local PUT of %lu-bytes for query %s of type %u\n",
499 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)), 504 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
500 GNUNET_h2s (&dht_msg->key), 505 GNUNET_h2s (&dht_msg->key),
501 (unsigned int) type); 506 (unsigned int) bd.type);
502 GNUNET_STATISTICS_update (GDS_stats, 507 GNUNET_STATISTICS_update (GDS_stats,
503 "# PUT requests received from clients", 508 "# PUT requests received from clients",
504 1, 509 1,
@@ -507,14 +512,10 @@ handle_dht_local_put (void *cls,
507 "CLIENT-PUT %s\n", 512 "CLIENT-PUT %s\n",
508 GNUNET_h2s_full (&dht_msg->key)); 513 GNUNET_h2s_full (&dht_msg->key));
509 /* give to local clients */ 514 /* give to local clients */
510 GDS_CLIENTS_handle_reply (expiration, 515 GDS_CLIENTS_handle_reply (&bd,
511 &dht_msg->key, 516 &bd.key,
512 &dht_msg->key, 517 0, NULL /* get path */);
513 0, NULL, /* get path */ 518
514 0, NULL, /* put path */
515 type,
516 size - sizeof(struct GNUNET_DHT_ClientPutMessage),
517 &dht_msg[1]);
518 { 519 {
519 struct GNUNET_CONTAINER_BloomFilter *peer_bf; 520 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
520 521
@@ -526,26 +527,14 @@ handle_dht_local_put (void *cls,
526 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 527 if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
527 (GDS_am_closest_peer (&dht_msg->key, 528 (GDS_am_closest_peer (&dht_msg->key,
528 peer_bf))) 529 peer_bf)))
529 GDS_DATACACHE_handle_put ( 530 GDS_DATACACHE_handle_put (&bd);
530 expiration,
531 &dht_msg->key,
532 0, NULL, /* put path */
533 type,
534 size - sizeof(struct GNUNET_DHT_ClientPutMessage),
535 &dht_msg[1]);
536 /* route to other peers */ 531 /* route to other peers */
537 if (GNUNET_OK != 532 if (GNUNET_OK !=
538 GDS_NEIGHBOURS_handle_put ( 533 GDS_NEIGHBOURS_handle_put (&bd,
539 type, 534 options,
540 options, 535 replication_level,
541 replication_level, 536 0 /* hop count */,
542 expiration, 537 peer_bf))
543 0 /* hop count */,
544 peer_bf,
545 &dht_msg->key,
546 0, NULL, /* put path */
547 &dht_msg[1],
548 size - sizeof(struct GNUNET_DHT_ClientPutMessage)))
549 { 538 {
550 GNUNET_STATISTICS_update (GDS_stats, 539 GNUNET_STATISTICS_update (GDS_stats,
551 "# Local PUT requests not routed", 540 "# Local PUT requests not routed",
@@ -556,15 +545,9 @@ handle_dht_local_put (void *cls,
556 } 545 }
557 GDS_CLIENTS_process_put ( 546 GDS_CLIENTS_process_put (
558 options, 547 options,
559 type, 548 &bd,
560 0, /* hop count */ 549 0, /* hop count */
561 replication_level, 550 replication_level);
562 1, /* path length */
563 GDS_NEIGHBOURS_get_id (),
564 expiration,
565 &dht_msg->key,
566 &dht_msg[1],
567 size - sizeof(struct GNUNET_DHT_ClientPutMessage));
568 GNUNET_SERVICE_client_continue (ch->client); 551 GNUNET_SERVICE_client_continue (ch->client);
569} 552}
570 553
@@ -573,37 +556,16 @@ handle_dht_local_put (void *cls,
573 * Handle a result from local datacache for a GET operation. 556 * Handle a result from local datacache for a GET operation.
574 * 557 *
575 * @param cls the `struct ClientHandle` of the client doing the query 558 * @param cls the `struct ClientHandle` of the client doing the query
576 * @param type type of the block 559 * @param bd details about the block that was found
577 * @param expiration_time when does the content expire
578 * @param key key for the content
579 * @param put_path_length number of entries in @a put_path
580 * @param put_path peers the original PUT traversed (if tracked)
581 * @param get_path_length number of entries in @a get_path
582 * @param get_path peers this reply has traversed so far (if tracked)
583 * @param data payload of the reply
584 * @param data_size number of bytes in @a data
585 */ 560 */
586static void 561static void
587handle_local_result (void *cls, 562handle_local_result (void *cls,
588 enum GNUNET_BLOCK_Type type, 563 const struct GDS_DATACACHE_BlockData *bd)
589 struct GNUNET_TIME_Absolute expiration_time,
590 const struct GNUNET_HashCode *key,
591 unsigned int put_path_length,
592 const struct GNUNET_PeerIdentity *put_path,
593 unsigned int get_path_length,
594 const struct GNUNET_PeerIdentity *get_path,
595 const void *data,
596 size_t data_size)
597{ 564{
598 // FIXME: this may deserve some clean up: inline the function, 565 /* FIXME: use 'cls' instead of looking up the client? */
599 // possibly avoid even looking up the client! 566 GDS_CLIENTS_handle_reply (bd,
600 GDS_CLIENTS_handle_reply (expiration_time, 567 &bd->key,
601 key, 568 0, NULL /* get_path */);
602 key,
603 0, NULL,
604 put_path_length, put_path,
605 type,
606 data_size, data);
607} 569}
608 570
609 571
@@ -713,6 +675,9 @@ struct FindByUniqueIdContext
713 */ 675 */
714 struct ClientQueryRecord *cqr; 676 struct ClientQueryRecord *cqr;
715 677
678 /**
679 * Unique ID to look for.
680 */
716 uint64_t unique_id; 681 uint64_t unique_id;
717}; 682};
718 683
@@ -968,9 +933,9 @@ handle_dht_local_monitor_stop (
968struct ForwardReplyContext 933struct ForwardReplyContext
969{ 934{
970 /** 935 /**
971 * Expiration time of the reply. 936 * Block details.
972 */ 937 */
973 struct GNUNET_TIME_Absolute expiration; 938 const struct GDS_DATACACHE_BlockData *bd;
974 939
975 /** 940 /**
976 * GET path taken. 941 * GET path taken.
@@ -978,39 +943,10 @@ struct ForwardReplyContext
978 const struct GNUNET_PeerIdentity *get_path; 943 const struct GNUNET_PeerIdentity *get_path;
979 944
980 /** 945 /**
981 * PUT path taken.
982 */
983 const struct GNUNET_PeerIdentity *put_path;
984
985 /**
986 * Hash under which the payload is stored.
987 */
988 const struct GNUNET_HashCode *query_hash;
989
990 /**
991 * Embedded payload.
992 */
993 const void *data;
994
995 /**
996 * Number of bytes in data.
997 */
998 size_t data_size;
999
1000 /**
1001 * Number of entries in @e get_path. 946 * Number of entries in @e get_path.
1002 */ 947 */
1003 unsigned int get_path_length; 948 unsigned int get_path_length;
1004 949
1005 /**
1006 * Number of entries in @e put_path.
1007 */
1008 unsigned int put_path_length;
1009
1010 /**
1011 * Type of the data.
1012 */
1013 enum GNUNET_BLOCK_Type type;
1014}; 950};
1015 951
1016 952
@@ -1019,15 +955,15 @@ struct ForwardReplyContext
1019 * each of the matching clients. With some tricky recycling 955 * each of the matching clients. With some tricky recycling
1020 * of the buffer. 956 * of the buffer.
1021 * 957 *
1022 * @param cls the 'struct ForwardReplyContext' 958 * @param cls the `struct ForwardReplyContext`
1023 * @param key current key 959 * @param query_hash hash of the query for which this may be a reply
1024 * @param value value in the hash map, a ClientQueryRecord 960 * @param value value in the hash map, a ClientQueryRecord
1025 * @return #GNUNET_YES (we should continue to iterate), 961 * @return #GNUNET_YES (we should continue to iterate),
1026 * if the result is mal-formed, #GNUNET_NO 962 * if the result is mal-formed, #GNUNET_NO
1027 */ 963 */
1028static enum GNUNET_GenericReturnValue 964static enum GNUNET_GenericReturnValue
1029forward_reply (void *cls, 965forward_reply (void *cls,
1030 const struct GNUNET_HashCode *key, 966 const struct GNUNET_HashCode *query_hash,
1031 void *value) 967 void *value)
1032{ 968{
1033 struct ForwardReplyContext *frc = cls; 969 struct ForwardReplyContext *frc = cls;
@@ -1041,13 +977,13 @@ forward_reply (void *cls,
1041 977
1042 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 978 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
1043 "CLIENT-RESULT %s\n", 979 "CLIENT-RESULT %s\n",
1044 GNUNET_h2s_full (frc->query_hash)); 980 GNUNET_h2s_full (&frc->bd->key));
1045 if ((record->type != GNUNET_BLOCK_TYPE_ANY) && 981 if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
1046 (record->type != frc->type)) 982 (record->type != frc->bd->type) )
1047 { 983 {
1048 LOG (GNUNET_ERROR_TYPE_DEBUG, 984 LOG (GNUNET_ERROR_TYPE_DEBUG,
1049 "Record type mismatch, not passing request for key %s to local client\n", 985 "Record type mismatch, not passing request for key %s to local client\n",
1050 GNUNET_h2s (key)); 986 GNUNET_h2s (&frc->bd->key));
1051 GNUNET_STATISTICS_update (GDS_stats, 987 GNUNET_STATISTICS_update (GDS_stats,
1052 "# Key match, type mismatches in REPLY to CLIENT", 988 "# Key match, type mismatches in REPLY to CLIENT",
1053 1, 989 1,
@@ -1055,8 +991,8 @@ forward_reply (void *cls,
1055 return GNUNET_YES; /* type mismatch */ 991 return GNUNET_YES; /* type mismatch */
1056 } 992 }
1057 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) && 993 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_PEER)) &&
1058 (0 != GNUNET_memcmp (key, 994 (0 != GNUNET_memcmp (&frc->bd->key,
1059 frc->query_hash)) ) 995 query_hash)) )
1060 { 996 {
1061 GNUNET_STATISTICS_update (GDS_stats, 997 GNUNET_STATISTICS_update (GDS_stats,
1062 "# Inexact key match, but exact match required", 998 "# Inexact key match, but exact match required",
@@ -1064,37 +1000,36 @@ forward_reply (void *cls,
1064 GNUNET_NO); 1000 GNUNET_NO);
1065 return GNUNET_YES; /* type mismatch */ 1001 return GNUNET_YES; /* type mismatch */
1066 } 1002 }
1067 GNUNET_CRYPTO_hash (frc->data, 1003 GNUNET_CRYPTO_hash (frc->bd->data,
1068 frc->data_size, 1004 frc->bd->data_size,
1069 &ch); 1005 &ch);
1070 for (unsigned int i = 0; i < record->seen_replies_count; i++) 1006 for (unsigned int i = 0; i < record->seen_replies_count; i++)
1071 if (0 == memcmp (&record->seen_replies[i], 1007 if (0 ==
1072 &ch, 1008 GNUNET_memcmp (&record->seen_replies[i],
1073 sizeof(struct GNUNET_HashCode))) 1009 &ch))
1074 { 1010 {
1075 LOG (GNUNET_ERROR_TYPE_DEBUG, 1011 LOG (GNUNET_ERROR_TYPE_DEBUG,
1076 "Duplicate reply, not passing request for key %s to local client\n", 1012 "Duplicate reply, not passing request for key %s to local client\n",
1077 GNUNET_h2s (key)); 1013 GNUNET_h2s (&frc->bd->key));
1078 GNUNET_STATISTICS_update (GDS_stats, 1014 GNUNET_STATISTICS_update (GDS_stats,
1079 gettext_noop 1015 "# Duplicate REPLIES to CLIENT request dropped",
1080 ( 1016 1,
1081 "# Duplicate REPLIES to CLIENT request dropped"), 1017 GNUNET_NO);
1082 1, GNUNET_NO);
1083 return GNUNET_YES; /* duplicate */ 1018 return GNUNET_YES; /* duplicate */
1084 } 1019 }
1085 eval 1020 eval
1086 = GNUNET_BLOCK_check_reply (GDS_block_context, 1021 = GNUNET_BLOCK_check_reply (GDS_block_context,
1087 record->type, 1022 record->type,
1088 NULL, 1023 NULL,
1089 key, 1024 &frc->bd->key,
1090 record->xquery, 1025 record->xquery,
1091 record->xquery_size, 1026 record->xquery_size,
1092 frc->data, 1027 frc->bd->data,
1093 frc->data_size); 1028 frc->bd->data_size);
1094 LOG (GNUNET_ERROR_TYPE_DEBUG, 1029 LOG (GNUNET_ERROR_TYPE_DEBUG,
1095 "Evaluation result is %d for key %s for local client's query\n", 1030 "Evaluation result is %d for key %s for local client's query\n",
1096 (int) eval, 1031 (int) eval,
1097 GNUNET_h2s (key)); 1032 GNUNET_h2s (&frc->bd->key));
1098 switch (eval) 1033 switch (eval)
1099 { 1034 {
1100 case GNUNET_BLOCK_REPLY_OK_LAST: 1035 case GNUNET_BLOCK_REPLY_OK_LAST:
@@ -1125,29 +1060,29 @@ forward_reply (void *cls,
1125 1, 1060 1,
1126 GNUNET_NO); 1061 GNUNET_NO);
1127 env = GNUNET_MQ_msg_extra (reply, 1062 env = GNUNET_MQ_msg_extra (reply,
1128 frc->data_size 1063 frc->bd->data_size
1129 + (frc->get_path_length + frc->put_path_length) 1064 + (frc->get_path_length + frc->bd->put_path_length)
1130 * sizeof(struct GNUNET_PeerIdentity), 1065 * sizeof(struct GNUNET_PeerIdentity),
1131 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT); 1066 GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT);
1132 reply->type = htonl (frc->type); 1067 reply->type = htonl (frc->bd->type);
1133 reply->get_path_length = htonl (frc->get_path_length); 1068 reply->get_path_length = htonl (frc->get_path_length);
1134 reply->put_path_length = htonl (frc->put_path_length); 1069 reply->put_path_length = htonl (frc->bd->put_path_length);
1135 reply->unique_id = record->unique_id; 1070 reply->unique_id = record->unique_id;
1136 reply->expiration = GNUNET_TIME_absolute_hton (frc->expiration); 1071 reply->expiration = GNUNET_TIME_absolute_hton (frc->bd->expiration_time);
1137 reply->key = *key; 1072 reply->key = frc->bd->key;
1138 paths = (struct GNUNET_PeerIdentity *) &reply[1]; 1073 paths = (struct GNUNET_PeerIdentity *) &reply[1];
1139 GNUNET_memcpy (paths, 1074 GNUNET_memcpy (paths,
1140 frc->put_path, 1075 frc->bd->put_path,
1141 sizeof(struct GNUNET_PeerIdentity) * frc->put_path_length); 1076 sizeof(struct GNUNET_PeerIdentity) * frc->bd->put_path_length);
1142 GNUNET_memcpy (&paths[frc->put_path_length], 1077 GNUNET_memcpy (&paths[frc->bd->put_path_length],
1143 frc->get_path, 1078 frc->get_path,
1144 sizeof(struct GNUNET_PeerIdentity) * frc->get_path_length); 1079 sizeof(struct GNUNET_PeerIdentity) * frc->get_path_length);
1145 GNUNET_memcpy (&paths[frc->get_path_length + frc->put_path_length], 1080 GNUNET_memcpy (&paths[frc->get_path_length + frc->bd->put_path_length],
1146 frc->data, 1081 frc->bd->data,
1147 frc->data_size); 1082 frc->bd->data_size);
1148 LOG (GNUNET_ERROR_TYPE_DEBUG, 1083 LOG (GNUNET_ERROR_TYPE_DEBUG,
1149 "Sending reply to query %s for client %p\n", 1084 "Sending reply to query %s for client %p\n",
1150 GNUNET_h2s (key), 1085 GNUNET_h2s (query_hash),
1151 record->ch->client); 1086 record->ch->client);
1152 GNUNET_MQ_send (record->ch->mq, 1087 GNUNET_MQ_send (record->ch->mq,
1153 env); 1088 env);
@@ -1157,66 +1092,38 @@ forward_reply (void *cls,
1157} 1092}
1158 1093
1159 1094
1160/**
1161 * Handle a reply we've received from another peer. If the reply
1162 * matches any of our pending queries, forward it to the respective
1163 * client(s).
1164 *
1165 * @param expiration when will the reply expire
1166 * @param key the key of the query that triggered the reply
1167 * @param query_hash the query hash of the response
1168 * @param get_path_length number of peers in @a get_path
1169 * @param get_path path the reply took on get
1170 * @param put_path_length number of peers in @a put_path
1171 * @param put_path path the reply took on put
1172 * @param type type of the reply
1173 * @param data_size number of bytes in @a data
1174 * @param data application payload data
1175 */
1176void 1095void
1177GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, 1096GDS_CLIENTS_handle_reply (const struct GDS_DATACACHE_BlockData *bd,
1178 const struct GNUNET_HashCode *key,
1179 const struct GNUNET_HashCode *query_hash, 1097 const struct GNUNET_HashCode *query_hash,
1180 unsigned int get_path_length, 1098 unsigned int get_path_length,
1181 const struct GNUNET_PeerIdentity *get_path, 1099 const struct GNUNET_PeerIdentity *get_path)
1182 unsigned int put_path_length,
1183 const struct GNUNET_PeerIdentity *put_path,
1184 enum GNUNET_BLOCK_Type type,
1185 size_t data_size,
1186 const void *data)
1187{ 1100{
1188 struct ForwardReplyContext frc; 1101 struct ForwardReplyContext frc;
1189 size_t msize; 1102 size_t msize = sizeof (struct GNUNET_DHT_ClientResultMessage)
1103 + bd->data_size
1104 + (get_path_length + bd->put_path_length)
1105 * sizeof(struct GNUNET_PeerIdentity);
1190 1106
1191 msize = sizeof(struct GNUNET_DHT_ClientResultMessage) + data_size
1192 + (get_path_length + put_path_length)
1193 * sizeof(struct GNUNET_PeerIdentity);
1194 if (msize >= GNUNET_MAX_MESSAGE_SIZE) 1107 if (msize >= GNUNET_MAX_MESSAGE_SIZE)
1195 { 1108 {
1196 GNUNET_break (0); 1109 GNUNET_break (0);
1197 return; 1110 return;
1198 } 1111 }
1199 frc.expiration = expiration; 1112 frc.bd = bd;
1200 frc.query_hash = query_hash;
1201 frc.get_path = get_path; 1113 frc.get_path = get_path;
1202 frc.put_path = put_path;
1203 frc.data = data;
1204 frc.data_size = data_size;
1205 frc.get_path_length = get_path_length; 1114 frc.get_path_length = get_path_length;
1206 frc.put_path_length = put_path_length;
1207 frc.type = type;
1208 LOG (GNUNET_ERROR_TYPE_DEBUG, 1115 LOG (GNUNET_ERROR_TYPE_DEBUG,
1209 "Forwarding reply for key %s to client\n", 1116 "Forwarding reply for query hash %s to client\n",
1210 GNUNET_h2s (key)); 1117 GNUNET_h2s (query_hash));
1211 if (0 == 1118 if (0 ==
1212 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, 1119 GNUNET_CONTAINER_multihashmap_get_multiple (forward_map,
1213 key, 1120 query_hash,
1214 &forward_reply, 1121 &forward_reply,
1215 &frc)) 1122 &frc))
1216 { 1123 {
1217 LOG (GNUNET_ERROR_TYPE_DEBUG, 1124 LOG (GNUNET_ERROR_TYPE_DEBUG,
1218 "No matching client for reply for key %s\n", 1125 "No matching client for reply for query %s\n",
1219 GNUNET_h2s (key)); 1126 GNUNET_h2s (query_hash));
1220 GNUNET_STATISTICS_update (GDS_stats, 1127 GNUNET_STATISTICS_update (GDS_stats,
1221 "# REPLIES ignored for CLIENTS (no match)", 1128 "# REPLIES ignored for CLIENTS (no match)",
1222 1, 1129 1,
@@ -1298,15 +1205,9 @@ GDS_CLIENTS_process_get (uint32_t options,
1298 1205
1299 1206
1300void 1207void
1301GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, 1208GDS_CLIENTS_process_get_resp (const struct GDS_DATACACHE_BlockData *bd,
1302 const struct GNUNET_PeerIdentity *get_path, 1209 const struct GNUNET_PeerIdentity *get_path,
1303 unsigned int get_path_length, 1210 unsigned int get_path_length)
1304 const struct GNUNET_PeerIdentity *put_path,
1305 unsigned int put_path_length,
1306 struct GNUNET_TIME_Absolute exp,
1307 const struct GNUNET_HashCode *key,
1308 const void *data,
1309 size_t size)
1310{ 1211{
1311 struct ClientHandle **cl = NULL; 1212 struct ClientHandle **cl = NULL;
1312 unsigned int cl_size = 0; 1213 unsigned int cl_size = 0;
@@ -1316,9 +1217,9 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
1316 m = m->next) 1217 m = m->next)
1317 { 1218 {
1318 if ( ( (GNUNET_BLOCK_TYPE_ANY == m->type) || 1219 if ( ( (GNUNET_BLOCK_TYPE_ANY == m->type) ||
1319 (m->type == type) ) && 1220 (m->type == bd->type) ) &&
1320 ( (GNUNET_is_zero (&m->key)) || 1221 ( (GNUNET_is_zero (&m->key)) ||
1321 (0 == GNUNET_memcmp (key, 1222 (0 == GNUNET_memcmp (&bd->key,
1322 &m->key)) ) ) 1223 &m->key)) ) )
1323 { 1224 {
1324 struct GNUNET_MQ_Envelope *env; 1225 struct GNUNET_MQ_Envelope *env;
@@ -1336,27 +1237,27 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
1336 GNUNET_array_append (cl, 1237 GNUNET_array_append (cl,
1337 cl_size, 1238 cl_size,
1338 m->ch); 1239 m->ch);
1339 msize = size; 1240 msize = bd->data_size;
1340 msize += (get_path_length + put_path_length) 1241 msize += (get_path_length + bd->put_path_length)
1341 * sizeof(struct GNUNET_PeerIdentity); 1242 * sizeof(struct GNUNET_PeerIdentity);
1342 env = GNUNET_MQ_msg_extra (mmsg, 1243 env = GNUNET_MQ_msg_extra (mmsg,
1343 msize, 1244 msize,
1344 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP); 1245 GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP);
1345 mmsg->type = htonl (type); 1246 mmsg->type = htonl (bd->type);
1346 mmsg->put_path_length = htonl (put_path_length); 1247 mmsg->put_path_length = htonl (bd->put_path_length);
1347 mmsg->get_path_length = htonl (get_path_length); 1248 mmsg->get_path_length = htonl (get_path_length);
1348 mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp); 1249 mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1349 mmsg->key = *key; 1250 mmsg->key = bd->key;
1350 path = (struct GNUNET_PeerIdentity *) &mmsg[1]; 1251 path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1351 GNUNET_memcpy (path, 1252 GNUNET_memcpy (path,
1352 put_path, 1253 bd->put_path,
1353 put_path_length * sizeof(struct GNUNET_PeerIdentity)); 1254 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1354 GNUNET_memcpy (path, 1255 GNUNET_memcpy (path,
1355 get_path, 1256 get_path,
1356 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 1257 get_path_length * sizeof(struct GNUNET_PeerIdentity));
1357 GNUNET_memcpy (&path[get_path_length], 1258 GNUNET_memcpy (&path[get_path_length],
1358 data, 1259 bd->data,
1359 size); 1260 bd->data_size);
1360 GNUNET_MQ_send (m->ch->mq, 1261 GNUNET_MQ_send (m->ch->mq,
1361 env); 1262 env);
1362 } 1263 }
@@ -1365,32 +1266,11 @@ GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type,
1365} 1266}
1366 1267
1367 1268
1368/**
1369 * Check if some client is monitoring PUT messages and notify
1370 * them in that case. The @a path should include our own peer ID.
1371 *
1372 * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
1373 * @param type The type of data in the request.
1374 * @param hop_count Hop count so far.
1375 * @param path_length number of entries in path (or 0 if not recorded).
1376 * @param path peers on the PUT path (or NULL if not recorded).
1377 * @param desired_replication_level Desired replication level.
1378 * @param exp Expiration time of the data.
1379 * @param key Key under which data is to be stored.
1380 * @param data Pointer to the data carried.
1381 * @param size Number of bytes in data.
1382 */
1383void 1269void
1384GDS_CLIENTS_process_put (uint32_t options, 1270GDS_CLIENTS_process_put (enum GNUNET_DHT_RouteOption options,
1385 enum GNUNET_BLOCK_Type type, 1271 const struct GDS_DATACACHE_BlockData *bd,
1386 uint32_t hop_count, 1272 uint32_t hop_count,
1387 uint32_t desired_replication_level, 1273 uint32_t desired_replication_level)
1388 unsigned int path_length,
1389 const struct GNUNET_PeerIdentity *path,
1390 struct GNUNET_TIME_Absolute exp,
1391 const struct GNUNET_HashCode *key,
1392 const void *data,
1393 size_t size)
1394{ 1274{
1395 struct ClientHandle **cl = NULL; 1275 struct ClientHandle **cl = NULL;
1396 unsigned int cl_size = 0; 1276 unsigned int cl_size = 0;
@@ -1400,10 +1280,10 @@ GDS_CLIENTS_process_put (uint32_t options,
1400 m = m->next) 1280 m = m->next)
1401 { 1281 {
1402 if ( ( (GNUNET_BLOCK_TYPE_ANY == m->type) || 1282 if ( ( (GNUNET_BLOCK_TYPE_ANY == m->type) ||
1403 (m->type == type) ) && 1283 (m->type == bd->type) ) &&
1404 ( (GNUNET_is_zero (&m->key)) || 1284 ( (GNUNET_is_zero (&m->key)) ||
1405 (0 == 1285 (0 ==
1406 GNUNET_memcmp (key, 1286 GNUNET_memcmp (&bd->key,
1407 &m->key)) ) ) 1287 &m->key)) ) )
1408 { 1288 {
1409 struct GNUNET_MQ_Envelope *env; 1289 struct GNUNET_MQ_Envelope *env;
@@ -1421,25 +1301,25 @@ GDS_CLIENTS_process_put (uint32_t options,
1421 GNUNET_array_append (cl, 1301 GNUNET_array_append (cl,
1422 cl_size, 1302 cl_size,
1423 m->ch); 1303 m->ch);
1424 msize = size; 1304 msize = bd->data_size;
1425 msize += path_length * sizeof(struct GNUNET_PeerIdentity); 1305 msize += bd->put_path_length * sizeof(struct GNUNET_PeerIdentity);
1426 env = GNUNET_MQ_msg_extra (mmsg, 1306 env = GNUNET_MQ_msg_extra (mmsg,
1427 msize, 1307 msize,
1428 GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT); 1308 GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT);
1429 mmsg->options = htonl (options); 1309 mmsg->options = htonl (options);
1430 mmsg->type = htonl (type); 1310 mmsg->type = htonl (bd->type);
1431 mmsg->hop_count = htonl (hop_count); 1311 mmsg->hop_count = htonl (hop_count);
1432 mmsg->desired_replication_level = htonl (desired_replication_level); 1312 mmsg->desired_replication_level = htonl (desired_replication_level);
1433 mmsg->put_path_length = htonl (path_length); 1313 mmsg->put_path_length = htonl (bd->put_path_length);
1434 mmsg->key = *key; 1314 mmsg->key = bd->key;
1435 mmsg->expiration_time = GNUNET_TIME_absolute_hton (exp); 1315 mmsg->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1436 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; 1316 msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1];
1437 GNUNET_memcpy (msg_path, 1317 GNUNET_memcpy (msg_path,
1438 path, 1318 bd->put_path,
1439 path_length * sizeof(struct GNUNET_PeerIdentity)); 1319 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1440 GNUNET_memcpy (&msg_path[path_length], 1320 GNUNET_memcpy (&msg_path[bd->put_path_length],
1441 data, 1321 bd->data,
1442 size); 1322 bd->data_size);
1443 GNUNET_MQ_send (m->ch->mq, 1323 GNUNET_MQ_send (m->ch->mq,
1444 env); 1324 env);
1445 } 1325 }
diff --git a/src/dht/gnunet-service-dht_datacache.c b/src/dht/gnunet-service-dht_datacache.c
index d80889635..a60f49a51 100644
--- a/src/dht/gnunet-service-dht_datacache.c
+++ b/src/dht/gnunet-service-dht_datacache.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 2015, 2017 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 2015, 2017, 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
@@ -38,35 +38,18 @@
38 */ 38 */
39#define NUM_CLOSEST 42 39#define NUM_CLOSEST 42
40 40
41
41/** 42/**
42 * Handle to the datacache service (for inserting/retrieving data) 43 * Handle to the datacache service (for inserting/retrieving data)
43 */ 44 */
44static struct GNUNET_DATACACHE_Handle *datacache; 45static struct GNUNET_DATACACHE_Handle *datacache;
45 46
46 47
47/**
48 * Handle a datum we've received from another peer. Cache if
49 * possible.
50 *
51 * @param expiration when will the reply expire
52 * @param key the query this reply is for
53 * @param put_path_length number of peers in @a put_path
54 * @param put_path path the reply took on put
55 * @param type type of the reply
56 * @param data_size number of bytes in @a data
57 * @param data application payload data
58 */
59void 48void
60GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, 49GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd)
61 const struct GNUNET_HashCode *key,
62 unsigned int put_path_length,
63 const struct GNUNET_PeerIdentity *put_path,
64 enum GNUNET_BLOCK_Type type,
65 size_t data_size,
66 const void *data)
67{ 50{
68 struct GNUNET_HashCode xor; 51 struct GNUNET_HashCode xor;
69 int r; 52 enum GNUNET_GenericReturnValue r;
70 53
71 if (NULL == datacache) 54 if (NULL == datacache)
72 { 55 {
@@ -74,7 +57,7 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
74 "PUT request received, but have no datacache!\n"); 57 "PUT request received, but have no datacache!\n");
75 return; 58 return;
76 } 59 }
77 if (data_size >= GNUNET_MAX_MESSAGE_SIZE) 60 if (bd->data_size >= GNUNET_MAX_MESSAGE_SIZE)
78 { 61 {
79 GNUNET_break (0); 62 GNUNET_break (0);
80 return; 63 return;
@@ -84,24 +67,24 @@ GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration,
84 "# ITEMS stored in datacache", 67 "# ITEMS stored in datacache",
85 1, 68 1,
86 GNUNET_NO); 69 GNUNET_NO);
87 GNUNET_CRYPTO_hash_xor (key, 70 GNUNET_CRYPTO_hash_xor (&bd->key,
88 &my_identity_hash, 71 &my_identity_hash,
89 &xor); 72 &xor);
90 r = GNUNET_DATACACHE_put (datacache, 73 r = GNUNET_DATACACHE_put (datacache,
91 key, 74 &bd->key,
92 GNUNET_CRYPTO_hash_count_leading_zeros (&xor), 75 GNUNET_CRYPTO_hash_count_leading_zeros (&xor),
93 data_size, 76 bd->data_size,
94 data, 77 bd->data,
95 type, 78 bd->type,
96 expiration, 79 bd->expiration_time,
97 put_path_length, 80 bd->put_path_length,
98 put_path); 81 bd->put_path);
99 LOG (GNUNET_ERROR_TYPE_DEBUG, 82 LOG (GNUNET_ERROR_TYPE_DEBUG,
100 "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n", 83 "DATACACHE PUT for key %s [%lu] completed (%d) after %u hops\n",
101 GNUNET_h2s (key), 84 GNUNET_h2s (&bd->key),
102 (unsigned long) data_size, 85 (unsigned long) bd->data_size,
103 r, 86 r,
104 put_path_length); 87 bd->put_path_length);
105} 88}
106 89
107 90
@@ -171,30 +154,34 @@ datacache_get_iterator (void *cls,
171 unsigned int put_path_length, 154 unsigned int put_path_length,
172 const struct GNUNET_PeerIdentity *put_path) 155 const struct GNUNET_PeerIdentity *put_path)
173{ 156{
174 static char non_null;
175 struct GetRequestContext *ctx = cls; 157 struct GetRequestContext *ctx = cls;
176 enum GNUNET_BLOCK_ReplyEvaluationResult eval; 158 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
177 159 struct GDS_DATACACHE_BlockData bd = {
178 if (0 == GNUNET_TIME_absolute_get_remaining (exp).rel_value_us) 160 .key = *key,
161 .expiration_time = exp,
162 .put_path = put_path,
163 .data = data,
164 .data_size = data_size,
165 .put_path_length = put_path_length,
166 .type = type
167 };
168
169 if (GNUNET_TIME_absolute_is_past (exp))
179 { 170 {
180 GNUNET_break (0); /* why does datacache return expired values? */ 171 GNUNET_break (0); /* why does datacache return expired values? */
181 return GNUNET_OK; /* skip expired record */ 172 return GNUNET_OK; /* skip expired record */
182 } 173 }
183 if ((NULL == data) &&
184 (0 == data_size))
185 data = &non_null; /* point anywhere, but not to NULL */
186
187 eval 174 eval
188 = GNUNET_BLOCK_check_reply (GDS_block_context, 175 = GNUNET_BLOCK_check_reply (GDS_block_context,
189 type, 176 bd.type,
190 ctx->bg, 177 ctx->bg,
191 key, 178 &bd.key,
192 ctx->xquery, 179 ctx->xquery,
193 ctx->xquery_size, 180 ctx->xquery_size,
194 data, 181 bd.data,
195 data_size); 182 bd.data_size);
196 LOG (GNUNET_ERROR_TYPE_DEBUG, 183 LOG (GNUNET_ERROR_TYPE_DEBUG,
197 "Found reply for query %s in datacache, evaluation result is %d\n", 184 "Evaluated reply for query %s in datacache, result is %d\n",
198 GNUNET_h2s (key), 185 GNUNET_h2s (key),
199 (int) eval); 186 (int) eval);
200 ctx->eval = eval; 187 ctx->eval = eval;
@@ -209,12 +196,7 @@ datacache_get_iterator (void *cls,
209 1, 196 1,
210 GNUNET_NO); 197 GNUNET_NO);
211 ctx->gc (ctx->gc_cls, 198 ctx->gc (ctx->gc_cls,
212 type, 199 &bd);
213 exp,
214 key,
215 put_path_length, put_path,
216 0, NULL,
217 data, data_size);
218 break; 200 break;
219 case GNUNET_BLOCK_REPLY_OK_DUPLICATE: 201 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
220 GNUNET_STATISTICS_update (GDS_stats, 202 GNUNET_STATISTICS_update (GDS_stats,
@@ -240,18 +222,6 @@ datacache_get_iterator (void *cls,
240} 222}
241 223
242 224
243/**
244 * Handle a GET request we've received from another peer.
245 *
246 * @param key the query
247 * @param type requested data type
248 * @param xquery extended query
249 * @param xquery_size number of bytes in @a xquery
250 * @param bg block group to use for reply evaluation
251 * @param gc function to call on the results
252 * @param gc_cls closure for @a gc
253 * @return evaluation result for the local replies
254 */
255enum GNUNET_BLOCK_EvaluationResult 225enum GNUNET_BLOCK_EvaluationResult
256GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key, 226GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
257 enum GNUNET_BLOCK_Type type, 227 enum GNUNET_BLOCK_Type type,
@@ -292,62 +262,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
292 262
293 263
294/** 264/**
295 * Function called with a random element from the datacache.
296 * Stores the key in the closure.
297 *
298 * @param cls a `struct GNUNET_HashCode *`, where to store the @a key
299 * @param key key for the content
300 * @param data_size number of bytes in @a data
301 * @param data content stored
302 * @param type type of the content
303 * @param exp when will the content expire?
304 * @param path_info_len number of entries in @a path_info
305 * @param path_info a path through the network
306 * @return #GNUNET_OK to continue iterating, #GNUNET_SYSERR to abort
307 */
308static int
309datacache_random_iterator (void *cls,
310 const struct GNUNET_HashCode *key,
311 size_t data_size,
312 const char *data,
313 enum GNUNET_BLOCK_Type type,
314 struct GNUNET_TIME_Absolute exp,
315 unsigned int path_info_len,
316 const struct GNUNET_PeerIdentity *path_info)
317{
318 struct GNUNET_HashCode *dest = cls;
319
320 *dest = *key;
321 return GNUNET_OK; /* should actually not matter which we return */
322}
323
324
325/**
326 * Obtain a random key from the datacache.
327 * Used by Whanau for load-balancing.
328 *
329 * @param[out] key where to store the key of a random element,
330 * randomized by PRNG if datacache is empty
331 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
332 */
333int
334GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key)
335{
336 if (0 ==
337 GNUNET_DATACACHE_get_random (datacache,
338 &datacache_random_iterator,
339 key))
340 {
341 /* randomize key in this case */
342 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE,
343 key);
344 return GNUNET_SYSERR;
345 }
346 return GNUNET_OK;
347}
348
349
350/**
351 * Closure for #datacache_get_successors_iterator(). 265 * Closure for #datacache_get_successors_iterator().
352 */ 266 */
353struct SuccContext 267struct SuccContext
@@ -355,12 +269,13 @@ struct SuccContext
355 /** 269 /**
356 * Function to call on the result 270 * Function to call on the result
357 */ 271 */
358 GDS_DATACACHE_SuccessorCallback cb; 272 GDS_DATACACHE_GetCallback cb;
359 273
360 /** 274 /**
361 * Closure for @e cb. 275 * Closure for @e cb.
362 */ 276 */
363 void *cb_cls; 277 void *cb_cls;
278
364}; 279};
365 280
366 281
@@ -378,7 +293,7 @@ struct SuccContext
378 * @return #GNUNET_OK to continue iteration, anything else 293 * @return #GNUNET_OK to continue iteration, anything else
379 * to stop iteration. 294 * to stop iteration.
380 */ 295 */
381static int 296static enum GNUNET_GenericReturnValue
382datacache_get_successors_iterator (void *cls, 297datacache_get_successors_iterator (void *cls,
383 const struct GNUNET_HashCode *key, 298 const struct GNUNET_HashCode *key,
384 size_t size, 299 size_t size,
@@ -389,40 +304,36 @@ datacache_get_successors_iterator (void *cls,
389 const struct GNUNET_PeerIdentity *put_path) 304 const struct GNUNET_PeerIdentity *put_path)
390{ 305{
391 const struct SuccContext *sc = cls; 306 const struct SuccContext *sc = cls;
307 struct GDS_DATACACHE_BlockData bd = {
308 .key = *key,
309 .expiration_time = exp,
310 .put_path = put_path,
311 .data = data,
312 .data_size = size,
313 .put_path_length = put_path_length,
314 .type = type
315 };
392 316
393 /* NOTE: The datacache currently does not store the RO from 317 /* NOTE: The datacache currently does not store the RO from
394 the original 'put', so we don't know the 'correct' option 318 the original 'put', so we don't know the 'correct' option
395 at this point anymore. Thus, we conservatively assume 319 at this point anymore. Thus, we conservatively assume
396 that recording is desired (for now). */ 320 that recording is desired (for now). */
397 sc->cb (sc->cb_cls, 321 sc->cb (sc->cb_cls,
398 GNUNET_DHT_RO_RECORD_ROUTE, 322 &bd);
399 key,
400 type,
401 put_path_length, put_path,
402 exp,
403 data,
404 size);
405 return GNUNET_OK; 323 return GNUNET_OK;
406} 324}
407 325
408 326
409/**
410 * Handle a request for data close to a key that we have received from
411 * another peer.
412 *
413 * @param key the location at which the peer is looking for data that is close
414 * @param cb function to call with the result
415 * @param cb_cls closure for @a cb
416 */
417void 327void
418GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key, 328GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
419 GDS_DATACACHE_SuccessorCallback cb, 329 GDS_DATACACHE_GetCallback cb,
420 void *cb_cls) 330 void *cb_cls)
421{ 331{
422 struct SuccContext sc; 332 struct SuccContext sc = {
333 .cb = cb,
334 .cb_cls = cb_cls
335 };
423 336
424 sc.cb = cb;
425 sc.cb_cls = cb_cls;
426 (void) GNUNET_DATACACHE_get_closest (datacache, 337 (void) GNUNET_DATACACHE_get_closest (datacache,
427 key, 338 key,
428 NUM_CLOSEST, 339 NUM_CLOSEST,
@@ -431,19 +342,14 @@ GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key,
431} 342}
432 343
433 344
434/**
435 * Initialize datacache subsystem.
436 */
437void 345void
438GDS_DATACACHE_init () 346GDS_DATACACHE_init ()
439{ 347{
440 datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache"); 348 datacache = GNUNET_DATACACHE_create (GDS_cfg,
349 "dhtcache");
441} 350}
442 351
443 352
444/**
445 * Shutdown datacache subsystem.
446 */
447void 353void
448GDS_DATACACHE_done () 354GDS_DATACACHE_done ()
449{ 355{
diff --git a/src/dht/gnunet-service-dht_datacache.h b/src/dht/gnunet-service-dht_datacache.h
index 5be59c90e..249bb8ee3 100644
--- a/src/dht/gnunet-service-dht_datacache.h
+++ b/src/dht/gnunet-service-dht_datacache.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 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
@@ -31,53 +31,68 @@
31#include "gnunet_block_lib.h" 31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33 33
34
35/**
36 * Information about a block stored in the datacache.
37 */
38struct GDS_DATACACHE_BlockData
39{
40 /**
41 * Key of the block.
42 */
43 struct GNUNET_HashCode key;
44
45 /**
46 * When does the block expire?
47 */
48 struct GNUNET_TIME_Absolute expiration_time;
49
50 /**
51 * PUT path taken by the block, array of peer identities.
52 */
53 const struct GNUNET_PeerIdentity *put_path;
54
55 /**
56 * Actual block data.
57 */
58 const void *data;
59
60 /**
61 * Number of bytes in @a data.
62 */
63 size_t data_size;
64
65 /**
66 * Length of the @e put_path array.
67 */
68 unsigned int put_path_length;
69
70 /**
71 * Type of the block.
72 */
73 enum GNUNET_BLOCK_Type type;
74};
75
76
34/** 77/**
35 * Handle a datum we've received from another peer. Cache if 78 * Handle a datum we've received from another peer. Cache if
36 * possible. 79 * possible.
37 * 80 *
38 * @param expiration when will the reply expire 81 * @param bd block data to cache
39 * @param key the query this reply is for
40 * @param put_path_length number of peers in 'put_path'
41 * @param put_path path the reply took on put
42 * @param type type of the reply
43 * @param data_size number of bytes in 'data'
44 * @param data application payload data
45 */ 82 */
46void 83void
47GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, 84GDS_DATACACHE_handle_put (const struct GDS_DATACACHE_BlockData *bd);
48 const struct GNUNET_HashCode *key,
49 unsigned int put_path_length,
50 const struct GNUNET_PeerIdentity *put_path,
51 enum GNUNET_BLOCK_Type type,
52 size_t data_size,
53 const void *data);
54 85
55 86
56/** 87/**
57 * Handle a result for a GET operation. 88 * Handle a result for a GET operation.
58 * 89 *
59 * @param cls closure 90 * @param cls closure
60 * @param type type of the block 91 * @param bd block details
61 * @param expiration_time when does the content expire
62 * @param key key for the content
63 * @param put_path_length number of entries in @a put_path
64 * @param put_path peers the original PUT traversed (if tracked)
65 * @param get_path_length number of entries in @a get_path
66 * @param get_path peers this reply has traversed so far (if tracked)
67 * @param data payload of the reply
68 * @param data_size number of bytes in @a data
69 */ 92 */
70typedef void 93typedef void
71(*GDS_DATACACHE_GetCallback)(void *cls, 94(*GDS_DATACACHE_GetCallback)(void *cls,
72 enum GNUNET_BLOCK_Type type, 95 const struct GDS_DATACACHE_BlockData *bd);
73 struct GNUNET_TIME_Absolute expiration_time,
74 const struct GNUNET_HashCode *key,
75 unsigned int put_path_length,
76 const struct GNUNET_PeerIdentity *put_path,
77 unsigned int get_path_length,
78 const struct GNUNET_PeerIdentity *get_path,
79 const void *data,
80 size_t data_size);
81 96
82 97
83/** 98/**
@@ -103,43 +118,6 @@ GDS_DATACACHE_handle_get (const struct GNUNET_HashCode *key,
103 118
104 119
105/** 120/**
106 * Obtain a random key from the datacache.
107 * Used by Whanau for load-balancing.
108 *
109 * @param[out] key where to store the key of a random element,
110 * randomized by PRNG if datacache is empty
111 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the datacache is empty
112 */
113int
114GDS_DATACACHE_get_random_key (struct GNUNET_HashCode *key);
115
116
117/**
118 * Send the get result to requesting client.
119 *
120 * @param cls closure
121 * @param options routing options (from GET request)
122 * @param key key of the requested data.
123 * @param type block type
124 * @param put_path_length number of peers in @a put_path
125 * @param put_path path taken to put the data at its stored location.
126 * @param expiration when will this result expire?
127 * @param data payload to store
128 * @param data_size size of the @a data
129 */
130typedef void
131(*GDS_DATACACHE_SuccessorCallback)(void *cls,
132 enum GNUNET_DHT_RouteOption options,
133 const struct GNUNET_HashCode *key,
134 enum GNUNET_BLOCK_Type type,
135 unsigned int put_path_length,
136 const struct GNUNET_PeerIdentity *put_path,
137 struct GNUNET_TIME_Absolute expiration,
138 const void *data,
139 size_t data_size);
140
141
142/**
143 * Handle a request for data close to a key that we have received from 121 * Handle a request for data close to a key that we have received from
144 * another peer. 122 * another peer.
145 * 123 *
@@ -148,9 +126,9 @@ typedef void
148 * @param cb_cls closure for @a cb 126 * @param cb_cls closure for @a cb
149 */ 127 */
150void 128void
151GDS_DATACACHE_get_successors (const struct GNUNET_HashCode *key, 129GDS_DATACACHE_get_closest (const struct GNUNET_HashCode *key,
152 GDS_DATACACHE_SuccessorCallback cb, 130 GDS_DATACACHE_GetCallback cb,
153 void *cb_cls); 131 void *cb_cls);
154 132
155 133
156/** 134/**
diff --git a/src/dht/gnunet-service-dht_hello.c b/src/dht/gnunet-service-dht_hello.c
index 906391334..949456575 100644
--- a/src/dht/gnunet-service-dht_hello.c
+++ b/src/dht/gnunet-service-dht_hello.c
@@ -54,7 +54,8 @@ GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
54{ 54{
55 if (NULL == peer_to_hello) 55 if (NULL == peer_to_hello)
56 return NULL; 56 return NULL;
57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); 57 return GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
58 peer);
58} 59}
59 60
60 61
@@ -83,15 +84,20 @@ process_hello (void *cls,
83 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us) 84 if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
84 return; 85 return;
85 GNUNET_STATISTICS_update (GDS_stats, 86 GNUNET_STATISTICS_update (GDS_stats,
86 gettext_noop ("# HELLOs obtained from peerinfo"), 1, 87 "# HELLOs obtained from peerinfo",
88 1,
87 GNUNET_NO); 89 GNUNET_NO);
88 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); 90 hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello,
91 peer);
89 GNUNET_free (hm); 92 GNUNET_free (hm);
90 hm = GNUNET_malloc (GNUNET_HELLO_size (hello)); 93 hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
91 GNUNET_memcpy (hm, hello, GNUNET_HELLO_size (hello)); 94 GNUNET_memcpy (hm,
95 hello,
96 GNUNET_HELLO_size (hello));
92 GNUNET_assert (GNUNET_SYSERR != 97 GNUNET_assert (GNUNET_SYSERR !=
93 GNUNET_CONTAINER_multipeermap_put (peer_to_hello, 98 GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
94 peer, hm, 99 peer,
100 hm,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); 101 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
96} 102}
97 103
@@ -114,7 +120,7 @@ GDS_HELLO_init ()
114/** 120/**
115 * Free memory occopied by the HELLO. 121 * Free memory occopied by the HELLO.
116 */ 122 */
117static int 123static enum GNUNET_GenericReturnValue
118free_hello (void *cls, 124free_hello (void *cls,
119 const struct GNUNET_PeerIdentity *key, 125 const struct GNUNET_PeerIdentity *key,
120 void *hello) 126 void *hello)
diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c
index ae3f34dce..0fc42d2ef 100644
--- a/src/dht/gnunet-service-dht_neighbours.c
+++ b/src/dht/gnunet-service-dht_neighbours.c
@@ -1163,38 +1163,12 @@ get_target_peers (const struct GNUNET_HashCode *key,
1163} 1163}
1164 1164
1165 1165
1166/**
1167 * Perform a PUT operation. Forwards the given request to other
1168 * peers. Does not store the data locally. Does not give the
1169 * data to local clients. May do nothing if this is the only
1170 * peer in the network (or if we are the closest peer in the
1171 * network).
1172 *
1173 * @param type type of the block
1174 * @param options routing options
1175 * @param desired_replication_level desired replication count
1176 * @param expiration_time when does the content expire
1177 * @param hop_count how many hops has this message traversed so far
1178 * @param bf Bloom filter of peers this PUT has already traversed
1179 * @param key key for the content
1180 * @param put_path_length number of entries in @a put_path
1181 * @param put_path peers this request has traversed so far (if tracked)
1182 * @param data payload to store
1183 * @param data_size number of bytes in @a data
1184 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
1185 */
1186enum GNUNET_GenericReturnValue 1166enum GNUNET_GenericReturnValue
1187GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, 1167GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
1188 enum GNUNET_DHT_RouteOption options, 1168 enum GNUNET_DHT_RouteOption options,
1189 uint32_t desired_replication_level, 1169 uint32_t desired_replication_level,
1190 struct GNUNET_TIME_Absolute expiration_time,
1191 uint32_t hop_count, 1170 uint32_t hop_count,
1192 struct GNUNET_CONTAINER_BloomFilter *bf, 1171 struct GNUNET_CONTAINER_BloomFilter *bf)
1193 const struct GNUNET_HashCode *key,
1194 unsigned int put_path_length,
1195 struct GNUNET_PeerIdentity *put_path,
1196 const void *data,
1197 size_t data_size)
1198{ 1172{
1199 unsigned int target_count; 1173 unsigned int target_count;
1200 unsigned int i; 1174 unsigned int i;
@@ -1205,20 +1179,21 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1205 struct PeerPutMessage *ppm; 1179 struct PeerPutMessage *ppm;
1206 struct GNUNET_PeerIdentity *pp; 1180 struct GNUNET_PeerIdentity *pp;
1207 unsigned int skip_count; 1181 unsigned int skip_count;
1182 unsigned int put_path_length = bd->put_path_length;
1208 1183
1209 GNUNET_assert (NULL != bf); 1184 GNUNET_assert (NULL != bf);
1210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1211 "Adding myself (%s) to PUT bloomfilter for %s\n", 1186 "Adding myself (%s) to PUT bloomfilter for %s\n",
1212 GNUNET_i2s (&my_identity), 1187 GNUNET_i2s (&my_identity),
1213 GNUNET_h2s (key)); 1188 GNUNET_h2s (&bd->key));
1214 GNUNET_CONTAINER_bloomfilter_add (bf, 1189 GNUNET_CONTAINER_bloomfilter_add (bf,
1215 &my_identity_hash); 1190 &my_identity_hash);
1216 GNUNET_STATISTICS_update (GDS_stats, 1191 GNUNET_STATISTICS_update (GDS_stats,
1217 gettext_noop ("# PUT requests routed"), 1192 "# PUT requests routed",
1218 1, 1193 1,
1219 GNUNET_NO); 1194 GNUNET_NO);
1220 target_count 1195 target_count
1221 = get_target_peers (key, 1196 = get_target_peers (&bd->key,
1222 bf, 1197 bf,
1223 hop_count, 1198 hop_count,
1224 desired_replication_level, 1199 desired_replication_level,
@@ -1227,17 +1202,18 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1227 { 1202 {
1228 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1229 "Routing PUT for %s terminates after %u hops at %s\n", 1204 "Routing PUT for %s terminates after %u hops at %s\n",
1230 GNUNET_h2s (key), 1205 GNUNET_h2s (&bd->key),
1231 (unsigned int) hop_count, 1206 (unsigned int) hop_count,
1232 GNUNET_i2s (&my_identity)); 1207 GNUNET_i2s (&my_identity));
1233 return GNUNET_NO; 1208 return GNUNET_NO;
1234 } 1209 }
1235 msize = put_path_length * sizeof(struct GNUNET_PeerIdentity) + data_size; 1210 msize = bd->put_path_length * sizeof(struct GNUNET_PeerIdentity)
1211 + bd->data_size;
1236 if (msize + sizeof(struct PeerPutMessage) 1212 if (msize + sizeof(struct PeerPutMessage)
1237 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) 1213 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
1238 { 1214 {
1239 put_path_length = 0; 1215 put_path_length = 0;
1240 msize = data_size; 1216 msize = bd->data_size;
1241 } 1217 }
1242 if (msize + sizeof(struct PeerPutMessage) 1218 if (msize + sizeof(struct PeerPutMessage)
1243 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) 1219 >= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
@@ -1267,18 +1243,18 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1267 } 1243 }
1268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1269 "Routing PUT for %s after %u hops to %s\n", 1245 "Routing PUT for %s after %u hops to %s\n",
1270 GNUNET_h2s (key), 1246 GNUNET_h2s (&bd->key),
1271 (unsigned int) hop_count, 1247 (unsigned int) hop_count,
1272 GNUNET_i2s (target->id)); 1248 GNUNET_i2s (target->id));
1273 env = GNUNET_MQ_msg_extra (ppm, 1249 env = GNUNET_MQ_msg_extra (ppm,
1274 msize, 1250 msize,
1275 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); 1251 GNUNET_MESSAGE_TYPE_DHT_P2P_PUT);
1276 ppm->options = htonl (options); 1252 ppm->options = htonl (options);
1277 ppm->type = htonl (type); 1253 ppm->type = htonl (bd->type);
1278 ppm->hop_count = htonl (hop_count + 1); 1254 ppm->hop_count = htonl (hop_count + 1);
1279 ppm->desired_replication_level = htonl (desired_replication_level); 1255 ppm->desired_replication_level = htonl (desired_replication_level);
1280 ppm->put_path_length = htonl (put_path_length); 1256 ppm->put_path_length = htonl (put_path_length);
1281 ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); 1257 ppm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1282 GNUNET_break (GNUNET_YES == 1258 GNUNET_break (GNUNET_YES ==
1283 GNUNET_CONTAINER_bloomfilter_test (bf, 1259 GNUNET_CONTAINER_bloomfilter_test (bf,
1284 &target->phash)); 1260 &target->phash));
@@ -1286,14 +1262,14 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1286 GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, 1262 GNUNET_CONTAINER_bloomfilter_get_raw_data (bf,
1287 ppm->bloomfilter, 1263 ppm->bloomfilter,
1288 DHT_BLOOM_SIZE)); 1264 DHT_BLOOM_SIZE));
1289 ppm->key = *key; 1265 ppm->key = bd->key;
1290 pp = (struct GNUNET_PeerIdentity *) &ppm[1]; 1266 pp = (struct GNUNET_PeerIdentity *) &ppm[1];
1291 GNUNET_memcpy (pp, 1267 GNUNET_memcpy (pp,
1292 put_path, 1268 bd->put_path,
1293 sizeof(struct GNUNET_PeerIdentity) * put_path_length); 1269 sizeof(struct GNUNET_PeerIdentity) * put_path_length);
1294 GNUNET_memcpy (&pp[put_path_length], 1270 GNUNET_memcpy (&pp[put_path_length],
1295 data, 1271 bd->data,
1296 data_size); 1272 bd->data_size);
1297 GNUNET_MQ_send (target->mq, 1273 GNUNET_MQ_send (target->mq,
1298 env); 1274 env);
1299 } 1275 }
@@ -1302,23 +1278,6 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
1302} 1278}
1303 1279
1304 1280
1305/**
1306 * Perform a GET operation. Forwards the given request to other
1307 * peers. Does not lookup the key locally. May do nothing if this is
1308 * the only peer in the network (or if we are the closest peer in the
1309 * network).
1310 *
1311 * @param type type of the block
1312 * @param options routing options
1313 * @param desired_replication_level desired replication count
1314 * @param hop_count how many hops did this request traverse so far?
1315 * @param key key for the content
1316 * @param xquery extended query
1317 * @param xquery_size number of bytes in @a xquery
1318 * @param bg group to use for filtering replies
1319 * @param peer_bf filter for peers not to select (again)
1320 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
1321 */
1322enum GNUNET_GenericReturnValue 1281enum GNUNET_GenericReturnValue
1323GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 1282GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1324 enum GNUNET_DHT_RouteOption options, 1283 enum GNUNET_DHT_RouteOption options,
@@ -1444,48 +1403,27 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
1444} 1403}
1445 1404
1446 1405
1447/**
1448 * Handle a reply (route to origin). Only forwards the reply back to
1449 * the given peer. Does not do local caching or forwarding to local
1450 * clients.
1451 *
1452 * @param target neighbour that should receive the block (if still connected)
1453 * @param type type of the block
1454 * @param expiration_time when does the content expire
1455 * @param key key for the content
1456 * @param put_path_length number of entries in @a put_path
1457 * @param put_path peers the original PUT traversed (if tracked)
1458 * @param get_path_length number of entries in @a get_path
1459 * @param get_path peers this reply has traversed so far (if tracked)
1460 * @param data payload of the reply
1461 * @param data_size number of bytes in @a data
1462 */
1463void 1406void
1464GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, 1407GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
1465 enum GNUNET_BLOCK_Type type, 1408 const struct GDS_DATACACHE_BlockData *bd,
1466 struct GNUNET_TIME_Absolute expiration_time, 1409 const struct GNUNET_HashCode *query_hash,
1467 const struct GNUNET_HashCode *key,
1468 unsigned int put_path_length,
1469 const struct GNUNET_PeerIdentity *put_path,
1470 unsigned int get_path_length, 1410 unsigned int get_path_length,
1471 const struct GNUNET_PeerIdentity *get_path, 1411 const struct GNUNET_PeerIdentity *get_path)
1472 const void *data,
1473 size_t data_size)
1474{ 1412{
1475 struct PeerInfo *pi; 1413 struct PeerInfo *pi;
1476 struct GNUNET_MQ_Envelope *env; 1414 struct GNUNET_MQ_Envelope *env;
1477 size_t msize;
1478 struct PeerResultMessage *prm; 1415 struct PeerResultMessage *prm;
1479 struct GNUNET_PeerIdentity *paths; 1416 struct GNUNET_PeerIdentity *paths;
1417 size_t msize;
1480 1418
1481 msize = data_size + (get_path_length + put_path_length) 1419 msize = bd->data_size + (get_path_length + bd->put_path_length)
1482 * sizeof(struct GNUNET_PeerIdentity); 1420 * sizeof(struct GNUNET_PeerIdentity);
1483 if ((msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) || 1421 if ( (msize + sizeof(struct PeerResultMessage) >= GNUNET_MAX_MESSAGE_SIZE) ||
1484 (get_path_length > 1422 (get_path_length >
1485 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) || 1423 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1486 (put_path_length > 1424 (bd->put_path_length >
1487 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) || 1425 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
1488 (data_size > GNUNET_MAX_MESSAGE_SIZE)) 1426 (bd->data_size > GNUNET_MAX_MESSAGE_SIZE))
1489 { 1427 {
1490 GNUNET_break (0); 1428 GNUNET_break (0);
1491 return; 1429 return;
@@ -1497,49 +1435,48 @@ GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
1497 /* peer disconnected in the meantime, drop reply */ 1435 /* peer disconnected in the meantime, drop reply */
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1499 "No matching peer for reply for key %s\n", 1437 "No matching peer for reply for key %s\n",
1500 GNUNET_h2s (key)); 1438 GNUNET_h2s (query_hash));
1501 return; 1439 return;
1502 } 1440 }
1503 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER) 1441 if (GNUNET_MQ_get_length (pi->mq) >= MAXIMUM_PENDING_PER_PEER)
1504 { 1442 {
1505 /* skip */ 1443 /* skip */
1506 GNUNET_STATISTICS_update (GDS_stats, 1444 GNUNET_STATISTICS_update (GDS_stats,
1507 gettext_noop ( 1445 "# P2P messages dropped due to full queue",
1508 "# P2P messages dropped due to full queue"),
1509 1, 1446 1,
1510 GNUNET_NO); 1447 GNUNET_NO);
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Peer queue full, ignoring reply for key %s\n", 1449 "Peer queue full, ignoring reply for key %s\n",
1513 GNUNET_h2s (key)); 1450 GNUNET_h2s (&bd->key));
1514 return; 1451 return;
1515 } 1452 }
1516 1453
1517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1518 "Forwarding reply for key %s to peer %s\n", 1455 "Forwarding reply for key %s to peer %s\n",
1519 GNUNET_h2s (key), 1456 GNUNET_h2s (query_hash),
1520 GNUNET_i2s (target)); 1457 GNUNET_i2s (target));
1521 GNUNET_STATISTICS_update (GDS_stats, 1458 GNUNET_STATISTICS_update (GDS_stats,
1522 gettext_noop 1459 "# RESULT messages queued for transmission",
1523 ("# RESULT messages queued for transmission"), 1, 1460 1,
1524 GNUNET_NO); 1461 GNUNET_NO);
1525 env = GNUNET_MQ_msg_extra (prm, 1462 env = GNUNET_MQ_msg_extra (prm,
1526 msize, 1463 msize,
1527 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); 1464 GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT);
1528 prm->type = htonl (type); 1465 prm->type = htonl (bd->type);
1529 prm->put_path_length = htonl (put_path_length); 1466 prm->put_path_length = htonl (bd->put_path_length);
1530 prm->get_path_length = htonl (get_path_length); 1467 prm->get_path_length = htonl (get_path_length);
1531 prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); 1468 prm->expiration_time = GNUNET_TIME_absolute_hton (bd->expiration_time);
1532 prm->key = *key; 1469 prm->key = *query_hash;
1533 paths = (struct GNUNET_PeerIdentity *) &prm[1]; 1470 paths = (struct GNUNET_PeerIdentity *) &prm[1];
1534 GNUNET_memcpy (paths, 1471 GNUNET_memcpy (paths,
1535 put_path, 1472 bd->put_path,
1536 put_path_length * sizeof(struct GNUNET_PeerIdentity)); 1473 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
1537 GNUNET_memcpy (&paths[put_path_length], 1474 GNUNET_memcpy (&paths[bd->put_path_length],
1538 get_path, 1475 get_path,
1539 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 1476 get_path_length * sizeof(struct GNUNET_PeerIdentity));
1540 GNUNET_memcpy (&paths[put_path_length + get_path_length], 1477 GNUNET_memcpy (&paths[bd->put_path_length + get_path_length],
1541 data, 1478 bd->data,
1542 data_size); 1479 bd->data_size);
1543 GNUNET_MQ_send (pi->mq, 1480 GNUNET_MQ_send (pi->mq,
1544 env); 1481 env);
1545} 1482}
@@ -1608,18 +1545,27 @@ handle_dht_p2p_put (void *cls,
1608 const struct PeerPutMessage *put) 1545 const struct PeerPutMessage *put)
1609{ 1546{
1610 struct PeerInfo *peer = cls; 1547 struct PeerInfo *peer = cls;
1611 const struct GNUNET_PeerIdentity *put_path; 1548 uint16_t msize = ntohs (put->header.size);
1612 const void *payload; 1549 enum GNUNET_DHT_RouteOption options
1613 uint32_t putlen; 1550 = (enum GNUNET_DHT_RouteOption) ntohl (put->options);
1614 uint16_t msize; 1551 struct GDS_DATACACHE_BlockData bd = {
1615 size_t payload_size; 1552 .key = put->key,
1616 enum GNUNET_DHT_RouteOption options; 1553 .expiration_time = GNUNET_TIME_absolute_ntoh (put->expiration_time),
1617 struct GNUNET_CONTAINER_BloomFilter *bf; 1554 .type = ntohl (put->type)
1618 int forwarded; 1555 };
1619 struct GNUNET_TIME_Absolute exp_time; 1556 const struct GNUNET_PeerIdentity *put_path
1557 = (const struct GNUNET_PeerIdentity *) &put[1];
1558 uint32_t putlen
1559 = ntohl (put->put_path_length);
1620 1560
1621 exp_time = GNUNET_TIME_absolute_ntoh (put->expiration_time); 1561 bd.data_size = msize - (sizeof(*put)
1622 if (GNUNET_TIME_absolute_is_past (exp_time)) 1562 + putlen * sizeof(struct GNUNET_PeerIdentity));
1563 bd.data = &put_path[putlen];
1564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1565 "PUT for `%s' from %s\n",
1566 GNUNET_h2s (&put->key),
1567 GNUNET_i2s (peer->id));
1568 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
1623 { 1569 {
1624 GNUNET_STATISTICS_update (GDS_stats, 1570 GNUNET_STATISTICS_update (GDS_stats,
1625 gettext_noop ("# Expired PUTs discarded"), 1571 gettext_noop ("# Expired PUTs discarded"),
@@ -1627,26 +1573,14 @@ handle_dht_p2p_put (void *cls,
1627 GNUNET_NO); 1573 GNUNET_NO);
1628 return; 1574 return;
1629 } 1575 }
1630 msize = ntohs (put->header.size);
1631 putlen = ntohl (put->put_path_length);
1632 GNUNET_STATISTICS_update (GDS_stats, 1576 GNUNET_STATISTICS_update (GDS_stats,
1633 gettext_noop ("# P2P PUT requests received"), 1577 "# P2P PUT requests received",
1634 1, 1578 1,
1635 GNUNET_NO); 1579 GNUNET_NO);
1636 GNUNET_STATISTICS_update (GDS_stats, 1580 GNUNET_STATISTICS_update (GDS_stats,
1637 gettext_noop ("# P2P PUT bytes received"), 1581 "# P2P PUT bytes received",
1638 msize, 1582 msize,
1639 GNUNET_NO); 1583 GNUNET_NO);
1640 put_path = (const struct GNUNET_PeerIdentity *) &put[1];
1641 payload = &put_path[putlen];
1642 options = ntohl (put->options);
1643 payload_size = msize - (sizeof(struct PeerPutMessage)
1644 + putlen * sizeof(struct GNUNET_PeerIdentity));
1645
1646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1647 "PUT for `%s' from %s\n",
1648 GNUNET_h2s (&put->key),
1649 GNUNET_i2s (peer->id));
1650 if (GNUNET_YES == log_route_details_stderr) 1584 if (GNUNET_YES == log_route_details_stderr)
1651 { 1585 {
1652 char *tmp; 1586 char *tmp;
@@ -1681,15 +1615,15 @@ handle_dht_p2p_put (void *cls,
1681 enum GNUNET_GenericReturnValue ret; 1615 enum GNUNET_GenericReturnValue ret;
1682 1616
1683 ret = GNUNET_BLOCK_get_key (GDS_block_context, 1617 ret = GNUNET_BLOCK_get_key (GDS_block_context,
1684 ntohl (put->type), 1618 bd.type,
1685 payload, 1619 bd.data,
1686 payload_size, 1620 bd.data_size,
1687 &test_key); 1621 &test_key);
1688 switch (ret) 1622 switch (ret)
1689 { 1623 {
1690 case GNUNET_YES: 1624 case GNUNET_YES:
1691 if (0 != GNUNET_memcmp (&test_key, 1625 if (0 != GNUNET_memcmp (&test_key,
1692 &put->key)) 1626 &bd.key))
1693 { 1627 {
1694 GNUNET_break_op (0); 1628 GNUNET_break_op (0);
1695 return; 1629 return;
@@ -1706,25 +1640,28 @@ handle_dht_p2p_put (void *cls,
1706 1640
1707 if (GNUNET_NO == 1641 if (GNUNET_NO ==
1708 GNUNET_BLOCK_check_block (GDS_block_context, 1642 GNUNET_BLOCK_check_block (GDS_block_context,
1709 ntohl (put->type), 1643 bd.type,
1710 &put->key, 1644 &bd.key,
1711 payload, 1645 bd.data,
1712 payload_size)) 1646 bd.data_size))
1713 { 1647 {
1714 GNUNET_break_op (0); 1648 GNUNET_break_op (0);
1715 return; 1649 return;
1716 } 1650 }
1717 1651
1718 bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
1719 DHT_BLOOM_SIZE,
1720 GNUNET_CONSTANTS_BLOOMFILTER_K);
1721 GNUNET_break_op (GNUNET_YES ==
1722 GNUNET_CONTAINER_bloomfilter_test (bf,
1723 &peer->phash));
1724 { 1652 {
1653 struct GNUNET_CONTAINER_BloomFilter *bf;
1725 struct GNUNET_PeerIdentity pp[putlen + 1]; 1654 struct GNUNET_PeerIdentity pp[putlen + 1];
1726 1655
1656 bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter,
1657 DHT_BLOOM_SIZE,
1658 GNUNET_CONSTANTS_BLOOMFILTER_K);
1659 GNUNET_break_op (GNUNET_YES ==
1660 GNUNET_CONTAINER_bloomfilter_test (bf,
1661 &peer->phash));
1727 /* extend 'put path' by sender */ 1662 /* extend 'put path' by sender */
1663 bd.put_path = (const struct GNUNET_PeerIdentity *) pp;
1664 bd.put_path_length = putlen + 1;
1728 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) 1665 if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE))
1729 { 1666 {
1730#if SANITY_CHECKS 1667#if SANITY_CHECKS
@@ -1732,13 +1669,13 @@ handle_dht_p2p_put (void *cls,
1732 { 1669 {
1733 for (unsigned int j = 0; j < i; j++) 1670 for (unsigned int j = 0; j < i; j++)
1734 { 1671 {
1735 GNUNET_break (0 != memcmp (&pp[i], 1672 GNUNET_break (0 !=
1736 &pp[j], 1673 GNUNET_memcmp (&pp[i],
1737 sizeof(struct GNUNET_PeerIdentity))); 1674 &pp[j]));
1738 } 1675 }
1739 GNUNET_break (0 != memcmp (&pp[i], 1676 GNUNET_break (0 !=
1740 peer->id, 1677 GNUNET_memcmp (&pp[i],
1741 sizeof(struct GNUNET_PeerIdentity))); 1678 peer->id));
1742 } 1679 }
1743#endif 1680#endif
1744 GNUNET_memcpy (pp, 1681 GNUNET_memcpy (pp,
@@ -1748,57 +1685,41 @@ handle_dht_p2p_put (void *cls,
1748 putlen++; 1685 putlen++;
1749 } 1686 }
1750 else 1687 else
1751 putlen = 0; 1688 {
1689 bd.put_path_length = 0;
1690 }
1752 1691
1753 /* give to local clients */ 1692 /* give to local clients */
1754 GDS_CLIENTS_handle_reply (exp_time, 1693 GDS_CLIENTS_handle_reply (&bd,
1755 &put->key, 1694 &bd.key,
1756 &put->key, 1695 0, NULL /* get path */);
1757 0, 1696
1758 NULL,
1759 putlen,
1760 pp,
1761 ntohl (put->type),
1762 payload_size,
1763 payload);
1764 /* store locally */ 1697 /* store locally */
1765 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || 1698 if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
1766 (GDS_am_closest_peer (&put->key, bf))) 1699 (GDS_am_closest_peer (&put->key,
1767 GDS_DATACACHE_handle_put (exp_time, 1700 bf)))
1768 &put->key, 1701 GDS_DATACACHE_handle_put (&bd);
1769 putlen, 1702 {
1770 pp, 1703 enum GNUNET_GenericReturnValue forwarded;
1771 ntohl (put->type), 1704
1772 payload_size, 1705 /* route to other peers */
1773 payload); 1706 forwarded
1774 /* route to other peers */ 1707 = GDS_NEIGHBOURS_handle_put (&bd,
1775 forwarded = GDS_NEIGHBOURS_handle_put (ntohl (put->type), 1708 options,
1776 options, 1709 ntohl (put->desired_replication_level),
1777 ntohl ( 1710 ntohl (put->hop_count),
1778 put->desired_replication_level), 1711 bf);
1779 exp_time, 1712 /* notify monitoring clients */
1780 ntohl (put->hop_count), 1713 GDS_CLIENTS_process_put (options
1781 bf, 1714 | ((GNUNET_OK == forwarded)
1782 &put->key,
1783 putlen,
1784 pp,
1785 payload,
1786 payload_size);
1787 /* notify monitoring clients */
1788 GDS_CLIENTS_process_put (options
1789 | ((GNUNET_OK == forwarded)
1790 ? GNUNET_DHT_RO_LAST_HOP 1715 ? GNUNET_DHT_RO_LAST_HOP
1791 : 0), 1716 : 0),
1792 ntohl (put->type), 1717 &bd,
1793 ntohl (put->hop_count), 1718 ntohl (put->hop_count),
1794 ntohl (put->desired_replication_level), 1719 ntohl (put->desired_replication_level));
1795 putlen, pp, 1720 }
1796 exp_time, 1721 GNUNET_CONTAINER_bloomfilter_free (bf);
1797 &put->key,
1798 payload,
1799 payload_size);
1800 } 1722 }
1801 GNUNET_CONTAINER_bloomfilter_free (bf);
1802} 1723}
1803 1724
1804 1725
@@ -1812,42 +1733,40 @@ handle_dht_p2p_put (void *cls,
1812 */ 1733 */
1813static void 1734static void
1814handle_find_peer (const struct GNUNET_PeerIdentity *sender, 1735handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1815 const struct GNUNET_HashCode *key, 1736 const struct GNUNET_HashCode *query_hash,
1816 struct GNUNET_BLOCK_Group *bg) 1737 struct GNUNET_BLOCK_Group *bg)
1817{ 1738{
1818 int bucket_idx; 1739 int bucket_idx;
1819 struct PeerBucket *bucket; 1740 struct PeerBucket *bucket;
1820 struct PeerInfo *peer; 1741 struct PeerInfo *peer;
1821 unsigned int choice; 1742 unsigned int choice;
1822 const struct GNUNET_HELLO_Message *hello; 1743 struct GDS_DATACACHE_BlockData bd = {
1823 size_t hello_size; 1744 .type = GNUNET_BLOCK_TYPE_DHT_HELLO
1745 };
1824 1746
1825 /* first, check about our own HELLO */ 1747 /* first, check about our own HELLO */
1826 if (NULL != GDS_my_hello) 1748 if (NULL != GDS_my_hello)
1827 { 1749 {
1828 hello_size = GNUNET_HELLO_size ( 1750 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1751 hello_expiration),
1752 bd.key = my_identity_hash,
1753 bd.data = GDS_my_hello;
1754 bd.data_size = GNUNET_HELLO_size (
1829 (const struct GNUNET_HELLO_Message *) GDS_my_hello); 1755 (const struct GNUNET_HELLO_Message *) GDS_my_hello);
1830 GNUNET_break (hello_size >= sizeof(struct GNUNET_MessageHeader)); 1756 GNUNET_break (bd.data_size >= sizeof(struct GNUNET_MessageHeader));
1831 if (GNUNET_BLOCK_REPLY_OK_MORE == 1757 if (GNUNET_BLOCK_REPLY_OK_MORE ==
1832 GNUNET_BLOCK_check_reply (GDS_block_context, 1758 GNUNET_BLOCK_check_reply (GDS_block_context,
1833 GNUNET_BLOCK_TYPE_DHT_HELLO, 1759 GNUNET_BLOCK_TYPE_DHT_HELLO,
1834 bg, 1760 bg,
1835 &my_identity_hash, 1761 &my_identity_hash,
1836 NULL, 0, 1762 NULL, 0,
1837 GDS_my_hello, 1763 bd.data,
1838 hello_size)) 1764 bd.data_size))
1839 { 1765 {
1840 GDS_NEIGHBOURS_handle_reply (sender, 1766 GDS_NEIGHBOURS_handle_reply (sender,
1841 GNUNET_BLOCK_TYPE_DHT_HELLO, 1767 &bd,
1842 GNUNET_TIME_relative_to_absolute ( 1768 query_hash,
1843 hello_expiration), 1769 0, NULL /* get path */);
1844 key,
1845 0,
1846 NULL,
1847 0,
1848 NULL,
1849 GDS_my_hello,
1850 hello_size);
1851 } 1770 }
1852 else 1771 else
1853 { 1772 {
@@ -1869,11 +1788,11 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1869 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */ 1788 /* FIXME: How can this be true? Shouldnt we just do find_bucket() ? */
1870 if (0 == 1789 if (0 ==
1871 GNUNET_memcmp (&my_identity_hash, 1790 GNUNET_memcmp (&my_identity_hash,
1872 key)) 1791 query_hash))
1873 bucket_idx = closest_bucket; 1792 bucket_idx = closest_bucket;
1874 else 1793 else
1875 bucket_idx = GNUNET_MIN ((int) closest_bucket, 1794 bucket_idx = GNUNET_MIN ((int) closest_bucket,
1876 find_bucket (key)); 1795 find_bucket (query_hash));
1877 if (bucket_idx < 0) 1796 if (bucket_idx < 0)
1878 return; 1797 return;
1879 bucket = &k_buckets[bucket_idx]; 1798 bucket = &k_buckets[bucket_idx];
@@ -1889,84 +1808,69 @@ handle_find_peer (const struct GNUNET_PeerIdentity *sender,
1889 choice--; 1808 choice--;
1890 } 1809 }
1891 choice = bucket->peers_size; 1810 choice = bucket->peers_size;
1892 do 1811
1893 { 1812 {
1894 peer = peer->next; 1813 const struct GNUNET_HELLO_Message *hello;
1895 if (0 == choice--) 1814 size_t hello_size;
1896 return; /* no non-masked peer available */ 1815
1897 if (NULL == peer) 1816 do
1898 peer = bucket->head; 1817 {
1899 hello = GDS_HELLO_get (peer->id); 1818 peer = peer->next;
1819 if (0 == choice--)
1820 return; /* no non-masked peer available */
1821 if (NULL == peer)
1822 peer = bucket->head;
1823 hello = GDS_HELLO_get (peer->id);
1824 } while ( (NULL == hello) ||
1825 (GNUNET_BLOCK_REPLY_OK_MORE !=
1826 GNUNET_BLOCK_check_reply (
1827 GDS_block_context,
1828 GNUNET_BLOCK_TYPE_DHT_HELLO,
1829 bg,
1830 &peer->phash,
1831 NULL, 0, /* xquery */
1832 hello,
1833 (hello_size = GNUNET_HELLO_size (hello)))));
1834 bd.expiration_time = GNUNET_TIME_relative_to_absolute (
1835 GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
1836 bd.key = peer->phash;
1837 bd.data = hello;
1838 bd.data_size = hello_size;
1839 GDS_NEIGHBOURS_handle_reply (sender,
1840 &bd,
1841 query_hash,
1842 0, NULL /* get path */);
1900 } 1843 }
1901 /* FIXME: this logic is strange. extra ';', maybe, but then why a while-loop at all? */
1902 while ((NULL == hello) ||
1903 (GNUNET_BLOCK_REPLY_OK_MORE !=
1904 GNUNET_BLOCK_check_reply (GDS_block_context,
1905 GNUNET_BLOCK_TYPE_DHT_HELLO,
1906 bg,
1907 &peer->phash,
1908 NULL, 0,
1909 hello,
1910 (hello_size = GNUNET_HELLO_size (hello)))));
1911 GDS_NEIGHBOURS_handle_reply (sender,
1912 GNUNET_BLOCK_TYPE_DHT_HELLO,
1913 GNUNET_TIME_relative_to_absolute
1914 (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION),
1915 key,
1916 0,
1917 NULL,
1918 0,
1919 NULL,
1920 hello,
1921 hello_size);
1922} 1844}
1923 1845
1924 1846
1925/** 1847/**
1926 * Handle a result from local datacache for a GET operation. 1848 * Handle an exact result from local datacache for a GET operation.
1927 * 1849 *
1928 * @param cls the `struct PeerInfo` for which this is a reply 1850 * @param cls the `struct PeerInfo` for which this is a reply
1929 * @param type type of the block 1851 * @param bd details about the block we found locally
1930 * @param expiration_time when does the content expire
1931 * @param key key for the content
1932 * @param put_path_length number of entries in @a put_path
1933 * @param put_path peers the original PUT traversed (if tracked)
1934 * @param get_path_length number of entries in @a get_path
1935 * @param get_path peers this reply has traversed so far (if tracked)
1936 * @param data payload of the reply
1937 * @param data_size number of bytes in @a data
1938 */ 1852 */
1939static void 1853static void
1940handle_local_result (void *cls, 1854handle_local_result (void *cls,
1941 enum GNUNET_BLOCK_Type type, 1855 const struct GDS_DATACACHE_BlockData *bd)
1942 struct GNUNET_TIME_Absolute expiration_time,
1943 const struct GNUNET_HashCode *key,
1944 unsigned int put_path_length,
1945 const struct GNUNET_PeerIdentity *put_path,
1946 unsigned int get_path_length,
1947 const struct GNUNET_PeerIdentity *get_path,
1948 const void *data,
1949 size_t data_size)
1950{ 1856{
1951 struct PeerInfo *peer = cls; 1857 struct PeerInfo *peer = cls;
1858
1952 { 1859 {
1953 char *pp; 1860 char *pp;
1954 1861
1955 pp = GNUNET_STRINGS_pp2s (put_path, 1862 pp = GNUNET_STRINGS_pp2s (bd->put_path,
1956 put_path_length); 1863 bd->put_path_length);
1957 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1958 "Found local result for %s (PP: %s)\n", 1865 "Found local result for %s (PP: %s)\n",
1959 GNUNET_h2s (key), 1866 GNUNET_h2s (&bd->key),
1960 pp); 1867 pp);
1961 GNUNET_free (pp); 1868 GNUNET_free (pp);
1962 } 1869 }
1963 GDS_NEIGHBOURS_handle_reply (peer->id, 1870 GDS_NEIGHBOURS_handle_reply (peer->id,
1964 type, 1871 bd,
1965 expiration_time, 1872 &bd->key,
1966 key, 1873 0, NULL /* get path */);
1967 put_path_length, put_path,
1968 get_path_length, get_path,
1969 data, data_size);
1970} 1874}
1971 1875
1972 1876
@@ -2160,115 +2064,80 @@ handle_dht_p2p_get (void *cls,
2160 2064
2161 2065
2162/** 2066/**
2163 * Check validity of p2p result message.
2164 *
2165 * @param cls closure
2166 * @param message message
2167 * @return #GNUNET_YES if the message is well-formed
2168 */
2169static enum GNUNET_GenericReturnValue
2170check_dht_p2p_result (void *cls,
2171 const struct PeerResultMessage *prm)
2172{
2173 uint32_t get_path_length;
2174 uint32_t put_path_length;
2175 uint16_t msize;
2176
2177 (void) cls;
2178 msize = ntohs (prm->header.size);
2179 put_path_length = ntohl (prm->put_path_length);
2180 get_path_length = ntohl (prm->get_path_length);
2181 if ((msize <
2182 sizeof(struct PeerResultMessage) + (get_path_length
2183 + put_path_length)
2184 * sizeof(struct GNUNET_PeerIdentity)) ||
2185 (get_path_length >
2186 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2187 (put_path_length >
2188 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)))
2189 {
2190 GNUNET_break_op (0);
2191 return GNUNET_SYSERR;
2192 }
2193 return GNUNET_OK;
2194}
2195
2196
2197/**
2198 * Process a reply, after the @a get_path has been updated. 2067 * Process a reply, after the @a get_path has been updated.
2199 * 2068 *
2200 * @param expiration_time when does the reply expire 2069 * @param bd block details
2201 * @param key key of the original inquiry 2070 * @param query_hash hash of the original query, might not match key in @a bd
2202 * @param query_hash key matching the block
2203 * @param get_path_length number of entries in @a get_path 2071 * @param get_path_length number of entries in @a get_path
2204 * @param get_path path the reply has taken 2072 * @param get_path path the reply has taken
2205 * @param put_path_length number of entries in @a put_path
2206 * @param put_path path the PUT has taken
2207 * @param type type of the block
2208 * @param data_size number of bytes in @a data
2209 * @param data payload of the reply
2210 */ 2073 */
2211static void 2074static void
2212process_reply_with_path (struct GNUNET_TIME_Absolute expiration_time, 2075process_reply_with_path (const struct GDS_DATACACHE_BlockData *bd,
2213 const struct GNUNET_HashCode *key,
2214 const struct GNUNET_HashCode *query_hash, 2076 const struct GNUNET_HashCode *query_hash,
2215 unsigned int get_path_length, 2077 unsigned int get_path_length,
2216 const struct GNUNET_PeerIdentity *get_path, 2078 const struct GNUNET_PeerIdentity *get_path)
2217 unsigned int put_path_length,
2218 const struct GNUNET_PeerIdentity *put_path,
2219 enum GNUNET_BLOCK_Type type,
2220 size_t data_size,
2221 const void *data)
2222{ 2079{
2223 /* forward to local clients */ 2080 /* forward to local clients */
2224 GDS_CLIENTS_handle_reply (expiration_time, 2081 GDS_CLIENTS_handle_reply (bd,
2225 key,
2226 query_hash, 2082 query_hash,
2227 get_path_length, 2083 get_path_length,
2228 get_path, 2084 get_path);
2229 put_path_length, 2085 GDS_CLIENTS_process_get_resp (bd,
2230 put_path,
2231 type,
2232 data_size,
2233 data);
2234 GDS_CLIENTS_process_get_resp (type,
2235 get_path, 2086 get_path,
2236 get_path_length, 2087 get_path_length);
2237 put_path,
2238 put_path_length,
2239 expiration_time,
2240 query_hash,
2241 data,
2242 data_size);
2243 if (GNUNET_YES == cache_results) 2088 if (GNUNET_YES == cache_results)
2244 { 2089 {
2245 struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length]; 2090 struct GNUNET_PeerIdentity xput_path[GNUNET_NZL (get_path_length
2091 + bd->put_path_length)];
2092 struct GDS_DATACACHE_BlockData bdx = *bd;
2246 2093
2247 GNUNET_memcpy (xput_path, 2094 GNUNET_memcpy (xput_path,
2248 put_path, 2095 bd->put_path,
2249 put_path_length * sizeof(struct GNUNET_PeerIdentity)); 2096 bd->put_path_length * sizeof(struct GNUNET_PeerIdentity));
2250 GNUNET_memcpy (&xput_path[put_path_length], 2097 GNUNET_memcpy (&xput_path[bd->put_path_length],
2251 get_path, 2098 get_path,
2252 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 2099 get_path_length * sizeof(struct GNUNET_PeerIdentity));
2253 2100 bdx.put_path = xput_path;
2254 GDS_DATACACHE_handle_put (expiration_time, 2101 bdx.put_path_length += get_path_length;
2255 query_hash, 2102 GDS_DATACACHE_handle_put (&bdx);
2256 get_path_length + put_path_length,
2257 xput_path,
2258 type,
2259 data_size,
2260 data);
2261 } 2103 }
2262 /* forward to other peers */ 2104 /* forward to other peers */
2263 GDS_ROUTING_process (type, 2105 GDS_ROUTING_process (bd,
2264 expiration_time, 2106 query_hash,
2265 key,
2266 put_path_length,
2267 put_path,
2268 get_path_length, 2107 get_path_length,
2269 get_path, 2108 get_path);
2270 data, 2109}
2271 data_size); 2110
2111
2112/**
2113 * Check validity of p2p result message.
2114 *
2115 * @param cls closure
2116 * @param message message
2117 * @return #GNUNET_YES if the message is well-formed
2118 */
2119static enum GNUNET_GenericReturnValue
2120check_dht_p2p_result (void *cls,
2121 const struct PeerResultMessage *prm)
2122{
2123 uint32_t get_path_length = ntohl (prm->get_path_length);
2124 uint32_t put_path_length = ntohl (prm->put_path_length);
2125 uint16_t msize = ntohs (prm->header.size);
2126
2127 (void) cls;
2128 if ( (msize <
2129 sizeof(struct PeerResultMessage)
2130 + (get_path_length + put_path_length)
2131 * sizeof(struct GNUNET_PeerIdentity)) ||
2132 (get_path_length >
2133 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) ||
2134 (put_path_length >
2135 GNUNET_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_PeerIdentity)) )
2136 {
2137 GNUNET_break_op (0);
2138 return GNUNET_SYSERR;
2139 }
2140 return GNUNET_OK;
2272} 2141}
2273 2142
2274 2143
@@ -2283,72 +2152,66 @@ handle_dht_p2p_result (void *cls,
2283 const struct PeerResultMessage *prm) 2152 const struct PeerResultMessage *prm)
2284{ 2153{
2285 struct PeerInfo *peer = cls; 2154 struct PeerInfo *peer = cls;
2286 const struct GNUNET_PeerIdentity *put_path; 2155 uint16_t msize = ntohs (prm->header.size);
2287 const struct GNUNET_PeerIdentity *get_path; 2156 uint32_t get_path_length = ntohl (prm->get_path_length);
2288 const void *data; 2157 struct GDS_DATACACHE_BlockData bd = {
2289 uint32_t get_path_length; 2158 .expiration_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time),
2290 uint32_t put_path_length; 2159 .put_path = (const struct GNUNET_PeerIdentity *) &prm[1],
2291 uint16_t msize; 2160 .put_path_length = ntohl (prm->put_path_length),
2292 size_t data_size; 2161 .type = ntohl (prm->type)
2293 enum GNUNET_BLOCK_Type type; 2162 };
2294 struct GNUNET_TIME_Absolute exp_time; 2163 const struct GNUNET_PeerIdentity *get_path
2295 const struct GNUNET_HashCode *pquery; 2164 = &bd.put_path[bd.put_path_length];
2296 struct GNUNET_HashCode dquery;
2297 2165
2298 /* parse and validate message */ 2166 /* parse and validate message */
2299 exp_time = GNUNET_TIME_absolute_ntoh (prm->expiration_time); 2167 if (GNUNET_TIME_absolute_is_past (bd.expiration_time))
2300 if (0 == GNUNET_TIME_absolute_get_remaining (exp_time).rel_value_us)
2301 { 2168 {
2302 GNUNET_STATISTICS_update (GDS_stats, 2169 GNUNET_STATISTICS_update (GDS_stats,
2303 gettext_noop ("# Expired results discarded"), 2170 "# Expired results discarded",
2304 1, 2171 1,
2305 GNUNET_NO); 2172 GNUNET_NO);
2306 return; 2173 return;
2307 } 2174 }
2308 msize = ntohs (prm->header.size); 2175 get_path = &bd.put_path[bd.put_path_length];
2309 put_path_length = ntohl (prm->put_path_length); 2176 bd.data = (const void *) &get_path[get_path_length];
2310 get_path_length = ntohl (prm->get_path_length); 2177 bd.data_size = msize - (sizeof(struct PeerResultMessage)
2311 put_path = (const struct GNUNET_PeerIdentity *) &prm[1]; 2178 + (get_path_length + bd.put_path_length)
2312 get_path = &put_path[put_path_length]; 2179 * sizeof(struct GNUNET_PeerIdentity));
2313 type = ntohl (prm->type);
2314 data = (const void *) &get_path[get_path_length];
2315 data_size = msize - (sizeof(struct PeerResultMessage)
2316 + (get_path_length
2317 + put_path_length)
2318 * sizeof(struct GNUNET_PeerIdentity));
2319 GNUNET_STATISTICS_update (GDS_stats, 2180 GNUNET_STATISTICS_update (GDS_stats,
2320 gettext_noop ("# P2P RESULTS received"), 2181 "# P2P RESULTS received",
2321 1, 2182 1,
2322 GNUNET_NO); 2183 GNUNET_NO);
2323 GNUNET_STATISTICS_update (GDS_stats, 2184 GNUNET_STATISTICS_update (GDS_stats,
2324 gettext_noop ("# P2P RESULT bytes received"), 2185 "# P2P RESULT bytes received",
2325 msize, 2186 msize,
2326 GNUNET_NO); 2187 GNUNET_NO);
2327 { 2188 {
2328 enum GNUNET_GenericReturnValue ret; 2189 enum GNUNET_GenericReturnValue ret;
2190 const struct GNUNET_HashCode *pquery;
2329 2191
2330 ret = GNUNET_BLOCK_get_key (GDS_block_context, 2192 ret = GNUNET_BLOCK_get_key (GDS_block_context,
2331 type, 2193 bd.type,
2332 data, 2194 bd.data,
2333 data_size, 2195 bd.data_size,
2334 &dquery); 2196 &bd.key);
2335 if (GNUNET_NO == ret) 2197 if (GNUNET_NO == ret)
2336 { 2198 {
2337 GNUNET_break_op (0); 2199 GNUNET_break_op (0);
2338 return; 2200 return;
2339 } 2201 }
2340 pquery = (GNUNET_OK == ret) ? &dquery : &prm->key; 2202 pquery = (GNUNET_OK == ret) ? &bd.key : &prm->key;
2341 if (GNUNET_OK != 2203 if (GNUNET_OK !=
2342 GNUNET_BLOCK_check_block (GDS_block_context, 2204 GNUNET_BLOCK_check_block (GDS_block_context,
2343 type, 2205 bd.type,
2344 pquery, 2206 pquery,
2345 data, 2207 bd.data,
2346 data_size)) 2208 bd.data_size))
2347 { 2209 {
2348 GNUNET_break_op (0); 2210 GNUNET_break_op (0);
2349 return; 2211 return;
2350 } 2212 }
2351 } 2213 }
2214
2352 if (GNUNET_YES == log_route_details_stderr) 2215 if (GNUNET_YES == log_route_details_stderr)
2353 { 2216 {
2354 char *tmp; 2217 char *tmp;
@@ -2357,8 +2220,8 @@ handle_dht_p2p_result (void *cls,
2357 2220
2358 gp = GNUNET_STRINGS_pp2s (get_path, 2221 gp = GNUNET_STRINGS_pp2s (get_path,
2359 get_path_length); 2222 get_path_length);
2360 pp = GNUNET_STRINGS_pp2s (put_path, 2223 pp = GNUNET_STRINGS_pp2s (bd.put_path,
2361 put_path_length); 2224 bd.put_path_length);
2362 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); 2225 tmp = GNUNET_strdup (GNUNET_i2s (&my_identity));
2363 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, 2226 LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG,
2364 "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n", 2227 "R5N RESULT %s: %s->%s (GP: %s, PP: %s)\n",
@@ -2371,22 +2234,22 @@ handle_dht_p2p_result (void *cls,
2371 GNUNET_free (pp); 2234 GNUNET_free (pp);
2372 GNUNET_free (tmp); 2235 GNUNET_free (tmp);
2373 } 2236 }
2237
2374 /* if we got a HELLO, consider it for our own routing table */ 2238 /* if we got a HELLO, consider it for our own routing table */
2375 if (GNUNET_BLOCK_TYPE_DHT_HELLO == type) 2239 if (GNUNET_BLOCK_TYPE_DHT_HELLO == bd.type)
2376 { 2240 {
2377 const struct GNUNET_MessageHeader *h; 2241 const struct GNUNET_MessageHeader *h = bd.data;
2378 struct GNUNET_PeerIdentity pid; 2242 struct GNUNET_PeerIdentity pid;
2379 2243
2380 /* Should be a HELLO, validate and consider using it! */ 2244 /* Should be a HELLO, validate and consider using it! */
2381 if (data_size < sizeof(struct GNUNET_HELLO_Message)) 2245 if (bd.data_size < sizeof(struct GNUNET_HELLO_Message))
2382 { 2246 {
2383 GNUNET_break_op (0); 2247 GNUNET_break (0);
2384 return; 2248 return;
2385 } 2249 }
2386 h = data; 2250 if (bd.data_size != ntohs (h->size))
2387 if (data_size != ntohs (h->size))
2388 { 2251 {
2389 GNUNET_break_op (0); 2252 GNUNET_break (0);
2390 return; 2253 return;
2391 } 2254 }
2392 if (GNUNET_OK != 2255 if (GNUNET_OK !=
@@ -2396,9 +2259,9 @@ handle_dht_p2p_result (void *cls,
2396 GNUNET_break_op (0); 2259 GNUNET_break_op (0);
2397 return; 2260 return;
2398 } 2261 }
2399 if ((GNUNET_YES != disable_try_connect) && 2262 if ( (GNUNET_YES != disable_try_connect) &&
2400 (0 != GNUNET_memcmp (&my_identity, 2263 (0 != GNUNET_memcmp (&my_identity,
2401 &pid))) 2264 &pid)) )
2402 try_connect (&pid, 2265 try_connect (&pid,
2403 h); 2266 h);
2404 } 2267 }
@@ -2409,16 +2272,9 @@ handle_dht_p2p_result (void *cls,
2409 if (0 == GNUNET_memcmp (&get_path[i], 2272 if (0 == GNUNET_memcmp (&get_path[i],
2410 peer->id)) 2273 peer->id))
2411 { 2274 {
2412 process_reply_with_path (exp_time, 2275 process_reply_with_path (&bd,
2413 &prm->key, 2276 &prm->key,
2414 pquery, 2277 i, get_path);
2415 i,
2416 get_path,
2417 put_path_length,
2418 put_path,
2419 type,
2420 data_size,
2421 data);
2422 return; 2278 return;
2423 } 2279 }
2424 2280
@@ -2430,16 +2286,9 @@ handle_dht_p2p_result (void *cls,
2430 get_path, 2286 get_path,
2431 get_path_length * sizeof(struct GNUNET_PeerIdentity)); 2287 get_path_length * sizeof(struct GNUNET_PeerIdentity));
2432 xget_path[get_path_length] = *peer->id; 2288 xget_path[get_path_length] = *peer->id;
2433 process_reply_with_path (exp_time, 2289 process_reply_with_path (&bd,
2434 &prm->key, 2290 &prm->key,
2435 pquery, 2291 get_path_length + 1, xget_path);
2436 get_path_length + 1,
2437 xget_path,
2438 put_path_length,
2439 put_path,
2440 type,
2441 data_size,
2442 data);
2443 } 2292 }
2444} 2293}
2445 2294
diff --git a/src/dht/gnunet-service-dht_neighbours.h b/src/dht/gnunet-service-dht_neighbours.h
index 55cc5b135..ba7cc6055 100644
--- a/src/dht/gnunet-service-dht_neighbours.h
+++ b/src/dht/gnunet-service-dht_neighbours.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 GNUnet e.V. 3 Copyright (C) 2009, 2010, 2011, 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
@@ -30,6 +30,7 @@
30#include "gnunet_util_lib.h" 30#include "gnunet_util_lib.h"
31#include "gnunet_block_lib.h" 31#include "gnunet_block_lib.h"
32#include "gnunet_dht_service.h" 32#include "gnunet_dht_service.h"
33#include "gnunet-service-dht_datacache.h"
33 34
34/** 35/**
35 * Hash of the identity of this peer. 36 * Hash of the identity of this peer.
@@ -44,30 +45,19 @@ extern struct GNUNET_HashCode my_identity_hash;
44 * peer in the network (or if we are the closest peer in the 45 * peer in the network (or if we are the closest peer in the
45 * network). 46 * network).
46 * 47 *
47 * @param type type of the block 48 * @param bd data about the block
48 * @param options routing options 49 * @param options routing options
49 * @param desired_replication_level desired replication level 50 * @param desired_replication_level desired replication level
50 * @param expiration_time when does the content expire
51 * @param hop_count how many hops has this message traversed so far 51 * @param hop_count how many hops has this message traversed so far
52 * @param bf Bloom filter of peers this PUT has already traversed 52 * @param bf Bloom filter of peers this PUT has already traversed
53 * @param key key for the content
54 * @param put_path_length number of entries in put_path
55 * @param put_path peers this request has traversed so far (if tracked)
56 * @param data payload to store
57 * @param data_size number of bytes in data
58 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not 53 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
59 */ 54 */
60int 55enum GNUNET_GenericReturnValue
61GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, 56GDS_NEIGHBOURS_handle_put (const struct GDS_DATACACHE_BlockData *bd,
62 enum GNUNET_DHT_RouteOption options, 57 enum GNUNET_DHT_RouteOption options,
63 uint32_t desired_replication_level, 58 uint32_t desired_replication_level,
64 struct GNUNET_TIME_Absolute expiration_time,
65 uint32_t hop_count, 59 uint32_t hop_count,
66 struct GNUNET_CONTAINER_BloomFilter *bf, 60 struct GNUNET_CONTAINER_BloomFilter *bf);
67 const struct GNUNET_HashCode *key,
68 unsigned int put_path_length,
69 struct GNUNET_PeerIdentity *put_path,
70 const void *data, size_t data_size);
71 61
72 62
73/** 63/**
@@ -87,7 +77,7 @@ GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type,
87 * @param peer_bf filter for peers not to select (again, updated) 77 * @param peer_bf filter for peers not to select (again, updated)
88 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not 78 * @return #GNUNET_OK if the request was forwarded, #GNUNET_NO if not
89 */ 79 */
90int 80enum GNUNET_GenericReturnValue
91GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, 81GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
92 enum GNUNET_DHT_RouteOption options, 82 enum GNUNET_DHT_RouteOption options,
93 uint32_t desired_replication_level, 83 uint32_t desired_replication_level,
@@ -106,26 +96,17 @@ GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type,
106 * 96 *
107 * @param target neighbour that should receive the block (if still connected) 97 * @param target neighbour that should receive the block (if still connected)
108 * @param type type of the block 98 * @param type type of the block
109 * @param expiration_time when does the content expire 99 * @param bd details about the reply
110 * @param key key for the content 100 * @param query_hash query that was used for the request
111 * @param put_path_length number of entries in put_path
112 * @param put_path peers the original PUT traversed (if tracked)
113 * @param get_path_length number of entries in put_path 101 * @param get_path_length number of entries in put_path
114 * @param get_path peers this reply has traversed so far (if tracked) 102 * @param get_path peers this reply has traversed so far (if tracked)
115 * @param data payload of the reply
116 * @param data_size number of bytes in data
117 */ 103 */
118void 104void
119GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, 105GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
120 enum GNUNET_BLOCK_Type type, 106 const struct GDS_DATACACHE_BlockData *bd,
121 struct GNUNET_TIME_Absolute expiration_time, 107 const struct GNUNET_HashCode *query_hash,
122 const struct GNUNET_HashCode *key,
123 unsigned int put_path_length,
124 const struct GNUNET_PeerIdentity *put_path,
125 unsigned int get_path_length, 108 unsigned int get_path_length,
126 const struct GNUNET_PeerIdentity *get_path, 109 const struct GNUNET_PeerIdentity *get_path);
127 const void *data,
128 size_t data_size);
129 110
130 111
131/** 112/**
@@ -138,7 +119,7 @@ GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target,
138 * @return #GNUNET_YES if node location is closest, 119 * @return #GNUNET_YES if node location is closest,
139 * #GNUNET_NO otherwise. 120 * #GNUNET_NO otherwise.
140 */ 121 */
141int 122enum GNUNET_GenericReturnValue
142GDS_am_closest_peer (const struct GNUNET_HashCode *key, 123GDS_am_closest_peer (const struct GNUNET_HashCode *key,
143 const struct GNUNET_CONTAINER_BloomFilter *bloom); 124 const struct GNUNET_CONTAINER_BloomFilter *bloom);
144 125
@@ -148,7 +129,7 @@ GDS_am_closest_peer (const struct GNUNET_HashCode *key,
148 * 129 *
149 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 130 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
150 */ 131 */
151int 132enum GNUNET_GenericReturnValue
152GDS_NEIGHBOURS_init (void); 133GDS_NEIGHBOURS_init (void);
153 134
154 135
diff --git a/src/dht/gnunet-service-dht_nse.c b/src/dht/gnunet-service-dht_nse.c
index 7f411cf71..58f18816a 100644
--- a/src/dht/gnunet-service-dht_nse.c
+++ b/src/dht/gnunet-service-dht_nse.c
@@ -52,11 +52,13 @@ static struct GNUNET_NSE_Handle *nse;
52 * 52 *
53 */ 53 */
54static void 54static void
55update_network_size_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, 55update_network_size_estimate (void *cls,
56 double logestimate, double std_dev) 56 struct GNUNET_TIME_Absolute timestamp,
57 double logestimate,
58 double std_dev)
57{ 59{
58 GNUNET_STATISTICS_update (GDS_stats, 60 GNUNET_STATISTICS_update (GDS_stats,
59 gettext_noop ("# Network size estimates received"), 61 "# Network size estimates received",
60 1, GNUNET_NO); 62 1, GNUNET_NO);
61 /* do not allow estimates < 0.5 */ 63 /* do not allow estimates < 0.5 */
62 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate); 64 log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate);
@@ -83,20 +85,22 @@ GDS_NSE_init ()
83{ 85{
84 unsigned long long hops; 86 unsigned long long hops;
85 87
86 if ((GNUNET_YES == 88 if ( (GNUNET_YES ==
87 GNUNET_CONFIGURATION_have_value (GDS_cfg, 89 GNUNET_CONFIGURATION_have_value (GDS_cfg,
88 "dht", 90 "dht",
89 "FORCE_NSE")) && 91 "FORCE_NSE")) &&
90 (GNUNET_OK == 92 (GNUNET_OK ==
91 GNUNET_CONFIGURATION_get_value_number (GDS_cfg, 93 GNUNET_CONFIGURATION_get_value_number (GDS_cfg,
92 "dht", 94 "dht",
93 "FORCE_NSE", 95 "FORCE_NSE",
94 &hops))) 96 &hops)) )
95 { 97 {
96 log_of_network_size_estimate = (double) hops; 98 log_of_network_size_estimate = (double) hops;
97 return; 99 return;
98 } 100 }
99 nse = GNUNET_NSE_connect (GDS_cfg, &update_network_size_estimate, NULL); 101 nse = GNUNET_NSE_connect (GDS_cfg,
102 &update_network_size_estimate,
103 NULL);
100} 104}
101 105
102 106
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index ef3aded77..8ba0c70ad 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V. 3 Copyright (C) 2011, 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
@@ -31,8 +31,9 @@
31 31
32/** 32/**
33 * Number of requests we track at most (for routing replies). 33 * Number of requests we track at most (for routing replies).
34 * TODO: make configurable!
34 */ 35 */
35#define DHT_MAX_RECENT (1024 * 16) 36#define DHT_MAX_RECENT (1024 * 128)
36 37
37 38
38/** 39/**
@@ -96,14 +97,14 @@ static struct GNUNET_CONTAINER_MultiHashMap *recent_map;
96 97
97 98
98/** 99/**
99 * Closure for the 'process' function. 100 * Closure for the process() function.
100 */ 101 */
101struct ProcessContext 102struct ProcessContext
102{ 103{
103 /** 104 /**
104 * Path of the original PUT 105 * Block data.
105 */ 106 */
106 const struct GNUNET_PeerIdentity *put_path; 107 const struct GDS_DATACACHE_BlockData *bd;
107 108
108 /** 109 /**
109 * Path of the reply. 110 * Path of the reply.
@@ -111,34 +112,10 @@ struct ProcessContext
111 const struct GNUNET_PeerIdentity *get_path; 112 const struct GNUNET_PeerIdentity *get_path;
112 113
113 /** 114 /**
114 * Payload of the reply.
115 */
116 const void *data;
117
118 /**
119 * Expiration time of the result.
120 */
121 struct GNUNET_TIME_Absolute expiration_time;
122
123 /**
124 * Number of entries in @e put_path.
125 */
126 unsigned int put_path_length;
127
128 /**
129 * Number of entries in @e get_path. 115 * Number of entries in @e get_path.
130 */ 116 */
131 unsigned int get_path_length; 117 unsigned int get_path_length;
132 118
133 /**
134 * Number of bytes in @e data.
135 */
136 size_t data_size;
137
138 /**
139 * Type of the reply.
140 */
141 enum GNUNET_BLOCK_Type type;
142}; 119};
143 120
144 121
@@ -146,71 +123,56 @@ struct ProcessContext
146 * Forward the result to the given peer if it matches the request. 123 * Forward the result to the given peer if it matches the request.
147 * 124 *
148 * @param cls the `struct ProcessContext` with the result 125 * @param cls the `struct ProcessContext` with the result
149 * @param key the query 126 * @param query_hash the hash from the original query
150 * @param value the `struct RecentRequest` with the request 127 * @param value the `struct RecentRequest` with the request
151 * @return #GNUNET_OK (continue to iterate) 128 * @return #GNUNET_OK (continue to iterate)
152 */ 129 */
153static enum GNUNET_GenericReturnValue 130static enum GNUNET_GenericReturnValue
154process (void *cls, 131process (void *cls,
155 const struct GNUNET_HashCode *key, 132 const struct GNUNET_HashCode *query_hash,
156 void *value) 133 void *value)
157{ 134{
158 struct ProcessContext *pc = cls; 135 struct ProcessContext *pc = cls;
159 struct RecentRequest *rr = value; 136 struct RecentRequest *rr = value;
160 enum GNUNET_BLOCK_ReplyEvaluationResult eval; 137 enum GNUNET_BLOCK_ReplyEvaluationResult eval;
161 unsigned int gpl; 138 unsigned int get_path_length;
162 unsigned int ppl; 139 struct GDS_DATACACHE_BlockData bdx = *pc->bd;
163 struct GNUNET_HashCode hc;
164 const struct GNUNET_HashCode *eval_key;
165 140
166 if ((rr->type != GNUNET_BLOCK_TYPE_ANY) && 141 if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) &&
167 (rr->type != pc->type)) 142 (rr->type != pc->bd->type) )
168 return GNUNET_OK; /* type mismatch */ 143 return GNUNET_OK; /* type mismatch */
169
170 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) 144 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
171 { 145 {
172 gpl = pc->get_path_length; 146 get_path_length = pc->get_path_length;
173 ppl = pc->put_path_length;
174 } 147 }
175 else 148 else
176 { 149 {
177 gpl = 0; 150 get_path_length = 0;
178 ppl = 0; 151 bdx.put_path_length = 0;
152 bdx.put_path = NULL;
179 } 153 }
180 /* FIXME-SCHANZEN: should we modify FIND_PEER to 154 if ( (0 == (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
181 be a generic approximate search and not check 155 (0 != GNUNET_memcmp (query_hash,
182 for the DHT_HELLO type here? */ 156 &bdx.key)) )
183 if ( (0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
184 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO) )
185 { 157 {
186 /* key may not match HELLO, which is OK since 158 GNUNET_STATISTICS_update (GDS_stats,
187 * the search is approximate. Still, the evaluation 159 "# Inexact matches discarded in exact search",
188 * would fail since the match is not exact. So 160 1,
189 * we fake it by changing the key to the actual PID ... */ 161 GNUNET_NO);
190 GNUNET_BLOCK_get_key (GDS_block_context, 162 return GNUNET_OK; /* exact search, but inexact match */
191 GNUNET_BLOCK_TYPE_DHT_HELLO,
192 pc->data,
193 pc->data_size,
194 &hc);
195 eval_key = &hc;
196 }
197 else
198 {
199 eval_key = key;
200 } 163 }
201 eval 164 eval = GNUNET_BLOCK_check_reply (GDS_block_context,
202 = GNUNET_BLOCK_check_reply (GDS_block_context, 165 bdx.type,
203 pc->type, 166 rr->bg,
204 rr->bg, 167 &bdx.key,
205 eval_key, 168 rr->xquery,
206 rr->xquery, 169 rr->xquery_size,
207 rr->xquery_size, 170 bdx.data,
208 pc->data, 171 bdx.data_size);
209 pc->data_size);
210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211 "Result for %s of type %d was evaluated as %d\n", 173 "Result for %s of type %d was evaluated as %d\n",
212 GNUNET_h2s (key), 174 GNUNET_h2s (&bdx.key),
213 pc->type, 175 bdx.type,
214 eval); 176 eval);
215 switch (eval) 177 switch (eval)
216 { 178 {
@@ -222,13 +184,9 @@ process (void *cls,
222 1, 184 1,
223 GNUNET_NO); 185 GNUNET_NO);
224 GDS_NEIGHBOURS_handle_reply (&rr->peer, 186 GDS_NEIGHBOURS_handle_reply (&rr->peer,
225 pc->type, 187 &bdx,
226 pc->expiration_time, 188 query_hash,
227 key, 189 get_path_length, pc->get_path);
228 ppl, pc->put_path,
229 gpl, pc->get_path,
230 pc->data,
231 pc->data_size);
232 break; 190 break;
233 case GNUNET_BLOCK_REPLY_OK_DUPLICATE: 191 case GNUNET_BLOCK_REPLY_OK_DUPLICATE:
234 GNUNET_STATISTICS_update (GDS_stats, 192 GNUNET_STATISTICS_update (GDS_stats,
@@ -264,39 +222,25 @@ process (void *cls,
264 * GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching 222 * GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching
265 * request recently. 223 * request recently.
266 * 224 *
267 * @param type type of the block 225 * @param bd block details
268 * @param expiration_time when does the content expire 226 * @param query_hash query used in the inquiry
269 * @param key key for the content
270 * @param put_path_length number of entries in @a put_path
271 * @param put_path peers the original PUT traversed (if tracked)
272 * @param get_path_length number of entries in @a get_path 227 * @param get_path_length number of entries in @a get_path
273 * @param get_path peers this reply has traversed so far (if tracked) 228 * @param get_path peers this reply has traversed so far (if tracked)
274 * @param data payload of the reply
275 * @param data_size number of bytes in data
276 */ 229 */
277void 230void
278GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, 231GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
279 struct GNUNET_TIME_Absolute expiration_time, 232 const struct GNUNET_HashCode *query_hash,
280 const struct GNUNET_HashCode *key,
281 unsigned int put_path_length,
282 const struct GNUNET_PeerIdentity *put_path,
283 unsigned int get_path_length, 233 unsigned int get_path_length,
284 const struct GNUNET_PeerIdentity *get_path, 234 const struct GNUNET_PeerIdentity *get_path)
285 const void *data,
286 size_t data_size)
287{ 235{
288 struct ProcessContext pc; 236 struct ProcessContext pc = {
289 237 .bd = bd,
290 pc.type = type; 238 .get_path = get_path,
291 pc.expiration_time = expiration_time; 239 .get_path_length = get_path_length
292 pc.put_path_length = put_path_length; 240 };
293 pc.put_path = put_path; 241
294 pc.get_path_length = get_path_length;
295 pc.get_path = get_path;
296 pc.data = data;
297 pc.data_size = data_size;
298 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, 242 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
299 key, 243 query_hash,
300 &process, 244 &process,
301 &pc); 245 &pc);
302} 246}
@@ -313,7 +257,7 @@ expire_oldest_entry (void)
313 struct RecentRequest *recent_req; 257 struct RecentRequest *recent_req;
314 258
315 GNUNET_STATISTICS_update (GDS_stats, 259 GNUNET_STATISTICS_update (GDS_stats,
316 "# Entries removed from routing table", 260 "# Old entries removed from routing table",
317 1, 261 1,
318 GNUNET_NO); 262 GNUNET_NO);
319 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); 263 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap);
@@ -334,7 +278,7 @@ expire_oldest_entry (void)
334 * 278 *
335 * @param cls the new `struct RecentRequest` (to discard upon successful combination) 279 * @param cls the new `struct RecentRequest` (to discard upon successful combination)
336 * @param key the query 280 * @param key the query
337 * @param value the existing 'struct RecentRequest' (to update upon successful combination) 281 * @param value the existing `struct RecentRequest` (to update upon successful combination)
338 * @return #GNUNET_OK (continue to iterate), 282 * @return #GNUNET_OK (continue to iterate),
339 * #GNUNET_SYSERR if the request was successfully combined 283 * #GNUNET_SYSERR if the request was successfully combined
340 */ 284 */
@@ -346,13 +290,13 @@ try_combine_recent (void *cls,
346 struct RecentRequest *in = cls; 290 struct RecentRequest *in = cls;
347 struct RecentRequest *rr = value; 291 struct RecentRequest *rr = value;
348 292
349 if ((0 != GNUNET_memcmp (&in->peer, 293 if ( (0 != GNUNET_memcmp (&in->peer,
350 &rr->peer)) || 294 &rr->peer)) ||
351 (in->type != rr->type) || 295 (in->type != rr->type) ||
352 (in->xquery_size != rr->xquery_size) || 296 (in->xquery_size != rr->xquery_size) ||
353 (0 != memcmp (in->xquery, 297 (0 != memcmp (in->xquery,
354 rr->xquery, 298 rr->xquery,
355 in->xquery_size))) 299 in->xquery_size) ) )
356 return GNUNET_OK; 300 return GNUNET_OK;
357 GNUNET_break (GNUNET_SYSERR != 301 GNUNET_break (GNUNET_SYSERR !=
358 GNUNET_BLOCK_group_merge (in->bg, 302 GNUNET_BLOCK_group_merge (in->bg,
@@ -410,19 +354,21 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
410 recent_req)) 354 recent_req))
411 { 355 {
412 GNUNET_STATISTICS_update (GDS_stats, 356 GNUNET_STATISTICS_update (GDS_stats,
413 gettext_noop 357 "# DHT requests combined",
414 ("# DHT requests combined"), 358 1,
415 1, GNUNET_NO); 359 GNUNET_NO);
416 return; 360 return;
417 } 361 }
418 recent_req->heap_node 362 recent_req->heap_node
419 = GNUNET_CONTAINER_heap_insert (recent_heap, 363 = GNUNET_CONTAINER_heap_insert (
420 recent_req, 364 recent_heap,
421 GNUNET_TIME_absolute_get ().abs_value_us); 365 recent_req,
422 GNUNET_CONTAINER_multihashmap_put (recent_map, 366 GNUNET_TIME_absolute_get ().abs_value_us);
423 key, 367 (void) GNUNET_CONTAINER_multihashmap_put (
424 recent_req, 368 recent_map,
425 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 369 key,
370 recent_req,
371 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
426} 372}
427 373
428 374
@@ -446,10 +392,12 @@ GDS_ROUTING_done ()
446{ 392{
447 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) 393 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0)
448 expire_oldest_entry (); 394 expire_oldest_entry ();
449 GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap)); 395 GNUNET_assert (0 ==
396 GNUNET_CONTAINER_heap_get_size (recent_heap));
450 GNUNET_CONTAINER_heap_destroy (recent_heap); 397 GNUNET_CONTAINER_heap_destroy (recent_heap);
451 recent_heap = NULL; 398 recent_heap = NULL;
452 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map)); 399 GNUNET_assert (0 ==
400 GNUNET_CONTAINER_multihashmap_size (recent_map));
453 GNUNET_CONTAINER_multihashmap_destroy (recent_map); 401 GNUNET_CONTAINER_multihashmap_destroy (recent_map);
454 recent_map = NULL; 402 recent_map = NULL;
455} 403}
diff --git a/src/dht/gnunet-service-dht_routing.h b/src/dht/gnunet-service-dht_routing.h
index 7fea01bae..1a1514cc5 100644
--- a/src/dht/gnunet-service-dht_routing.h
+++ b/src/dht/gnunet-service-dht_routing.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V. 3 Copyright (C) 2011, 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
@@ -35,29 +35,19 @@
35 * Handle a reply (route to origin). Only forwards the reply back to 35 * Handle a reply (route to origin). Only forwards the reply back to
36 * other peers waiting for it. Does not do local caching or 36 * other peers waiting for it. Does not do local caching or
37 * forwarding to local clients. Essentially calls 37 * forwarding to local clients. Essentially calls
38 * #GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching 38 * GDS_NEIGHBOURS_handle_reply() for all peers that sent us a matching
39 * request recently. 39 * request recently.
40 * 40 *
41 * @param type type of the block 41 * @param bd block details
42 * @param expiration_time when does the content expire 42 * @param query_hash query used in the inquiry
43 * @param key key for the content
44 * @param put_path_length number of entries in @a put_path
45 * @param put_path peers the original PUT traversed (if tracked)
46 * @param get_path_length number of entries in @a get_path 43 * @param get_path_length number of entries in @a get_path
47 * @param get_path peers this reply has traversed so far (if tracked) 44 * @param get_path peers this reply has traversed so far (if tracked)
48 * @param data payload of the reply
49 * @param data_size number of bytes in @a data
50 */ 45 */
51void 46void
52GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, 47GDS_ROUTING_process (const struct GDS_DATACACHE_BlockData *bd,
53 struct GNUNET_TIME_Absolute expiration_time, 48 const struct GNUNET_HashCode *query_hash,
54 const struct GNUNET_HashCode *key,
55 unsigned int put_path_length,
56 const struct GNUNET_PeerIdentity *put_path,
57 unsigned int get_path_length, 49 unsigned int get_path_length,
58 const struct GNUNET_PeerIdentity *get_path, 50 const struct GNUNET_PeerIdentity *get_path);
59 const void *data,
60 size_t data_size);
61 51
62 52
63/** 53/**