GNUnet 0.28.1-dev.4-8-g14b9efcb0
 
Loading...
Searching...
No Matches
gnunet-service-dht_clients.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2011, 2016-2017, 2022, 2026 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
28#include "gnunet_pils_service.h"
29#include "gnunet_util_lib.h"
30
37#define SANITY_CHECKS 0
38
42#define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \
43 __VA_ARGS__)
44
45#define LOG(kind, ...) GNUNET_log_from (kind, "dht-clients", __VA_ARGS__)
46
54#define UNROUTED_RETRY_INTERVAL GNUNET_TIME_relative_multiply ( \
55 GNUNET_TIME_UNIT_SECONDS, 5)
56
57
63struct ClientHandle;
64
65
147
148
153{
158
163
168
173
178
182 int16_t get;
183
187 int16_t get_resp;
188
192 uint16_t put;
193
194};
195
196
224
225
230
235
240
245
250
255
260
265
270
275
276
282static void
284{
285 struct ClientHandle *ch = record->ch;
286
288 ch->cqr_tail,
289 record);
292 &record->key,
293 record));
294 if (NULL != record->hnode)
296 GNUNET_array_grow (record->seen_replies,
297 record->seen_replies_count,
298 0);
300}
301
302
312static void *
315 struct GNUNET_MQ_Handle *mq)
316{
317 struct ClientHandle *ch;
318
319 (void) cls;
320 ch = GNUNET_new (struct ClientHandle);
321 ch->client = client;
322 ch->mq = mq;
323 return ch;
324}
325
326
335static void
338 void *app_ctx)
339{
340 struct ClientHandle *ch = app_ctx;
341
342 (void) cls;
343 (void) client;
345 "Local client %p disconnects\n",
346 ch);
347 {
349
351 NULL != monitor;
352 monitor = next)
353 {
354 next = monitor->next;
355 if (monitor->ch != ch)
356 continue;
359 monitor);
361 }
362 }
363
364 {
365 struct ClientQueryRecord *cqr;
366
367 while (NULL != (cqr = ch->cqr_head))
369 }
370 GNUNET_free (ch);
371}
372
373
381static void
383{
384 struct GNUNET_BLOCK_Group *bg;
385 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
386 enum GNUNET_GenericReturnValue routed;
387
389 "# GET requests from clients injected",
390 1,
391 GNUNET_NO);
393 cqr->type,
394 NULL, /* raw data */
395 0, /* raw data size */
396 "seen-set-size",
398 NULL);
400 cqr->seen_replies,
401 cqr->seen_replies_count);
402 peer_bf
407 "Initiating GET for %s, replication %u, already have %u replies\n",
408 GNUNET_h2s (&cqr->key),
409 cqr->replication,
410 cqr->seen_replies_count);
411 routed = GDS_NEIGHBOURS_handle_get (cqr->type,
412 cqr->msg_options,
413 cqr->replication,
414 0 /* hop count */,
415 &cqr->key,
416 cqr->xquery,
417 cqr->xquery_size,
418 bg,
419 peer_bf);
422
423 /* Exponential back-off for retries.
424 * max. is #GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
426 if (GNUNET_OK != routed)
427 {
428 /* We had no peer to route this to, so nothing was sent and nothing
429 can answer. Cap the interval so we come back as soon as the
430 routing table recovers instead of idling for up to 15 minutes. */
432 "# GET requests from clients not routed",
433 1,
434 GNUNET_NO);
435 cqr->retry_frequency
437 cqr->retry_frequency);
438 }
440}
441
442
450static void
452{
453 struct ClientQueryRecord *cqr;
454
455 (void) cls;
456 retry_task = NULL;
457 while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
458 {
459 cqr->hnode = NULL;
461 {
462 cqr->hnode
464 cqr,
469 NULL);
470 return;
471 }
472 transmit_request (cqr);
473 cqr->hnode
475 cqr,
477 }
478}
479
480
491 const struct GNUNET_HashCode *key,
492 void *value)
493{
494 struct ClientQueryRecord *cqr = value;
495
496 (void) cls;
497 (void) key;
500 if (NULL != cqr->hnode)
503 return GNUNET_YES;
504}
505
506
507void
509{
511 return;
513 "Routing table changed, re-transmitting %u pending GET request(s)\n",
516 "# GET requests retried after routing table change",
518 GNUNET_NO);
521 NULL);
522 if (NULL != retry_task)
525 NULL);
526}
527
528
538 const struct GNUNET_DHT_ClientPutMessage *dht_msg)
539{
540 uint32_t replication_level = ntohl (dht_msg->desired_replication_level);
541
542 (void) cls;
544 {
545 GNUNET_break_op (0);
546 return GNUNET_SYSERR;
547 }
548 return GNUNET_OK;
549}
550
551
552static void
554 enum GNUNET_GenericReturnValue forwarded)
555{
556 if (GNUNET_OK != forwarded)
557 {
559 "# Local PUT requests not routed",
560 1,
561 GNUNET_NO);
562 }
563}
564
565
572static void
574 const struct GNUNET_DHT_ClientPutMessage *dht_msg)
575{
576 struct ClientHandle *ch = cls;
577 uint16_t size = ntohs (dht_msg->header.size);
578 uint32_t replication_level
579 = ntohl (dht_msg->desired_replication_level);
580 struct GNUNET_DATACACHE_Block bd = {
581 .key = dht_msg->key,
582 .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
583 .data = &dht_msg[1],
584 .data_size = size - sizeof (*dht_msg),
585 .type = ntohl (dht_msg->type),
586 .ro = ntohl (dht_msg->options)
587 };
588
590 "Handling local PUT of %lu-bytes for query %s of type %u\n",
591 (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
592 GNUNET_h2s (&dht_msg->key),
593 (unsigned int) bd.type);
595 {
596 /* Without our own identity we can neither decide whether to store
597 this block nor route it: GDS_am_closest_peer(),
598 GDS_DATACACHE_handle_put() and GDS_NEIGHBOURS_handle_put() all
599 require it. Should not happen -- the service stays suspended
600 until PILS answers -- but drop the request rather than abort. */
601 GNUNET_break (0);
603 "# PUT requests dropped (no identity yet)",
604 1,
605 GNUNET_NO);
607 return;
608 }
609#if SANITY_CHECKS > 0
610 if (GNUNET_OK !=
612 bd.type,
613 bd.data,
614 bd.data_size))
615 {
616 GNUNET_break (0);
618 return;
619 }
620#endif
622 "# PUT requests received from clients",
623 1,
624 GNUNET_NO);
626 "CLIENT-PUT %s\n",
627 GNUNET_h2s_full (&dht_msg->key));
628 /* give to local clients */
630 &bd.key,
631 0, NULL /* get path */));
632
633 {
634 struct GNUNET_CONTAINER_BloomFilter *peer_bf;
635
636 peer_bf
640 /* store locally */
641 if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
642 (GDS_am_closest_peer (&dht_msg->key,
643 peer_bf)))
645 /* route to other peers */
648 0 /* hop count */,
649 peer_bf,
651 NULL);
653 }
655 &bd,
656 0, /* hop count */
659}
660
661
668static void
670 const struct GNUNET_DATACACHE_Block *bd)
671{
673 "Datacache provided result for query key %s\n",
674 GNUNET_h2s (&bd->key));
676 &bd->key,
677 0, NULL /* get_path */));
678}
679
680
690 const struct GNUNET_DHT_ClientGetMessage *get)
691{
692 (void) cls;
693 (void) get;
694 /* always well-formed */
695 return GNUNET_OK;
696}
697
698
705static void
707 const struct GNUNET_DHT_ClientGetMessage *get)
708{
709 struct ClientHandle *ch = cls;
710 struct ClientQueryRecord *cqr;
711 uint16_t size = ntohs (get->header.size);
712 const char *xquery = (const char *) &get[1];
713 size_t xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
714
716 "Received GET request for %s from local client %p, xq: %.*s\n",
717 GNUNET_h2s (&get->key),
718 ch->client,
719 (int) xquery_size,
720 xquery);
722 "# GET requests received from clients",
723 1,
724 GNUNET_NO);
726 "CLIENT-GET %s\n",
727 GNUNET_h2s_full (&get->key));
729 {
730 /* GDS_NEIGHBOURS_handle_get() requires our identity. Should not
731 happen -- the service stays suspended until PILS answers -- but
732 drop the request rather than abort. */
733 GNUNET_break (0);
735 "# GET requests dropped (no identity yet)",
736 1,
737 GNUNET_NO);
739 return;
740 }
741
742 cqr = GNUNET_malloc (sizeof(struct ClientQueryRecord) + xquery_size);
743 cqr->key = get->key;
744 cqr->ch = ch;
745 cqr->xquery = (const void *) &cqr[1];
746 GNUNET_memcpy (&cqr[1],
747 xquery,
748 xquery_size);
750 cqr,
751 0);
754 cqr->unique_id = get->unique_id;
755 cqr->xquery_size = xquery_size;
756 cqr->replication = ntohl (get->desired_replication_level);
757 cqr->msg_options = ntohl (get->options);
758 cqr->type = ntohl (get->type);
760 ch->cqr_tail,
761 cqr);
763 &cqr->key,
764 cqr,
767 cqr->type,
768 0, /* hop count */
769 cqr->replication,
770 &get->key);
771 /* start remote requests */
772 if (NULL != retry_task)
775 NULL);
776 /* perform local lookup */
778 cqr->type,
779 cqr->xquery,
780 xquery_size,
781 NULL,
783 ch);
785}
786
787
792{
797
801 uint64_t unique_id;
802};
803
804
817 const struct GNUNET_HashCode *key,
818 void *value)
819{
820 struct FindByUniqueIdContext *fui_ctx = cls;
821 struct ClientQueryRecord *cqr = value;
822
823 if (cqr->unique_id != fui_ctx->unique_id)
824 return GNUNET_YES;
825 fui_ctx->cqr = cqr;
826 return GNUNET_NO;
827}
828
829
839 void *cls,
840 const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
841{
842 uint16_t size = ntohs (seen->header.size);
843 unsigned int hash_count =
844 (size - sizeof(*seen))
845 / sizeof(struct GNUNET_HashCode);
846
847 if (size != sizeof(*seen) + hash_count * sizeof(struct GNUNET_HashCode))
848 {
849 GNUNET_break (0);
850 return GNUNET_SYSERR;
851 }
852 return GNUNET_OK;
853}
854
855
862static void
864 void *cls,
865 const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
866{
867 struct ClientHandle *ch = cls;
868 uint16_t size = ntohs (seen->header.size);
869 unsigned int hash_count = (size - sizeof(*seen))
870 / sizeof(struct GNUNET_HashCode);
871 const struct GNUNET_HashCode *hc = (const struct GNUNET_HashCode*) &seen[1];
872 struct FindByUniqueIdContext fui_ctx = {
873 .unique_id = seen->unique_id
874 };
875 unsigned int old_count;
876 struct ClientQueryRecord *cqr;
877
879 &seen->key,
881 &fui_ctx);
882 if (NULL == (cqr = fui_ctx.cqr))
883 {
884 GNUNET_break (0);
886 return;
887 }
888 /* finally, update 'seen' list */
889 old_count = cqr->seen_replies_count;
892 cqr->seen_replies_count + hash_count);
893 GNUNET_memcpy (&cqr->seen_replies[old_count],
894 hc,
895 sizeof(struct GNUNET_HashCode) * hash_count);
897}
898
899
904{
909
913 uint64_t unique_id;
914};
915
916
928 const struct GNUNET_HashCode *key,
929 void *value)
930{
931 const struct RemoveByUniqueIdContext *ctx = cls;
932 struct ClientQueryRecord *cqr = value;
933
934 if (cqr->unique_id != ctx->unique_id)
935 return GNUNET_YES;
937 "Removing client %p's record for key %s (by unique id)\n",
938 ctx->ch->client,
939 GNUNET_h2s (key));
941 return GNUNET_YES;
942}
943
944
953static void
955 void *cls,
956 const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
957{
958 struct ClientHandle *ch = cls;
960
962 "# GET STOP requests received from clients",
963 1,
964 GNUNET_NO);
966 "Received GET STOP request for %s from local client %p\n",
967 GNUNET_h2s (&dht_stop_msg->key),
968 ch->client);
969 ctx.ch = ch;
970 ctx.unique_id = dht_stop_msg->unique_id;
972 &dht_stop_msg->key,
974 &ctx);
976}
977
978
983{
988
993
997 unsigned int get_path_length;
998
999};
1000
1001
1013static enum GNUNET_GenericReturnValue
1014forward_reply (void *cls,
1015 const struct GNUNET_HashCode *query_hash,
1016 void *value)
1017{
1018 struct ForwardReplyContext *frc = cls;
1019 struct ClientQueryRecord *record = value;
1020 const struct GNUNET_DATACACHE_Block *bd = frc->bd;
1021 struct GNUNET_MQ_Envelope *env;
1022 struct GNUNET_DHT_ClientResultMessage *reply;
1024 bool do_free;
1025 struct GNUNET_HashCode ch;
1026 struct GNUNET_DHT_PathElement *paths;
1027 bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1028 size_t xsize = bd->data_size;
1029
1031 "CLIENT-RESULT %s\n",
1032 GNUNET_h2s_full (&bd->key));
1033 if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
1034 (record->type != bd->type) )
1035 {
1037 "Record type mismatch, not passing request for key %s to local client\n",
1038 GNUNET_h2s (&bd->key));
1040 "# Key match, type mismatches in REPLY to CLIENT",
1041 1,
1042 GNUNET_NO);
1043 return GNUNET_YES; /* type mismatch */
1044 }
1045 if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
1046 (0 != GNUNET_memcmp (&bd->key,
1047 query_hash)) )
1048 {
1050 "# Inexact key match, but exact match required",
1051 1,
1052 GNUNET_NO);
1053 return GNUNET_YES; /* type mismatch */
1054 }
1056 bd->data_size,
1057 &ch);
1058 for (unsigned int i = 0; i < record->seen_replies_count; i++)
1059 if (0 ==
1060 GNUNET_memcmp (&record->seen_replies[i],
1061 &ch))
1062 {
1064 "Duplicate reply, not passing request for key %s to local client\n",
1065 GNUNET_h2s (&bd->key));
1067 "# Duplicate REPLIES to CLIENT request dropped",
1068 1,
1069 GNUNET_NO);
1070 return GNUNET_YES; /* duplicate */
1071 }
1072 eval
1074 record->type,
1075 NULL,
1076 &bd->key,
1077 record->xquery,
1078 record->xquery_size,
1079 bd->data,
1080 bd->data_size);
1082 "Evaluation result is %d for key %s for local client's query\n",
1083 (int) eval,
1084 GNUNET_h2s (&bd->key));
1085 switch (eval)
1086 {
1088 do_free = true;
1089 break;
1092 GNUNET_array_append (record->seen_replies,
1093 record->seen_replies_count,
1094 ch);
1095 do_free = false;
1096 break;
1098 /* should be impossible to encounter here */
1099 GNUNET_break (0);
1100 return GNUNET_YES;
1102 return GNUNET_YES;
1103 default:
1104 GNUNET_break (0);
1105 return GNUNET_NO;
1106 }
1108 "# RESULTS queued for clients",
1109 1,
1110 GNUNET_NO);
1111 xsize += (frc->get_path_length + bd->put_path_length)
1112 * sizeof(struct GNUNET_DHT_PathElement);
1113 if (truncated)
1114 xsize += sizeof (struct GNUNET_PeerIdentity);
1115
1116#if SUPER_REDUNDANT_CHECK
1117 {
1118 const struct GNUNET_PeerIdentity *my_identity;
1120 GNUNET_assert (NULL != my_identity);
1121 GNUNET_break (0 ==
1123 bd->data_size,
1124 bd->expiration_time,
1125 truncated
1126 ? &bd->trunc_peer
1127 : NULL,
1128 bd->put_path,
1129 bd->put_path_length,
1130 frc->get_path,
1131 frc->get_path_length,
1132 my_identity));
1133 }
1134#endif
1135
1136 env = GNUNET_MQ_msg_extra (reply,
1137 xsize,
1139 reply->type = htonl (bd->type);
1140 reply->options = htonl (bd->ro);
1141 reply->get_path_length = htonl (frc->get_path_length);
1142 reply->put_path_length = htonl (bd->put_path_length);
1143 reply->unique_id = record->unique_id;
1145 reply->key = *query_hash;
1146 if (truncated)
1147 {
1148 void *tgt = &reply[1];
1149
1150 GNUNET_memcpy (tgt,
1151 &bd->trunc_peer,
1152 sizeof (struct GNUNET_PeerIdentity));
1153 paths = (struct GNUNET_DHT_PathElement *)
1154 (tgt + sizeof (struct GNUNET_PeerIdentity));
1155 }
1156 else
1157 {
1158 paths = (struct GNUNET_DHT_PathElement *) &reply[1];
1159 }
1160 GNUNET_memcpy (paths,
1161 bd->put_path,
1162 sizeof(struct GNUNET_DHT_PathElement)
1163 * bd->put_path_length);
1164 GNUNET_memcpy (&paths[bd->put_path_length],
1165 frc->get_path,
1166 sizeof(struct GNUNET_DHT_PathElement)
1167 * frc->get_path_length);
1168 GNUNET_memcpy (&paths[frc->get_path_length + bd->put_path_length],
1169 bd->data,
1170 bd->data_size);
1172 "Sending reply to query %s for client %p\n",
1173 GNUNET_h2s (query_hash),
1174 record->ch->client);
1175 GNUNET_MQ_send (record->ch->mq,
1176 env);
1177 if (GNUNET_YES == do_free)
1179 return GNUNET_YES;
1180}
1181
1182
1183bool
1185 const struct GNUNET_HashCode *query_hash,
1186 unsigned int get_path_length,
1187 const struct GNUNET_DHT_PathElement *get_path)
1188{
1189 struct ForwardReplyContext frc;
1190 size_t msize = sizeof (struct GNUNET_DHT_ClientResultMessage)
1191 + bd->data_size
1193 * sizeof(struct GNUNET_DHT_PathElement);
1194#if SANITY_CHECKS > 1
1195 bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1196#endif
1197
1198 if (msize >= GNUNET_MAX_MESSAGE_SIZE)
1199 {
1200 GNUNET_break (0);
1201 return false;
1202 }
1203#if SANITY_CHECKS > 1
1204 {
1205 const struct GNUNET_PeerIdentity *my_identity;
1207 GNUNET_assert (NULL != my_identity);
1208 if (0 !=
1210 bd->data_size,
1211 bd->expiration_time,
1212 truncated
1213 ? &bd->trunc_peer
1214 : NULL,
1215 bd->put_path,
1216 bd->put_path_length,
1217 get_path,
1218 get_path_length,
1219 my_identity))
1220 {
1221 GNUNET_break (0);
1222 return false;
1223 }
1224 }
1225#endif
1226 frc.bd = bd;
1227 frc.get_path = get_path;
1228 frc.get_path_length = get_path_length;
1230 "Forwarding reply for query hash %s with GPL %u and PPL %u to client\n",
1231 GNUNET_h2s (query_hash),
1232 get_path_length,
1233 bd->put_path_length);
1234 if (0 ==
1236 query_hash,
1238 &frc))
1239 {
1241 "No matching client for reply for query %s\n",
1242 GNUNET_h2s (query_hash));
1244 "# REPLIES ignored for CLIENTS (no match)",
1245 1,
1246 GNUNET_NO);
1247 }
1248 return true;
1249}
1250
1251
1252/* **************** HELLO logic ***************** */
1253
1254
1263static void
1265 const struct GNUNET_MessageHeader *msg)
1266{
1267 struct ClientHandle *ch = cls;
1268 const struct GNUNET_PeerIdentity *my_identity;
1269 struct GNUNET_HELLO_Parser *p;
1270 struct GNUNET_MessageHeader *hdr;
1271 struct GNUNET_MQ_Envelope *env;
1272
1274
1275 if (NULL != GDS_my_hello)
1277 else
1278 p = NULL;
1279
1281 "Handling request from local client for my HELLO\n");
1282
1283 if (NULL != p)
1284 {
1285 char *url;
1286 size_t slen;
1287
1289 slen = strlen (url) + 1;
1290
1291 env = GNUNET_MQ_msg_extra (hdr,
1292 slen,
1294 memcpy (&hdr[1],
1295 url,
1296 slen);
1297 GNUNET_free (url);
1299 }
1300 else
1301 {
1303 ;
1304 }
1305
1307 env);
1309}
1310
1311
1319static enum GNUNET_GenericReturnValue
1321 const struct GNUNET_MessageHeader *hdr)
1322{
1323 uint16_t len = ntohs (hdr->size);
1324 const char *buf = (const char *) &hdr[1];
1325
1326 (void) cls;
1327 if ('\0' != buf[len - sizeof (*hdr) - 1])
1328 {
1329 GNUNET_break (0);
1330 return GNUNET_SYSERR;
1331 }
1332 return GNUNET_OK;
1333}
1334
1335
1343static void
1345 const struct GNUNET_MessageHeader *msg)
1346{
1347 struct ClientHandle *ch = cls;
1348 const char *url = (const char *) &msg[1];
1349 struct GNUNET_HELLO_Parser *b;
1350
1352 "Local client provided HELLO URL %s\n",
1353 url);
1355 if (NULL == b)
1356 {
1357 GNUNET_break (0);
1359 return;
1360 }
1364 NULL);
1366}
1367
1368
1369/* ************* logic for monitors ************** */
1370
1371
1379static void
1382{
1383 struct ClientHandle *ch = cls;
1384 struct ClientMonitorRecord *r;
1385
1386 r = GNUNET_new (struct ClientMonitorRecord);
1387 r->ch = ch;
1388 r->type = ntohl (msg->type);
1389 r->get = ntohs (msg->get);
1390 r->get_resp = ntohs (msg->get_resp);
1391 r->put = ntohs (msg->put);
1392 if (0 != ntohs (msg->filter_key))
1393 r->key = msg->key;
1396 r);
1398}
1399
1400
1407static void
1409 void *cls,
1411{
1412 struct ClientHandle *ch = cls;
1413
1415 for (struct ClientMonitorRecord *r = monitor_head;
1416 NULL != r;
1417 r = r->next)
1418 {
1419 bool keys_match;
1420
1421 keys_match =
1422 (GNUNET_is_zero (&r->key))
1423 ? (0 == ntohs (msg->filter_key))
1424 : ( (0 != ntohs (msg->filter_key)) &&
1425 (! GNUNET_memcmp (&r->key,
1426 &msg->key)) );
1427 if ( (ch == r->ch) &&
1428 (ntohl (msg->type) == r->type) &&
1429 (r->get == msg->get) &&
1430 (r->get_resp == msg->get_resp) &&
1431 (r->put == msg->put) &&
1432 keys_match)
1433 {
1436 r);
1437 GNUNET_free (r);
1438 return; /* Delete only ONE entry */
1439 }
1440 }
1441}
1442
1443
1450typedef void
1451(*MonitorAction)(void *cls,
1452 struct ClientMonitorRecord *m);
1453
1454
1464static void
1466 const struct GNUNET_HashCode *key,
1467 MonitorAction cb,
1468 void *cb_cls)
1469{
1470 struct ClientHandle **cl = NULL;
1471 unsigned int cl_size = 0;
1472
1473 for (struct ClientMonitorRecord *m = monitor_head;
1474 NULL != m;
1475 m = m->next)
1476 {
1477 bool found = false;
1478
1479 if ( (GNUNET_BLOCK_TYPE_ANY != m->type) &&
1480 (m->type != type) )
1481 continue;
1482 if ( (! GNUNET_is_zero (&m->key)) &&
1483 (0 ==
1485 &m->key)) )
1486 continue;
1487 /* Don't send duplicates */
1488 for (unsigned i = 0; i < cl_size; i++)
1489 if (cl[i] == m->ch)
1490 {
1491 found = true;
1492 break;
1493 }
1494 if (found)
1495 continue;
1497 cl_size,
1498 m->ch);
1499 cb (cb_cls,
1500 m);
1501 }
1502 GNUNET_free (cl);
1503}
1504
1505
1518
1519
1527static void
1528get_action (void *cls,
1529 struct ClientMonitorRecord *m)
1530{
1531 struct GetActionContext *gac = cls;
1532 struct GNUNET_MQ_Envelope *env;
1533 struct GNUNET_DHT_MonitorGetMessage *mmsg;
1534
1535 env = GNUNET_MQ_msg (mmsg,
1537 mmsg->options = htonl (gac->options);
1538 mmsg->type = htonl (gac->type);
1539 mmsg->hop_count = htonl (gac->hop_count);
1541 mmsg->key = *gac->key;
1542 GNUNET_MQ_send (m->ch->mq,
1543 env);
1544}
1545
1546
1547void
1550 uint32_t hop_count,
1552 const struct GNUNET_HashCode *key)
1553{
1554 struct GetActionContext gac = {
1555 .options = options,
1556 .type = type,
1557 .hop_count = hop_count,
1558 .desired_replication_level = desired_replication_level,
1559 .key = key
1560 };
1561
1563 key,
1564 &get_action,
1565 &gac);
1566}
1567
1568
1578
1579
1587static void
1589 struct ClientMonitorRecord *m)
1590{
1591 const struct ResponseActionContext *resp_ctx = cls;
1592 const struct GNUNET_DATACACHE_Block *bd = resp_ctx->bd;
1593 bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1594 struct GNUNET_MQ_Envelope *env;
1596 struct GNUNET_DHT_PathElement *path;
1597 size_t msize;
1598
1599 msize = bd->data_size;
1600 msize += (resp_ctx->get_path_length + bd->put_path_length)
1601 * sizeof(struct GNUNET_DHT_PathElement);
1602 if (truncated)
1603 msize += sizeof (struct GNUNET_PeerIdentity);
1604 env = GNUNET_MQ_msg_extra (mmsg,
1605 msize,
1607 mmsg->type = htonl (bd->type);
1608 mmsg->put_path_length = htonl (bd->put_path_length);
1609 mmsg->get_path_length = htonl (resp_ctx->get_path_length);
1611 mmsg->key = bd->key;
1612 if (truncated)
1613 {
1614 void *tgt = &mmsg[1];
1615
1616 GNUNET_memcpy (tgt,
1617 &bd->trunc_peer,
1618 sizeof (struct GNUNET_PeerIdentity));
1619 path = (struct GNUNET_DHT_PathElement *)
1620 (tgt + sizeof (struct GNUNET_PeerIdentity));
1621 }
1622 else
1623 {
1624 path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
1625 }
1626 GNUNET_memcpy (path,
1627 bd->put_path,
1628 bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
1629 GNUNET_memcpy (path,
1630 resp_ctx->get_path,
1631 resp_ctx->get_path_length
1632 * sizeof(struct GNUNET_DHT_PathElement));
1633 GNUNET_memcpy (&path[resp_ctx->get_path_length],
1634 bd->data,
1635 bd->data_size);
1636 GNUNET_MQ_send (m->ch->mq,
1637 env);
1638}
1639
1640
1641void
1643 const struct GNUNET_DHT_PathElement *get_path,
1644 unsigned int get_path_length)
1645{
1646 struct ResponseActionContext rac = {
1647 .bd = bd,
1648 .get_path = get_path,
1649 .get_path_length = get_path_length
1650 };
1651
1653 &bd->key,
1655 &rac);
1656}
1657
1658
1668
1669
1677static void
1678put_action (void *cls,
1679 struct ClientMonitorRecord *m)
1680{
1681 const struct PutActionContext *put_ctx = cls;
1682 const struct GNUNET_DATACACHE_Block *bd = put_ctx->bd;
1683 bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1684 struct GNUNET_MQ_Envelope *env;
1685 struct GNUNET_DHT_MonitorPutMessage *mmsg;
1686 struct GNUNET_DHT_PathElement *msg_path;
1687 size_t msize;
1688
1689 msize = bd->data_size
1690 + bd->put_path_length
1691 * sizeof(struct GNUNET_DHT_PathElement);
1692 if (truncated)
1693 msize += sizeof (struct GNUNET_PeerIdentity);
1694 env = GNUNET_MQ_msg_extra (mmsg,
1695 msize,
1697 mmsg->options = htonl (bd->ro);
1698 mmsg->type = htonl (bd->type);
1699 mmsg->hop_count = htonl (put_ctx->hop_count);
1701 mmsg->put_path_length = htonl (bd->put_path_length);
1702 mmsg->key = bd->key;
1704 if (truncated)
1705 {
1706 void *tgt = &mmsg[1];
1707
1708 GNUNET_memcpy (tgt,
1709 &bd->trunc_peer,
1710 sizeof (struct GNUNET_PeerIdentity));
1711 msg_path = (struct GNUNET_DHT_PathElement *)
1712 (tgt + sizeof (struct GNUNET_PeerIdentity));
1713 }
1714 else
1715 {
1716 msg_path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
1717 }
1718 GNUNET_memcpy (msg_path,
1719 bd->put_path,
1720 bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
1721 GNUNET_memcpy (&msg_path[bd->put_path_length],
1722 bd->data,
1723 bd->data_size);
1724 GNUNET_MQ_send (m->ch->mq,
1725 env);
1726}
1727
1728
1729void
1731 uint32_t hop_count,
1732 uint32_t desired_replication_level)
1733{
1734 struct PutActionContext put_ctx = {
1735 .bd = bd,
1736 .hop_count = hop_count,
1737 .desired_replication_level = desired_replication_level
1738 };
1739
1741 &bd->key,
1742 &put_action,
1743 &put_ctx);
1744}
1745
1746
1747/* ********************** Initialization logic ***************** */
1748
1749
1753void
1762
1763
1767void
1769{
1770 if (NULL != retry_task)
1771 {
1773 retry_task = NULL;
1774 }
1775}
1776
1777
1784#define GDS_DHT_SERVICE_INIT(name, run) \
1785 GNUNET_SERVICE_MAIN \
1786 (GNUNET_OS_project_data_gnunet (), \
1787 name, \
1788 GNUNET_SERVICE_OPTION_NONE, \
1789 run, \
1790 &client_connect_cb, \
1791 &client_disconnect_cb, \
1792 NULL, \
1793 GNUNET_MQ_hd_var_size (dht_local_put, \
1794 GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT, \
1795 struct GNUNET_DHT_ClientPutMessage, \
1796 NULL), \
1797 GNUNET_MQ_hd_var_size (dht_local_get, \
1798 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET, \
1799 struct GNUNET_DHT_ClientGetMessage, \
1800 NULL), \
1801 GNUNET_MQ_hd_fixed_size (dht_local_get_stop, \
1802 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP, \
1803 struct GNUNET_DHT_ClientGetStopMessage, \
1804 NULL), \
1805 GNUNET_MQ_hd_fixed_size (dht_local_monitor, \
1806 GNUNET_MESSAGE_TYPE_DHT_MONITOR_START, \
1807 struct GNUNET_DHT_MonitorStartStopMessage, \
1808 NULL), \
1809 GNUNET_MQ_hd_fixed_size (dht_local_monitor_stop, \
1810 GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, \
1811 struct GNUNET_DHT_MonitorStartStopMessage, \
1812 NULL), \
1813 GNUNET_MQ_hd_var_size (dht_local_get_result_seen, \
1814 GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, \
1815 struct GNUNET_DHT_ClientGetResultSeenMessage, \
1816 NULL), \
1817 GNUNET_MQ_hd_fixed_size (dht_local_hello_get, \
1818 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET, \
1819 struct GNUNET_MessageHeader, \
1820 NULL), \
1821 GNUNET_MQ_hd_var_size (dht_local_hello_offer, \
1822 GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL, \
1823 struct GNUNET_MessageHeader, \
1824 NULL), \
1825 GNUNET_MQ_handler_end ())
1826
1828
1832void __attribute__ ((destructor))
1833GDS_CLIENTS_done (void)
1834{
1835 if (NULL != retry_heap)
1836 {
1839 retry_heap = NULL;
1840 }
1841 if (NULL != forward_map)
1842 {
1845 forward_map = NULL;
1846 }
1847}
1848
1849
1850/* end of gnunet-service-dht_clients.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition dht.h:34
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int monitor
Monitor ARM activity.
Definition gnunet-arm.c:63
static unsigned int replication_level
Replication level option to use for publishing.
static struct GNUNET_CADET_Channel * ch
Channel handle.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
struct GNUNET_HashCode key
The key used in the DHT.
static int get
Get DID Documement for DID Flag.
Definition gnunet-did.c:63
static struct GNUNET_FS_Handle * ctx
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
struct GNUNET_MessageHeader * GDS_my_hello
Our HELLO.
static void transmit_request(struct ClientQueryRecord *cqr)
Route the given request via the DHT.
void GDS_CLIENTS_process_get(enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, const struct GNUNET_HashCode *key)
Check if some client is monitoring GET messages and notify them in that case.
static void handle_dht_local_get_stop(void *cls, const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
Handler for any generic DHT stop messages, calls the appropriate handler depending on message type (i...
struct GNUNET_PILS_Handle * GDS_pils
Handle for the pils service.
void GDS_CLIENTS_process_get_resp(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_length)
Check if some client is monitoring GET RESP messages and notify them in that case.
static struct ClientMonitorRecord * monitor_head
List of active monitoring requests.
static enum GNUNET_GenericReturnValue forward_reply(void *cls, const struct GNUNET_HashCode *query_hash, void *value)
Iterator over hash map entries that send a given reply to each of the matching clients.
static enum GNUNET_GenericReturnValue reset_retry_backoff(void *cls, const struct GNUNET_HashCode *key, void *value)
Make a client's GET request eligible for immediate re-transmission.
static void handle_dht_local_get(void *cls, const struct GNUNET_DHT_ClientGetMessage *get)
Handler for DHT GET messages from the client.
static enum GNUNET_GenericReturnValue find_by_unique_id(void *cls, const struct GNUNET_HashCode *key, void *value)
Function called for each existing DHT record for the given query.
static enum GNUNET_GenericReturnValue remove_by_unique_id(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over hash map entries that frees all entries that match the given client and unique ID.
static void response_action(void *cls, struct ClientMonitorRecord *m)
Function called on monitors that match a response.
void GDS_CLIENTS_init(void)
Initialize client subsystem.
static struct GNUNET_CONTAINER_Heap * retry_heap
Heap with all of our client's request, sorted by retry time (earliest on top).
struct GNUNET_STATISTICS_Handle * GDS_stats
Handle for the statistics service.
static struct GNUNET_SCHEDULER_Task * retry_task
Task that re-transmits requests (using retry_heap).
static void handle_dht_local_hello_get(void *cls, const struct GNUNET_MessageHeader *msg)
Handler for HELLO GET message.
static void handle_dht_local_monitor_stop(void *cls, const struct GNUNET_DHT_MonitorStartStopMessage *msg)
Handler for monitor stop messages.
static void handle_dht_local_get_result_seen(void *cls, const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
Handler for "GET result seen" messages from the client.
static void cb_forwarded_dht_local_put(void *cls, enum GNUNET_GenericReturnValue forwarded)
static struct GNUNET_CONTAINER_MultiHashMap * forward_map
Hashmap for fast key based lookup, maps keys to struct ClientQueryRecord entries.
static void handle_dht_local_monitor(void *cls, const struct GNUNET_DHT_MonitorStartStopMessage *msg)
Handler for monitor start messages.
void GDS_CLIENTS_done(void)
static void handle_local_result(void *cls, const struct GNUNET_DATACACHE_Block *bd)
Handle a result from local datacache for a GET operation.
struct GNUNET_BLOCK_Context * GDS_block_context
Our handle to the BLOCK library.
struct GNUNET_SERVICE_Handle * GDS_service
Handle for the service.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Functions with this signature are called whenever a local client is connects to us.
void GDS_CLIENTS_retry_requests(void)
Our routing table gained a peer.
void GDS_CLIENTS_process_put(const struct GNUNET_DATACACHE_Block *bd, uint32_t hop_count, uint32_t desired_replication_level)
Check if some client is monitoring PUT messages and notify them in that case.
static enum GNUNET_GenericReturnValue check_dht_local_hello_offer(void *cls, const struct GNUNET_MessageHeader *hdr)
Process a client HELLO message received from the service.
static enum GNUNET_GenericReturnValue check_dht_local_put(void *cls, const struct GNUNET_DHT_ClientPutMessage *dht_msg)
Check DHT PUT messages from the client.
static void for_matching_monitors(enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, MonitorAction cb, void *cb_cls)
Call cb on all monitors that watch for blocks of type and key key.
bool GDS_CLIENTS_handle_reply(const struct GNUNET_DATACACHE_Block *bd, const struct GNUNET_HashCode *query_hash, unsigned int get_path_length, const struct GNUNET_DHT_PathElement *get_path)
Handle a reply we've received from another peer.
static void handle_dht_local_put(void *cls, const struct GNUNET_DHT_ClientPutMessage *dht_msg)
Handler for PUT messages.
static struct ClientMonitorRecord * monitor_tail
List of active monitoring requests.
#define UNROUTED_RETRY_INTERVAL
Upper bound on the retry interval for a GET that we were unable to route anywhere.
#define LOG(kind,...)
void GDS_CLIENTS_stop(void)
Shutdown client subsystem.
static enum GNUNET_GenericReturnValue check_dht_local_get(void *cls, const struct GNUNET_DHT_ClientGetMessage *get)
Check DHT GET messages from the client.
static void handle_dht_local_hello_offer(void *cls, const struct GNUNET_MessageHeader *msg)
Handler for HELLO OFFER message.
#define LOG_TRAFFIC(kind,...)
Should routing details be logged to stderr (for debugging)?
static enum GNUNET_GenericReturnValue check_dht_local_get_result_seen(void *cls, const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
Check "GET result seen" messages from the client.
static void transmit_next_request_task(void *cls)
Task that looks at the retry_heap and transmits all of the requests on the heap that are ready for tr...
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Functions with this signature are called whenever a client is disconnected on the network level.
static void put_action(void *cls, struct ClientMonitorRecord *m)
Function called on monitors that match a PUT.
static void remove_client_query_record(struct ClientQueryRecord *record)
Free data structures associated with the given query.
static void get_action(void *cls, struct ClientMonitorRecord *m)
Function called on monitors that match a GET.
const struct GNUNET_CONFIGURATION_Handle * GDS_cfg
The configuration the DHT service is running with.
void(* MonitorAction)(void *cls, struct ClientMonitorRecord *m)
Function to call by for_matching_monitors().
enum GNUNET_BLOCK_ReplyEvaluationResult GDS_DATACACHE_handle_get(const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, GDS_DATACACHE_GetCallback gc, void *gc_cls)
Handle a GET request we've received from another peer.
void GDS_DATACACHE_handle_put(const struct GNUNET_DATACACHE_Block *bd)
Handle a datum we've received from another peer.
void GDS_try_connect(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
Callback function used to extract URIs from a builder.
enum GNUNET_GenericReturnValue GDS_am_closest_peer(const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom)
Check whether my identity is closer than any known peers.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_get(enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint16_t desired_replication_level, uint16_t hop_count, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size, struct GNUNET_BLOCK_Group *bg, struct GNUNET_CONTAINER_BloomFilter *peer_bf)
Perform a GET operation.
void GDS_NEIGHBOURS_handle_put(const struct GNUNET_DATACACHE_Block *bd, uint16_t desired_replication_level, uint16_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf, GDS_PutOperationCallback cb, void *cb_cls)
Perform a PUT operation.
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
@ GNUNET_BLOCK_TYPE_ANY
Identifier for any block.
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:875
struct GNUNET_PQ_ResultSpec __attribute__
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_BLOCK_group_set_seen(struct GNUNET_BLOCK_Group *bg, const struct GNUNET_HashCode *seen_results, unsigned int seen_results_count)
Update block group to filter out the given results.
Definition block.c:365
enum GNUNET_BLOCK_ReplyEvaluationResult GNUNET_BLOCK_check_reply(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, struct GNUNET_BLOCK_Group *group, const struct GNUNET_HashCode *query, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size)
Function called to validate if a reply is good for a particular query.
Definition block.c:339
enum GNUNET_GenericReturnValue GNUNET_BLOCK_check_block(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size)
Function called to validate a block.
Definition block.c:321
GNUNET_BLOCK_ReplyEvaluationResult
Possible ways for how a block may relate to a query.
void GNUNET_BLOCK_group_destroy(struct GNUNET_BLOCK_Group *bg)
Destroy resources used by a block group.
Definition block.c:194
struct GNUNET_BLOCK_Group * GNUNET_BLOCK_group_create(struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *raw_data, size_t raw_data_size,...)
Create a new block group.
Definition block.c:249
@ GNUNET_BLOCK_REPLY_OK_MORE
Valid result, and there may be more.
@ GNUNET_BLOCK_REPLY_OK_DUPLICATE
Valid result, but suppressed because it is a duplicate.
@ GNUNET_BLOCK_REPLY_OK_LAST
Last possible valid result.
@ GNUNET_BLOCK_REPLY_TYPE_NOT_SUPPORTED
Specified block type not supported by any plugin.
@ GNUNET_BLOCK_REPLY_IRRELEVANT
Block does not match xquery (valid result, not relevant for the request)
struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init(const char *data, size_t size, unsigned int k)
Create a Bloom filter from raw bits.
void GNUNET_CONTAINER_bloomfilter_free(struct GNUNET_CONTAINER_BloomFilter *bf)
Free the space associated with a filter in memory, flush to drive if needed (do not free the space on...
#define GNUNET_CONSTANTS_BLOOMFILTER_K
K-value that must be used for the bloom filters in 'GET' queries.
GNUNET_DHT_RouteOption
Options for routing.
#define GNUNET_DHT_MAXIMUM_REPLICATION_LEVEL
Maximum allowed replication level for all requests.
unsigned int GNUNET_DHT_verify_path(const void *data, size_t data_size, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_len, const struct GNUNET_PeerIdentity *me)
Verify signatures on a path consisting of put_path and get_path in reverse order (starting at the las...
Definition dht_api.c:1354
@ GNUNET_DHT_RO_TRUNCATED
Flag set if the path was truncated.
@ GNUNET_DHT_RO_FIND_APPROXIMATE
Approximate results are fine.
@ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE
Each peer along the way should process the request (otherwise only peers locally closest to the key w...
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void GNUNET_CONTAINER_heap_update_cost(struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost)
Updates the cost of any node in the tree.
struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert(struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost)
Inserts a new element into the heap.
unsigned int GNUNET_CONTAINER_heap_get_size(const struct GNUNET_CONTAINER_Heap *heap)
Get the current size of the heap.
struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create(enum GNUNET_CONTAINER_HeapOrder order)
Create a new heap.
void GNUNET_CONTAINER_heap_destroy(struct GNUNET_CONTAINER_Heap *heap)
Destroys the heap.
@ GNUNET_CONTAINER_HEAP_ORDER_MIN
Heap with the minimum cost at the root.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:380
char * GNUNET_HELLO_parser_to_url(const struct GNUNET_HELLO_Parser *parser)
Generate GNUnet HELLO URI from a parser.
Definition hello-uri.c:867
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_iterate(const struct GNUNET_HELLO_Parser *parser, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a parser.
Definition hello-uri.c:1039
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_msg(const struct GNUNET_MessageHeader *msg, const struct GNUNET_PeerIdentity *pid)
Parse msg.
Definition hello-uri.c:416
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_url(const char *url)
Parse GNUnet HELLO url.
Definition hello-uri.c:727
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:337
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET
Receive information about transiting GETs.
#define GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP
Receive information about transiting GET responses.
#define GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT
Receive information about transiting PUTs.
#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT
Service returns result to client.
#define GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL
HELLO URL send between client and service (in either direction).
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2463
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition time.c:344
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition time.c:667
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static unsigned int size
Size of the "table".
Definition peer.c:68
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct ClientQueryRecord * cqr_tail
Linked list of active queries of this client.
struct GNUNET_SERVICE_Client * client
The handle to this client.
struct GNUNET_MQ_Handle * mq
The message queue to this client.
struct ClientQueryRecord * cqr_head
Linked list of active queries of this client.
Struct containing parameters of monitoring requests.
struct ClientMonitorRecord * next
Next element in DLL.
uint16_t put
Flag whether to notify about PUT messages.
struct ClientMonitorRecord * prev
Previous element in DLL.
struct ClientHandle * ch
Client to notify of these requests.
enum GNUNET_BLOCK_Type type
Type of blocks that are of interest.
int16_t get
Flag whether to notify about GET messages.
struct GNUNET_HashCode key
Key of data of interest.
int16_t get_resp
Flag whether to notify about GET_REPONSE messages.
Entry in the local forwarding map for a client's GET request.
unsigned int seen_replies_count
Number of entries in seen_replies.
size_t xquery_size
Number of bytes in xquery.
struct GNUNET_TIME_Relative retry_frequency
What's the delay between re-try operations that we currently use for this request?
struct ClientQueryRecord * prev
Kept in a DLL with client.
struct GNUNET_CONTAINER_HeapNode * hnode
Pointer to this nodes heap location in the retry-heap (for fast removal)
struct ClientHandle * ch
Client responsible for the request.
struct GNUNET_HashCode * seen_replies
Array of (hashes of) replies we have already seen for this request.
uint64_t unique_id
The unique identifier of this request.
enum GNUNET_DHT_RouteOption msg_options
Any message options for this request.
struct GNUNET_HashCode key
The key this request was about.
enum GNUNET_BLOCK_Type type
The type for the data for the GET request.
const void * xquery
Extended query (see gnunet_block_lib.h), allocated at the end of this struct.
struct GNUNET_TIME_Absolute retry_time
What's the next time we should re-try this request?
struct ClientQueryRecord * next
Kept in a DLL with client.
uint32_t replication
Desired replication level.
Closure for find_by_unique_id().
uint64_t unique_id
Unique ID to look for.
struct ClientQueryRecord * cqr
Where to store the result, if found.
Closure for forward_reply()
const struct GNUNET_DATACACHE_Block * bd
Block details.
const struct GNUNET_DHT_PathElement * get_path
GET path taken.
unsigned int get_path_length
Number of entries in get_path.
struct GNUNET_MQ_Handle * mq
Our control connection to the ARM service.
Handle to an initialized block library.
Definition block.c:55
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition cadet.h:142
Handle to a node in a heap.
Internal representation of the hash map.
Information about a block stored in the datacache.
const struct GNUNET_DHT_PathElement * put_path
PUT path taken by the block, array of peer identities.
enum GNUNET_BLOCK_Type type
Type of the block.
const void * data
Actual block data.
enum GNUNET_DHT_RouteOption ro
Options for routing for the block.
struct GNUNET_PeerIdentity trunc_peer
If the path was truncated, this is the peer ID at which the path was truncated.
struct GNUNET_HashCode key
Key of the block.
size_t data_size
Number of bytes in data.
unsigned int put_path_length
Length of the put_path array.
struct GNUNET_TIME_Absolute expiration_time
When does the block expire?
DHT GET message sent from clients to service.
Definition dht.h:72
DHT GET RESULTS KNOWN message sent from clients to service.
Definition dht.h:114
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN.
Definition dht.h:118
struct GNUNET_HashCode key
The key we are searching for (to make it easy to find the corresponding GET inside the service).
Definition dht.h:129
uint64_t unique_id
Unique ID identifying this request.
Definition dht.h:134
Message which indicates the DHT should cancel outstanding requests and discard any state.
Definition dht.h:44
uint64_t unique_id
Unique ID identifying this request.
Definition dht.h:58
struct GNUNET_HashCode key
Key of this request.
Definition dht.h:63
Message to insert data into the DHT, sent from clients to DHT service.
Definition dht.h:200
struct GNUNET_HashCode key
The key to store the value under.
Definition dht.h:229
uint32_t type
The type of data to insert.
Definition dht.h:209
uint32_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
Definition dht.h:214
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT.
Definition dht.h:204
uint32_t desired_replication_level
Replication level for this message.
Definition dht.h:219
struct GNUNET_TIME_AbsoluteNBO expiration
How long should this data persist?
Definition dht.h:224
Reply to a GET send from the service to a client.
Definition dht.h:144
uint32_t put_path_length
Number of peers recorded in the outgoing path from source to the storgage location of this message.
Definition dht.h:169
uint64_t unique_id
Unique ID of the matching GET request.
Definition dht.h:180
struct GNUNET_TIME_AbsoluteNBO expiration
When does this entry expire?
Definition dht.h:185
struct GNUNET_HashCode key
The key that was searched for.
Definition dht.h:190
uint32_t type
The type for the data.
Definition dht.h:153
uint32_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
Definition dht.h:163
uint32_t get_path_length
The number of peer identities recorded from the storage location to this peer.
Definition dht.h:175
Message to monitor get requests going through peer, DHT service -> clients.
Definition dht.h:334
uint32_t hop_count
Hop count.
Definition dht.h:353
uint32_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
Definition dht.h:343
uint32_t desired_replication_level
Replication level for this message.
Definition dht.h:358
struct GNUNET_HashCode key
The key to store the value under.
Definition dht.h:368
uint32_t type
The type of data in the request.
Definition dht.h:348
Message to monitor get results going through peer, DHT service -> clients.
Definition dht.h:377
struct GNUNET_HashCode key
The key of the corresponding GET request.
Definition dht.h:416
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
Definition dht.h:411
uint32_t type
Content type.
Definition dht.h:386
uint32_t get_path_length
Length of the GET path that follows (if tracked).
Definition dht.h:406
uint32_t put_path_length
Length of the PUT path that follows (if tracked).
Definition dht.h:401
Message to monitor put requests going through peer, DHT service -> clients.
Definition dht.h:239
uint32_t options
Message options, actually an 'enum GNUNET_DHT_RouteOption' value.
Definition dht.h:248
struct GNUNET_TIME_AbsoluteNBO expiration_time
How long should this data persist?
Definition dht.h:274
uint32_t desired_replication_level
Replication level for this message.
Definition dht.h:263
struct GNUNET_HashCode key
The key to store the value under.
Definition dht.h:279
uint32_t hop_count
Hop count so far.
Definition dht.h:258
uint32_t type
The type of data in the request.
Definition dht.h:253
uint32_t put_path_length
Number of peers recorded in the outgoing path from source to the storage location of this message.
Definition dht.h:269
Message to request monitoring messages, clients -> DHT service.
Definition dht.h:291
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
Context for parsing HELLOs.
Definition hello-uri.c:233
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
A handle for the PILS service.
Definition pils_api.c:86
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Handle to a client that is connected to a service.
Definition service.c:249
Handle to a service.
Definition service.c:116
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
Closure for get_action();.
const struct GNUNET_HashCode * key
enum GNUNET_DHT_RouteOption options
struct GNUNET_PeerIdentity trunc_peer
enum GNUNET_BLOCK_Type type
Closure for put_action().
const struct GNUNET_DATACACHE_Block * bd
Closure for remove_by_unique_id().
struct ClientHandle * ch
Client that issued the removal request.
uint64_t unique_id
Unique ID of the request.
Closure for response_action().
const struct GNUNET_DHT_PathElement * get_path
const struct GNUNET_DATACACHE_Block * bd