GNUnet  0.11.x
gnunet-service-rps.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013-2015 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 
26 #include "platform.h"
27 #include "gnunet_applications.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_cadet_service.h"
30 #include "gnunet_core_service.h"
32 #include "gnunet_nse_service.h"
34 #include "rps.h"
35 #include "rps-test_util.h"
39 
40 #include <math.h>
41 #include <inttypes.h>
42 #include <string.h>
43 
44 #define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
45 
46 // TODO check for overflows
47 
48 // TODO align message structs
49 
50 // TODO connect to friends
51 
52 // TODO blacklist? (-> mal peer detection on top of brahms)
53 
54 // hist_size_init, hist_size_max
55 
56 /***********************************************************************
57 * Old gnunet-service-rps_peers.c
58 ***********************************************************************/
59 
63 #define SET_PEER_FLAG(peer_ctx, mask) ((peer_ctx->peer_flags) |= (mask))
64 
68 #define check_peer_flag_set(peer_ctx, mask) \
69  ((peer_ctx->peer_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
70 
74 #define UNSET_PEER_FLAG(peer_ctx, mask) ((peer_ctx->peer_flags) &= ~(mask))
75 
79 #define check_channel_flag_set(channel_flags, mask) \
80  ((*channel_flags) & (mask) ? GNUNET_YES : GNUNET_NO)
81 
85 #define unset_channel_flag(channel_flags, mask) ((*channel_flags) &= ~(mask))
86 
87 
95 {
100 
104  void *op_cls;
105 };
106 
114 {
120 
125 
130 
134  const char *type;
135 };
136 
140 struct ChannelCtx;
141 
151 {
155  struct Sub *sub;
156 
161 
166 
171 
176 
183 
187  unsigned int num_pending_ops;
188 
193 
197  uint32_t peer_flags;
198 
202  struct GNUNET_TIME_Absolute last_message_recv;
203 
207  struct GNUNET_TIME_Absolute last_keepalive;
208 
214 
220  uint32_t round_pull_req;
221 };
222 
227 {
232 
236  void *cls;
237 };
238 
243 {
248 
253 
260 };
261 
262 
263 #if ENABLE_MALICIOUS
264 
268 struct AttackedPeer
269 {
273  struct AttackedPeer *next;
274  struct AttackedPeer *prev;
275 
279  struct GNUNET_PeerIdentity peer_id;
280 };
281 
282 #endif /* ENABLE_MALICIOUS */
283 
288 #define HISTOGRAM_FILE_SLOTS 32
289 
296 #define SIZE_DUMP_FILE (HISTOGRAM_FILE_SLOTS * 5) + 1
297 
304 struct Sub
305 {
309  struct GNUNET_HashCode hash;
310 
315 
320 
325 
330 
336  unsigned int sampler_size_est_min;
337 
344  unsigned int sampler_size_est_need;
345 
349  struct GNUNET_TIME_Relative round_interval;
350 
355 
356 #ifdef TO_FILE_FULL
357 
360  char *file_name_view_log;
361 #endif /* TO_FILE_FULL */
362 
363 #ifdef TO_FILE
364 #ifdef TO_FILE_FULL
365 
368  char *file_name_observed_log;
369 #endif /* TO_FILE_FULL */
370 
375 
380 #endif /* TO_FILE */
381 
386 
391 
397  unsigned int view_size_est_need;
398 
404  unsigned int view_size_est_min;
405 
409  struct View *view;
410 
415 
416  /* === stats === */
417 
421  uint32_t num_rounds;
422 
428  uint32_t push_recv[HISTOGRAM_FILE_SLOTS];
429 
437  uint32_t push_delta[HISTOGRAM_FILE_SLOTS];
438 
445  uint32_t pull_delays[HISTOGRAM_FILE_SLOTS];
446 };
447 
448 
449 /***********************************************************************
450 * Globals
451 ***********************************************************************/
452 
456 static const struct GNUNET_CONFIGURATION_Handle *cfg;
457 
462 
467 
472 
477 
482 
487 static float alpha;
488 
493 static float beta;
494 
498 static struct GNUNET_NSE_Handle *nse;
499 
504 
509 
510 
511 #if ENABLE_MALICIOUS
512 
520 static uint32_t mal_type;
521 
525 static struct GNUNET_PeerIdentity *mal_peers;
526 
531 static struct GNUNET_CONTAINER_MultiPeerMap *mal_peer_set;
532 
536 static uint32_t num_mal_peers;
537 
538 
542 static struct AttackedPeer *att_peers_head;
543 static struct AttackedPeer *att_peers_tail;
544 
549 static struct AttackedPeer *att_peer_index;
550 
555 static struct GNUNET_CONTAINER_MultiPeerMap *att_peer_set;
556 
560 static uint32_t num_attacked_peers;
561 
565 static struct GNUNET_PeerIdentity attacked_peer;
566 
574 static uint32_t push_limit = 10000;
575 #endif /* ENABLE_MALICIOUS */
576 
583 static struct Sub *msub;
584 
589 static const uint32_t num_valid_peers_max = UINT32_MAX;
590 
591 /***********************************************************************
592 * /Globals
593 ***********************************************************************/
594 
595 
596 static void
597 do_round (void *cls);
598 
599 #if ENABLE_MALICIOUS
600 static void
601 do_mal_round (void *cls);
602 
603 #endif /* ENABLE_MALICIOUS */
604 
605 
614 static struct PeerContext *
616  const struct GNUNET_PeerIdentity *peer)
617 {
618  struct PeerContext *ctx;
619  int ret;
620 
621  ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
622  GNUNET_assert (GNUNET_YES == ret);
623  ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
624  GNUNET_assert (NULL != ctx);
625  return ctx;
626 }
627 
628 
640 static int
642  const struct GNUNET_PeerIdentity *peer)
643 {
644  if (NULL != peer_map)
645  {
646  return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
647  }
648  else
649  {
650  return GNUNET_NO;
651  }
652 }
653 
654 
663 static struct PeerContext *
665  const struct GNUNET_PeerIdentity *peer)
666 {
667  struct PeerContext *ctx;
668  int ret;
669 
671 
672  ctx = GNUNET_new (struct PeerContext);
673  ctx->peer_id = *peer;
674  ctx->sub = sub;
675  ret = GNUNET_CONTAINER_multipeermap_put (sub->peer_map, peer, ctx,
677  GNUNET_assert (GNUNET_OK == ret);
678  if (sub == msub)
679  {
680  GNUNET_STATISTICS_set (stats,
681  "# known peers",
683  GNUNET_NO);
684  }
685  return ctx;
686 }
687 
688 
697 static struct PeerContext *
699  const struct GNUNET_PeerIdentity *peer)
700 {
701  if (GNUNET_NO == check_peer_known (sub->peer_map, peer))
702  {
703  return create_peer_ctx (sub, peer);
704  }
705  return get_peer_ctx (sub->peer_map, peer);
706 }
707 
708 
719 static int
720 check_connected (struct PeerContext *peer_ctx)
721 {
722  /* If we don't know about this peer we don't know whether it's online */
723  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
724  &peer_ctx->peer_id))
725  {
726  return GNUNET_NO;
727  }
728  /* Get the context */
729  peer_ctx = get_peer_ctx (peer_ctx->sub->peer_map, &peer_ctx->peer_id);
730  /* If we have no channel to this peer we don't know whether it's online */
731  if ((NULL == peer_ctx->send_channel_ctx) &&
732  (NULL == peer_ctx->recv_channel_ctx))
733  {
734  UNSET_PEER_FLAG (peer_ctx, Peers_ONLINE);
735  return GNUNET_NO;
736  }
737  /* Otherwise (if we have a channel, we know that it's online */
738  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
739  return GNUNET_YES;
740 }
741 
742 
747 {
753  uint32_t index;
754 
758  const struct GNUNET_PeerIdentity *peer;
759 };
760 
761 
777 static int
779  const struct GNUNET_PeerIdentity *peer,
780  void *value)
781 {
782  struct GetRandPeerIteratorCls *iterator_cls = cls;
783 
784  (void) value;
785 
786  if (0 >= iterator_cls->index)
787  {
788  iterator_cls->peer = peer;
789  return GNUNET_NO;
790  }
791  iterator_cls->index--;
792  return GNUNET_YES;
793 }
794 
795 
804 static const struct GNUNET_PeerIdentity *
806 {
807  struct GetRandPeerIteratorCls *iterator_cls;
808  const struct GNUNET_PeerIdentity *ret;
809 
810  iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
813  valid_peers));
814  (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
816  iterator_cls);
817  ret = iterator_cls->peer;
818  GNUNET_free (iterator_cls);
819  return ret;
820 }
821 
822 
834 static int
836  struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
837 {
838  const struct GNUNET_PeerIdentity *rand_peer;
839  int ret;
840 
841  ret = GNUNET_YES;
842  /* Remove random peers until there is space for a new one */
843  while (num_valid_peers_max <=
845  {
846  rand_peer = get_random_peer_from_peermap (valid_peers);
847  GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
848  ret = GNUNET_NO;
849  }
850  (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
852  if (valid_peers == msub->valid_peers)
853  {
854  GNUNET_STATISTICS_set (stats,
855  "# valid peers",
857  GNUNET_NO);
858  }
859  return ret;
860 }
861 
862 
863 static void
864 remove_pending_message (struct PendingMessage *pending_msg, int cancel);
865 
874 static void
875 set_peer_online (struct PeerContext *peer_ctx)
876 {
877  struct GNUNET_PeerIdentity *peer;
878  unsigned int i;
879 
880  peer = &peer_ctx->peer_id;
882  "Peer %s is online and valid, calling %i pending operations on it\n",
883  GNUNET_i2s (peer),
884  peer_ctx->num_pending_ops);
885 
886  if (NULL != peer_ctx->online_check_pending)
887  {
889  "Removing pending online check for peer %s\n",
890  GNUNET_i2s (&peer_ctx->peer_id));
891  // TODO wait until cadet sets mq->cancel_impl
892  // GNUNET_MQ_send_cancel (peer_ctx->online_check_pending->ev);
894  peer_ctx->online_check_pending = NULL;
895  }
896 
897  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
898 
899  /* Call pending operations */
900  for (i = 0; i < peer_ctx->num_pending_ops; i++)
901  {
902  peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
903  }
904  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
905 }
906 
907 
908 static void
909 cleanup_destroyed_channel (void *cls,
910  const struct GNUNET_CADET_Channel *channel);
911 
912 /* Declaration of handlers */
913 static void
914 handle_peer_check (void *cls,
915  const struct GNUNET_MessageHeader *msg);
916 
917 static void
918 handle_peer_push (void *cls,
919  const struct GNUNET_MessageHeader *msg);
920 
921 static void
922 handle_peer_pull_request (void *cls,
923  const struct GNUNET_MessageHeader *msg);
924 
925 static int
926 check_peer_pull_reply (void *cls,
927  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
928 
929 static void
930 handle_peer_pull_reply (void *cls,
931  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
932 
933 /* End declaration of handlers */
934 
942 static struct ChannelCtx *
944 {
945  struct ChannelCtx *channel_ctx;
946 
947  channel_ctx = GNUNET_new (struct ChannelCtx);
948  channel_ctx->peer_ctx = peer_ctx;
949  return channel_ctx;
950 }
951 
952 
958 static void
959 remove_channel_ctx (struct ChannelCtx *channel_ctx)
960 {
961  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
962 
963  if (NULL != channel_ctx->destruction_task)
964  {
966  channel_ctx->destruction_task = NULL;
967  }
968 
969  if (NULL == peer_ctx)
970  return;
971  if (channel_ctx == peer_ctx->send_channel_ctx)
972  {
973  peer_ctx->send_channel_ctx = NULL;
974  peer_ctx->mq = NULL;
975  }
976  else if (channel_ctx == peer_ctx->recv_channel_ctx)
977  {
978  peer_ctx->recv_channel_ctx = NULL;
979  }
980  GNUNET_free (channel_ctx);
981 }
982 
983 
990 struct GNUNET_CADET_Channel *
991 get_channel (struct PeerContext *peer_ctx)
992 {
993  /* There exists a copy-paste-clone in run() */
994  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
995  GNUNET_MQ_hd_fixed_size (peer_check,
997  struct GNUNET_MessageHeader,
998  NULL),
999  GNUNET_MQ_hd_fixed_size (peer_push,
1001  struct GNUNET_MessageHeader,
1002  NULL),
1003  GNUNET_MQ_hd_fixed_size (peer_pull_request,
1005  struct GNUNET_MessageHeader,
1006  NULL),
1007  GNUNET_MQ_hd_var_size (peer_pull_reply,
1010  NULL),
1012  };
1013 
1014 
1015  if (NULL == peer_ctx->send_channel_ctx)
1016  {
1018  "Trying to establish channel to peer %s\n",
1019  GNUNET_i2s (&peer_ctx->peer_id));
1020  peer_ctx->send_channel_ctx = add_channel_ctx (peer_ctx);
1021  peer_ctx->send_channel_ctx->channel =
1022  GNUNET_CADET_channel_create (cadet_handle,
1023  peer_ctx->send_channel_ctx, /* context */
1024  &peer_ctx->peer_id,
1025  &peer_ctx->sub->hash,
1026  NULL, /* WindowSize handler */
1027  &cleanup_destroyed_channel, /* Disconnect handler */
1028  cadet_handlers);
1029  }
1030  GNUNET_assert (NULL != peer_ctx->send_channel_ctx);
1031  GNUNET_assert (NULL != peer_ctx->send_channel_ctx->channel);
1032  return peer_ctx->send_channel_ctx->channel;
1033 }
1034 
1035 
1045 static struct GNUNET_MQ_Handle *
1046 get_mq (struct PeerContext *peer_ctx)
1047 {
1048  if (NULL == peer_ctx->mq)
1049  {
1050  peer_ctx->mq = GNUNET_CADET_get_mq (get_channel (peer_ctx));
1051  }
1052  return peer_ctx->mq;
1053 }
1054 
1055 
1064 static struct PendingMessage *
1066  struct GNUNET_MQ_Envelope *ev,
1067  const char *type)
1068 {
1069  struct PendingMessage *pending_msg;
1070 
1071  pending_msg = GNUNET_new (struct PendingMessage);
1072  pending_msg->ev = ev;
1073  pending_msg->peer_ctx = peer_ctx;
1074  pending_msg->type = type;
1076  peer_ctx->pending_messages_tail,
1077  pending_msg);
1078  return pending_msg;
1079 }
1080 
1081 
1088 static void
1089 remove_pending_message (struct PendingMessage *pending_msg, int cancel)
1090 {
1091  struct PeerContext *peer_ctx;
1092 
1093  (void) cancel;
1094 
1095  peer_ctx = pending_msg->peer_ctx;
1096  GNUNET_assert (NULL != peer_ctx);
1098  peer_ctx->pending_messages_tail,
1099  pending_msg);
1100  // TODO wait for the cadet implementation of message cancellation
1101  // if (GNUNET_YES == cancel)
1102  // {
1103  // GNUNET_MQ_send_cancel (pending_msg->ev);
1104  // }
1105  GNUNET_free (pending_msg);
1106 }
1107 
1108 
1115 static void
1117 {
1118  struct PeerContext *peer_ctx = cls;
1119 
1120  if (NULL != peer_ctx->online_check_pending)
1121  {
1123  "Online check for peer %s was successful\n",
1124  GNUNET_i2s (&peer_ctx->peer_id));
1126  peer_ctx->online_check_pending = NULL;
1127  set_peer_online (peer_ctx);
1128  (void) add_valid_peer (&peer_ctx->peer_id, peer_ctx->sub->valid_peers);
1129  }
1130 }
1131 
1132 
1138 static void
1139 check_peer_online (struct PeerContext *peer_ctx)
1140 {
1142  "Get informed about peer %s getting online\n",
1143  GNUNET_i2s (&peer_ctx->peer_id));
1144 
1145  struct GNUNET_MQ_Handle *mq;
1146  struct GNUNET_MQ_Envelope *ev;
1147 
1149  peer_ctx->online_check_pending =
1150  insert_pending_message (peer_ctx, ev, "Check online");
1151  mq = get_mq (peer_ctx);
1154  peer_ctx);
1155  GNUNET_MQ_send (mq, ev);
1156  if (peer_ctx->sub == msub)
1157  {
1158  GNUNET_STATISTICS_update (stats,
1159  "# pending online checks",
1160  1,
1161  GNUNET_NO);
1162  }
1163 }
1164 
1165 
1178 static int
1179 check_operation_scheduled (const struct PeerContext *peer_ctx,
1180  const PeerOp peer_op)
1181 {
1182  unsigned int i;
1183 
1184  for (i = 0; i < peer_ctx->num_pending_ops; i++)
1185  if (peer_op == peer_ctx->pending_ops[i].op)
1186  return GNUNET_YES;
1187  return GNUNET_NO;
1188 }
1189 
1190 
1196 static void
1197 destroy_channel (struct ChannelCtx *channel_ctx)
1198 {
1199  struct GNUNET_CADET_Channel *channel;
1200 
1201  if (NULL != channel_ctx->destruction_task)
1202  {
1204  channel_ctx->destruction_task = NULL;
1205  }
1206  GNUNET_assert (channel_ctx->channel != NULL);
1207  channel = channel_ctx->channel;
1208  channel_ctx->channel = NULL;
1209  GNUNET_CADET_channel_destroy (channel);
1210  remove_channel_ctx (channel_ctx);
1211 }
1212 
1213 
1221 static void
1223 {
1224  struct ChannelCtx *channel_ctx = cls;
1225 
1226  channel_ctx->destruction_task = NULL;
1227  destroy_channel (channel_ctx);
1228 }
1229 
1230 
1241 static void
1243 {
1244  GNUNET_assert (NULL ==
1245  channel_ctx->destruction_task);
1246  GNUNET_assert (NULL !=
1247  channel_ctx->channel);
1248  channel_ctx->destruction_task =
1250  channel_ctx);
1251 }
1252 
1253 
1267 static int
1269 {
1270  GNUNET_assert (NULL != peer_ctx);
1271  GNUNET_assert (NULL != peer_ctx->sub->peer_map);
1272  if (GNUNET_NO ==
1274  &peer_ctx->peer_id))
1275  {
1276  return GNUNET_NO;
1277  }
1278  SET_PEER_FLAG (peer_ctx, Peers_TO_DESTROY);
1280  "Going to remove peer %s\n",
1281  GNUNET_i2s (&peer_ctx->peer_id));
1282  UNSET_PEER_FLAG (peer_ctx, Peers_ONLINE);
1283 
1284  /* Clear list of pending operations */
1285  // TODO this probably leaks memory
1286  // ('only' the cls to the function. Not sure what to do with it)
1287  GNUNET_array_grow (peer_ctx->pending_ops,
1288  peer_ctx->num_pending_ops,
1289  0);
1290  /* Remove all pending messages */
1291  while (NULL != peer_ctx->pending_messages_head)
1292  {
1294  "Removing unsent %s\n",
1295  peer_ctx->pending_messages_head->type);
1296  /* Cancel pending message, too */
1297  if ((NULL != peer_ctx->online_check_pending) &&
1298  (0 == memcmp (peer_ctx->pending_messages_head,
1299  peer_ctx->online_check_pending,
1300  sizeof(struct PendingMessage))))
1301  {
1302  peer_ctx->online_check_pending = NULL;
1303  if (peer_ctx->sub == msub)
1304  {
1305  GNUNET_STATISTICS_update (stats,
1306  "# pending online checks",
1307  -1,
1308  GNUNET_NO);
1309  }
1310  }
1312  GNUNET_YES);
1313  }
1314 
1315  /* If we are still waiting for notification whether this peer is online
1316  * cancel the according task */
1317  if (NULL != peer_ctx->online_check_pending)
1318  {
1320  "Removing pending online check for peer %s\n",
1321  GNUNET_i2s (&peer_ctx->peer_id));
1322  // TODO wait until cadet sets mq->cancel_impl
1323  // GNUNET_MQ_send_cancel (peer_ctx->online_check_pending->ev);
1325  GNUNET_YES);
1326  peer_ctx->online_check_pending = NULL;
1327  }
1328 
1329  if (NULL != peer_ctx->send_channel_ctx)
1330  {
1331  /* This is possibly called from within channel destruction */
1332  peer_ctx->send_channel_ctx->peer_ctx = NULL;
1334  peer_ctx->send_channel_ctx = NULL;
1335  peer_ctx->mq = NULL;
1336  }
1337  if (NULL != peer_ctx->recv_channel_ctx)
1338  {
1339  /* This is possibly called from within channel destruction */
1340  peer_ctx->recv_channel_ctx->peer_ctx = NULL;
1342  peer_ctx->recv_channel_ctx = NULL;
1343  }
1344 
1345  if (GNUNET_YES !=
1347  &peer_ctx->peer_id))
1348  {
1350  "removing peer from peer_ctx->sub->peer_map failed\n");
1351  }
1352  if (peer_ctx->sub == msub)
1353  {
1354  GNUNET_STATISTICS_set (stats,
1355  "# known peers",
1357  peer_ctx->sub->peer_map),
1358  GNUNET_NO);
1359  }
1360  GNUNET_free (peer_ctx);
1361  return GNUNET_YES;
1362 }
1363 
1364 
1374 static int
1376  const struct GNUNET_PeerIdentity *key,
1377  void *value)
1378 {
1379  struct Sub *sub = cls;
1380 
1381  (void) value;
1382 
1383  destroy_peer (get_peer_ctx (sub->peer_map, key));
1384  return GNUNET_YES;
1385 }
1386 
1387 
1395 static void
1397 {
1398  struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
1399 
1401  "%s was sent.\n",
1402  pending_msg->type);
1403  if (pending_msg->peer_ctx->sub == msub)
1404  {
1405  if (0 == strncmp ("PULL REPLY", pending_msg->type, 10))
1406  GNUNET_STATISTICS_update (stats, "# pull replies sent", 1, GNUNET_NO);
1407  if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12))
1408  GNUNET_STATISTICS_update (stats, "# pull requests sent", 1, GNUNET_NO);
1409  if (0 == strncmp ("PUSH", pending_msg->type, 4))
1410  GNUNET_STATISTICS_update (stats, "# pushes sent", 1, GNUNET_NO);
1411  if ((0 == strncmp ("PULL REQUEST", pending_msg->type, 12)) &&
1412  (NULL != map_single_hop) &&
1414  &pending_msg->
1415  peer_ctx->peer_id)) )
1416  GNUNET_STATISTICS_update (stats,
1417  "# pull requests sent (multi-hop peer)",
1418  1,
1419  GNUNET_NO);
1420  }
1421  /* Do not cancel message */
1422  remove_pending_message (pending_msg, GNUNET_NO);
1423 }
1424 
1425 
1440 static int
1442  const struct GNUNET_PeerIdentity *peer,
1443  void *value)
1444 {
1445  const struct GNUNET_DISK_FileHandle *fh = cls;
1446  char peer_string[128];
1447  int size;
1448  ssize_t ret;
1449 
1450  (void) value;
1451 
1452  if (NULL == peer)
1453  {
1454  return GNUNET_YES;
1455  }
1456  size = GNUNET_snprintf (peer_string,
1457  sizeof(peer_string),
1458  "%s\n",
1459  GNUNET_i2s_full (peer));
1460  GNUNET_assert (53 == size);
1461  ret = GNUNET_DISK_file_write (fh,
1462  peer_string,
1463  size);
1464  GNUNET_assert (size == ret);
1465  return GNUNET_YES;
1466 }
1467 
1468 
1474 static void
1475 store_valid_peers (const struct Sub *sub)
1476 {
1477  struct GNUNET_DISK_FileHandle *fh;
1478  uint32_t number_written_peers;
1479  int ret;
1480 
1481  if (0 == strncmp ("DISABLE", sub->filename_valid_peers, 7))
1482  {
1483  return;
1484  }
1485 
1487  if (GNUNET_SYSERR == ret)
1488  {
1490  "Not able to create directory for file `%s'\n",
1491  sub->filename_valid_peers);
1492  GNUNET_break (0);
1493  }
1494  else if (GNUNET_NO == ret)
1495  {
1497  "Directory for file `%s' exists but is not writable for us\n",
1498  sub->filename_valid_peers);
1499  GNUNET_break (0);
1500  }
1506  if (NULL == fh)
1507  {
1509  "Not able to write valid peers to file `%s'\n",
1510  sub->filename_valid_peers);
1511  return;
1512  }
1514  "Writing %u valid peers to disk\n",
1516  number_written_peers =
1519  fh);
1521  GNUNET_assert (number_written_peers ==
1523 }
1524 
1525 
1535 static const struct GNUNET_PeerIdentity *
1536 s2i_full (const char *string_repr)
1537 {
1538  struct GNUNET_PeerIdentity *peer;
1539  size_t len;
1540  int ret;
1541 
1542  peer = GNUNET_new (struct GNUNET_PeerIdentity);
1543  len = strlen (string_repr);
1544  if (52 > len)
1545  {
1547  "Not able to convert string representation of PeerID to PeerID\n"
1548  "String representation: %s (len %lu) - too short\n",
1549  string_repr,
1550  len);
1551  GNUNET_break (0);
1552  }
1553  else if (52 < len)
1554  {
1555  len = 52;
1556  }
1557  ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
1558  len,
1559  &peer->public_key);
1560  if (GNUNET_OK != ret)
1561  {
1563  "Not able to convert string representation of PeerID to PeerID\n"
1564  "String representation: %s\n",
1565  string_repr);
1566  GNUNET_break (0);
1567  }
1568  return peer;
1569 }
1570 
1571 
1577 static void
1578 restore_valid_peers (const struct Sub *sub)
1579 {
1580  off_t file_size;
1581  uint32_t num_peers;
1582  struct GNUNET_DISK_FileHandle *fh;
1583  char *buf;
1584  ssize_t size_read;
1585  char *iter_buf;
1586  char *str_repr;
1587  const struct GNUNET_PeerIdentity *peer;
1588 
1589  if (0 == strncmp ("DISABLE", sub->filename_valid_peers, 7))
1590  {
1591  return;
1592  }
1593 
1595  {
1596  return;
1597  }
1601  GNUNET_assert (NULL != fh);
1603  num_peers = file_size / 53;
1604  buf = GNUNET_malloc (file_size);
1605  size_read = GNUNET_DISK_file_read (fh, buf, file_size);
1606  GNUNET_assert (size_read == file_size);
1608  "Restoring %" PRIu32 " peers from file `%s'\n",
1609  num_peers,
1610  sub->filename_valid_peers);
1611  for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
1612  {
1613  str_repr = GNUNET_strndup (iter_buf, 53);
1614  peer = s2i_full (str_repr);
1615  GNUNET_free (str_repr);
1616  add_valid_peer (peer, sub->valid_peers);
1618  "Restored valid peer %s from disk\n",
1619  GNUNET_i2s_full (peer));
1620  }
1621  iter_buf = NULL;
1622  GNUNET_free (buf);
1624  "num_peers: %" PRIu32 ", _size (sub->valid_peers): %u\n",
1625  num_peers,
1627  if (num_peers != GNUNET_CONTAINER_multipeermap_size (sub->valid_peers))
1628  {
1630  "Number of restored peers does not match file size. Have probably duplicates.\n");
1631  }
1634  "Restored %u valid peers from disk\n",
1636 }
1637 
1638 
1644 static void
1645 peers_terminate (struct Sub *sub)
1646 {
1647  if (GNUNET_SYSERR ==
1650  sub))
1651  {
1653  "Iteration destroying peers was aborted.\n");
1654  }
1656  sub->peer_map = NULL;
1657  store_valid_peers (sub);
1659  sub->filename_valid_peers = NULL;
1661  sub->valid_peers = NULL;
1662 }
1663 
1664 
1675 static int
1677  const struct GNUNET_PeerIdentity *peer,
1678  void *value)
1679 {
1680  struct PeersIteratorCls *it_cls = cls;
1681 
1682  (void) value;
1683 
1684  return it_cls->iterator (it_cls->cls, peer);
1685 }
1686 
1687 
1697 static int
1700  void *it_cls)
1701 {
1702  struct PeersIteratorCls *cls;
1703  int ret;
1704 
1705  cls = GNUNET_new (struct PeersIteratorCls);
1706  cls->iterator = iterator;
1707  cls->cls = it_cls;
1708  ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1710  cls);
1711  GNUNET_free (cls);
1712  return ret;
1713 }
1714 
1715 
1728 static int
1729 insert_peer (struct Sub *sub,
1730  const struct GNUNET_PeerIdentity *peer)
1731 {
1732  if (GNUNET_YES == check_peer_known (sub->peer_map, peer))
1733  {
1734  return GNUNET_NO; /* We already know this peer - nothing to do */
1735  }
1736  (void) create_peer_ctx (sub, peer);
1737  return GNUNET_YES;
1738 }
1739 
1740 
1752 static int
1754  const struct GNUNET_PeerIdentity *peer,
1755  enum Peers_PeerFlags flags)
1756 {
1757  struct PeerContext *peer_ctx;
1758 
1759  if (GNUNET_NO == check_peer_known (peer_map, peer))
1760  {
1761  return GNUNET_SYSERR;
1762  }
1763  peer_ctx = get_peer_ctx (peer_map, peer);
1764  return check_peer_flag_set (peer_ctx, flags);
1765 }
1766 
1767 
1778 static int
1780  const struct GNUNET_PeerIdentity *peer)
1781 {
1782  struct PeerContext *peer_ctx;
1783 
1784  (void) insert_peer (sub, peer); // TODO even needed?
1785  peer_ctx = get_peer_ctx (sub->peer_map, peer);
1786  if ((GNUNET_NO == check_peer_flag (sub->peer_map, peer, Peers_ONLINE)) &&
1787  (NULL == peer_ctx->online_check_pending))
1788  {
1789  check_peer_online (peer_ctx);
1790  return GNUNET_YES;
1791  }
1792  return GNUNET_NO;
1793 }
1794 
1795 
1809 static int
1810 check_removable (const struct PeerContext *peer_ctx)
1811 {
1813  peer_ctx->sub->peer_map,
1814  &peer_ctx->peer_id))
1815  {
1816  return GNUNET_SYSERR;
1817  }
1818 
1819  if ((NULL != peer_ctx->recv_channel_ctx) ||
1820  (NULL != peer_ctx->pending_messages_head) ||
1822  {
1823  return GNUNET_NO;
1824  }
1825  return GNUNET_YES;
1826 }
1827 
1828 
1840 static int
1842  const struct GNUNET_PeerIdentity *peer)
1843 {
1844  return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1845 }
1846 
1847 
1855 static void
1857 {
1859  &peer_ctx->peer_id));
1860  (void) get_channel (peer_ctx);
1861 }
1862 
1863 
1873 static int
1874 check_peer_send_intention (const struct PeerContext *peer_ctx)
1875 {
1876  if (NULL != peer_ctx->recv_channel_ctx)
1877  {
1878  return GNUNET_YES;
1879  }
1880  return GNUNET_NO;
1881 }
1882 
1883 
1894 static void *
1896  struct GNUNET_CADET_Channel *channel,
1897  const struct GNUNET_PeerIdentity *initiator)
1898 {
1899  struct PeerContext *peer_ctx;
1900  struct ChannelCtx *channel_ctx;
1901  struct Sub *sub = cls;
1902 
1904  "New channel was established to us (Peer %s).\n",
1905  GNUNET_i2s (initiator));
1906  GNUNET_assert (NULL != channel); /* according to cadet API */
1907  /* Make sure we 'know' about this peer */
1908  peer_ctx = create_or_get_peer_ctx (sub, initiator);
1909  set_peer_online (peer_ctx);
1910  (void) add_valid_peer (&peer_ctx->peer_id, peer_ctx->sub->valid_peers);
1911  channel_ctx = add_channel_ctx (peer_ctx);
1912  channel_ctx->channel = channel;
1913  /* We only accept one incoming channel per peer */
1915  initiator)))
1916  {
1918  "Already got one receive channel. Destroying old one.\n");
1919  GNUNET_break_op (0);
1920  destroy_channel (peer_ctx->recv_channel_ctx);
1921  peer_ctx->recv_channel_ctx = channel_ctx;
1922  /* return the channel context */
1923  return channel_ctx;
1924  }
1925  peer_ctx->recv_channel_ctx = channel_ctx;
1926  return channel_ctx;
1927 }
1928 
1929 
1938 static int
1940 {
1941  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
1942  &peer_ctx->peer_id))
1943  { /* If no such peer exists, there is no channel */
1944  return GNUNET_NO;
1945  }
1946  if (NULL == peer_ctx->send_channel_ctx)
1947  {
1948  return GNUNET_NO;
1949  }
1950  return GNUNET_YES;
1951 }
1952 
1953 
1962 static int
1964 {
1965  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
1966  &peer_ctx->peer_id))
1967  {
1968  return GNUNET_NO;
1969  }
1970  if (NULL != peer_ctx->send_channel_ctx)
1971  {
1972  destroy_channel (peer_ctx->send_channel_ctx);
1973  (void) check_connected (peer_ctx);
1974  return GNUNET_YES;
1975  }
1976  return GNUNET_NO;
1977 }
1978 
1979 
1990 static void
1991 send_message (struct PeerContext *peer_ctx,
1992  struct GNUNET_MQ_Envelope *ev,
1993  const char *type)
1994 {
1995  struct PendingMessage *pending_msg;
1996  struct GNUNET_MQ_Handle *mq;
1997 
1999  "Sending message to %s of type %s\n",
2000  GNUNET_i2s (&peer_ctx->peer_id),
2001  type);
2002  pending_msg = insert_pending_message (peer_ctx, ev, type);
2003  mq = get_mq (peer_ctx);
2006  pending_msg);
2007  GNUNET_MQ_send (mq, ev);
2008 }
2009 
2010 
2023 static int
2025  const PeerOp peer_op,
2026  void *cls)
2027 {
2028  struct PeerPendingOp pending_op;
2029 
2031  &peer_ctx->peer_id));
2032 
2033  // TODO if ONLINE execute immediately
2034 
2035  if (GNUNET_NO == check_operation_scheduled (peer_ctx, peer_op))
2036  {
2037  pending_op.op = peer_op;
2038  pending_op.op_cls = cls;
2039  GNUNET_array_append (peer_ctx->pending_ops,
2040  peer_ctx->num_pending_ops,
2041  pending_op);
2042  return GNUNET_YES;
2043  }
2044  return GNUNET_NO;
2045 }
2046 
2047 
2048 /***********************************************************************
2049 * /Old gnunet-service-rps_peers.c
2050 ***********************************************************************/
2051 
2052 
2053 /***********************************************************************
2054 * Housekeeping with clients
2055 ***********************************************************************/
2056 
2061 struct ReplyCls
2062 {
2066  struct ReplyCls *next;
2067  struct ReplyCls *prev;
2068 
2072  uint32_t id;
2073 
2078 
2083 };
2084 
2085 
2090 {
2096 
2101 
2106 
2112 
2117 
2121  struct Sub *sub;
2122 };
2123 
2129 
2130 /***********************************************************************
2131 * /Housekeeping with clients
2132 ***********************************************************************/
2133 
2134 
2135 /***********************************************************************
2136 * Util functions
2137 ***********************************************************************/
2138 
2139 
2143 static void
2145  unsigned int len)
2146 {
2147  unsigned int i;
2148 
2150  "Printing peer list of length %u at %p:\n",
2151  len,
2152  list);
2153  for (i = 0; i < len; i++)
2154  {
2156  "%u. peer: %s\n",
2157  i, GNUNET_i2s (&list[i]));
2158  }
2159 }
2160 
2161 
2165 static void
2167  unsigned int *list_size,
2168  const struct GNUNET_PeerIdentity *peer)
2169 {
2170  unsigned int i;
2171  struct GNUNET_PeerIdentity *tmp;
2172 
2173  tmp = *peer_list;
2174 
2176  "Removing peer %s from list at %p\n",
2177  GNUNET_i2s (peer),
2178  tmp);
2179 
2180  for (i = 0; i < *list_size; i++)
2181  {
2182  if (0 == GNUNET_memcmp (&tmp[i], peer))
2183  {
2184  if (i < *list_size - 1)
2185  { /* Not at the last entry -- shift peers left */
2186  memmove (&tmp[i], &tmp[i + 1],
2187  ((*list_size) - i - 1) * sizeof(struct GNUNET_PeerIdentity));
2188  }
2189  /* Remove last entry (should be now useless PeerID) */
2190  GNUNET_array_grow (tmp, *list_size, (*list_size) - 1);
2191  }
2192  }
2193  *peer_list = tmp;
2194 }
2195 
2196 
2206 static void
2207 insert_in_view_op (void *cls,
2208  const struct GNUNET_PeerIdentity *peer);
2209 
2221 static int
2222 insert_in_view (struct Sub *sub,
2223  const struct GNUNET_PeerIdentity *peer)
2224 {
2225  struct PeerContext *peer_ctx;
2226  int online;
2227  int ret;
2228 
2229  online = check_peer_flag (sub->peer_map, peer, Peers_ONLINE);
2230  peer_ctx = get_peer_ctx (sub->peer_map, peer); // TODO indirection needed?
2231  if ((GNUNET_NO == online) ||
2232  (GNUNET_SYSERR == online)) /* peer is not even known */
2233  {
2234  (void) issue_peer_online_check (sub, peer);
2235  (void) schedule_operation (peer_ctx, insert_in_view_op, sub);
2236  return GNUNET_NO;
2237  }
2238  /* Open channel towards peer to keep connection open */
2239  indicate_sending_intention (peer_ctx);
2240  ret = View_put (sub->view, peer);
2241  if (peer_ctx->sub == msub)
2242  {
2243  GNUNET_STATISTICS_set (stats,
2244  "view size",
2245  View_size (peer_ctx->sub->view),
2246  GNUNET_NO);
2247  }
2248  return ret;
2249 }
2250 
2251 
2259 static void
2260 send_view (const struct ClientContext *cli_ctx,
2261  const struct GNUNET_PeerIdentity *view_array,
2262  uint64_t view_size)
2263 {
2264  struct GNUNET_MQ_Envelope *ev;
2265  struct GNUNET_RPS_CS_DEBUG_ViewReply *out_msg;
2266  struct Sub *sub;
2267 
2268  if (NULL == view_array)
2269  {
2270  if (NULL == cli_ctx->sub)
2271  sub = msub;
2272  else
2273  sub = cli_ctx->sub;
2274  view_size = View_size (sub->view);
2275  view_array = View_get_as_array (sub->view);
2276  }
2277 
2278  ev = GNUNET_MQ_msg_extra (out_msg,
2279  view_size * sizeof(struct GNUNET_PeerIdentity),
2281  out_msg->num_peers = htonl (view_size);
2282 
2283  GNUNET_memcpy (&out_msg[1],
2284  view_array,
2285  view_size * sizeof(struct GNUNET_PeerIdentity));
2286  GNUNET_MQ_send (cli_ctx->mq, ev);
2287 }
2288 
2289 
2299 static void
2300 send_stream_peers (const struct ClientContext *cli_ctx,
2301  uint64_t num_peers,
2302  const struct GNUNET_PeerIdentity *peers)
2303 {
2304  struct GNUNET_MQ_Envelope *ev;
2305  struct GNUNET_RPS_CS_DEBUG_StreamReply *out_msg;
2306 
2307  GNUNET_assert (NULL != peers);
2308 
2309  ev = GNUNET_MQ_msg_extra (out_msg,
2310  num_peers * sizeof(struct GNUNET_PeerIdentity),
2312  out_msg->num_peers = htonl (num_peers);
2313 
2314  GNUNET_memcpy (&out_msg[1],
2315  peers,
2316  num_peers * sizeof(struct GNUNET_PeerIdentity));
2317  GNUNET_MQ_send (cli_ctx->mq, ev);
2318 }
2319 
2320 
2326 static void
2327 clients_notify_view_update (const struct Sub *sub)
2328 {
2329  struct ClientContext *cli_ctx_iter;
2330  uint64_t num_peers;
2331  const struct GNUNET_PeerIdentity *view_array;
2332 
2333  num_peers = View_size (sub->view);
2334  view_array = View_get_as_array (sub->view);
2335  /* check size of view is small enough */
2336  if (GNUNET_MAX_MESSAGE_SIZE < num_peers)
2337  {
2339  "View is too big to send\n");
2340  return;
2341  }
2342 
2343  for (cli_ctx_iter = cli_ctx_head;
2344  NULL != cli_ctx_iter;
2345  cli_ctx_iter = cli_ctx_iter->next)
2346  {
2347  if (1 < cli_ctx_iter->view_updates_left)
2348  {
2349  /* Client wants to receive limited amount of updates */
2350  cli_ctx_iter->view_updates_left -= 1;
2351  }
2352  else if (1 == cli_ctx_iter->view_updates_left)
2353  {
2354  /* Last update of view for client */
2355  cli_ctx_iter->view_updates_left = -1;
2356  }
2357  else if (0 > cli_ctx_iter->view_updates_left)
2358  {
2359  /* Client is not interested in updates */
2360  continue;
2361  }
2362  /* else _updates_left == 0 - infinite amount of updates */
2363 
2364  /* send view */
2365  send_view (cli_ctx_iter, view_array, num_peers);
2366  }
2367 }
2368 
2369 
2376 static void
2377 clients_notify_stream_peer (const struct Sub *sub,
2378  uint64_t num_peers,
2379  const struct GNUNET_PeerIdentity *peers)
2380 // TODO enum StreamPeerSource)
2381 {
2382  struct ClientContext *cli_ctx_iter;
2383 
2385  "Got peer (%s) from biased stream - update all clients\n",
2386  GNUNET_i2s (peers));
2387 
2388  for (cli_ctx_iter = cli_ctx_head;
2389  NULL != cli_ctx_iter;
2390  cli_ctx_iter = cli_ctx_iter->next)
2391  {
2392  if ((GNUNET_YES == cli_ctx_iter->stream_update) &&
2393  ((sub == cli_ctx_iter->sub) || (sub == msub) ))
2394  {
2395  send_stream_peers (cli_ctx_iter, num_peers, peers);
2396  }
2397  }
2398 }
2399 
2400 
2408 static void
2410  uint32_t num_peers,
2411  void *cls)
2412 {
2413  unsigned int i;
2414  struct Sub *sub = cls;
2415 
2416  for (i = 0; i < num_peers; i++)
2417  {
2418  int inserted;
2419  if (GNUNET_YES != check_peer_known (sub->peer_map, &ids[i]))
2420  {
2422  "Peer in history update not known!\n");
2423  continue;
2424  }
2425  inserted = insert_in_view (sub, &ids[i]);
2426  if (GNUNET_OK == inserted)
2427  {
2428  clients_notify_stream_peer (sub, 1, &ids[i]);
2429  }
2430 #ifdef TO_FILE_FULL
2431  to_file (sub->file_name_view_log,
2432  "+%s\t(history)",
2433  GNUNET_i2s_full (ids));
2434 #endif /* TO_FILE_FULL */
2435  }
2437 }
2438 
2439 
2449 static void
2450 resize_wrapper (struct RPS_Sampler *sampler, uint32_t new_size)
2451 {
2452  unsigned int sampler_size;
2453 
2454  // TODO statistics
2455  // TODO respect the min, max
2456  sampler_size = RPS_sampler_get_size (sampler);
2457  if (sampler_size > new_size * 4)
2458  { /* Shrinking */
2459  RPS_sampler_resize (sampler, sampler_size / 2);
2460  }
2461  else if (sampler_size < new_size)
2462  { /* Growing */
2463  RPS_sampler_resize (sampler, sampler_size * 2);
2464  }
2465  LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size is now %u\n", sampler_size);
2466 }
2467 
2468 
2469 #if ENABLE_MALICIOUS
2470 
2477 static void
2478 add_peer_array_to_set (const struct GNUNET_PeerIdentity *peer_array,
2479  unsigned int num_peers,
2481 {
2482  unsigned int i;
2483 
2484  if (NULL == peer_map)
2485  {
2487  "Trying to add peers to non-existing peermap.\n");
2488  return;
2489  }
2490 
2491  for (i = 0; i < num_peers; i++)
2492  {
2494  &peer_array[i],
2495  NULL,
2497  if (msub->peer_map == peer_map)
2498  {
2499  GNUNET_STATISTICS_set (stats,
2500  "# known peers",
2502  GNUNET_NO);
2503  }
2504  }
2505 }
2506 
2507 
2508 #endif /* ENABLE_MALICIOUS */
2509 
2510 
2518 static void
2519 send_pull_reply (struct PeerContext *peer_ctx,
2520  const struct GNUNET_PeerIdentity *peer_ids,
2521  unsigned int num_peer_ids)
2522 {
2523  uint32_t send_size;
2524  struct GNUNET_MQ_Envelope *ev;
2525  struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
2526 
2527  /* Compute actual size */
2528  send_size = sizeof(struct GNUNET_RPS_P2P_PullReplyMessage)
2529  + num_peer_ids * sizeof(struct GNUNET_PeerIdentity);
2530 
2532  /* Compute number of peers to send
2533  * If too long, simply truncate */
2534  // TODO select random ones via permutation
2535  // or even better: do good protocol design
2536  send_size =
2538  - sizeof(struct GNUNET_RPS_P2P_PullReplyMessage))
2539  / sizeof(struct GNUNET_PeerIdentity);
2540  else
2541  send_size = num_peer_ids;
2542 
2544  "Going to send PULL REPLY with %u peers to %s\n",
2545  send_size, GNUNET_i2s (&peer_ctx->peer_id));
2546 
2547  ev = GNUNET_MQ_msg_extra (out_msg,
2548  send_size * sizeof(struct GNUNET_PeerIdentity),
2550  out_msg->num_peers = htonl (send_size);
2551  GNUNET_memcpy (&out_msg[1], peer_ids,
2552  send_size * sizeof(struct GNUNET_PeerIdentity));
2553 
2554  send_message (peer_ctx, ev, "PULL REPLY");
2555  if (peer_ctx->sub == msub)
2556  {
2557  GNUNET_STATISTICS_update (stats, "# pull reply send issued", 1, GNUNET_NO);
2558  }
2559  // TODO check with send intention: as send_channel is used/opened we indicate
2560  // a sending intention without intending it.
2561  // -> clean peer afterwards?
2562  // -> use recv_channel?
2563 }
2564 
2565 
2574 static void
2576  const struct GNUNET_PeerIdentity *peer)
2577 {
2578  struct Sub *sub = cls;
2579 
2580  CustomPeerMap_put (sub->pull_map, peer);
2581 }
2582 
2583 
2593 static void
2595  const struct GNUNET_PeerIdentity *peer)
2596 {
2597  struct Sub *sub = cls;
2598  int inserted;
2599 
2600  inserted = insert_in_view (sub, peer);
2601  if (GNUNET_OK == inserted)
2602  {
2603  clients_notify_stream_peer (sub, 1, peer);
2604  }
2605 }
2606 
2607 
2615 static void
2617  const struct GNUNET_PeerIdentity *peer)
2618 {
2619  struct Sub *sub = cls;
2620 
2622  "Updating samplers with peer %s from insert_in_sampler()\n",
2623  GNUNET_i2s (peer));
2624  RPS_sampler_update (sub->sampler, peer);
2625  if (0 < RPS_sampler_count_id (sub->sampler, peer))
2626  {
2627  /* Make sure we 'know' about this peer */
2628  (void) issue_peer_online_check (sub, peer);
2629  /* Establish a channel towards that peer to indicate we are going to send
2630  * messages to it */
2631  // indicate_sending_intention (peer);
2632  }
2633  if (sub == msub)
2634  {
2635  GNUNET_STATISTICS_update (stats,
2636  "# observed peers in gossip",
2637  1,
2638  GNUNET_NO);
2639  }
2640 #ifdef TO_FILE
2641  sub->num_observed_peers++;
2643  (sub->observed_unique_peers,
2644  peer,
2645  NULL,
2647  uint32_t num_observed_unique_peers =
2649  GNUNET_STATISTICS_set (stats,
2650  "# unique peers in gossip",
2651  num_observed_unique_peers,
2652  GNUNET_NO);
2653 #ifdef TO_FILE_FULL
2654  to_file (sub->file_name_observed_log,
2655  "%" PRIu32 " %" PRIu32 " %f\n",
2656  sub->num_observed_peers,
2657  num_observed_unique_peers,
2658  1.0 * num_observed_unique_peers / sub->num_observed_peers)
2659 #endif /* TO_FILE_FULL */
2660 #endif /* TO_FILE */
2661 }
2662 
2663 
2674 static void
2675 got_peer (struct Sub *sub,
2676  const struct GNUNET_PeerIdentity *peer)
2677 {
2678  /* If we did not know this peer already, insert it into sampler and view */
2679  if (GNUNET_YES == issue_peer_online_check (sub, peer))
2680  {
2682  &insert_in_sampler, sub);
2684  &insert_in_view_op, sub);
2685  }
2686  if (sub == msub)
2687  {
2688  GNUNET_STATISTICS_update (stats,
2689  "# learnd peers",
2690  1,
2691  GNUNET_NO);
2692  }
2693 }
2694 
2695 
2703 static int
2705 {
2706  /* struct GNUNET_CADET_Channel *channel; */
2707  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
2708  &peer_ctx->peer_id))
2709  {
2710  return GNUNET_NO;
2711  }
2712  if (GNUNET_YES == check_sending_channel_exists (peer_ctx))
2713  {
2714  if ((0 < RPS_sampler_count_id (peer_ctx->sub->sampler,
2715  &peer_ctx->peer_id)) ||
2716  (GNUNET_YES == View_contains_peer (peer_ctx->sub->view,
2717  &peer_ctx->peer_id)) ||
2719  &peer_ctx->peer_id)) ||
2721  &peer_ctx->peer_id)) ||
2722  (GNUNET_YES == check_peer_flag (peer_ctx->sub->peer_map,
2723  &peer_ctx->peer_id,
2725  { /* If we want to keep the connection to peer open */
2726  return GNUNET_YES;
2727  }
2728  return GNUNET_NO;
2729  }
2730  return GNUNET_NO;
2731 }
2732 
2733 
2741 static void
2742 remove_peer (struct Sub *sub,
2743  const struct GNUNET_PeerIdentity *peer)
2744 {
2745  (void) View_remove_peer (sub->view,
2746  peer);
2748  peer);
2750  peer);
2752  peer);
2753  /* We want to destroy the peer now.
2754  * Sometimes, it just seems that it's already been removed from the peer_map,
2755  * so check the peer_map first. */
2756  if (GNUNET_YES == check_peer_known (sub->peer_map,
2757  peer))
2758  {
2760  peer));
2761  }
2762 }
2763 
2764 
2773 static void
2774 clean_peer (struct Sub *sub,
2775  const struct GNUNET_PeerIdentity *peer)
2776 {
2778  peer)))
2779  {
2781  "Going to remove send channel to peer %s\n",
2782  GNUNET_i2s (peer));
2783  #if ENABLE_MALICIOUS
2784  if (0 != GNUNET_memcmp (&attacked_peer,
2785  peer))
2787  peer));
2788  #else /* ENABLE_MALICIOUS */
2790  peer));
2791  #endif /* ENABLE_MALICIOUS */
2792  }
2793 
2795  peer))
2796  {
2797  /* Peer was already removed by callback on destroyed channel */
2799  "Peer was removed from our knowledge during cleanup\n");
2800  return;
2801  }
2802 
2804  peer))) &&
2805  (GNUNET_NO == View_contains_peer (sub->view, peer)) &&
2806  (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2807  (GNUNET_NO == CustomPeerMap_contains_peer (sub->pull_map, peer)) &&
2808  (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
2809  (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer))))
2810  { /* We can safely remove this peer */
2812  "Going to remove peer %s\n",
2813  GNUNET_i2s (peer));
2814  remove_peer (sub, peer);
2815  return;
2816  }
2817 }
2818 
2819 
2831 static void
2833  const struct GNUNET_CADET_Channel *channel)
2834 {
2835  struct ChannelCtx *channel_ctx = cls;
2836  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
2837 
2838  (void) channel;
2839 
2840  channel_ctx->channel = NULL;
2841  if ((NULL != peer_ctx) &&
2842  (peer_ctx->send_channel_ctx == channel_ctx) &&
2843  (GNUNET_YES == check_sending_channel_needed (peer_ctx)) )
2844  {
2845  remove_channel_ctx (channel_ctx);
2846  remove_peer (peer_ctx->sub, &peer_ctx->peer_id);
2847  }
2848  else
2849  {
2850  /* We need this if-else construct because we need to make sure the channel
2851  * (context) is cleaned up before removing the peer, but still need to
2852  * compare it while checking the condition */
2853  remove_channel_ctx (channel_ctx);
2854  }
2855 }
2856 
2857 
2858 /***********************************************************************
2859 * /Util functions
2860 ***********************************************************************/
2861 
2862 
2863 /***********************************************************************
2864 * Sub
2865 ***********************************************************************/
2866 
2877 struct Sub *
2879  uint32_t sampler_size,
2881 {
2882  struct Sub *sub;
2883 
2884  sub = GNUNET_new (struct Sub);
2885 
2886  /* With the hash generated from the secret value this service only connects
2887  * to rps instances that share the value */
2888  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2889  GNUNET_MQ_hd_fixed_size (peer_check,
2891  struct GNUNET_MessageHeader,
2892  NULL),
2893  GNUNET_MQ_hd_fixed_size (peer_push,
2895  struct GNUNET_MessageHeader,
2896  NULL),
2897  GNUNET_MQ_hd_fixed_size (peer_pull_request,
2899  struct GNUNET_MessageHeader,
2900  NULL),
2901  GNUNET_MQ_hd_var_size (peer_pull_reply,
2904  NULL),
2906  };
2907  sub->hash = *hash;
2908  sub->cadet_port =
2909  GNUNET_CADET_open_port (cadet_handle,
2910  &sub->hash,
2911  &handle_inbound_channel, /* Connect handler */
2912  sub, /* cls */
2913  NULL, /* WindowSize handler */
2914  &cleanup_destroyed_channel, /* Disconnect handler */
2915  cadet_handlers);
2916  if (NULL == sub->cadet_port)
2917  {
2919  "Cadet port `%s' is already in use.\n",
2921  GNUNET_assert (0);
2922  }
2923 
2924  /* Set up general data structure to keep track about peers */
2926  if (GNUNET_OK !=
2928  "rps",
2929  "FILENAME_VALID_PEERS",
2930  &sub->filename_valid_peers))
2931  {
2933  "rps",
2934  "FILENAME_VALID_PEERS");
2935  }
2936  if (0 != strncmp ("DISABLE", sub->filename_valid_peers, 7))
2937  {
2938  char *tmp_filename_valid_peers;
2939  char str_hash[105];
2940 
2941  GNUNET_snprintf (str_hash,
2942  sizeof(str_hash), "%s",
2943  GNUNET_h2s_full (hash));
2944  tmp_filename_valid_peers = sub->filename_valid_peers;
2946  "%s%s",
2947  tmp_filename_valid_peers,
2948  str_hash);
2949  GNUNET_free (tmp_filename_valid_peers);
2950  }
2952 
2953  /* Set up the sampler */
2954  sub->sampler_size_est_min = sampler_size;
2955  sub->sampler_size_est_need = sampler_size;;
2956  LOG (GNUNET_ERROR_TYPE_DEBUG, "MINSIZE is %u\n", sub->sampler_size_est_min);
2957  GNUNET_assert (0 != round_interval.rel_value_us);
2958  sub->round_interval = round_interval;
2959  sub->sampler = RPS_sampler_init (sampler_size,
2960  round_interval);
2961 
2962  /* Logging of internals */
2963 #ifdef TO_FILE_FULL
2964  // FIXME: The service cannot know the index, which is required by this
2965  // function:
2966  // sub->file_name_view_log = store_prefix_file_name (&own_identity, "view");
2967 #endif /* TO_FILE_FULL */
2968 #ifdef TO_FILE
2969 #ifdef TO_FILE_FULL
2970  // FIXME: The service cannot know the index, which is required by this
2971  // function:
2972  // sub->file_name_observed_log = store_prefix_file_name (&own_identity,
2973  // "observed");
2974 #endif /* TO_FILE_FULL */
2975  sub->num_observed_peers = 0;
2977  GNUNET_NO);
2978 #endif /* TO_FILE */
2979 
2980  /* Set up data structures for gossip */
2981  sub->push_map = CustomPeerMap_create (4);
2982  sub->pull_map = CustomPeerMap_create (4);
2983  sub->view_size_est_min = sampler_size;;
2984  sub->view = View_create (sub->view_size_est_min);
2985  if (sub == msub)
2986  {
2987  GNUNET_STATISTICS_set (stats,
2988  "view size aim",
2989  sub->view_size_est_min,
2990  GNUNET_NO);
2991  }
2992 
2993  /* Start executing rounds */
2995 
2996  return sub;
2997 }
2998 
2999 
3000 #ifdef TO_FILE
3001 // /**
3002 // * @brief Write all numbers in the given array into the given file
3003 // *
3004 // * Single numbers divided by a newline
3005 // *
3006 // * FIXME: The call to store_prefix_file_name expects the index of the peer,
3007 // * which cannot be known to the service.
3008 // * Write a dedicated function that uses the peer id.
3009 // *
3010 // * @param hist_array[] the array to dump
3011 // * @param file_name file to dump into
3012 // */
3013 // static void
3014 // write_histogram_to_file (const uint32_t hist_array[],
3015 // const char *file_name)
3016 // {
3017 // char collect_str[SIZE_DUMP_FILE + 1] = "";
3018 // char *recv_str_iter;
3019 // char *file_name_full;
3020 //
3021 // recv_str_iter = collect_str;
3022 // file_name_full = store_prefix_file_name (&own_identity,
3023 // file_name);
3024 // for (uint32_t i = 0; i < HISTOGRAM_FILE_SLOTS; i++)
3025 // {
3026 // char collect_str_tmp[8];
3027 //
3028 // GNUNET_snprintf (collect_str_tmp,
3029 // sizeof(collect_str_tmp),
3030 // "%" PRIu32 "\n",
3031 // hist_array[i]);
3032 // recv_str_iter = stpncpy (recv_str_iter,
3033 // collect_str_tmp,
3034 // 6);
3035 // }
3036 // (void) stpcpy (recv_str_iter,
3037 // "\n");
3038 // LOG (GNUNET_ERROR_TYPE_DEBUG,
3039 // "Writing push stats to disk\n");
3040 // to_file_w_len (file_name_full,
3041 // SIZE_DUMP_FILE, "%s",
3042 // collect_str);
3043 // GNUNET_free (file_name_full);
3044 // }
3045 
3046 
3047 #endif /* TO_FILE */
3048 
3049 
3055 static void
3056 destroy_sub (struct Sub *sub)
3057 {
3058  GNUNET_assert (NULL != sub);
3059  GNUNET_assert (NULL != sub->do_round_task);
3061  sub->do_round_task = NULL;
3062 
3063  /* Disconnect from cadet */
3065  sub->cadet_port = NULL;
3066 
3067  /* Clean up data structures for peers */
3069  sub->sampler = NULL;
3070  View_destroy (sub->view);
3071  sub->view = NULL;
3073  sub->push_map = NULL;
3075  sub->pull_map = NULL;
3076  peers_terminate (sub);
3077 
3078  /* Free leftover data structures */
3079 #ifdef TO_FILE_FULL
3080  GNUNET_free (sub->file_name_view_log);
3081  sub->file_name_view_log = NULL;
3082 #endif /* TO_FILE_FULL */
3083 #ifdef TO_FILE
3084 #ifdef TO_FILE_FULL
3085  GNUNET_free (sub->file_name_observed_log);
3086  sub->file_name_observed_log = NULL;
3087 #endif /* TO_FILE_FULL */
3088 
3089  // FIXME: Currently this calls malfunctionning code
3090  // /* Write push frequencies to disk */
3091  // write_histogram_to_file (sub->push_recv,
3092  // "push_recv");
3093 
3094  // /* Write push deltas to disk */
3095  // write_histogram_to_file (sub->push_delta,
3096  // "push_delta");
3097 
3098  // /* Write pull delays to disk */
3099  // write_histogram_to_file (sub->pull_delays,
3100  // "pull_delays");
3101 
3103  sub->observed_unique_peers = NULL;
3104 #endif /* TO_FILE */
3105 
3106  GNUNET_free (sub);
3107 }
3108 
3109 
3110 /***********************************************************************
3111 * /Sub
3112 ***********************************************************************/
3113 
3114 
3115 /***********************************************************************
3116 * Core handlers
3117 ***********************************************************************/
3118 
3125 void
3127  const struct GNUNET_PeerIdentity *my_identity)
3128 {
3129  (void) cls;
3130  (void) my_identity;
3131 
3132  map_single_hop = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
3133 }
3134 
3135 
3144 void *
3146  const struct GNUNET_PeerIdentity *peer,
3147  struct GNUNET_MQ_Handle *mq)
3148 {
3149  (void) cls;
3150  (void) mq;
3151 
3153  GNUNET_CONTAINER_multipeermap_put (map_single_hop,
3154  peer,
3155  NULL,
3157  return NULL;
3158 }
3159 
3160 
3169 void
3171  const struct GNUNET_PeerIdentity *peer,
3172  void *peer_cls)
3173 {
3174  (void) cls;
3175  (void) peer_cls;
3176 
3177  GNUNET_CONTAINER_multipeermap_remove_all (map_single_hop, peer);
3178 }
3179 
3180 
3181 /***********************************************************************
3182 * /Core handlers
3183 ***********************************************************************/
3184 
3185 
3191 static void
3193 {
3194  GNUNET_assert (NULL != cli_ctx);
3195  GNUNET_CONTAINER_DLL_remove (cli_ctx_head,
3196  cli_ctx_tail,
3197  cli_ctx);
3198  if (NULL != cli_ctx->sub)
3199  {
3200  destroy_sub (cli_ctx->sub);
3201  cli_ctx->sub = NULL;
3202  }
3203  GNUNET_free (cli_ctx);
3204 }
3205 
3206 
3214 static void
3215 adapt_sizes (struct Sub *sub, double logestimate, double std_dev)
3216 {
3217  double estimate;
3218 
3219  // double scale; // TODO this might go global/config
3220 
3222  "Received a ns estimate - logest: %f, std_dev: %f (old_size: %u)\n",
3223  logestimate, std_dev, RPS_sampler_get_size (sub->sampler));
3224  // scale = .01;
3225  estimate = GNUNET_NSE_log_estimate_to_n (logestimate);
3226  // GNUNET_NSE_log_estimate_to_n (logestimate);
3227  estimate = pow (estimate, 1.0 / 3);
3228  // TODO add if std_dev is a number
3229  // estimate += (std_dev * scale);
3230  if (sub->view_size_est_min < ceil (estimate))
3231  {
3232  LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing estimate to %f\n", estimate);
3233  sub->sampler_size_est_need = estimate;
3234  sub->view_size_est_need = estimate;
3235  }
3236  else
3237  {
3238  LOG (GNUNET_ERROR_TYPE_DEBUG, "Not using estimate %f\n", estimate);
3239  // sub->sampler_size_est_need = sub->view_size_est_min;
3241  }
3242  if (sub == msub)
3243  {
3244  GNUNET_STATISTICS_set (stats,
3245  "view size aim",
3246  sub->view_size_est_need,
3247  GNUNET_NO);
3248  }
3249 
3250  /* If the NSE has changed adapt the lists accordingly */
3253 }
3254 
3255 
3269 static void
3271  struct GNUNET_TIME_Absolute timestamp,
3272  double logestimate, double std_dev)
3273 {
3274  (void) cls;
3275  (void) timestamp;
3276  struct ClientContext *cli_ctx_iter;
3277 
3278  adapt_sizes (msub, logestimate, std_dev);
3279  for (cli_ctx_iter = cli_ctx_head;
3280  NULL != cli_ctx_iter;
3281  cli_ctx_iter = cli_ctx_iter->next)
3282  {
3283  if (NULL != cli_ctx_iter->sub)
3284  {
3285  adapt_sizes (cli_ctx_iter->sub, logestimate, std_dev);
3286  }
3287  }
3288 }
3289 
3290 
3300 static int
3301 check_client_seed (void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
3302 {
3303  struct ClientContext *cli_ctx = cls;
3304  uint16_t msize = ntohs (msg->header.size);
3305  uint32_t num_peers = ntohl (msg->num_peers);
3306 
3307  msize -= sizeof(struct GNUNET_RPS_CS_SeedMessage);
3308  if ((msize / sizeof(struct GNUNET_PeerIdentity) != num_peers) ||
3309  (msize % sizeof(struct GNUNET_PeerIdentity) != 0))
3310  {
3312  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3313  ntohl (msg->num_peers),
3314  (msize / sizeof(struct GNUNET_PeerIdentity)));
3315  GNUNET_break (0);
3317  return GNUNET_SYSERR;
3318  }
3319  return GNUNET_OK;
3320 }
3321 
3322 
3329 static void
3331  const struct GNUNET_RPS_CS_SeedMessage *msg)
3332 {
3333  struct ClientContext *cli_ctx = cls;
3334  struct GNUNET_PeerIdentity *peers;
3335  uint32_t num_peers;
3336  uint32_t i;
3337 
3338  num_peers = ntohl (msg->num_peers);
3339  peers = (struct GNUNET_PeerIdentity *) &msg[1];
3340 
3342  "Client seeded peers:\n");
3343  print_peer_list (peers, num_peers);
3344 
3345  for (i = 0; i < num_peers; i++)
3346  {
3348  "Updating samplers with seed %" PRIu32 ": %s\n",
3349  i,
3350  GNUNET_i2s (&peers[i]));
3351 
3352  if (NULL != msub)
3353  got_peer (msub, &peers[i]); /* Condition needed? */
3354  if (NULL != cli_ctx->sub)
3355  got_peer (cli_ctx->sub, &peers[i]);
3356  }
3358 }
3359 
3360 
3368 static void
3370  const struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg)
3371 {
3372  struct ClientContext *cli_ctx = cls;
3373  uint64_t num_updates;
3374 
3375  num_updates = ntohl (msg->num_updates);
3376 
3378  "Client requested %" PRIu64 " updates of view.\n",
3379  num_updates);
3380 
3381  GNUNET_assert (NULL != cli_ctx);
3382  cli_ctx->view_updates_left = num_updates;
3383  send_view (cli_ctx, NULL, 0);
3385 }
3386 
3387 
3394 static void
3396  const struct GNUNET_MessageHeader *msg)
3397 {
3398  struct ClientContext *cli_ctx = cls;
3399 
3400  (void) msg;
3401 
3403  "Client does not want to receive updates of view any more.\n");
3404 
3405  GNUNET_assert (NULL != cli_ctx);
3406  cli_ctx->view_updates_left = 0;
3408  if (GNUNET_YES == cli_ctx->stream_update)
3409  {
3410  destroy_cli_ctx (cli_ctx);
3411  }
3412 }
3413 
3414 
3421 static void
3423  const struct
3425 {
3426  struct ClientContext *cli_ctx = cls;
3427 
3428  (void) msg;
3429 
3431  "Client requested peers from biased stream.\n");
3432  cli_ctx->stream_update = GNUNET_YES;
3433 
3434  GNUNET_assert (NULL != cli_ctx);
3436 }
3437 
3438 
3445 static void
3447  const struct GNUNET_MessageHeader *msg)
3448 {
3449  struct ClientContext *cli_ctx = cls;
3450 
3451  (void) msg;
3452 
3454  "Client canceled receiving peers from biased stream.\n");
3455  cli_ctx->stream_update = GNUNET_NO;
3456 
3457  GNUNET_assert (NULL != cli_ctx);
3459 }
3460 
3461 
3468 static void
3470  const struct GNUNET_RPS_CS_SubStartMessage *msg)
3471 {
3472  struct ClientContext *cli_ctx = cls;
3473 
3474  LOG (GNUNET_ERROR_TYPE_DEBUG, "Client requested start of a new sub.\n");
3475  if ((NULL != cli_ctx->sub) &&
3476  (0 != memcmp (&cli_ctx->sub->hash,
3477  &msg->hash,
3478  sizeof(struct GNUNET_HashCode))) )
3479  {
3481  "Already have a Sub with different share for this client. Remove old one, add new.\n");
3482  destroy_sub (cli_ctx->sub);
3483  cli_ctx->sub = NULL;
3484  }
3485  cli_ctx->sub = new_sub (&msg->hash,
3486  msub->sampler_size_est_min, // TODO make api input?
3489 }
3490 
3491 
3498 static void
3500  const struct GNUNET_RPS_CS_SubStopMessage *msg)
3501 {
3502  struct ClientContext *cli_ctx = cls;
3503 
3504  GNUNET_assert (NULL != cli_ctx->sub);
3505  if (0 != memcmp (&cli_ctx->sub->hash, &msg->hash, sizeof(struct
3506  GNUNET_HashCode)))
3507  {
3509  "Share of current sub and request differ!\n");
3510  }
3511  destroy_sub (cli_ctx->sub);
3512  cli_ctx->sub = NULL;
3514 }
3515 
3516 
3526 static void
3528  const struct GNUNET_MessageHeader *msg)
3529 {
3530  const struct ChannelCtx *channel_ctx = cls;
3531  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3532 
3533  (void) msg;
3534 
3536  "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer));
3537  if (channel_ctx->peer_ctx->sub == msub)
3538  {
3539  GNUNET_STATISTICS_update (stats,
3540  "# pending online checks",
3541  -1,
3542  GNUNET_NO);
3543  }
3544 
3545  GNUNET_CADET_receive_done (channel_ctx->channel);
3546 }
3547 
3548 
3558 static void
3559 handle_peer_push (void *cls,
3560  const struct GNUNET_MessageHeader *msg)
3561 {
3562  const struct ChannelCtx *channel_ctx = cls;
3563  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3564 
3565  (void) msg;
3566 
3567  // (check the proof of work (?))
3568 
3570  "Received PUSH (%s)\n",
3571  GNUNET_i2s (peer));
3572  if (channel_ctx->peer_ctx->sub == msub)
3573  {
3574  GNUNET_STATISTICS_update (stats, "# push message received", 1, GNUNET_NO);
3575  if ((NULL != map_single_hop) &&
3577  peer)))
3578  {
3579  GNUNET_STATISTICS_update (stats,
3580  "# push message received (multi-hop peer)",
3581  1,
3582  GNUNET_NO);
3583  }
3584  }
3585 
3586  #if ENABLE_MALICIOUS
3587  struct AttackedPeer *tmp_att_peer;
3588 
3589  if ((1 == mal_type) ||
3590  (3 == mal_type))
3591  { /* Try to maximise representation */
3592  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3593  tmp_att_peer->peer_id = *peer;
3594  if (NULL == att_peer_set)
3595  att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
3597  peer))
3598  {
3599  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3600  att_peers_tail,
3601  tmp_att_peer);
3602  add_peer_array_to_set (peer, 1, att_peer_set);
3603  }
3604  else
3605  {
3606  GNUNET_free (tmp_att_peer);
3607  }
3608  }
3609 
3610 
3611  else if (2 == mal_type)
3612  {
3613  /* We attack one single well-known peer - simply ignore */
3614  }
3615  #endif /* ENABLE_MALICIOUS */
3616 
3617  /* Add the sending peer to the push_map */
3618  CustomPeerMap_put (channel_ctx->peer_ctx->sub->push_map, peer);
3619 
3621  &channel_ctx->peer_ctx->peer_id));
3622  GNUNET_CADET_receive_done (channel_ctx->channel);
3623 }
3624 
3625 
3634 static void
3636  const struct GNUNET_MessageHeader *msg)
3637 {
3638  const struct ChannelCtx *channel_ctx = cls;
3639  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
3640  const struct GNUNET_PeerIdentity *peer = &peer_ctx->peer_id;
3641  const struct GNUNET_PeerIdentity *view_array;
3642 
3643  (void) msg;
3644 
3645  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (
3646  peer));
3647  if (peer_ctx->sub == msub)
3648  {
3649  GNUNET_STATISTICS_update (stats,
3650  "# pull request message received",
3651  1,
3652  GNUNET_NO);
3653  if ((NULL != map_single_hop) &&
3655  &peer_ctx->peer_id)))
3656  {
3657  GNUNET_STATISTICS_update (stats,
3658  "# pull request message received (multi-hop peer)",
3659  1,
3660  GNUNET_NO);
3661  }
3662  }
3663 
3664  #if ENABLE_MALICIOUS
3665  if ((1 == mal_type)
3666  || (3 == mal_type))
3667  { /* Try to maximise representation */
3668  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3669  }
3670 
3671  else if (2 == mal_type)
3672  { /* Try to partition network */
3673  if (0 == GNUNET_memcmp (&attacked_peer, peer))
3674  {
3675  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3676  }
3677  }
3678  #endif /* ENABLE_MALICIOUS */
3679 
3681  &channel_ctx->peer_ctx->peer_id));
3682  GNUNET_CADET_receive_done (channel_ctx->channel);
3683  view_array = View_get_as_array (channel_ctx->peer_ctx->sub->view);
3684  send_pull_reply (peer_ctx,
3685  view_array,
3686  View_size (channel_ctx->peer_ctx->sub->view));
3687 }
3688 
3689 
3697 static int
3699  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3700 {
3701  struct ChannelCtx *channel_ctx = cls;
3702  struct PeerContext *sender_ctx = channel_ctx->peer_ctx;
3703 
3704  if (sizeof(struct GNUNET_RPS_P2P_PullReplyMessage) > ntohs (msg->header.size))
3705  {
3706  GNUNET_break_op (0);
3707  return GNUNET_SYSERR;
3708  }
3709 
3710  if ((ntohs (msg->header.size) - sizeof(struct
3712  / sizeof(struct GNUNET_PeerIdentity) != ntohl (msg->num_peers))
3713  {
3715  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3716  ntohl (msg->num_peers),
3717  (ntohs (msg->header.size) - sizeof(struct
3719  / sizeof(struct GNUNET_PeerIdentity));
3720  GNUNET_break_op (0);
3721  return GNUNET_SYSERR;
3722  }
3723 
3724  if (GNUNET_YES != check_peer_flag (sender_ctx->sub->peer_map,
3725  &sender_ctx->peer_id,
3727  {
3729  "Received a pull reply from a peer (%s) we didn't request one from!\n",
3730  GNUNET_i2s (&sender_ctx->peer_id));
3731  if (sender_ctx->sub == msub)
3732  {
3733  GNUNET_STATISTICS_update (stats,
3734  "# unrequested pull replies",
3735  1,
3736  GNUNET_NO);
3737  }
3738  }
3739  return GNUNET_OK;
3740 }
3741 
3742 
3749 static void
3751  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3752 {
3753  const struct ChannelCtx *channel_ctx = cls;
3754  const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id;
3755  const struct GNUNET_PeerIdentity *peers;
3756  struct Sub *sub = channel_ctx->peer_ctx->sub;
3757  uint32_t i;
3758 
3759 #if ENABLE_MALICIOUS
3760  struct AttackedPeer *tmp_att_peer;
3761 #endif /* ENABLE_MALICIOUS */
3762 
3763  sub->pull_delays[sub->num_rounds - channel_ctx->peer_ctx->round_pull_req]++;
3764  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (
3765  sender));
3766  if (channel_ctx->peer_ctx->sub == msub)
3767  {
3768  GNUNET_STATISTICS_update (stats,
3769  "# pull reply messages received",
3770  1,
3771  GNUNET_NO);
3772  if ((NULL != map_single_hop) &&
3774  &channel_ctx->
3775  peer_ctx->peer_id)) )
3776  {
3777  GNUNET_STATISTICS_update (stats,
3778  "# pull reply messages received (multi-hop peer)",
3779  1,
3780  GNUNET_NO);
3781  }
3782  }
3783 
3784  #if ENABLE_MALICIOUS
3785  // We shouldn't even receive pull replies as we're not sending
3786  if (2 == mal_type)
3787  {
3788  }
3789  #endif /* ENABLE_MALICIOUS */
3790 
3791  /* Do actual logic */
3792  peers = (const struct GNUNET_PeerIdentity *) &msg[1];
3793 
3795  "PULL REPLY received, got following %u peers:\n",
3796  ntohl (msg->num_peers));
3797 
3798  for (i = 0; i < ntohl (msg->num_peers); i++)
3799  {
3801  "%u. %s\n",
3802  i,
3803  GNUNET_i2s (&peers[i]));
3804 
3805  #if ENABLE_MALICIOUS
3806  if ((NULL != att_peer_set) &&
3807  ((1 == mal_type) || (3 == mal_type) ))
3808  { /* Add attacked peer to local list */
3809  // TODO check if we sent a request and this was the first reply
3810  if ((GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
3811  &peers[i]))
3813  &peers[i])) )
3814  {
3815  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3816  tmp_att_peer->peer_id = peers[i];
3817  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3818  att_peers_tail,
3819  tmp_att_peer);
3820  add_peer_array_to_set (&peers[i], 1, att_peer_set);
3821  }
3822  continue;
3823  }
3824  #endif /* ENABLE_MALICIOUS */
3825  /* Make sure we 'know' about this peer */
3826  (void) insert_peer (channel_ctx->peer_ctx->sub,
3827  &peers[i]);
3828 
3829  if (GNUNET_YES == check_peer_valid (channel_ctx->peer_ctx->sub->valid_peers,
3830  &peers[i]))
3831  {
3832  CustomPeerMap_put (channel_ctx->peer_ctx->sub->pull_map,
3833  &peers[i]);
3834  }
3835  else
3836  {
3837  schedule_operation (channel_ctx->peer_ctx,
3839  channel_ctx->peer_ctx->sub); /* cls */
3840  (void) issue_peer_online_check (channel_ctx->peer_ctx->sub,
3841  &peers[i]);
3842  }
3843  }
3844 
3846  sender),
3848  clean_peer (channel_ctx->peer_ctx->sub,
3849  sender);
3850 
3852  sender));
3853  GNUNET_CADET_receive_done (channel_ctx->channel);
3854 }
3855 
3856 
3867 static struct GNUNET_TIME_Relative
3869  unsigned int spread)
3870 {
3871  struct GNUNET_TIME_Relative half_interval;
3872  struct GNUNET_TIME_Relative ret;
3873  unsigned int rand_delay;
3874  unsigned int max_rand_delay;
3875 
3876  if (0 == spread)
3877  {
3879  "Not accepting spread of 0\n");
3880  GNUNET_break (0);
3881  GNUNET_assert (0);
3882  }
3883  GNUNET_assert (0 != mean.rel_value_us);
3884 
3885  /* Compute random time value between spread * mean and spread * mean */
3886  half_interval = GNUNET_TIME_relative_divide (mean, spread);
3887 
3888  max_rand_delay = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us
3889  / mean.rel_value_us * (2 / spread);
3895  max_rand_delay);
3896  ret = GNUNET_TIME_relative_saturating_multiply (mean, rand_delay);
3897  ret = GNUNET_TIME_relative_divide (ret, max_rand_delay);
3898  ret = GNUNET_TIME_relative_add (ret, half_interval);
3899 
3900  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == ret.rel_value_us)
3902  "Returning FOREVER_REL\n");
3903 
3904  return ret;
3905 }
3906 
3907 
3913 static void
3914 send_pull_request (struct PeerContext *peer_ctx)
3915 {
3916  struct GNUNET_MQ_Envelope *ev;
3917 
3919  &peer_ctx->peer_id,
3921  SET_PEER_FLAG (peer_ctx,
3923  peer_ctx->round_pull_req = peer_ctx->sub->num_rounds;
3924 
3926  "Going to send PULL REQUEST to peer %s.\n",
3927  GNUNET_i2s (&peer_ctx->peer_id));
3928 
3930  send_message (peer_ctx,
3931  ev,
3932  "PULL REQUEST");
3933  if (peer_ctx->sub)
3934  {
3935  GNUNET_STATISTICS_update (stats,
3936  "# pull request send issued",
3937  1,
3938  GNUNET_NO);
3939  if ((NULL != map_single_hop) &&
3941  &peer_ctx->peer_id)))
3942  {
3943  GNUNET_STATISTICS_update (stats,
3944  "# pull request send issued (multi-hop peer)",
3945  1,
3946  GNUNET_NO);
3947  }
3948  }
3949 }
3950 
3951 
3957 static void
3958 send_push (struct PeerContext *peer_ctx)
3959 {
3960  struct GNUNET_MQ_Envelope *ev;
3961 
3963  "Going to send PUSH to peer %s.\n",
3964  GNUNET_i2s (&peer_ctx->peer_id));
3965 
3967  send_message (peer_ctx, ev, "PUSH");
3968  if (peer_ctx->sub)
3969  {
3970  GNUNET_STATISTICS_update (stats,
3971  "# push send issued",
3972  1,
3973  GNUNET_NO);
3974  if ((NULL != map_single_hop) &&
3976  &peer_ctx->peer_id)))
3977  {
3978  GNUNET_STATISTICS_update (stats,
3979  "# push send issued (multi-hop peer)",
3980  1,
3981  GNUNET_NO);
3982  }
3983  }
3984 }
3985 
3986 
3987 #if ENABLE_MALICIOUS
3988 
3989 
3998 static int
3999 check_client_act_malicious (void *cls,
4000  const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
4001 {
4002  struct ClientContext *cli_ctx = cls;
4003  uint16_t msize = ntohs (msg->header.size);
4004  uint32_t num_peers = ntohl (msg->num_peers);
4005 
4006  msize -= sizeof(struct GNUNET_RPS_CS_ActMaliciousMessage);
4007  if ((msize / sizeof(struct GNUNET_PeerIdentity) != num_peers) ||
4008  (msize % sizeof(struct GNUNET_PeerIdentity) != 0))
4009  {
4011  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
4012  ntohl (msg->num_peers),
4013  (msize / sizeof(struct GNUNET_PeerIdentity)));
4014  GNUNET_break (0);
4016  return GNUNET_SYSERR;
4017  }
4018  return GNUNET_OK;
4019 }
4020 
4021 
4029 static void
4030 handle_client_act_malicious (void *cls,
4031  const struct
4032  GNUNET_RPS_CS_ActMaliciousMessage *msg)
4033 {
4034  struct ClientContext *cli_ctx = cls;
4035  struct GNUNET_PeerIdentity *peers;
4036  uint32_t num_mal_peers_sent;
4037  uint32_t num_mal_peers_old;
4038  struct Sub *sub = cli_ctx->sub;
4039 
4040  if (NULL == sub)
4041  sub = msub;
4042  /* Do actual logic */
4043  peers = (struct GNUNET_PeerIdentity *) &msg[1];
4044  mal_type = ntohl (msg->type);
4045  if (NULL == mal_peer_set)
4046  mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
4047 
4049  "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
4050  mal_type,
4051  ntohl (msg->num_peers));
4052 
4053  if (1 == mal_type)
4054  { /* Try to maximise representation */
4055  /* Add other malicious peers to those we already know */
4056 
4057  num_mal_peers_sent = ntohl (msg->num_peers);
4058  num_mal_peers_old = num_mal_peers;
4059  GNUNET_array_grow (mal_peers,
4060  num_mal_peers,
4061  num_mal_peers + num_mal_peers_sent);
4062  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
4063  peers,
4064  num_mal_peers_sent * sizeof(struct GNUNET_PeerIdentity));
4065 
4066  /* Add all mal peers to mal_peer_set */
4067  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
4068  num_mal_peers_sent,
4069  mal_peer_set);
4070 
4071  /* Substitute do_round () with do_mal_round () */
4072  GNUNET_assert (NULL != sub->do_round_task);
4074  sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
4075  }
4076 
4077  else if ((2 == mal_type) ||
4078  (3 == mal_type))
4079  { /* Try to partition the network */
4080  /* Add other malicious peers to those we already know */
4081 
4082  num_mal_peers_sent = ntohl (msg->num_peers) - 1;
4083  num_mal_peers_old = num_mal_peers;
4084  GNUNET_assert (GNUNET_MAX_MALLOC_CHECKED > num_mal_peers_sent);
4085  GNUNET_array_grow (mal_peers,
4086  num_mal_peers,
4087  num_mal_peers + num_mal_peers_sent);
4088  if ((NULL != mal_peers) &&
4089  (0 != num_mal_peers) )
4090  {
4091  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
4092  peers,
4093  num_mal_peers_sent * sizeof(struct GNUNET_PeerIdentity));
4094 
4095  /* Add all mal peers to mal_peer_set */
4096  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
4097  num_mal_peers_sent,
4098  mal_peer_set);
4099  }
4100 
4101  /* Store the one attacked peer */
4102  GNUNET_memcpy (&attacked_peer,
4103  &msg->attacked_peer,
4104  sizeof(struct GNUNET_PeerIdentity));
4105  /* Set the flag of the attacked peer to valid to avoid problems */
4106  if (GNUNET_NO == check_peer_known (sub->peer_map, &attacked_peer))
4107  {
4108  (void) issue_peer_online_check (sub, &attacked_peer);
4109  }
4110 
4112  "Attacked peer is %s\n",
4113  GNUNET_i2s (&attacked_peer));
4114 
4115  /* Substitute do_round () with do_mal_round () */
4116  if (NULL != sub->do_round_task)
4117  {
4118  /* Probably in shutdown */
4120  sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
4121  }
4122  }
4123  else if (0 == mal_type)
4124  { /* Stop acting malicious */
4125  GNUNET_array_grow (mal_peers, num_mal_peers, 0);
4126 
4127  /* Substitute do_mal_round () with do_round () */
4130  }
4131  else
4132  {
4133  GNUNET_break (0);
4135  }
4137 }
4138 
4139 
4147 static void
4148 do_mal_round (void *cls)
4149 {
4150  uint32_t num_pushes;
4151  uint32_t i;
4152  struct GNUNET_TIME_Relative time_next_round;
4153  struct AttackedPeer *tmp_att_peer;
4154  struct Sub *sub = cls;
4155 
4157  "Going to execute next round maliciously type %" PRIu32 ".\n",
4158  mal_type);
4159  sub->do_round_task = NULL;
4160  GNUNET_assert (mal_type <= 3);
4161  /* Do malicious actions */
4162  if (1 == mal_type)
4163  { /* Try to maximise representation */
4164  /* The maximum of pushes we're going to send this round */
4165  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit,
4166  num_attacked_peers),
4168 
4170  "Going to send %" PRIu32 " pushes\n",
4171  num_pushes);
4172 
4173  /* Send PUSHes to attacked peers */
4174  for (i = 0; i < num_pushes; i++)
4175  {
4176  if (att_peers_tail == att_peer_index)
4177  att_peer_index = att_peers_head;
4178  else
4179  att_peer_index = att_peer_index->next;
4180 
4181  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4182  }
4183 
4184  /* Send PULLs to some peers to learn about additional peers to attack */
4185  tmp_att_peer = att_peer_index;
4186  for (i = 0; i < num_pushes * alpha; i++)
4187  {
4188  if (att_peers_tail == tmp_att_peer)
4189  tmp_att_peer = att_peers_head;
4190  else
4191  att_peer_index = tmp_att_peer->next;
4192 
4193  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4194  }
4195  }
4196 
4197 
4198  else if (2 == mal_type)
4199  {
4204  (void) issue_peer_online_check (sub, &attacked_peer);
4205  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4206  &attacked_peer,
4207  Peers_ONLINE))
4208  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4209  }
4210 
4211 
4212  if (3 == mal_type)
4213  { /* Combined attack */
4214  /* Send PUSH to attacked peers */
4215  if (GNUNET_YES == check_peer_known (sub->peer_map, &attacked_peer))
4216  {
4217  (void) issue_peer_online_check (sub, &attacked_peer);
4218  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4219  &attacked_peer,
4220  Peers_ONLINE))
4221  {
4223  "Goding to send push to attacked peer (%s)\n",
4224  GNUNET_i2s (&attacked_peer));
4225  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4226  }
4227  }
4228  (void) issue_peer_online_check (sub, &attacked_peer);
4229 
4230  /* The maximum of pushes we're going to send this round */
4231  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
4232  num_attacked_peers),
4234 
4236  "Going to send %" PRIu32 " pushes\n",
4237  num_pushes);
4238 
4239  for (i = 0; i < num_pushes; i++)
4240  {
4241  if (att_peers_tail == att_peer_index)
4242  att_peer_index = att_peers_head;
4243  else
4244  att_peer_index = att_peer_index->next;
4245 
4246  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4247  }
4248 
4249  /* Send PULLs to some peers to learn about additional peers to attack */
4250  tmp_att_peer = att_peer_index;
4251  for (i = 0; i < num_pushes * alpha; i++)
4252  {
4253  if (att_peers_tail == tmp_att_peer)
4254  tmp_att_peer = att_peers_head;
4255  else
4256  att_peer_index = tmp_att_peer->next;
4257 
4258  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4259  }
4260  }
4261 
4262  /* Schedule next round */
4263  time_next_round = compute_rand_delay (sub->round_interval, 2);
4264 
4265  GNUNET_assert (NULL == sub->do_round_task);
4266  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4267  &do_mal_round, sub);
4268  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4269 }
4270 
4271 
4272 #endif /* ENABLE_MALICIOUS */
4273 
4274 
4282 static void
4283 do_round (void *cls)
4284 {
4285  unsigned int i;
4286  const struct GNUNET_PeerIdentity *view_array;
4287  unsigned int *permut;
4288  unsigned int a_peers; /* Number of peers we send pushes to */
4289  unsigned int b_peers; /* Number of peers we send pull requests to */
4290  uint32_t first_border;
4291  uint32_t second_border;
4292  struct GNUNET_PeerIdentity peer;
4293  struct GNUNET_PeerIdentity *update_peer;
4294  struct Sub *sub = cls;
4295 
4296  sub->num_rounds++;
4298  "Going to execute next round.\n");
4299  if (sub == msub)
4300  {
4301  GNUNET_STATISTICS_update (stats, "# rounds", 1, GNUNET_NO);
4302  }
4303  sub->do_round_task = NULL;
4304 #ifdef TO_FILE_FULL
4305  to_file (sub->file_name_view_log,
4306  "___ new round ___");
4307 #endif /* TO_FILE_FULL */
4308  view_array = View_get_as_array (sub->view);
4309  for (i = 0; i < View_size (sub->view); i++)
4310  {
4312  "\t%s\n", GNUNET_i2s (&view_array[i]));
4313 #ifdef TO_FILE_FULL
4314  to_file (sub->file_name_view_log,
4315  "=%s\t(do round)",
4316  GNUNET_i2s_full (&view_array[i]));
4317 #endif /* TO_FILE_FULL */
4318  }
4319 
4320 
4321  /* Send pushes and pull requests */
4322  if (0 < View_size (sub->view))
4323  {
4325  View_size (sub->view));
4326 
4327  /* Send PUSHes */
4328  a_peers = ceil (alpha * View_size (sub->view));
4329 
4331  "Going to send pushes to %u (ceil (%f * %u)) peers.\n",
4332  a_peers, alpha, View_size (sub->view));
4333  for (i = 0; i < a_peers; i++)
4334  {
4335  peer = view_array[permut[i]];
4336  // FIXME if this fails schedule/loop this for later
4337  send_push (get_peer_ctx (sub->peer_map, &peer));
4338  }
4339 
4340  /* Send PULL requests */
4341  b_peers = ceil (beta * View_size (sub->view));
4342  first_border = a_peers;
4343  second_border = a_peers + b_peers;
4344  if (second_border > View_size (sub->view))
4345  {
4346  first_border = View_size (sub->view) - b_peers;
4347  second_border = View_size (sub->view);
4348  }
4350  "Going to send pulls to %u (ceil (%f * %u)) peers.\n",
4351  b_peers, beta, View_size (sub->view));
4352  for (i = first_border; i < second_border; i++)
4353  {
4354  peer = view_array[permut[i]];
4355  if (GNUNET_NO == check_peer_flag (sub->peer_map,
4356  &peer,
4358  { // FIXME if this fails schedule/loop this for later
4359  send_pull_request (get_peer_ctx (sub->peer_map, &peer));
4360  }
4361  }
4362 
4363  GNUNET_free (permut);
4364  permut = NULL;
4365  }
4366 
4367 
4368  /* Update view */
4369  /* TODO see how many peers are in push-/pull- list! */
4370 
4371  if ((CustomPeerMap_size (sub->push_map) <= alpha * sub->view_size_est_need) &&
4372  (0 < CustomPeerMap_size (sub->push_map)) &&
4373  (0 < CustomPeerMap_size (sub->pull_map)))
4374  { /* If conditions for update are fulfilled, update */
4375  LOG (GNUNET_ERROR_TYPE_DEBUG, "Update of the view.\n");
4376 
4377  uint32_t final_size;
4378  uint32_t peers_to_clean_size;
4379  struct GNUNET_PeerIdentity *peers_to_clean;
4380 
4381  peers_to_clean = NULL;
4382  peers_to_clean_size = 0;
4383  GNUNET_array_grow (peers_to_clean,
4384  peers_to_clean_size,
4385  View_size (sub->view));
4386  GNUNET_memcpy (peers_to_clean,
4387  view_array,
4388  View_size (sub->view) * sizeof(struct GNUNET_PeerIdentity));
4389 
4390  /* Seems like recreating is the easiest way of emptying the peermap */
4391  View_clear (sub->view);
4392 #ifdef TO_FILE_FULL
4393  to_file (sub->file_name_view_log,
4394  "--- emptied ---");
4395 #endif /* TO_FILE_FULL */
4396 
4397  first_border = GNUNET_MIN (ceil (alpha * sub->view_size_est_need),
4398  CustomPeerMap_size (sub->push_map));
4399  second_border = first_border
4400  + GNUNET_MIN (floor (beta * sub->view_size_est_need),
4401  CustomPeerMap_size (sub->pull_map));
4402  final_size = second_border
4403  + ceil ((1 - (alpha + beta)) * sub->view_size_est_need);
4405  "first border: %" PRIu32 ", second border: %" PRIu32 ", final size: %"
4406  PRIu32 "\n",
4407  first_border,
4408  second_border,
4409  final_size);
4410 
4411  /* Update view with peers received through PUSHes */
4413  CustomPeerMap_size (sub->push_map));
4414  for (i = 0; i < first_border; i++)
4415  {
4416  int inserted;
4417  inserted = insert_in_view (sub,
4419  permut[i]));
4420  if (GNUNET_OK == inserted)
4421  {
4423  1,
4425  sub->push_map, permut[i]));
4426  }
4427 #ifdef TO_FILE_FULL
4428  to_file (sub->file_name_view_log,
4429  "+%s\t(push list)",
4430  GNUNET_i2s_full (&view_array[i]));
4431 #endif /* TO_FILE_FULL */
4432  // TODO change the peer_flags accordingly
4433  }
4434  GNUNET_free (permut);
4435  permut = NULL;
4436 
4437  /* Update view with peers received through PULLs */
4439  CustomPeerMap_size (sub->pull_map));
4440  for (i = first_border; i < second_border; i++)
4441  {
4442  int inserted;
4443  inserted = insert_in_view (sub,
4445  permut[i
4446  -
4447  first_border
4448  ]));
4449  if (GNUNET_OK == inserted)
4450  {
4452  1,
4454  sub->pull_map,
4455  permut[i
4456  - first_border]));
4457  }
4458 #ifdef TO_FILE_FULL
4459  to_file (sub->file_name_view_log,
4460  "+%s\t(pull list)",
4461  GNUNET_i2s_full (&view_array[i]));
4462 #endif /* TO_FILE_FULL */
4463  // TODO change the peer_flags accordingly
4464  }
4465  GNUNET_free (permut);
4466  permut = NULL;
4467 
4468  /* Update view with peers from history */
4470  final_size - second_border,
4471  hist_update,
4472  sub);
4473  // TODO change the peer_flags accordingly
4474 
4475  for (i = 0; i < View_size (sub->view); i++)
4476  rem_from_list (&peers_to_clean, &peers_to_clean_size, &view_array[i]);
4477 
4478  /* Clean peers that were removed from the view */
4479  for (i = 0; i < peers_to_clean_size; i++)
4480  {
4481 #ifdef TO_FILE_FULL
4482  to_file (sub->file_name_view_log,
4483  "-%s",
4484  GNUNET_i2s_full (&peers_to_clean[i]));
4485 #endif /* TO_FILE_FULL */
4486  clean_peer (sub, &peers_to_clean[i]);
4487  }
4488 
4489  GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
4491  }
4492  else
4493  {
4494  LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
4495  if (sub == msub)
4496  {
4497  GNUNET_STATISTICS_update (stats, "# rounds blocked", 1, GNUNET_NO);
4498  if ((CustomPeerMap_size (sub->push_map) > alpha
4499  * sub->view_size_est_need) &&
4500  ! (0 >= CustomPeerMap_size (sub->pull_map)))
4501  GNUNET_STATISTICS_update (stats, "# rounds blocked - too many pushes",
4502  1, GNUNET_NO);
4503  if ((CustomPeerMap_size (sub->push_map) > alpha
4504  * sub->view_size_est_need) &&
4505  (0 >= CustomPeerMap_size (sub->pull_map)))
4506  GNUNET_STATISTICS_update (stats,
4507  "# rounds blocked - too many pushes, no pull replies",
4508  1, GNUNET_NO);
4509  if ((0 >= CustomPeerMap_size (sub->push_map)) &&
4510  ! (0 >= CustomPeerMap_size (sub->pull_map)))
4511  GNUNET_STATISTICS_update (stats, "# rounds blocked - no pushes", 1,
4512  GNUNET_NO);
4513  if ((0 >= CustomPeerMap_size (sub->push_map)) &&
4514  (0 >= CustomPeerMap_size (sub->pull_map)))
4515  GNUNET_STATISTICS_update (stats,
4516  "# rounds blocked - no pushes, no pull replies",
4517  1, GNUNET_NO);
4518  if ((0 >= CustomPeerMap_size (sub->pull_map)) &&
4520  * sub->view_size_est_need) &&
4521  (0 >= CustomPeerMap_size (sub->push_map)) )
4522  GNUNET_STATISTICS_update (stats, "# rounds blocked - no pull replies",
4523  1, GNUNET_NO);
4524  }
4525  }
4526  // TODO independent of that also get some peers from CADET_get_peers()?
4528  {
4529  sub->push_recv[CustomPeerMap_size (sub->push_map)]++;
4530  }
4531  else
4532  {
4534  "Push map size too big for histogram (%u, %u)\n",
4537  }
4538  // FIXME check bounds of histogram
4539  sub->push_delta[(int32_t) (CustomPeerMap_size (sub->push_map)
4540  - (alpha * sub->view_size_est_need))
4541  + (HISTOGRAM_FILE_SLOTS / 2)]++;
4542  if (sub == msub)
4543  {
4544  GNUNET_STATISTICS_set (stats,
4545  "# peers in push map at end of round",
4547  GNUNET_NO);
4548  GNUNET_STATISTICS_set (stats,
4549  "# peers in pull map at end of round",
4551  GNUNET_NO);
4552  GNUNET_STATISTICS_set (stats,
4553  "# peers in view at end of round",
4554  View_size (sub->view),
4555  GNUNET_NO);
4556  GNUNET_STATISTICS_set (stats,
4557  "# expected pushes",
4558  alpha * sub->view_size_est_need,
4559  GNUNET_NO);
4560  GNUNET_STATISTICS_set (stats,
4561  "delta expected - received pushes",
4563  * sub->
4564  view_size_est_need),
4565  GNUNET_NO);
4566  }
4567 
4569  "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (sub->view%u) = %.2f)\n",
4572  alpha,
4573  View_size (sub->view),
4574  alpha * View_size (sub->view));
4575 
4576  /* Update samplers */
4577  for (i = 0; i < CustomPeerMap_size (sub->push_map); i++)
4578  {
4579  update_peer = CustomPeerMap_get_peer_by_index (sub->push_map, i);
4581  "Updating with peer %s from push list\n",
4582  GNUNET_i2s (update_peer));
4583  insert_in_sampler (sub, update_peer);
4584  clean_peer (sub, update_peer); /* This cleans only if it is not in the view */
4585  }
4586 
4587  for (i = 0; i < CustomPeerMap_size (sub->pull_map); i++)
4588  {
4590  "Updating with peer %s from pull list\n",
4593  /* This cleans only if it is not in the view */
4595  }
4596 
4597 
4598  /* Empty push/pull lists */
4601 
4602  if (sub == msub)
4603  {
4604  GNUNET_STATISTICS_set (stats,
4605  "view size",
4606  View_size (sub->view),
4607  GNUNET_NO);
4608  }
4609 
4610  struct GNUNET_TIME_Relative time_next_round;
4611 
4612  time_next_round = compute_rand_delay (sub->round_interval, 2);
4613 
4614  /* Schedule next round */
4615  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4616  &do_round, sub);
4617  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4618 }
4619 
4620 
4636 void
4637 init_peer_cb (void *cls,
4638  const struct GNUNET_PeerIdentity *peer,
4639  int tunnel, /* "Do we have a tunnel towards this peer?" */
4640  unsigned int n_paths, /* "Number of known paths towards this peer" */
4641  unsigned int best_path) /* "How long is the best path?
4642  * (0 = unknown, 1 = ourselves, 2 = neighbor)" */
4643 {
4644  struct Sub *sub = cls;
4645 
4646  (void) tunnel;
4647  (void) n_paths;
4648  (void) best_path;
4649 
4650  if (NULL != peer)
4651  {
4653  "Got peer_id %s from cadet\n",
4654  GNUNET_i2s (peer));
4655  got_peer (sub, peer);
4656  }
4657 }
4658 
4659 
4671 static int
4673  const struct GNUNET_PeerIdentity *peer)
4674 {
4675  struct Sub *sub = cls;
4676 
4677  if (NULL != peer)
4678  {
4680  "Got stored, valid peer %s\n",
4681  GNUNET_i2s (peer));
4682  got_peer (sub, peer);
4683  }
4684  return GNUNET_YES;
4685 }
4686 
4687 
4696 void
4698  const struct GNUNET_PeerIdentity *peer,
4699  const struct GNUNET_HELLO_Message *hello,
4700  const char *err_msg)
4701 {
4702  struct Sub *sub = cls;
4703 
4704  (void) hello;
4705  (void) err_msg;
4706 
4707  if (NULL != peer)
4708  {
4710  "Got peer_id %s from peerinfo\n",
4711  GNUNET_i2s (peer));
4712  got_peer (sub, peer);
4713  }
4714 }
4715 
4716 
4722 static void
4723 shutdown_task (void *cls)
4724 {
4725  (void) cls;
4726  struct ClientContext *client_ctx;
4727 
4729  "RPS service is going down\n");
4730 
4731  /* Clean all clients */
4732  for (client_ctx = cli_ctx_head;
4733  NULL != cli_ctx_head;
4734  client_ctx = cli_ctx_head)
4735  {
4736  destroy_cli_ctx (client_ctx);
4737  }
4738  if (NULL != msub)
4739  {
4740  destroy_sub (msub);
4741  msub = NULL;
4742  }
4743 
4744  /* Disconnect from other services */
4745  GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
4746  GNUNET_PEERINFO_disconnect (peerinfo_handle);
4747  peerinfo_handle = NULL;
4748  GNUNET_NSE_disconnect (nse);
4749  if (NULL != map_single_hop)
4750  {
4751  /* core_init was called - core was initialised */
4752  /* disconnect first, so no callback tries to access missing peermap */
4753  GNUNET_CORE_disconnect (core_handle);
4754  core_handle = NULL;
4755  GNUNET_CONTAINER_multipeermap_destroy (map_single_hop);
4756  map_single_hop = NULL;
4757  }
4758 
4759  if (NULL != stats)
4760  {
4762  GNUNET_NO);
4763  stats = NULL;
4764  }
4765  GNUNET_CADET_disconnect (cadet_handle);
4766  cadet_handle = NULL;
4767 #if ENABLE_MALICIOUS
4768  struct AttackedPeer *tmp_att_peer;
4769  GNUNET_array_grow (mal_peers,
4770  num_mal_peers,
4771  0);
4772  if (NULL != mal_peer_set)
4774  if (NULL != att_peer_set)
4776  while (NULL != att_peers_head)
4777  {
4778  tmp_att_peer = att_peers_head;
4779  GNUNET_CONTAINER_DLL_remove (att_peers_head,
4780  att_peers_tail,
4781  tmp_att_peer);
4782  GNUNET_free (tmp_att_peer);
4783  }
4784 #endif /* ENABLE_MALICIOUS */
4785  close_all_files ();
4786 }
4787 
4788 
4797 static void *
4799  struct GNUNET_SERVICE_Client *client,
4800  struct GNUNET_MQ_Handle *mq)
4801 {
4802  struct ClientContext *cli_ctx;
4803 
4804  (void) cls;
4805 
4807  "Client connected\n");
4808  if (NULL == client)
4809  return client; /* Server was destroyed before a client connected. Shutting down */
4810  cli_ctx = GNUNET_new (struct ClientContext);
4811  cli_ctx->mq = mq;
4812  cli_ctx->view_updates_left = -1;
4813  cli_ctx->stream_update = GNUNET_NO;
4814  cli_ctx->client = client;
4815  GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
4816  cli_ctx_tail,
4817  cli_ctx);
4818  return cli_ctx;
4819 }
4820 
4821 
4829 static void
4831  struct GNUNET_SERVICE_Client *client,
4832  void *internal_cls)
4833 {
4834  struct ClientContext *cli_ctx = internal_cls;
4835 
4836  (void) cls;
4837  GNUNET_assert (client == cli_ctx->client);
4838  if (NULL == client)
4839  { /* shutdown task - destroy all clients */
4840  while (NULL != cli_ctx_head)
4841  destroy_cli_ctx (cli_ctx_head);
4842  }
4843  else
4844  { /* destroy this client */
4846  "Client disconnected. Destroy its context.\n");
4847  destroy_cli_ctx (cli_ctx);
4848  }
4849 }
4850 
4851 
4859 static void
4860 run (void *cls,
4861  const struct GNUNET_CONFIGURATION_Handle *c,
4863 {
4864  struct GNUNET_TIME_Relative round_interval;
4865  long long unsigned int sampler_size;
4866  char hash_port_string[] = GNUNET_APPLICATION_PORT_RPS;
4867  struct GNUNET_HashCode hash;
4868 
4869  (void) cls;
4870  (void) service;
4871 
4872  GNUNET_log_setup ("rps",
4874  NULL);
4875  cfg = c;
4876  /* Get own ID */
4878  &own_identity); // TODO check return value
4880  "STARTING SERVICE (rps) for peer [%s]\n",
4882 #if ENABLE_MALICIOUS
4884  "Malicious execution compiled in.\n");
4885 #endif /* ENABLE_MALICIOUS */
4886 
4887  /* Get time interval from the configuration */
4888  if (GNUNET_OK !=
4890  "RPS",
4891  "ROUNDINTERVAL",
4892  &round_interval))
4893  {
4895  "RPS", "ROUNDINTERVAL");
4897  return;
4898  }
4899 
4900  /* Get initial size of sampler/view from the configuration */
4901  if (GNUNET_OK !=
4903  "RPS",
4904  "MINSIZE",
4905  &sampler_size))
4906  {
4908  "RPS", "MINSIZE");
4910  return;
4911  }
4912 
4913  cadet_handle = GNUNET_CADET_connect (cfg);
4914  GNUNET_assert (NULL != cadet_handle);
4915  core_handle = GNUNET_CORE_connect (cfg,
4916  NULL, /* cls */
4917  core_init, /* init */
4918  core_connects, /* connects */
4919  core_disconnects, /* disconnects */
4920  NULL); /* handlers */
4921  GNUNET_assert (NULL != core_handle);
4922 
4923 
4924  alpha = 0.45;
4925  beta = 0.45;
4926 
4927 
4928  /* Set up main Sub */
4929  GNUNET_CRYPTO_hash (hash_port_string,
4930  strlen (hash_port_string),
4931  &hash);
4932  msub = new_sub (&hash,
4933  sampler_size, /* Will be overwritten by config */
4934  round_interval);
4935 
4936 
4937  peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
4938 
4939  /* connect to NSE */
4940  nse = GNUNET_NSE_connect (cfg, nse_callback, NULL);
4941 
4942  // LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
4943  // GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, msub);
4944  // TODO send push/pull to each of those peers?
4945  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
4946  restore_valid_peers (msub);
4948 
4949  peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
4950  GNUNET_NO,
4952  msub);
4953 
4954  LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
4955 
4957  stats = GNUNET_STATISTICS_create ("rps", cfg);
4958 }
4959 
4960 
4965  ("rps",
4967  &run,
4970  NULL,
4971  GNUNET_MQ_hd_var_size (client_seed,
4974  NULL),
4975 #if ENABLE_MALICIOUS
4976  GNUNET_MQ_hd_var_size (client_act_malicious,
4977  GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
4978  struct GNUNET_RPS_CS_ActMaliciousMessage,
4979  NULL),
4980 #endif /* ENABLE_MALICIOUS */
4981  GNUNET_MQ_hd_fixed_size (client_view_request,
4984  NULL),
4985  GNUNET_MQ_hd_fixed_size (client_view_cancel,
4987  struct GNUNET_MessageHeader,
4988  NULL),
4989  GNUNET_MQ_hd_fixed_size (client_stream_request,
4992  NULL),
4993  GNUNET_MQ_hd_fixed_size (client_stream_cancel,
4995  struct GNUNET_MessageHeader,
4996  NULL),
4997  GNUNET_MQ_hd_fixed_size (client_start_sub,
5000  NULL),
5001  GNUNET_MQ_hd_fixed_size (client_stop_sub,
5004  NULL),
5006 
5007 /* end of gnunet-service-rps.c */
static void do_round(void *cls)
Send out PUSHes and PULLs, possibly update #view, samplers.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
static void send_pull_reply(struct PeerContext *peer_ctx, const struct GNUNET_PeerIdentity *peer_ids, unsigned int num_peer_ids)
Send a PULL REPLY to peer_id.
static void store_valid_peers(const struct Sub *sub)
Store the peers currently in #valid_peers to disk.
struct PeerPendingOp * pending_ops
Array of pending operations on this peer.
#define check_peer_flag_set(peer_ctx, mask)
Get peer flag of given peer context.
struct GNUNET_CORE_Handle * core_handle
Handle to CORE.
Struct used to store the context of a connected client.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition: disk.c:193
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_REPLY
Send peer of biased stream.
static int schedule_operation(struct PeerContext *peer_ctx, const PeerOp peer_op, void *cls)
Schedule a operation on given peer.
Open the file for reading.
static int insert_in_view(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Insert PeerID in #view.
void GNUNET_CADET_disconnect(struct GNUNET_CADET_Handle *handle)
Disconnect from the cadet service.
Definition: cadet_api.c:775
static void destroy_sub(struct Sub *sub)
Write all numbers in the given array into the given file.
Create file if it doesn&#39;t exist.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
#define GNUNET_MESSAGE_TYPE_RPS_CS_SUB_START
RPS client-service message to start a sub sampler.
Handle to the peerinfo service.
Definition: peerinfo_api.c:84
Message from service to client containing current update of view.
Definition: rps.h:185
A HELLO message is used to exchange information about transports with other peers.
uint32_t num_rounds
Counts the executed rounds.
struct ClientContext * cli_ctx_tail
struct GNUNET_HashCode hash
Hash of the shared value that defines Subs.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
Message from client to service indicating that clients wants to get stream of biased peers...
Definition: rps.h:208
static void handle_peer_pull_reply(void *cls, const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
Handle PULL REPLY message from another peer.
struct ClientContext * next
DLL.
void core_init(void *cls, const struct GNUNET_PeerIdentity *my_identity)
Callback on initialisation of Core.
static void * handle_inbound_channel(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Handle the channel a peer opens to us.
uint64_t rel_value_us
The actual value.
static int store_peer_presistently_iterator(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Iterator function for store_valid_peers.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
static void cleanup_destroyed_channel(void *cls, const struct GNUNET_CADET_Channel *channel)
This is called when a channel is destroyed.
static void insert_in_sampler(void *cls, const struct GNUNET_PeerIdentity *peer)
Update sampler with given PeerID.
struct GNUNET_MessageHeader header
Header including size and type in NBO.
Definition: rps.h:48
unsigned int * GNUNET_CRYPTO_random_permute(enum GNUNET_CRYPTO_Quality mode, unsigned int n)
Get an array with a random permutation of the numbers 0...n-1.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_PeerIdentity peer_id
Identity of the peer.
#define HISTOGRAM_FILE_SLOTS
This number determines the number of slots for files that represent histograms.
static float alpha
Percentage of total peer number in the view to send random PUSHes to.
Context for the core service connection.
Definition: core_api.c:77
static void resize_wrapper(struct RPS_Sampler *sampler, uint32_t new_size)
Wrapper around RPS_sampler_resize()
uint32_t num_updates
Number of updates 0 for sending updates until cancellation.
Definition: rps.h:179
Opaque handle to the service.
Definition: cadet_api.c:38
struct GNUNET_PeerIdentity * CustomPeerMap_get_peer_by_index(const struct CustomPeerMap *c_peer_map, uint32_t index)
Get a peer by index.
void * cls
Closure to iterator.
Handle to a service.
Definition: service.c:116
struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the peerinfo service.
Definition: peerinfo_api.c:130
Context for the info handler.
int GNUNET_CONTAINER_multipeermap_remove_all(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Remove all entries for the given key from the map.
void(* PeerOp)(void *cls, const struct GNUNET_PeerIdentity *peer)
Functions of this type can be used to be stored at a peer for later execution.
Definition: rps.h:317
static void insert_in_view_op(void *cls, const struct GNUNET_PeerIdentity *peer)
Insert PeerID in #view.
static int check_operation_scheduled(const struct PeerContext *peer_ctx, const PeerOp peer_op)
Check whether function of type PeerOp was already scheduled.
Message from client to service indicating that clients wants to get updates of the view...
Definition: rps.h:168
const char * GNUNET_error_type_to_string(enum GNUNET_ErrorType kind)
Convert error type to string.
unsigned int sampler_size_est_min
This is the minimum estimate used as sampler size.
P2P Message to send PeerIDs to other peer.
Definition: rps.h:43
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:602
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
utilities for managing (information about) peers
static struct PeerContext * create_peer_ctx(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Create a new PeerContext and insert it into the peer map.
struct ClientContext * cli_ctx
The client handle to send the reply to.
Peer map to store peers with specialised use-cases (push_list, pull_list, view, ...)
static int destroy_sending_channel(struct PeerContext *peer_ctx)
Destroy the send channel of a peer e.g.
int(* PeersIterator)(void *cls, const struct GNUNET_PeerIdentity *peer)
Iterator over valid peers.
Definition: rps.h:329
#define GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE
RPS check liveliness message to check liveliness of other peer.
#define GNUNET_MESSAGE_TYPE_RPS_CS_SUB_STOP
RPS client-service message to stop a sub sampler.
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REQUEST
Request updates of the view.
The closure to get_rand_peer_iterator.
Some utils facilitating the view into the internals for the sampler needed for evaluation.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
#define to_file(file_name,...)
This function is used to facilitate writing important information to disk.
Definition: rps-test_util.h:65
struct GNUNET_CADET_Handle * cadet_handle
Handler to CADET.
static void schedule_channel_destruction(struct ChannelCtx *channel_ctx)
Schedule the destruction of a channel for immediately afterwards.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
static void send_pull_request(struct PeerContext *peer_ctx)
Send single pull request.
int CustomPeerMap_contains_peer(const struct CustomPeerMap *c_peer_map, const struct GNUNET_PeerIdentity *peer)
Check whether custom peer map contains a peer.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Closure to valid_peer_iterator.
uint32_t num_peers
Number of PeerIDs sent.
Definition: rps.h:53
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1126
struct PeerContext * peer_ctx
The peer context associated with the channel.
static const struct GNUNET_PeerIdentity * get_random_peer_from_peermap(struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
Get a random peer from peer_map.
struct GNUNET_NSE_Handle * GNUNET_NSE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_NSE_Callback func, void *func_cls)
Connect to the network size estimation service.
Definition: nse_api.c:165
struct PeerContext * peer_ctx
The corresponding context.
unsigned int sampler_size_est_need
The size of sampler we need to be able to satisfy the Brahms protocol&#39;s need of random peers...
static void handle_peer_pull_request(void *cls, const struct GNUNET_MessageHeader *msg)
Handle PULL REQUEST request message from another peer.
void GNUNET_PEERINFO_notify_cancel(struct GNUNET_PEERINFO_NotifyContext *nc)
Stop notifying about changes.
void View_change_len(struct View *view, uint32_t len)
Change length of view.
static void hist_update(const struct GNUNET_PeerIdentity *ids, uint32_t num_peers, void *cls)
Put random peer from sampler into the view as history update.
struct RPS_SamplerRequestHandle * req_handle
The handle to the request.
#define GNUNET_MESSAGE_TYPE_RPS_PP_PUSH
RPS PUSH message to push own ID to another peer.
void process_peerinfo_peers(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
Iterator over peers from peerinfo.
static struct ChannelCtx * add_channel_ctx(struct PeerContext *peer_ctx)
Allocate memory for a new channel context and insert it into DLL.
struct RPS_Sampler * sampler
Sampler used for the Brahms protocol itself.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Handle client connecting to the service.
int View_contains_peer(const struct View *view, const struct GNUNET_PeerIdentity *peer)
Check whether view contains a peer.
struct Sub * sub
The Sub this context belongs to.
struct GNUNET_MQ_Envelope * ev
The envelope to the corresponding message.
Nobody is allowed to do anything to the file.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
unsigned int RPS_sampler_get_size(struct RPS_Sampler *sampler)
Get the size of the sampler.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
struct PendingMessage * next
DLL next, prev.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void RPS_sampler_update(struct RPS_Sampler *sampler, const struct GNUNET_PeerIdentity *id)
Update every sampler element of this sampler with given peer.
static void send_view(const struct ClientContext *cli_ctx, const struct GNUNET_PeerIdentity *view_array, uint64_t view_size)
Send view to client.
#define UNSET_PEER_FLAG(peer_ctx, mask)
Unset flag of given peer context.
static unsigned int mal_type
Portion of malicious peers.
static void check_peer_online(struct PeerContext *peer_ctx)
Issue a check whether peer is online.
void init_peer_cb(void *cls, const struct GNUNET_PeerIdentity *peer, int tunnel, unsigned int n_paths, unsigned int best_path)
This is called from GNUNET_CADET_get_peers().
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
struct ClientContext * prev
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
Opaque handle to a channel.
Definition: cadet.h:116
Peers_PeerFlags
Different flags indicating the status of another peer.
Definition: rps.h:245
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REPLY
Send update of the view.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
example IPC messages between RPS API and GNS service
struct GNUNET_SCHEDULER_Task * destruction_task
When channel destruction needs to be delayed (because it is called from within the cadet routine of a...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
uint32_t id
The identifier of the request.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls)
Callback called when a client disconnected from the service.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static struct Sub * msub
Main Sub.
void CustomPeerMap_destroy(struct CustomPeerMap *c_peer_map)
Destroy peermap.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
int64_t view_updates_left
How many updates this client expects to receive.
static void mq_online_check_successful(void *cls)
This is called in response to the first message we sent as a online check.
struct CustomPeerMap * push_map
List to store peers received through pushes temporary.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
Handle for the service.
static int check_client_seed(void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
This function is called, when the client seeds peers.
static int get_valid_peers(struct GNUNET_CONTAINER_MultiPeerMap *valid_peers, PeersIterator iterator, void *it_cls)
Get all currently known, valid peer ids.
struct GNUNET_MQ_Handle * mq
The message queue to communicate with the client.
static void mq_notify_sent_cb(void *cls)
This is called once a message is sent.
int8_t stream_update
Whether this client wants to receive stream updates.
const struct GNUNET_PeerIdentity * View_get_as_array(const struct View *view)
Get the view as an array.
static void send_stream_peers(const struct ClientContext *cli_ctx, uint64_t num_peers, const struct GNUNET_PeerIdentity *peers)
Send peer from biased stream to client.
Closure used to pass the client and the id to the callback that replies to a client&#39;s request...
static int check_removable(const struct PeerContext *peer_ctx)
Check if peer is removable.
static void remove_pending_message(struct PendingMessage *pending_msg, int cancel)
Remove a pending message from the respective DLL.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static void destroy_channel_cb(void *cls)
Destroy a cadet channel.
static struct PeerContext * get_peer_ctx(const struct GNUNET_CONTAINER_MultiPeerMap *peer_map, const struct GNUNET_PeerIdentity *peer)
Get the PeerContext associated with a peer.
int CustomPeerMap_remove_peer(const struct CustomPeerMap *c_peer_map, const struct GNUNET_PeerIdentity *peer)
Remove peer from custom peer map.
unsigned int view_size_est_need
This is the estimate used as view size.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
struct CustomPeerMap * CustomPeerMap_create(unsigned int len)
Create an empty peermap.
struct GNUNET_CADET_Handle * GNUNET_CADET_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the MQ-based cadet service.
Definition: cadet_api.c:910
struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify(const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls)
Call a method whenever our known information about peers changes.
unsigned int view_size_est_min
This is the minimum estimate used as view size.
static void print_peer_list(struct GNUNET_PeerIdentity *list, unsigned int len)
Print peerlist to log.
static void indicate_sending_intention(struct PeerContext *peer_ctx)
Indicate that we want to send to the other peer.
Message from client to service with seed of peers.
Definition: rps.h:66
uint32_t peer_flags
Flags indicating status of peer.
Closure to _get_n_rand_peers_ready_cb()
int View_put(struct View *view, const struct GNUNET_PeerIdentity *peer)
Insert peer into the view.
struct PendingMessage * online_check_pending
Handle to the callback given to cadet_ntfy_tmt_rdy()
static void restore_valid_peers(const struct Sub *sub)
Restore the peers on disk to #valid_peers.
Handle to a client that is connected to a service.
Definition: service.c:250
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
struct RPS_Sampler * RPS_sampler_init(size_t init_size, struct GNUNET_TIME_Relative max_round_interval)
Initialise a tuple of sampler elements.
static void handle_client_view_request(void *cls, const struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg)
Handle RPS request from the client.
static void handle_peer_check(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a CHECK_LIVE message from another peer.
static struct PendingMessage * insert_pending_message(struct PeerContext *peer_ctx, struct GNUNET_MQ_Envelope *ev, const char *type)
Add an envelope to a message passed to mq to list of pending messages.
uint32_t push_delta[32]
Histogram of deltas between the expected and actual number of received pushes.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
#define LOG(kind,...)
static void clients_notify_stream_peer(const struct Sub *sub, uint64_t num_peers, const struct GNUNET_PeerIdentity *peers)
sends updates to clients that are interested
static int check_peer_known(const struct GNUNET_CONTAINER_MultiPeerMap *peer_map, const struct GNUNET_PeerIdentity *peer)
Check whether we have information about the given peer.
#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:52
struct GNUNET_TIME_Relative round_interval
Time interval the do_round task runs in.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
If we are waiting for a reply from that peer (sent a pull request).
Definition: rps.h:250
int CustomPeerMap_put(const struct CustomPeerMap *c_peer_map, const struct GNUNET_PeerIdentity *peer)
Insert peer into the custom peer map.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
wrapper around the "local view"
#define GNUNET_APPLICATION_PORT_RPS
Transfer of blocks for random peer sampling.
uint64_t num_peers
Number of peers.
Definition: rps.h:229
struct GNUNET_CADET_Port * GNUNET_CADET_open_port(struct GNUNET_CADET_Handle *h, const struct GNUNET_HashCode *port, GNUNET_CADET_ConnectEventHandler connects, void *connects_cls, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Open a port to receive incoming MQ-based channels.
Definition: cadet_api.c:970
Context for a channel.
static void insert_in_pull_map(void *cls, const struct GNUNET_PeerIdentity *peer)
Insert PeerID in #pull_map.
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_CANCEL
Cancel getting updates of the view.
void * cls
Closure for mv and cb.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
void GNUNET_MQ_notify_sent(struct GNUNET_MQ_Envelope *ev, GNUNET_SCHEDULER_TaskCallback cb, void *cb_cls)
Call a callback once the envelope has been sent, that is, sending it can not be canceled anymore...
Definition: mq.c:787
static char * value
Value of the record to add/remove.
static struct GNUNET_PeerIdentity * peer_ids
struct ReplyCls * prev
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
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
static struct GNUNET_CONTAINER_MultiPeerMap * ids
GNUNET_PeerIdentity -> CadetPeer.
static void peers_terminate(struct Sub *sub)
Delete storage of peers that was created with #initialise_peers ()
void core_disconnects(void *cls, const struct GNUNET_PeerIdentity *peer, void *peer_cls)
Callback for core.
const char * type
The message type.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:666
static const struct GNUNET_PeerIdentity * s2i_full(const char *string_repr)
Convert string representation of peer id to peer id.
static void adapt_sizes(struct Sub *sub, double logestimate, double std_dev)
Update sizes in sampler and view on estimate update from nse service.
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:1296
static struct GNUNET_CONTAINER_MultiPeerMap * peer_map
Peermap to get the index of a given peer ID quick.
struct GNUNET_CONTAINER_MultiPeerMap * observed_unique_peers
Multipeermap (ab-) used to count unique peer_ids.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_public_key_from_string(const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a string representing a public key to a public key.
Definition: crypto_ecc.c:357
void CustomPeerMap_clear(const struct CustomPeerMap *c_peer_map)
Clear the custom peer map.
struct GNUNET_HashCode hash
Length of the shared value represented as string.
Definition: rps.h:158
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:93
struct GNUNET_CADET_Channel * get_channel(struct PeerContext *peer_ctx)
Get the channel of a peer.
struct Sub * new_sub(const struct GNUNET_HashCode *hash, uint32_t sampler_size, struct GNUNET_TIME_Relative round_interval)
Create a new Sub.
struct GNUNET_CONTAINER_MultiPeerMap * valid_peers
Hashmap of valid peers.
uint32_t num_observed_peers
Count the observed peers.
struct GNUNET_CADET_Channel * channel
The channel itself.
static char buf[2048]
Message from client to service telling it to stop a new sub.
Definition: rps.h:148
uint32_t round_pull_req
This is pobably followed by &#39;statistical&#39; data (when we first saw it, how did we get its ID...
static void handle_peer_push(void *cls, const struct GNUNET_MessageHeader *msg)
Handle a PUSH message from another peer.
struct CustomPeerMap * pull_map
List to store peers received through pulls temporary.
void RPS_sampler_destroy(struct RPS_Sampler *sampler)
Cleans the samplers.
#define GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REQUEST
RPS PULL REQUEST message to request the local view of another peer.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Handle random peer sampling clients.
struct RPS_SamplerRequestHandle * RPS_sampler_get_n_rand_peers(struct RPS_Sampler *sampler, uint32_t num_peers, RPS_sampler_n_rand_peers_ready_cb cb, void *cls)
Get n random peers out of the sampled peers.
struct View * View_create(uint32_t len)
Create an empty view.
Struct used to keep track of other peer&#39;s status.
static int check_peer_pull_reply(void *cls, const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
Check whether we sent a corresponding request and whether this reply is the first one...
static int fh
Handle to the unique file.
static void rem_from_list(struct GNUNET_PeerIdentity **peer_list, unsigned int *list_size, const struct GNUNET_PeerIdentity *peer)
Remove peer from list.
Internal representation of the hash map.
static int issue_peer_online_check(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Try connecting to a peer to see whether it is online.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh(struct GNUNET_TIME_RelativeNBO a)
Convert relative time from network byte order.
Definition: time.c:454
#define GNUNET_MESSAGE_TYPE_RPS_CS_SEED
RPS CS SEED Message for the Client to seed peers into rps.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
A 512-bit hashcode.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2325
Message handler for a specific message type.
#define SET_PEER_FLAG(peer_ctx, mask)
Set a peer flag of given peer context.
int close_all_files()
Close all files that were opened with get_file_handle.
static int add_valid_peer(const struct GNUNET_PeerIdentity *peer, struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
Add a given peer to valid peers.
#define GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE
Maximum message size that can be sent on CADET.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
Message from service to client containing peer from biased stream.
Definition: rps.h:219
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_CANCEL
Cancel getting biased stream.
void GNUNET_NSE_disconnect(struct GNUNET_NSE_Handle *h)
Disconnect from network size estimation service.
Definition: nse_api.c:193
Message from client to service telling it to start a new sub.
Definition: rps.h:121
void RPS_sampler_resize(struct RPS_Sampler *sampler, unsigned int new_size)
Grow or shrink the size of the sampler.
static int destroy_peer(struct PeerContext *peer_ctx)
Remove peer.
PeerOp op
Callback.
static struct GNUNET_MQ_Handle * get_mq(struct PeerContext *peer_ctx)
Get the message queue (GNUNET_MQ_Handle) of a specific peer.
Handle for talking with the NSE service.
Definition: nse_api.c:40
struct PendingMessage * prev
This is a doubly-linked list.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static void handle_client_view_cancel(void *cls, const struct GNUNET_MessageHeader *msg)
Handle the cancellation of the view updates.
We set this bit when we are going to destroy the channel to this peer.
Definition: rps.h:266
unsigned int num_pending_ops
Number of pending operations.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_CONTAINER_MultiPeerMap * peer_map
Set of all peers to keep track of them.
struct GNUNET_CADET_Port * cadet_port
Port to communicate to other peers.
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_SERVICE_Client * client
The client handle to send the reply to.
One Sub.
Open the file for writing.
struct GNUNET_CORE_Handle * GNUNET_CORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Connect to the core service.
Definition: core_api.c:692
static void handle_client_stop_sub(void *cls, const struct GNUNET_RPS_CS_SubStopMessage *msg)
Destroy the Sub.
static struct GNUNET_PeerIdentity own_identity
Our own identity.
void GNUNET_CORE_disconnect(struct GNUNET_CORE_Handle *handle)
Disconnect from the core service.
Definition: core_api.c:730
struct GNUNET_MessageHeader header
Header including size and type in NBO.
Definition: rps.h:71
static int check_peer_valid(const struct GNUNET_CONTAINER_MultiPeerMap *valid_peers, const struct GNUNET_PeerIdentity *peer)
Check whether peer is actually a peer.
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
uint32_t index
The index of the peer to return.
sampler implementation
uint32_t num_peers
Number of peers.
Definition: rps.h:76
static unsigned int num_peers
static void set_peer_online(struct PeerContext *peer_ctx)
Set the peer flag to living and call the pending operations on this peer.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
PeersIterator iterator
Iterator function.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
uint32_t push_recv[32]
This array accumulates the number of received pushes per round.
static void handle_client_start_sub(void *cls, const struct GNUNET_RPS_CS_SubStartMessage *msg)
Create and start a Sub.
static void handle_client_stream_request(void *cls, const struct GNUNET_RPS_CS_DEBUG_StreamRequest *msg)
Handle RPS request for biased stream from the client.
unsigned int CustomPeerMap_size(const struct CustomPeerMap *c_peer_map)
Get the size of the custom peer map.
static struct PeerContext * create_or_get_peer_ctx(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Create or get a PeerContext.
static int check_connected(struct PeerContext *peer_ctx)
Check whether we have a connection to this peer.
Handle to a message queue.
Definition: mq.c:85
static void clean_peer(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Remove data that is not needed anymore.
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_REQUEST
Request biased input stream.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
static void destroy_cli_ctx(struct ClientContext *cli_ctx)
Destroy the context for a (connected) client.
struct GNUNET_TIME_RelativeNBO round_interval
Mean interval between two rounds.
Definition: rps.h:136
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:411
#define GNUNET_MQ_msg_header(type)
Allocate a GNUNET_MQ_Envelope, where the message only consists of a header.
Definition: gnunet_mq_lib.h:76
The identity of the host (wraps the signing key of the peer).
void GNUNET_CADET_receive_done(struct GNUNET_CADET_Channel *channel)
Send an ack on the channel to confirm the processing of a message.
Definition: cadet_api.c:888
const struct GNUNET_PeerIdentity * peer
Pointer to peer to return.
struct GNUNET_CADET_Channel * GNUNET_CADET_channel_create(struct GNUNET_CADET_Handle *h, void *channel_cls, const struct GNUNET_PeerIdentity *destination, const struct GNUNET_HashCode *port, GNUNET_CADET_WindowSizeEventHandler window_changes, GNUNET_CADET_DisconnectEventHandler disconnects, const struct GNUNET_MQ_MessageHandler *handlers)
Create a new channel towards a remote peer.
Definition: cadet_api.c:1031
configuration data
Definition: configuration.c:84
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
static void remove_peer(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
remove peer from our knowledge, the view, push and pull maps and samplers.
struct ReplyCls * next
DLL.
static struct CadetPeer * peers
Operation to get peer ids.
static void send_push(struct PeerContext *peer_ctx)
Send single push.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
static int check_peer_send_intention(const struct PeerContext *peer_ctx)
Check whether other peer has the intention to send/opened channel towars us.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
void * core_connects(void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MQ_Handle *mq)
Callback for core.
Entry in list of pending tasks.
Definition: scheduler.c:134
static struct GNUNET_PEERINFO_Handle * peerinfo_handle
Handler to PEERINFO.
struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
uint32_t pull_delays[32]
Number of pull replies with this delay measured in rounds.
void View_destroy(struct View *view)
Destroy view.
static void handle_client_stream_cancel(void *cls, const struct GNUNET_MessageHeader *msg)
Handles the cancellation of the stream of biased peer ids.
List containing all messages that are yet to be send.
struct GNUNET_MQ_Handle * mq
Message queue open to client.
static void got_peer(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
This is called on peers from external sources (cadet, peerinfo, ...) If the peer is not known...
struct ChannelCtx * send_channel_ctx
Channel open to client.
unsigned int View_size(const struct View *view)
Get the size of the view.
Opaque handle to a port.
Definition: cadet_api.c:79
struct GNUNET_CONTAINER_MultiPeerMap * map_single_hop
PeerMap to keep track of connected peers.
void GNUNET_PEERINFO_disconnect(struct GNUNET_PEERINFO_Handle *h)
Disconnect from the peerinfo service.
Definition: peerinfo_api.c:156
struct ClientContext * cli_ctx_head
DLL with all clients currently connected to us.
int GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host&#39;s peer.
void View_clear(struct View *view)
Clear the view.
#define GNUNET_MESSAGE_TYPE_RPS_PP_PULL_REPLY
RPS PULL REPLY message which contains the view of the other peer.
static void send_message(struct PeerContext *peer_ctx, struct GNUNET_MQ_Envelope *ev, const char *type)
Send a message to another peer.
static void handle_client_seed(void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
Handle seed from the client.
static void destroy_channel(struct ChannelCtx *channel_ctx)
Callback for scheduler to destroy a channel.
static int insert_peer(struct Sub *sub, const struct GNUNET_PeerIdentity *peer)
Add peer to known peers.
void RPS_sampler_reinitialise_by_value(struct RPS_Sampler *sampler, const struct GNUNET_PeerIdentity *id)
Reinitialise all previously initialised sampler elements with the given value.
void * op_cls
Closure.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
static int check_sending_channel_exists(const struct PeerContext *peer_ctx)
Check whether a sending channel towards the given peer exists.
struct ChannelCtx * recv_channel_ctx
Channel open from client.
Header for all communications.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:376
static int valid_peer_iterator(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Iterator over #valid_peers hash map entries.
void GNUNET_CADET_close_port(struct GNUNET_CADET_Port *p)
Close a port opened with GNUNET_CADET_open_port().
Definition: cadet_api.c:808
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_SCHEDULER_Task * do_round_task
Identifier for the main task that runs periodically.
struct Sub * sub
The Sub this context belongs to.
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:355
struct PendingMessage * pending_messages_head
DLL with all messages that are yet to be sent.
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:562
static float beta
Percentage of total peer number in the view to send random PULLs to.
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
int View_remove_peer(struct View *view, const struct GNUNET_PeerIdentity *peer)
Remove peer from view.
static const uint32_t num_valid_peers_max
Maximum number of valid peers to keep.
static struct GNUNET_NSE_Handle * nse
Handler to NSE.
struct View * view
The view.
uint32_t RPS_sampler_count_id(struct RPS_Sampler *sampler, const struct GNUNET_PeerIdentity *id)
Counts how many Samplers currently hold a given PeerID.
static void shutdown_task(void *cls)
Task run during shutdown.
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
static struct GNUNET_PEERINFO_NotifyContext * peerinfo_notify_handle
Handle for cancellation of iteration over peers.
static void remove_channel_ctx(struct ChannelCtx *channel_ctx)
Free memory and NULL pointers.
struct PendingMessage * pending_messages_tail
static int check_sending_channel_needed(const struct PeerContext *peer_ctx)
Checks if there is a sending channel and if it is needed.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1055
uint64_t num_peers
Number of peers in the view.
Definition: rps.h:200
#define GNUNET_NSE_log_estimate_to_n(loge)
Convert the logarithmic estimated returned to the &#39;GNUNET_NSE_Callback&#39; into an absolute estimate in ...
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
void GNUNET_CADET_channel_destroy(struct GNUNET_CADET_Channel *channel)
Destroy an existing channel.
Definition: cadet_api.c:837
static void nse_callback(void *cls, struct GNUNET_TIME_Absolute timestamp, double logestimate, double std_dev)
Function called by NSE.
static int check_peer_flag(const struct GNUNET_CONTAINER_MultiPeerMap *peer_map, const struct GNUNET_PeerIdentity *peer, enum Peers_PeerFlags flags)
Check whether flags on a peer are set.
static struct GNUNET_TIME_Relative compute_rand_delay(struct GNUNET_TIME_Relative mean, unsigned int spread)
Compute a random delay.
Handle used to access files (and pipes).
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:357
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
static void clients_notify_view_update(const struct Sub *sub)
sends updates to clients that are interested
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2244
Pending operation on peer consisting of callback and closure.
Sampler with its own array of SamplerElements.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int peermap_clear_iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
We set this bit when we know the peer is online.
Definition: rps.h:259
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:437
#define GNUNET_malloc(size)
Wrapper around malloc.
GNUNET_SERVICE_MAIN("rps", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(client_seed, GNUNET_MESSAGE_TYPE_RPS_CS_SEED, struct GNUNET_RPS_CS_SeedMessage, NULL), GNUNET_MQ_hd_fixed_size(client_view_request, GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REQUEST, struct GNUNET_RPS_CS_DEBUG_ViewRequest, NULL), GNUNET_MQ_hd_fixed_size(client_view_cancel, GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_CANCEL, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(client_stream_request, GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_REQUEST, struct GNUNET_RPS_CS_DEBUG_StreamRequest, NULL), GNUNET_MQ_hd_fixed_size(client_stream_cancel, GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_CANCEL, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(client_start_sub, GNUNET_MESSAGE_TYPE_RPS_CS_SUB_START, struct GNUNET_RPS_CS_SubStartMessage, NULL), GNUNET_MQ_hd_fixed_size(client_stop_sub, GNUNET_MESSAGE_TYPE_RPS_CS_SUB_STOP, struct GNUNET_RPS_CS_SubStopMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
#define GNUNET_free(ptr)
Wrapper around free.
static int valid_peers_iterator(void *cls, const struct GNUNET_PeerIdentity *peer)
Iterator function over stored, valid peers.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
char * filename_valid_peers
Filename of the file that stores the valid peers persistently.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static int get_rand_peer_iterator(void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
Iterator function for get_random_peer_from_peermap.
struct GNUNET_MQ_Handle * GNUNET_CADET_get_mq(const struct GNUNET_CADET_Channel *channel)
Obtain the message queue for a connected peer.
Definition: cadet_api.c:1082
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
High-quality operations are desired.
struct GNUNET_HashCode hash
Length of the shared value represented as string.
Definition: rps.h:141