GNUnet  0.17.6
gnunet-service-dht_clients.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2011, 2016, 2017, 2022 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 
27 #include "platform.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
31 #include "gnunet-service-dht.h"
34 #include "dht.h"
35 
36 
43 #define SANITY_CHECKS 2
44 
48 #define LOG_TRAFFIC(kind, ...) GNUNET_log_from (kind, "dht-traffic", \
49  __VA_ARGS__)
50 
51 #define LOG(kind, ...) GNUNET_log_from (kind, "dht-clients", __VA_ARGS__)
52 
53 
59 struct ClientHandle;
60 
61 
66 {
70  struct GNUNET_HashCode key;
71 
76 
81 
85  struct ClientHandle *ch;
86 
90  const void *xquery;
91 
96 
101 
107 
112 
116  uint64_t unique_id;
117 
121  size_t xquery_size;
122 
126  unsigned int seen_replies_count;
127 
131  uint32_t replication;
132 
137 
141  enum GNUNET_BLOCK_Type type;
142 };
143 
144 
149 {
154 
159 
163  struct ClientHandle *ch;
164 
168  struct GNUNET_HashCode key;
169 
173  enum GNUNET_BLOCK_Type type;
174 
178  int16_t get;
179 
183  int16_t get_resp;
184 
188  uint16_t put;
189 
190 };
191 
192 
199 {
204 
209 
214 
219 };
220 
221 
226 
231 
236 
241 
246 
251 
256 
261 
266 
267 
273 static void
275 {
276  struct ClientHandle *ch = record->ch;
277 
278  GNUNET_CONTAINER_DLL_remove (ch->cqr_head,
279  ch->cqr_tail,
280  record);
283  &record->key,
284  record));
285  if (NULL != record->hnode)
287  GNUNET_array_grow (record->seen_replies,
288  record->seen_replies_count,
289  0);
291 }
292 
293 
303 static void *
304 client_connect_cb (void *cls,
306  struct GNUNET_MQ_Handle *mq)
307 {
308  struct ClientHandle *ch;
309 
310  (void) cls;
311  ch = GNUNET_new (struct ClientHandle);
312  ch->client = client;
313  ch->mq = mq;
314  return ch;
315 }
316 
317 
326 static void
329  void *app_ctx)
330 {
331  struct ClientHandle *ch = app_ctx;
332 
333  (void) cls;
334  (void) client;
336  "Local client %p disconnects\n",
337  ch);
338  {
339  struct ClientMonitorRecord *next;
340 
342  NULL != monitor;
343  monitor = next)
344  {
345  next = monitor->next;
346  if (monitor->ch != ch)
347  continue;
349  monitor_tail,
350  monitor);
352  }
353  }
354 
355  {
356  struct ClientQueryRecord *cqr;
357 
358  while (NULL != (cqr = ch->cqr_head))
360  }
361  GNUNET_free (ch);
362 }
363 
364 
372 static void
374 {
375  struct GNUNET_BLOCK_Group *bg;
376  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
377 
379  "# GET requests from clients injected",
380  1,
381  GNUNET_NO);
383  cqr->type,
384  NULL, /* raw data */
385  0, /* raw data size */
386  "seen-set-size",
387  cqr->seen_replies_count,
388  NULL);
390  cqr->seen_replies,
391  cqr->seen_replies_count);
392  peer_bf
397  "Initiating GET for %s, replication %u, already have %u replies\n",
398  GNUNET_h2s (&cqr->key),
399  cqr->replication,
400  cqr->seen_replies_count);
402  cqr->msg_options,
403  cqr->replication,
404  0 /* hop count */,
405  &cqr->key,
406  cqr->xquery,
407  cqr->xquery_size,
408  bg,
409  peer_bf);
412 
413  /* Exponential back-off for retries.
414  * max. is #GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */
417 }
418 
419 
427 static void
429 {
430  struct ClientQueryRecord *cqr;
431 
432  (void) cls;
433  retry_task = NULL;
434  while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap)))
435  {
436  cqr->hnode = NULL;
438  {
439  cqr->hnode
441  cqr,
442  cqr->retry_time.abs_value_us);
443  retry_task
446  NULL);
447  return;
448  }
449  transmit_request (cqr);
450  cqr->hnode
452  cqr,
453  cqr->retry_time.abs_value_us);
454  }
455 }
456 
457 
465 static enum GNUNET_GenericReturnValue
466 check_dht_local_put (void *cls,
467  const struct GNUNET_DHT_ClientPutMessage *dht_msg)
468 {
469  uint32_t replication_level = ntohl (dht_msg->desired_replication_level);
470 
471  (void) cls;
473  {
474  GNUNET_break_op (0);
475  return GNUNET_SYSERR;
476  }
477  return GNUNET_OK;
478 }
479 
480 
487 static void
489  const struct GNUNET_DHT_ClientPutMessage *dht_msg)
490 {
491  struct ClientHandle *ch = cls;
492  uint16_t size = ntohs (dht_msg->header.size);
493  uint32_t replication_level
494  = ntohl (dht_msg->desired_replication_level);
495  struct GNUNET_DATACACHE_Block bd = {
496  .key = dht_msg->key,
497  .expiration_time = GNUNET_TIME_absolute_ntoh (dht_msg->expiration),
498  .data = &dht_msg[1],
499  .data_size = size - sizeof (*dht_msg),
500  .type = ntohl (dht_msg->type),
501  .ro = (enum GNUNET_DHT_RouteOption) ntohl (dht_msg->options)
502  };
503 
505  "Handling local PUT of %lu-bytes for query %s of type %u\n",
506  (unsigned long) (size - sizeof(struct GNUNET_DHT_ClientPutMessage)),
507  GNUNET_h2s (&dht_msg->key),
508  (unsigned int) bd.type);
509  if (GNUNET_OK !=
511  bd.type,
512  bd.data,
513  bd.data_size))
514  {
515  GNUNET_break (0);
516  return;
517  }
519  "# PUT requests received from clients",
520  1,
521  GNUNET_NO);
523  "CLIENT-PUT %s\n",
524  GNUNET_h2s_full (&dht_msg->key));
525  /* give to local clients */
527  &bd.key,
528  0, NULL /* get path */));
529 
530  {
531  struct GNUNET_CONTAINER_BloomFilter *peer_bf;
532 
533  peer_bf
537  /* store locally */
538  if ( (0 != (bd.ro & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) ||
539  (GDS_am_closest_peer (&dht_msg->key,
540  peer_bf)))
542  /* route to other peers */
543  if (GNUNET_OK !=
546  0 /* hop count */,
547  peer_bf))
548  {
550  "# Local PUT requests not routed",
551  1,
552  GNUNET_NO);
553  }
555  }
557  &bd,
558  0, /* hop count */
561 }
562 
563 
570 static void
572  const struct GNUNET_DATACACHE_Block *bd)
573 {
575  "Datacache provided result for query key %s\n",
576  GNUNET_h2s (&bd->key));
578  &bd->key,
579  0, NULL /* get_path */));
580 }
581 
582 
590 static enum GNUNET_GenericReturnValue
591 check_dht_local_get (void *cls,
592  const struct GNUNET_DHT_ClientGetMessage *get)
593 {
594  (void) cls;
595  (void) get;
596  /* always well-formed */
597  return GNUNET_OK;
598 }
599 
600 
607 static void
609  const struct GNUNET_DHT_ClientGetMessage *get)
610 {
611  struct ClientHandle *ch = cls;
612  struct ClientQueryRecord *cqr;
613  uint16_t size = ntohs (get->header.size);
614  const char *xquery = (const char *) &get[1];
615  size_t xquery_size = size - sizeof(struct GNUNET_DHT_ClientGetMessage);
616 
618  "Received GET request for %s from local client %p, xq: %.*s\n",
619  GNUNET_h2s (&get->key),
620  ch->client,
621  (int) xquery_size,
622  xquery);
624  "# GET requests received from clients",
625  1,
626  GNUNET_NO);
628  "CLIENT-GET %s\n",
629  GNUNET_h2s_full (&get->key));
630 
631  cqr = GNUNET_malloc (sizeof(struct ClientQueryRecord) + xquery_size);
632  cqr->key = get->key;
633  cqr->ch = ch;
634  cqr->xquery = (const void *) &cqr[1];
635  GNUNET_memcpy (&cqr[1],
636  xquery,
637  xquery_size);
639  cqr,
640  0);
643  cqr->unique_id = get->unique_id;
644  cqr->xquery_size = xquery_size;
645  cqr->replication = ntohl (get->desired_replication_level);
646  cqr->msg_options = (enum GNUNET_DHT_RouteOption) ntohl (get->options);
647  cqr->type = ntohl (get->type);
648  GNUNET_CONTAINER_DLL_insert (ch->cqr_head,
649  ch->cqr_tail,
650  cqr);
652  &cqr->key,
653  cqr,
656  cqr->type,
657  0, /* hop count */
658  cqr->replication,
659  &get->key);
660  /* start remote requests */
661  if (NULL != retry_task)
664  NULL);
665  /* perform local lookup */
667  cqr->type,
668  cqr->xquery,
669  xquery_size,
670  NULL,
672  ch);
674 }
675 
676 
681 {
686 
690  uint64_t unique_id;
691 };
692 
693 
704 static enum GNUNET_GenericReturnValue
705 find_by_unique_id (void *cls,
706  const struct GNUNET_HashCode *key,
707  void *value)
708 {
709  struct FindByUniqueIdContext *fui_ctx = cls;
710  struct ClientQueryRecord *cqr = value;
711 
712  if (cqr->unique_id != fui_ctx->unique_id)
713  return GNUNET_YES;
714  fui_ctx->cqr = cqr;
715  return GNUNET_NO;
716 }
717 
718 
726 static enum GNUNET_GenericReturnValue
728  void *cls,
729  const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
730 {
731  uint16_t size = ntohs (seen->header.size);
732  unsigned int hash_count =
733  (size - sizeof(*seen))
734  / sizeof(struct GNUNET_HashCode);
735 
736  if (size != sizeof(*seen) + hash_count * sizeof(struct GNUNET_HashCode))
737  {
738  GNUNET_break (0);
739  return GNUNET_SYSERR;
740  }
741  return GNUNET_OK;
742 }
743 
744 
751 static void
753  void *cls,
754  const struct GNUNET_DHT_ClientGetResultSeenMessage *seen)
755 {
756  struct ClientHandle *ch = cls;
757  uint16_t size = ntohs (seen->header.size);
758  unsigned int hash_count = (size - sizeof(*seen))
759  / sizeof(struct GNUNET_HashCode);
760  const struct GNUNET_HashCode *hc = (const struct GNUNET_HashCode*) &seen[1];
761  struct FindByUniqueIdContext fui_ctx = {
762  .unique_id = seen->unique_id
763  };
764  unsigned int old_count;
765  struct ClientQueryRecord *cqr;
766 
768  &seen->key,
770  &fui_ctx);
771  if (NULL == (cqr = fui_ctx.cqr))
772  {
773  GNUNET_break (0);
774  GNUNET_SERVICE_client_drop (ch->client);
775  return;
776  }
777  /* finally, update 'seen' list */
778  old_count = cqr->seen_replies_count;
780  cqr->seen_replies_count,
781  cqr->seen_replies_count + hash_count);
782  GNUNET_memcpy (&cqr->seen_replies[old_count],
783  hc,
784  sizeof(struct GNUNET_HashCode) * hash_count);
785 }
786 
787 
792 {
796  struct ClientHandle *ch;
797 
801  uint64_t unique_id;
802 };
803 
804 
814 static enum GNUNET_GenericReturnValue
815 remove_by_unique_id (void *cls,
816  const struct GNUNET_HashCode *key,
817  void *value)
818 {
819  const struct RemoveByUniqueIdContext *ctx = cls;
820  struct ClientQueryRecord *cqr = value;
821 
822  if (cqr->unique_id != ctx->unique_id)
823  return GNUNET_YES;
825  "Removing client %p's record for key %s (by unique id)\n",
826  ctx->ch->client,
827  GNUNET_h2s (key));
829  return GNUNET_YES;
830 }
831 
832 
841 static void
843  void *cls,
844  const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg)
845 {
846  struct ClientHandle *ch = cls;
848 
850  "# GET STOP requests received from clients",
851  1,
852  GNUNET_NO);
854  "Received GET STOP request for %s from local client %p\n",
855  GNUNET_h2s (&dht_stop_msg->key),
856  ch->client);
857  ctx.ch = ch;
858  ctx.unique_id = dht_stop_msg->unique_id;
860  &dht_stop_msg->key,
862  &ctx);
864 }
865 
866 
871 {
875  const struct GNUNET_DATACACHE_Block *bd;
876 
881 
885  unsigned int get_path_length;
886 
887 };
888 
889 
901 static enum GNUNET_GenericReturnValue
902 forward_reply (void *cls,
903  const struct GNUNET_HashCode *query_hash,
904  void *value)
905 {
906  struct ForwardReplyContext *frc = cls;
907  struct ClientQueryRecord *record = value;
908  const struct GNUNET_DATACACHE_Block *bd = frc->bd;
909  struct GNUNET_MQ_Envelope *env;
910  struct GNUNET_DHT_ClientResultMessage *reply;
912  bool do_free;
913  struct GNUNET_HashCode ch;
914  struct GNUNET_DHT_PathElement *paths;
915  bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
916  size_t xsize = bd->data_size;
917 
919  "CLIENT-RESULT %s\n",
920  GNUNET_h2s_full (&bd->key));
921  if ( (record->type != GNUNET_BLOCK_TYPE_ANY) &&
922  (record->type != bd->type) )
923  {
925  "Record type mismatch, not passing request for key %s to local client\n",
926  GNUNET_h2s (&bd->key));
928  "# Key match, type mismatches in REPLY to CLIENT",
929  1,
930  GNUNET_NO);
931  return GNUNET_YES; /* type mismatch */
932  }
933  if ( (0 == (record->msg_options & GNUNET_DHT_RO_FIND_APPROXIMATE)) &&
934  (0 != GNUNET_memcmp (&bd->key,
935  query_hash)) )
936  {
938  "# Inexact key match, but exact match required",
939  1,
940  GNUNET_NO);
941  return GNUNET_YES; /* type mismatch */
942  }
944  bd->data_size,
945  &ch);
946  for (unsigned int i = 0; i < record->seen_replies_count; i++)
947  if (0 ==
948  GNUNET_memcmp (&record->seen_replies[i],
949  &ch))
950  {
952  "Duplicate reply, not passing request for key %s to local client\n",
953  GNUNET_h2s (&bd->key));
955  "# Duplicate REPLIES to CLIENT request dropped",
956  1,
957  GNUNET_NO);
958  return GNUNET_YES; /* duplicate */
959  }
960  eval
962  record->type,
963  NULL,
964  &bd->key,
965  record->xquery,
966  record->xquery_size,
967  bd->data,
968  bd->data_size);
970  "Evaluation result is %d for key %s for local client's query\n",
971  (int) eval,
972  GNUNET_h2s (&bd->key));
973  switch (eval)
974  {
976  do_free = true;
977  break;
980  GNUNET_array_append (record->seen_replies,
981  record->seen_replies_count,
982  ch);
983  do_free = false;
984  break;
986  /* should be impossible to encounter here */
987  GNUNET_break (0);
988  return GNUNET_YES;
990  return GNUNET_YES;
991  default:
992  GNUNET_break (0);
993  return GNUNET_NO;
994  }
996  "# RESULTS queued for clients",
997  1,
998  GNUNET_NO);
999  xsize += (frc->get_path_length + bd->put_path_length)
1000  * sizeof(struct GNUNET_DHT_PathElement);
1001  if (truncated)
1002  xsize += sizeof (struct GNUNET_PeerIdentity);
1003 
1004 #if SUPER_REDUNDANT_CHECK
1005  GNUNET_break (0 ==
1007  bd->data_size,
1008  bd->expiration_time,
1009  truncated
1010  ? &bd->trunc_peer
1011  : NULL,
1012  bd->put_path,
1013  bd->put_path_length,
1014  frc->get_path,
1015  frc->get_path_length,
1016  &GDS_my_identity));
1017 #endif
1018 
1019  env = GNUNET_MQ_msg_extra (reply,
1020  xsize,
1022  reply->type = htonl (bd->type);
1023  reply->options = htonl (bd->ro);
1024  reply->get_path_length = htonl (frc->get_path_length);
1025  reply->put_path_length = htonl (bd->put_path_length);
1026  reply->unique_id = record->unique_id;
1028  reply->key = *query_hash;
1029  if (truncated)
1030  {
1031  void *tgt = &reply[1];
1032 
1033  GNUNET_memcpy (tgt,
1034  &bd->trunc_peer,
1035  sizeof (struct GNUNET_PeerIdentity));
1036  paths = (struct GNUNET_DHT_PathElement *)
1037  (tgt + sizeof (struct GNUNET_PeerIdentity));
1038  }
1039  else
1040  {
1041  paths = (struct GNUNET_DHT_PathElement *) &reply[1];
1042  }
1043  GNUNET_memcpy (paths,
1044  bd->put_path,
1045  sizeof(struct GNUNET_DHT_PathElement)
1046  * bd->put_path_length);
1047  GNUNET_memcpy (&paths[bd->put_path_length],
1048  frc->get_path,
1049  sizeof(struct GNUNET_DHT_PathElement)
1050  * frc->get_path_length);
1051  GNUNET_memcpy (&paths[frc->get_path_length + bd->put_path_length],
1052  bd->data,
1053  bd->data_size);
1055  "Sending reply to query %s for client %p\n",
1056  GNUNET_h2s (query_hash),
1057  record->ch->client);
1058  GNUNET_MQ_send (record->ch->mq,
1059  env);
1060  if (GNUNET_YES == do_free)
1062  return GNUNET_YES;
1063 }
1064 
1065 
1066 bool
1068  const struct GNUNET_HashCode *query_hash,
1069  unsigned int get_path_length,
1070  const struct GNUNET_DHT_PathElement *get_path)
1071 {
1072  struct ForwardReplyContext frc;
1073  size_t msize = sizeof (struct GNUNET_DHT_ClientResultMessage)
1074  + bd->data_size
1076  * sizeof(struct GNUNET_DHT_PathElement);
1077  bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1078 
1079  if (msize >= GNUNET_MAX_MESSAGE_SIZE)
1080  {
1081  GNUNET_break (0);
1082  return false;
1083  }
1084 #if SANITY_CHECKS > 1
1085  if (0 !=
1087  bd->data_size,
1088  bd->expiration_time,
1089  truncated
1090  ? &bd->trunc_peer
1091  : NULL,
1092  bd->put_path,
1093  bd->put_path_length,
1094  get_path,
1095  get_path_length,
1096  &GDS_my_identity))
1097  {
1098  GNUNET_break (0);
1099  return false;
1100  }
1101 #endif
1102  frc.bd = bd;
1103  frc.get_path = get_path;
1104  frc.get_path_length = get_path_length;
1106  "Forwarding reply for query hash %s with GPL %u and PPL %u to client\n",
1107  GNUNET_h2s (query_hash),
1108  get_path_length,
1109  bd->put_path_length);
1110  if (0 ==
1112  query_hash,
1113  &forward_reply,
1114  &frc))
1115  {
1117  "No matching client for reply for query %s\n",
1118  GNUNET_h2s (query_hash));
1120  "# REPLIES ignored for CLIENTS (no match)",
1121  1,
1122  GNUNET_NO);
1123  }
1124  return true;
1125 }
1126 
1127 
1128 /* **************** HELLO logic ***************** */
1129 
1138 static void
1140  const struct GNUNET_MessageHeader *msg)
1141 {
1142  struct ClientHandle *ch = cls;
1145  size_t slen = strlen (url) + 1;
1146  struct GNUNET_MessageHeader *hdr;
1147  struct GNUNET_MQ_Envelope *env;
1148 
1150  "Handling request from local client for my HELLO\n");
1151  env = GNUNET_MQ_msg_extra (hdr,
1152  slen,
1154  memcpy (&hdr[1],
1155  url,
1156  slen);
1157  GNUNET_free (url);
1158  GNUNET_MQ_send (ch->mq,
1159  env);
1161 }
1162 
1163 
1171 static enum GNUNET_GenericReturnValue
1172 check_dht_local_hello_offer (void *cls,
1173  const struct GNUNET_MessageHeader *hdr)
1174 {
1175  uint16_t len = ntohs (hdr->size);
1176  const char *buf = (const char *) &hdr[1];
1177 
1178  (void) cls;
1179  if ('\0' != buf[len - sizeof (*hdr) - 1])
1180  {
1181  GNUNET_break (0);
1182  return GNUNET_SYSERR;
1183  }
1184  return GNUNET_OK;
1185 }
1186 
1187 
1195 static void
1197  const struct GNUNET_MessageHeader *msg)
1198 {
1199  struct ClientHandle *ch = cls;
1200  const char *url = (const char *) &msg[1];
1201  struct GNUNET_HELLO_Builder *b;
1202  struct GNUNET_PeerIdentity pid;
1203 
1205  "Local client provided HELLO URL %s\n",
1206  url);
1208  if (NULL == b)
1209  {
1210  GNUNET_break (0);
1211  GNUNET_SERVICE_client_drop (ch->client);
1212  return;
1213  }
1216  &pid,
1217  &GDS_try_connect,
1218  &pid);
1220 }
1221 
1222 
1223 /* ************* logic for monitors ************** */
1224 
1225 
1233 static void
1236 {
1237  struct ClientHandle *ch = cls;
1238  struct ClientMonitorRecord *r;
1239 
1240  r = GNUNET_new (struct ClientMonitorRecord);
1241  r->ch = ch;
1242  r->type = ntohl (msg->type);
1243  r->get = ntohs (msg->get);
1244  r->get_resp = ntohs (msg->get_resp);
1245  r->put = ntohs (msg->put);
1246  if (0 != ntohs (msg->filter_key))
1247  r->key = msg->key;
1249  monitor_tail,
1250  r);
1252 }
1253 
1254 
1261 static void
1263  void *cls,
1265 {
1266  struct ClientHandle *ch = cls;
1267 
1269  for (struct ClientMonitorRecord *r = monitor_head;
1270  NULL != r;
1271  r = r->next)
1272  {
1273  bool keys_match;
1274 
1275  keys_match =
1276  (GNUNET_is_zero (&r->key))
1277  ? (0 == ntohs (msg->filter_key))
1278  : ( (0 != ntohs (msg->filter_key)) &&
1279  (! GNUNET_memcmp (&r->key,
1280  &msg->key)) );
1281  if ( (ch == r->ch) &&
1282  (ntohl (msg->type) == r->type) &&
1283  (r->get == msg->get) &&
1284  (r->get_resp == msg->get_resp) &&
1285  (r->put == msg->put) &&
1286  keys_match)
1287  {
1289  monitor_tail,
1290  r);
1291  GNUNET_free (r);
1292  return; /* Delete only ONE entry */
1293  }
1294  }
1295 }
1296 
1297 
1304 typedef void
1305 (*MonitorAction)(void *cls,
1306  struct ClientMonitorRecord *m);
1307 
1308 
1318 static void
1320  const struct GNUNET_HashCode *key,
1321  MonitorAction cb,
1322  void *cb_cls)
1323 {
1324  struct ClientHandle **cl = NULL;
1325  unsigned int cl_size = 0;
1326 
1327  for (struct ClientMonitorRecord *m = monitor_head;
1328  NULL != m;
1329  m = m->next)
1330  {
1331  bool found = false;
1332 
1333  if ( (GNUNET_BLOCK_TYPE_ANY != m->type) &&
1334  (m->type != type) )
1335  continue;
1336  if ( (! GNUNET_is_zero (&m->key)) &&
1337  (0 ==
1338  GNUNET_memcmp (key,
1339  &m->key)) )
1340  continue;
1341  /* Don't send duplicates */
1342  for (unsigned i = 0; i < cl_size; i++)
1343  if (cl[i] == m->ch)
1344  {
1345  found = true;
1346  break;
1347  }
1348  if (found)
1349  continue;
1350  GNUNET_array_append (cl,
1351  cl_size,
1352  m->ch);
1353  cb (cb_cls,
1354  m);
1355  }
1356  GNUNET_free (cl);
1357 }
1358 
1359 
1364 {
1366  enum GNUNET_BLOCK_Type type;
1367  uint32_t hop_count;
1370  const struct GNUNET_HashCode *key;
1371 };
1372 
1373 
1381 static void
1382 get_action (void *cls,
1383  struct ClientMonitorRecord *m)
1384 {
1385  struct GetActionContext *gac = cls;
1386  struct GNUNET_MQ_Envelope *env;
1387  struct GNUNET_DHT_MonitorGetMessage *mmsg;
1388 
1389  env = GNUNET_MQ_msg (mmsg,
1391  mmsg->options = htonl (gac->options);
1392  mmsg->type = htonl (gac->type);
1393  mmsg->hop_count = htonl (gac->hop_count);
1395  mmsg->key = *gac->key;
1396  GNUNET_MQ_send (m->ch->mq,
1397  env);
1398 }
1399 
1400 
1401 void
1403  enum GNUNET_BLOCK_Type type,
1404  uint32_t hop_count,
1405  uint32_t desired_replication_level,
1406  const struct GNUNET_HashCode *key)
1407 {
1408  struct GetActionContext gac = {
1409  .options = options,
1410  .type = type,
1411  .hop_count = hop_count,
1412  .desired_replication_level = desired_replication_level,
1413  .key = key
1414  };
1415 
1417  key,
1418  &get_action,
1419  &gac);
1420 }
1421 
1422 
1427 {
1430  unsigned int get_path_length;
1431 };
1432 
1433 
1441 static void
1442 response_action (void *cls,
1443  struct ClientMonitorRecord *m)
1444 {
1445  const struct ResponseActionContext *resp_ctx = cls;
1446  const struct GNUNET_DATACACHE_Block *bd = resp_ctx->bd;
1447  bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1448  struct GNUNET_MQ_Envelope *env;
1449  struct GNUNET_DHT_MonitorGetRespMessage *mmsg;
1450  struct GNUNET_DHT_PathElement *path;
1451  size_t msize;
1452 
1453  msize = bd->data_size;
1454  msize += (resp_ctx->get_path_length + bd->put_path_length)
1455  * sizeof(struct GNUNET_DHT_PathElement);
1456  if (truncated)
1457  msize += sizeof (struct GNUNET_PeerIdentity);
1458  env = GNUNET_MQ_msg_extra (mmsg,
1459  msize,
1461  mmsg->type = htonl (bd->type);
1462  mmsg->put_path_length = htonl (bd->put_path_length);
1463  mmsg->get_path_length = htonl (resp_ctx->get_path_length);
1465  mmsg->key = bd->key;
1466  if (truncated)
1467  {
1468  void *tgt = &mmsg[1];
1469 
1470  GNUNET_memcpy (tgt,
1471  &bd->trunc_peer,
1472  sizeof (struct GNUNET_PeerIdentity));
1473  path = (struct GNUNET_DHT_PathElement *)
1474  (tgt + sizeof (struct GNUNET_PeerIdentity));
1475  }
1476  else
1477  {
1478  path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
1479  }
1480  GNUNET_memcpy (path,
1481  bd->put_path,
1482  bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
1483  GNUNET_memcpy (path,
1484  resp_ctx->get_path,
1485  resp_ctx->get_path_length
1486  * sizeof(struct GNUNET_DHT_PathElement));
1487  GNUNET_memcpy (&path[resp_ctx->get_path_length],
1488  bd->data,
1489  bd->data_size);
1490  GNUNET_MQ_send (m->ch->mq,
1491  env);
1492 }
1493 
1494 
1495 void
1497  const struct GNUNET_DHT_PathElement *get_path,
1498  unsigned int get_path_length)
1499 {
1500  struct ResponseActionContext rac = {
1501  .bd = bd,
1502  .get_path = get_path,
1503  .get_path_length = get_path_length
1504  };
1505 
1507  &bd->key,
1508  &response_action,
1509  &rac);
1510 }
1511 
1512 
1517 {
1519  uint32_t hop_count;
1521 };
1522 
1523 
1531 static void
1532 put_action (void *cls,
1533  struct ClientMonitorRecord *m)
1534 {
1535  const struct PutActionContext *put_ctx = cls;
1536  const struct GNUNET_DATACACHE_Block *bd = put_ctx->bd;
1537  bool truncated = (0 != (bd->ro & GNUNET_DHT_RO_TRUNCATED));
1538  struct GNUNET_MQ_Envelope *env;
1539  struct GNUNET_DHT_MonitorPutMessage *mmsg;
1540  struct GNUNET_DHT_PathElement *msg_path;
1541  size_t msize;
1542 
1543  msize = bd->data_size
1544  + bd->put_path_length
1545  * sizeof(struct GNUNET_DHT_PathElement);
1546  if (truncated)
1547  msize += sizeof (struct GNUNET_PeerIdentity);
1548  env = GNUNET_MQ_msg_extra (mmsg,
1549  msize,
1551  mmsg->options = htonl (bd->ro);
1552  mmsg->type = htonl (bd->type);
1553  mmsg->hop_count = htonl (put_ctx->hop_count);
1554  mmsg->desired_replication_level = htonl (put_ctx->desired_replication_level);
1555  mmsg->put_path_length = htonl (bd->put_path_length);
1556  mmsg->key = bd->key;
1558  if (truncated)
1559  {
1560  void *tgt = &mmsg[1];
1561 
1562  GNUNET_memcpy (tgt,
1563  &bd->trunc_peer,
1564  sizeof (struct GNUNET_PeerIdentity));
1565  msg_path = (struct GNUNET_DHT_PathElement *)
1566  (tgt + sizeof (struct GNUNET_PeerIdentity));
1567  }
1568  else
1569  {
1570  msg_path = (struct GNUNET_DHT_PathElement *) &mmsg[1];
1571  }
1572  GNUNET_memcpy (msg_path,
1573  bd->put_path,
1574  bd->put_path_length * sizeof(struct GNUNET_DHT_PathElement));
1575  GNUNET_memcpy (&msg_path[bd->put_path_length],
1576  bd->data,
1577  bd->data_size);
1578  GNUNET_MQ_send (m->ch->mq,
1579  env);
1580 }
1581 
1582 
1583 void
1585  uint32_t hop_count,
1586  uint32_t desired_replication_level)
1587 {
1588  struct PutActionContext put_ctx = {
1589  .bd = bd,
1590  .hop_count = hop_count,
1591  .desired_replication_level = desired_replication_level
1592  };
1593 
1595  &bd->key,
1596  &put_action,
1597  &put_ctx);
1598 }
1599 
1600 
1601 /* ********************** Initialization logic ***************** */
1602 
1603 
1609 static void
1611 {
1612  forward_map
1614  GNUNET_YES);
1615  retry_heap
1617 }
1618 
1619 
1623 static void
1625 {
1626  if (NULL != retry_task)
1627  {
1629  retry_task = NULL;
1630  }
1631 }
1632 
1633 
1640 #define GDS_DHT_SERVICE_INIT(name, run) \
1641  GNUNET_SERVICE_MAIN \
1642  (name, \
1643  GNUNET_SERVICE_OPTION_NONE, \
1644  run, \
1645  &client_connect_cb, \
1646  &client_disconnect_cb, \
1647  NULL, \
1648  GNUNET_MQ_hd_var_size (dht_local_put, \
1649  GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT, \
1650  struct GNUNET_DHT_ClientPutMessage, \
1651  NULL), \
1652  GNUNET_MQ_hd_var_size (dht_local_get, \
1653  GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET, \
1654  struct GNUNET_DHT_ClientGetMessage, \
1655  NULL), \
1656  GNUNET_MQ_hd_fixed_size (dht_local_get_stop, \
1657  GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP, \
1658  struct GNUNET_DHT_ClientGetStopMessage, \
1659  NULL), \
1660  GNUNET_MQ_hd_fixed_size (dht_local_monitor, \
1661  GNUNET_MESSAGE_TYPE_DHT_MONITOR_START, \
1662  struct GNUNET_DHT_MonitorStartStopMessage, \
1663  NULL), \
1664  GNUNET_MQ_hd_fixed_size (dht_local_monitor_stop, \
1665  GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, \
1666  struct GNUNET_DHT_MonitorStartStopMessage, \
1667  NULL), \
1668  GNUNET_MQ_hd_var_size (dht_local_get_result_seen, \
1669  GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, \
1670  struct GNUNET_DHT_ClientGetResultSeenMessage, \
1671  NULL), \
1672  GNUNET_MQ_hd_fixed_size (dht_local_hello_get, \
1673  GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_GET, \
1674  struct GNUNET_MessageHeader, \
1675  NULL), \
1676  GNUNET_MQ_hd_var_size (dht_local_hello_offer, \
1677  GNUNET_MESSAGE_TYPE_DHT_CLIENT_HELLO_URL, \
1678  struct GNUNET_MessageHeader, \
1679  NULL), \
1680  GNUNET_MQ_handler_end ())
1681 
1682 
1686 void __attribute__ ((destructor))
1687 GDS_CLIENTS_done ()
1688 {
1689  if (NULL != retry_heap)
1690  {
1693  retry_heap = NULL;
1694  }
1695  if (NULL != forward_map)
1696  {
1699  forward_map = NULL;
1700  }
1701 }
1702 
1703 
1704 /* end of gnunet-service-dht_clients.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
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.
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static int monitor
Monitor ARM activity.
Definition: gnunet-arm.c:64
static unsigned int replication_level
Replication level option to use for publishing.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
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:66
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
struct GNUNET_PeerIdentity GDS_my_identity
Identity of this peer.
struct GNUNET_CRYPTO_EddsaPrivateKey GDS_my_private_key
Our private key.
struct GNUNET_HELLO_Builder * GDS_my_hello
Our HELLO.
GNUnet DHT globals.
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...
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 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.
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 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.
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 GDS_CLIENTS_init(void)
Initialize client subsystem.
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.
static void GDS_CLIENTS_stop(void)
Shutdown client subsystem.
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.
#define LOG(kind,...)
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)?
void __attribute__((destructor))
MINIMIZE heap size (way below 128k) since this process doesn't need much.
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.
GNUnet DHT service's datacache integration.
enum GNUNET_GenericReturnValue GDS_NEIGHBOURS_handle_put(const struct GNUNET_DATACACHE_Block *bd, uint16_t desired_replication_level, uint16_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf)
Perform a PUT operation.
void GDS_try_connect(void *cls, 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.
GNUnet DHT routing code.
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
Constants for network protocols.
API to create, modify and access statistics.
#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:360
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:334
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:316
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:192
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:247
@ 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 *bpid, 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:1353
@ 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:41
int GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
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.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
void * GNUNET_CONTAINER_heap_remove_root(struct GNUNET_CONTAINER_Heap *heap)
Remove root of the heap.
void * GNUNET_CONTAINER_heap_remove_node(struct GNUNET_CONTAINER_HeapNode *node)
Removes a node from the heap.
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_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition: hello-uri.c:319
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, struct GNUNET_PeerIdentity *pid, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition: hello-uri.c:822
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_url(const char *url)
Parse GNUnet HELLO url into builder.
Definition: hello-uri.c:416
char * GNUNET_HELLO_builder_to_url(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
Generate GNUnet HELLO URI from a builder.
Definition: hello-uri.c:634
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
#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.
Definition: gnunet_common.h:96
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#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:302
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:56
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:71
#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_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1281
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:1231
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2329
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2248
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:736
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:315
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:637
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition: time.c:668
#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:67
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
Block group data.
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition: cadet.h:143
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 building (or parsing) HELLO URIs.
Definition: hello-uri.c:184
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:86
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition: scheduler.c:135
Handle to a client that is connected to a service.
Definition: service.c:251
Handle to a service.
Definition: service.c:117
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
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model