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 #endif /* ENABLE_MALICIOUS */
603 
604 
613 static struct PeerContext *
615  const struct GNUNET_PeerIdentity *peer)
616 {
617  struct PeerContext *ctx;
618  int ret;
619 
620  ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
621  GNUNET_assert (GNUNET_YES == ret);
622  ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
623  GNUNET_assert (NULL != ctx);
624  return ctx;
625 }
626 
627 
639 static int
641  const struct GNUNET_PeerIdentity *peer)
642 {
643  if (NULL != peer_map)
644  {
645  return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
646  }
647  else
648  {
649  return GNUNET_NO;
650  }
651 }
652 
653 
662 static struct PeerContext *
664  const struct GNUNET_PeerIdentity *peer)
665 {
666  struct PeerContext *ctx;
667  int ret;
668 
670 
671  ctx = GNUNET_new (struct PeerContext);
672  ctx->peer_id = *peer;
673  ctx->sub = sub;
674  ret = GNUNET_CONTAINER_multipeermap_put (sub->peer_map, peer, ctx,
676  GNUNET_assert (GNUNET_OK == ret);
677  if (sub == msub)
678  {
679  GNUNET_STATISTICS_set (stats,
680  "# known peers",
682  GNUNET_NO);
683  }
684  return ctx;
685 }
686 
687 
696 static struct PeerContext *
698  const struct GNUNET_PeerIdentity *peer)
699 {
700  if (GNUNET_NO == check_peer_known (sub->peer_map, peer))
701  {
702  return create_peer_ctx (sub, peer);
703  }
704  return get_peer_ctx (sub->peer_map, peer);
705 }
706 
707 
718 static int
719 check_connected (struct PeerContext *peer_ctx)
720 {
721  /* If we don't know about this peer we don't know whether it's online */
722  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
723  &peer_ctx->peer_id))
724  {
725  return GNUNET_NO;
726  }
727  /* Get the context */
728  peer_ctx = get_peer_ctx (peer_ctx->sub->peer_map, &peer_ctx->peer_id);
729  /* If we have no channel to this peer we don't know whether it's online */
730  if ((NULL == peer_ctx->send_channel_ctx) &&
731  (NULL == peer_ctx->recv_channel_ctx))
732  {
733  UNSET_PEER_FLAG (peer_ctx, Peers_ONLINE);
734  return GNUNET_NO;
735  }
736  /* Otherwise (if we have a channel, we know that it's online */
737  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
738  return GNUNET_YES;
739 }
740 
741 
746 {
752  uint32_t index;
753 
757  const struct GNUNET_PeerIdentity *peer;
758 };
759 
760 
776 static int
778  const struct GNUNET_PeerIdentity *peer,
779  void *value)
780 {
781  struct GetRandPeerIteratorCls *iterator_cls = cls;
782 
783  (void) value;
784 
785  if (0 >= iterator_cls->index)
786  {
787  iterator_cls->peer = peer;
788  return GNUNET_NO;
789  }
790  iterator_cls->index--;
791  return GNUNET_YES;
792 }
793 
794 
803 static const struct GNUNET_PeerIdentity *
805 {
806  struct GetRandPeerIteratorCls *iterator_cls;
807  const struct GNUNET_PeerIdentity *ret;
808 
809  iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
812  valid_peers));
813  (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
815  iterator_cls);
816  ret = iterator_cls->peer;
817  GNUNET_free (iterator_cls);
818  return ret;
819 }
820 
821 
833 static int
835  struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
836 {
837  const struct GNUNET_PeerIdentity *rand_peer;
838  int ret;
839 
840  ret = GNUNET_YES;
841  /* Remove random peers until there is space for a new one */
842  while (num_valid_peers_max <=
844  {
845  rand_peer = get_random_peer_from_peermap (valid_peers);
846  GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
847  ret = GNUNET_NO;
848  }
849  (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
851  if (valid_peers == msub->valid_peers)
852  {
853  GNUNET_STATISTICS_set (stats,
854  "# valid peers",
856  GNUNET_NO);
857  }
858  return ret;
859 }
860 
861 
862 static void
863 remove_pending_message (struct PendingMessage *pending_msg, int cancel);
864 
873 static void
874 set_peer_online (struct PeerContext *peer_ctx)
875 {
876  struct GNUNET_PeerIdentity *peer;
877  unsigned int i;
878 
879  peer = &peer_ctx->peer_id;
881  "Peer %s is online and valid, calling %i pending operations on it\n",
882  GNUNET_i2s (peer),
883  peer_ctx->num_pending_ops);
884 
885  if (NULL != peer_ctx->online_check_pending)
886  {
888  "Removing pending online check for peer %s\n",
889  GNUNET_i2s (&peer_ctx->peer_id));
890  // TODO wait until cadet sets mq->cancel_impl
891  // GNUNET_MQ_send_cancel (peer_ctx->online_check_pending->ev);
893  peer_ctx->online_check_pending = NULL;
894  }
895 
896  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
897 
898  /* Call pending operations */
899  for (i = 0; i < peer_ctx->num_pending_ops; i++)
900  {
901  peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
902  }
903  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
904 }
905 
906 
907 static void
908 cleanup_destroyed_channel (void *cls,
909  const struct GNUNET_CADET_Channel *channel);
910 
911 /* Declaration of handlers */
912 static void
913 handle_peer_check (void *cls,
914  const struct GNUNET_MessageHeader *msg);
915 
916 static void
917 handle_peer_push (void *cls,
918  const struct GNUNET_MessageHeader *msg);
919 
920 static void
921 handle_peer_pull_request (void *cls,
922  const struct GNUNET_MessageHeader *msg);
923 
924 static int
925 check_peer_pull_reply (void *cls,
926  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
927 
928 static void
929 handle_peer_pull_reply (void *cls,
930  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
931 
932 /* End declaration of handlers */
933 
941 static struct ChannelCtx *
943 {
944  struct ChannelCtx *channel_ctx;
945 
946  channel_ctx = GNUNET_new (struct ChannelCtx);
947  channel_ctx->peer_ctx = peer_ctx;
948  return channel_ctx;
949 }
950 
951 
957 static void
958 remove_channel_ctx (struct ChannelCtx *channel_ctx)
959 {
960  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
961 
962  if (NULL != channel_ctx->destruction_task)
963  {
965  channel_ctx->destruction_task = NULL;
966  }
967 
968  GNUNET_free (channel_ctx);
969 
970  if (NULL == peer_ctx)
971  return;
972  if (channel_ctx == peer_ctx->send_channel_ctx)
973  {
974  peer_ctx->send_channel_ctx = NULL;
975  peer_ctx->mq = NULL;
976  }
977  else if (channel_ctx == peer_ctx->recv_channel_ctx)
978  {
979  peer_ctx->recv_channel_ctx = NULL;
980  }
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 successfull\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  /* Cancle 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 replys 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 cancle 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  "Sting 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  "Sting 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(hist)",
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 #endif /* ENABLE_MALICIOUS */
2507 
2508 
2516 static void
2517 send_pull_reply (struct PeerContext *peer_ctx,
2518  const struct GNUNET_PeerIdentity *peer_ids,
2519  unsigned int num_peer_ids)
2520 {
2521  uint32_t send_size;
2522  struct GNUNET_MQ_Envelope *ev;
2523  struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
2524 
2525  /* Compute actual size */
2526  send_size = sizeof(struct GNUNET_RPS_P2P_PullReplyMessage)
2527  + num_peer_ids * sizeof(struct GNUNET_PeerIdentity);
2528 
2530  /* Compute number of peers to send
2531  * If too long, simply truncate */
2532  // TODO select random ones via permutation
2533  // or even better: do good protocol design
2534  send_size =
2536  - sizeof(struct GNUNET_RPS_P2P_PullReplyMessage))
2537  / sizeof(struct GNUNET_PeerIdentity);
2538  else
2539  send_size = num_peer_ids;
2540 
2542  "Going to send PULL REPLY with %u peers to %s\n",
2543  send_size, GNUNET_i2s (&peer_ctx->peer_id));
2544 
2545  ev = GNUNET_MQ_msg_extra (out_msg,
2546  send_size * sizeof(struct GNUNET_PeerIdentity),
2548  out_msg->num_peers = htonl (send_size);
2549  GNUNET_memcpy (&out_msg[1], peer_ids,
2550  send_size * sizeof(struct GNUNET_PeerIdentity));
2551 
2552  send_message (peer_ctx, ev, "PULL REPLY");
2553  if (peer_ctx->sub == msub)
2554  {
2555  GNUNET_STATISTICS_update (stats, "# pull reply send issued", 1, GNUNET_NO);
2556  }
2557  // TODO check with send intention: as send_channel is used/opened we indicate
2558  // a sending intention without intending it.
2559  // -> clean peer afterwards?
2560  // -> use recv_channel?
2561 }
2562 
2563 
2572 static void
2574  const struct GNUNET_PeerIdentity *peer)
2575 {
2576  struct Sub *sub = cls;
2577 
2578  CustomPeerMap_put (sub->pull_map, peer);
2579 }
2580 
2581 
2591 static void
2593  const struct GNUNET_PeerIdentity *peer)
2594 {
2595  struct Sub *sub = cls;
2596  int inserted;
2597 
2598  inserted = insert_in_view (sub, peer);
2599  if (GNUNET_OK == inserted)
2600  {
2601  clients_notify_stream_peer (sub, 1, peer);
2602  }
2603 }
2604 
2605 
2613 static void
2615  const struct GNUNET_PeerIdentity *peer)
2616 {
2617  struct Sub *sub = cls;
2618 
2620  "Updating samplers with peer %s from insert_in_sampler()\n",
2621  GNUNET_i2s (peer));
2622  RPS_sampler_update (sub->sampler, peer);
2623  if (0 < RPS_sampler_count_id (sub->sampler, peer))
2624  {
2625  /* Make sure we 'know' about this peer */
2626  (void) issue_peer_online_check (sub, peer);
2627  /* Establish a channel towards that peer to indicate we are going to send
2628  * messages to it */
2629  // indicate_sending_intention (peer);
2630  }
2631  if (sub == msub)
2632  {
2633  GNUNET_STATISTICS_update (stats,
2634  "# observed peers in gossip",
2635  1,
2636  GNUNET_NO);
2637  }
2638 #ifdef TO_FILE
2639  sub->num_observed_peers++;
2641  (sub->observed_unique_peers,
2642  peer,
2643  NULL,
2645  uint32_t num_observed_unique_peers =
2647  GNUNET_STATISTICS_set (stats,
2648  "# unique peers in gossip",
2649  num_observed_unique_peers,
2650  GNUNET_NO);
2651 #ifdef TO_FILE_FULL
2652  to_file (sub->file_name_observed_log,
2653  "%" PRIu32 " %" PRIu32 " %f\n",
2654  sub->num_observed_peers,
2655  num_observed_unique_peers,
2656  1.0 * num_observed_unique_peers / sub->num_observed_peers)
2657 #endif /* TO_FILE_FULL */
2658 #endif /* TO_FILE */
2659 }
2660 
2661 
2672 static void
2673 got_peer (struct Sub *sub,
2674  const struct GNUNET_PeerIdentity *peer)
2675 {
2676  /* If we did not know this peer already, insert it into sampler and view */
2677  if (GNUNET_YES == issue_peer_online_check (sub, peer))
2678  {
2680  &insert_in_sampler, sub);
2682  &insert_in_view_op, sub);
2683  }
2684  if (sub == msub)
2685  {
2686  GNUNET_STATISTICS_update (stats,
2687  "# learnd peers",
2688  1,
2689  GNUNET_NO);
2690  }
2691 }
2692 
2693 
2701 static int
2703 {
2704  /* struct GNUNET_CADET_Channel *channel; */
2705  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
2706  &peer_ctx->peer_id))
2707  {
2708  return GNUNET_NO;
2709  }
2710  if (GNUNET_YES == check_sending_channel_exists (peer_ctx))
2711  {
2712  if ((0 < RPS_sampler_count_id (peer_ctx->sub->sampler,
2713  &peer_ctx->peer_id)) ||
2714  (GNUNET_YES == View_contains_peer (peer_ctx->sub->view,
2715  &peer_ctx->peer_id)) ||
2717  &peer_ctx->peer_id)) ||
2719  &peer_ctx->peer_id)) ||
2720  (GNUNET_YES == check_peer_flag (peer_ctx->sub->peer_map,
2721  &peer_ctx->peer_id,
2723  { /* If we want to keep the connection to peer open */
2724  return GNUNET_YES;
2725  }
2726  return GNUNET_NO;
2727  }
2728  return GNUNET_NO;
2729 }
2730 
2731 
2739 static void
2740 remove_peer (struct Sub *sub,
2741  const struct GNUNET_PeerIdentity *peer)
2742 {
2743  (void) View_remove_peer (sub->view,
2744  peer);
2746  peer);
2748  peer);
2750  peer);
2751  /* We want to destroy the peer now.
2752  * Sometimes, it just seems that it's already been removed from the peer_map,
2753  * so check the peer_map first. */
2754  if (GNUNET_YES == check_peer_known (sub->peer_map,
2755  peer))
2756  {
2758  peer));
2759  }
2760 }
2761 
2762 
2771 static void
2772 clean_peer (struct Sub *sub,
2773  const struct GNUNET_PeerIdentity *peer)
2774 {
2776  peer)))
2777  {
2779  "Going to remove send channel to peer %s\n",
2780  GNUNET_i2s (peer));
2781  #if ENABLE_MALICIOUS
2782  if (0 != GNUNET_memcmp (&attacked_peer,
2783  peer))
2785  peer));
2786  #else /* ENABLE_MALICIOUS */
2788  peer));
2789  #endif /* ENABLE_MALICIOUS */
2790  }
2791 
2793  peer))
2794  {
2795  /* Peer was already removed by callback on destroyed channel */
2797  "Peer was removed from our knowledge during cleanup\n");
2798  return;
2799  }
2800 
2802  peer))) &&
2803  (GNUNET_NO == View_contains_peer (sub->view, peer)) &&
2804  (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2805  (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2806  (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
2807  (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer))))
2808  { /* We can safely remove this peer */
2810  "Going to remove peer %s\n",
2811  GNUNET_i2s (peer));
2812  remove_peer (sub, peer);
2813  return;
2814  }
2815 }
2816 
2817 
2829 static void
2831  const struct GNUNET_CADET_Channel *channel)
2832 {
2833  struct ChannelCtx *channel_ctx = cls;
2834  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
2835 
2836  (void) channel;
2837 
2838  channel_ctx->channel = NULL;
2839  remove_channel_ctx (channel_ctx);
2840  if ((NULL != peer_ctx) &&
2841  (peer_ctx->send_channel_ctx == channel_ctx) &&
2842  (GNUNET_YES == check_sending_channel_needed (channel_ctx->peer_ctx)) )
2843  {
2844  remove_peer (peer_ctx->sub, &peer_ctx->peer_id);
2845  }
2846 }
2847 
2848 
2849 /***********************************************************************
2850 * /Util functions
2851 ***********************************************************************/
2852 
2853 
2854 /***********************************************************************
2855 * Sub
2856 ***********************************************************************/
2857 
2868 struct Sub *
2870  uint32_t sampler_size,
2872 {
2873  struct Sub *sub;
2874 
2875  sub = GNUNET_new (struct Sub);
2876 
2877  /* With the hash generated from the secret value this service only connects
2878  * to rps instances that share the value */
2879  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2880  GNUNET_MQ_hd_fixed_size (peer_check,
2882  struct GNUNET_MessageHeader,
2883  NULL),
2884  GNUNET_MQ_hd_fixed_size (peer_push,
2886  struct GNUNET_MessageHeader,
2887  NULL),
2888  GNUNET_MQ_hd_fixed_size (peer_pull_request,
2890  struct GNUNET_MessageHeader,
2891  NULL),
2892  GNUNET_MQ_hd_var_size (peer_pull_reply,
2895  NULL),
2897  };
2898  sub->hash = *hash;
2899  sub->cadet_port =
2900  GNUNET_CADET_open_port (cadet_handle,
2901  &sub->hash,
2902  &handle_inbound_channel, /* Connect handler */
2903  sub, /* cls */
2904  NULL, /* WindowSize handler */
2905  &cleanup_destroyed_channel, /* Disconnect handler */
2906  cadet_handlers);
2907  if (NULL == sub->cadet_port)
2908  {
2910  "Cadet port `%s' is already in use.\n",
2912  GNUNET_assert (0);
2913  }
2914 
2915  /* Set up general data structure to keep track about peers */
2917  if (GNUNET_OK !=
2919  "rps",
2920  "FILENAME_VALID_PEERS",
2921  &sub->filename_valid_peers))
2922  {
2924  "rps",
2925  "FILENAME_VALID_PEERS");
2926  }
2927  if (0 != strncmp ("DISABLE", sub->filename_valid_peers, 7))
2928  {
2929  char *tmp_filename_valid_peers;
2930  char str_hash[105];
2931 
2932  GNUNET_snprintf (str_hash,
2933  sizeof(str_hash), "%s",
2934  GNUNET_h2s_full (hash));
2935  tmp_filename_valid_peers = sub->filename_valid_peers;
2937  "%s%s",
2938  tmp_filename_valid_peers,
2939  str_hash);
2940  GNUNET_free (tmp_filename_valid_peers);
2941  }
2943 
2944  /* Set up the sampler */
2945  sub->sampler_size_est_min = sampler_size;
2946  sub->sampler_size_est_need = sampler_size;;
2947  LOG (GNUNET_ERROR_TYPE_DEBUG, "MINSIZE is %u\n", sub->sampler_size_est_min);
2948  GNUNET_assert (0 != round_interval.rel_value_us);
2949  sub->round_interval = round_interval;
2950  sub->sampler = RPS_sampler_init (sampler_size,
2951  round_interval);
2952 
2953  /* Logging of internals */
2954 #ifdef TO_FILE_FULL
2955  // FIXME: The service cannot know the index, which is required by this
2956  // function:
2957  // sub->file_name_view_log = store_prefix_file_name (&own_identity, "view");
2958 #endif /* TO_FILE_FULL */
2959 #ifdef TO_FILE
2960 #ifdef TO_FILE_FULL
2961  // FIXME: The service cannot know the index, which is required by this
2962  // function:
2963  // sub->file_name_observed_log = store_prefix_file_name (&own_identity,
2964  // "observed");
2965 #endif /* TO_FILE_FULL */
2966  sub->num_observed_peers = 0;
2968  GNUNET_NO);
2969 #endif /* TO_FILE */
2970 
2971  /* Set up data structures for gossip */
2972  sub->push_map = CustomPeerMap_create (4);
2973  sub->pull_map = CustomPeerMap_create (4);
2974  sub->view_size_est_min = sampler_size;;
2975  sub->view = View_create (sub->view_size_est_min);
2976  if (sub == msub)
2977  {
2978  GNUNET_STATISTICS_set (stats,
2979  "view size aim",
2980  sub->view_size_est_min,
2981  GNUNET_NO);
2982  }
2983 
2984  /* Start executing rounds */
2986 
2987  return sub;
2988 }
2989 
2990 
2991 #ifdef TO_FILE
2992 // /**
2993 // * @brief Write all numbers in the given array into the given file
2994 // *
2995 // * Single numbers devided by a newline
2996 // *
2997 // * FIXME: The call to store_prefix_file_name expects the index of the peer,
2998 // * which cannot be known to the service.
2999 // * Write a dedicated function that uses the peer id.
3000 // *
3001 // * @param hist_array[] the array to dump
3002 // * @param file_name file to dump into
3003 // */
3004 // static void
3005 // write_histogram_to_file (const uint32_t hist_array[],
3006 // const char *file_name)
3007 // {
3008 // char collect_str[SIZE_DUMP_FILE + 1] = "";
3009 // char *recv_str_iter;
3010 // char *file_name_full;
3011 //
3012 // recv_str_iter = collect_str;
3013 // file_name_full = store_prefix_file_name (&own_identity,
3014 // file_name);
3015 // for (uint32_t i = 0; i < HISTOGRAM_FILE_SLOTS; i++)
3016 // {
3017 // char collect_str_tmp[8];
3018 //
3019 // GNUNET_snprintf (collect_str_tmp,
3020 // sizeof(collect_str_tmp),
3021 // "%" PRIu32 "\n",
3022 // hist_array[i]);
3023 // recv_str_iter = stpncpy (recv_str_iter,
3024 // collect_str_tmp,
3025 // 6);
3026 // }
3027 // (void) stpcpy (recv_str_iter,
3028 // "\n");
3029 // LOG (GNUNET_ERROR_TYPE_DEBUG,
3030 // "Writing push stats to disk\n");
3031 // to_file_w_len (file_name_full,
3032 // SIZE_DUMP_FILE, "%s",
3033 // collect_str);
3034 // GNUNET_free (file_name_full);
3035 // }
3036 
3037 
3038 #endif /* TO_FILE */
3039 
3040 
3046 static void
3047 destroy_sub (struct Sub *sub)
3048 {
3049  GNUNET_assert (NULL != sub);
3050  GNUNET_assert (NULL != sub->do_round_task);
3052  sub->do_round_task = NULL;
3053 
3054  /* Disconnect from cadet */
3056  sub->cadet_port = NULL;
3057 
3058  /* Clean up data structures for peers */
3060  sub->sampler = NULL;
3061  View_destroy (sub->view);
3062  sub->view = NULL;
3064  sub->push_map = NULL;
3066  sub->pull_map = NULL;
3067  peers_terminate (sub);
3068 
3069  /* Free leftover data structures */
3070 #ifdef TO_FILE_FULL
3071  GNUNET_free (sub->file_name_view_log);
3072  sub->file_name_view_log = NULL;
3073 #endif /* TO_FILE_FULL */
3074 #ifdef TO_FILE
3075 #ifdef TO_FILE_FULL
3076  GNUNET_free (sub->file_name_observed_log);
3077  sub->file_name_observed_log = NULL;
3078 #endif /* TO_FILE_FULL */
3079 
3080  // FIXME: Currently this calls malfunctionning code
3081  // /* Write push frequencies to disk */
3082  // write_histogram_to_file (sub->push_recv,
3083  // "push_recv");
3084 
3085  // /* Write push deltas to disk */
3086  // write_histogram_to_file (sub->push_delta,
3087  // "push_delta");
3088 
3089  // /* Write pull delays to disk */
3090  // write_histogram_to_file (sub->pull_delays,
3091  // "pull_delays");
3092 
3094  sub->observed_unique_peers = NULL;
3095 #endif /* TO_FILE */
3096 
3097  GNUNET_free (sub);
3098 }
3099 
3100 
3101 /***********************************************************************
3102 * /Sub
3103 ***********************************************************************/
3104 
3105 
3106 /***********************************************************************
3107 * Core handlers
3108 ***********************************************************************/
3109 
3116 void
3118  const struct GNUNET_PeerIdentity *my_identity)
3119 {
3120  (void) cls;
3121  (void) my_identity;
3122 
3123  map_single_hop = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
3124 }
3125 
3126 
3135 void *
3137  const struct GNUNET_PeerIdentity *peer,
3138  struct GNUNET_MQ_Handle *mq)
3139 {
3140  (void) cls;
3141  (void) mq;
3142 
3144  GNUNET_CONTAINER_multipeermap_put (map_single_hop,
3145  peer,
3146  NULL,
3148  return NULL;
3149 }
3150 
3151 
3160 void
3162  const struct GNUNET_PeerIdentity *peer,
3163  void *peer_cls)
3164 {
3165  (void) cls;
3166  (void) peer_cls;
3167 
3168  GNUNET_CONTAINER_multipeermap_remove_all (map_single_hop, peer);
3169 }
3170 
3171 
3172 /***********************************************************************
3173 * /Core handlers
3174 ***********************************************************************/
3175 
3176 
3182 static void
3184 {
3185  GNUNET_assert (NULL != cli_ctx);
3186  GNUNET_CONTAINER_DLL_remove (cli_ctx_head,
3187  cli_ctx_tail,
3188  cli_ctx);
3189  if (NULL != cli_ctx->sub)
3190  {
3191  destroy_sub (cli_ctx->sub);
3192  cli_ctx->sub = NULL;
3193  }
3194  GNUNET_free (cli_ctx);
3195 }
3196 
3197 
3205 static void
3206 adapt_sizes (struct Sub *sub, double logestimate, double std_dev)
3207 {
3208  double estimate;
3209 
3210  // double scale; // TODO this might go gloabal/config
3211 
3213  "Received a ns estimate - logest: %f, std_dev: %f (old_size: %u)\n",
3214  logestimate, std_dev, RPS_sampler_get_size (sub->sampler));
3215  // scale = .01;
3216  estimate = GNUNET_NSE_log_estimate_to_n (logestimate);
3217  // GNUNET_NSE_log_estimate_to_n (logestimate);
3218  estimate = pow (estimate, 1.0 / 3);
3219  // TODO add if std_dev is a number
3220  // estimate += (std_dev * scale);
3221  if (sub->view_size_est_min < ceil (estimate))
3222  {
3223  LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing estimate to %f\n", estimate);
3224  sub->sampler_size_est_need = estimate;
3225  sub->view_size_est_need = estimate;
3226  }
3227  else
3228  {
3229  LOG (GNUNET_ERROR_TYPE_DEBUG, "Not using estimate %f\n", estimate);
3230  // sub->sampler_size_est_need = sub->view_size_est_min;
3232  }
3233  if (sub == msub)
3234  {
3235  GNUNET_STATISTICS_set (stats,
3236  "view size aim",
3237  sub->view_size_est_need,
3238  GNUNET_NO);
3239  }
3240 
3241  /* If the NSE has changed adapt the lists accordingly */
3244 }
3245 
3246 
3260 static void
3262  struct GNUNET_TIME_Absolute timestamp,
3263  double logestimate, double std_dev)
3264 {
3265  (void) cls;
3266  (void) timestamp;
3267  struct ClientContext *cli_ctx_iter;
3268 
3269  adapt_sizes (msub, logestimate, std_dev);
3270  for (cli_ctx_iter = cli_ctx_head;
3271  NULL != cli_ctx_iter;
3272  cli_ctx_iter = cli_ctx_iter->next)
3273  {
3274  if (NULL != cli_ctx_iter->sub)
3275  {
3276  adapt_sizes (cli_ctx_iter->sub, logestimate, std_dev);
3277  }
3278  }
3279 }
3280 
3281 
3291 static int
3292 check_client_seed (void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
3293 {
3294  struct ClientContext *cli_ctx = cls;
3295  uint16_t msize = ntohs (msg->header.size);
3296  uint32_t num_peers = ntohl (msg->num_peers);
3297 
3298  msize -= sizeof(struct GNUNET_RPS_CS_SeedMessage);
3299  if ((msize / sizeof(struct GNUNET_PeerIdentity) != num_peers) ||
3300  (msize % sizeof(struct GNUNET_PeerIdentity) != 0))
3301  {
3303  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3304  ntohl (msg->num_peers),
3305  (msize / sizeof(struct GNUNET_PeerIdentity)));
3306  GNUNET_break (0);
3308  return GNUNET_SYSERR;
3309  }
3310  return GNUNET_OK;
3311 }
3312 
3313 
3320 static void
3322  const struct GNUNET_RPS_CS_SeedMessage *msg)
3323 {
3324  struct ClientContext *cli_ctx = cls;
3325  struct GNUNET_PeerIdentity *peers;
3326  uint32_t num_peers;
3327  uint32_t i;
3328 
3329  num_peers = ntohl (msg->num_peers);
3330  peers = (struct GNUNET_PeerIdentity *) &msg[1];
3331 
3333  "Client seeded peers:\n");
3334  print_peer_list (peers, num_peers);
3335 
3336  for (i = 0; i < num_peers; i++)
3337  {
3339  "Updating samplers with seed %" PRIu32 ": %s\n",
3340  i,
3341  GNUNET_i2s (&peers[i]));
3342 
3343  if (NULL != msub)
3344  got_peer (msub, &peers[i]); /* Condition needed? */
3345  if (NULL != cli_ctx->sub)
3346  got_peer (cli_ctx->sub, &peers[i]);
3347  }
3349 }
3350 
3351 
3359 static void
3361  const struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg)
3362 {
3363  struct ClientContext *cli_ctx = cls;
3364  uint64_t num_updates;
3365 
3366  num_updates = ntohl (msg->num_updates);
3367 
3369  "Client requested %" PRIu64 " updates of view.\n",
3370  num_updates);
3371 
3372  GNUNET_assert (NULL != cli_ctx);
3373  cli_ctx->view_updates_left = num_updates;
3374  send_view (cli_ctx, NULL, 0);
3376 }
3377 
3378 
3385 static void
3387  const struct GNUNET_MessageHeader *msg)
3388 {
3389  struct ClientContext *cli_ctx = cls;
3390 
3391  (void) msg;
3392 
3394  "Client does not want to receive updates of view any more.\n");
3395 
3396  GNUNET_assert (NULL != cli_ctx);
3397  cli_ctx->view_updates_left = 0;
3399  if (GNUNET_YES == cli_ctx->stream_update)
3400  {
3401  destroy_cli_ctx (cli_ctx);
3402  }
3403 }
3404 
3405 
3412 static void
3414  const struct
3416 {
3417  struct ClientContext *cli_ctx = cls;
3418 
3419  (void) msg;
3420 
3422  "Client requested peers from biased stream.\n");
3423  cli_ctx->stream_update = GNUNET_YES;
3424 
3425  GNUNET_assert (NULL != cli_ctx);
3427 }
3428 
3429 
3436 static void
3438  const struct GNUNET_MessageHeader *msg)
3439 {
3440  struct ClientContext *cli_ctx = cls;
3441 
3442  (void) msg;
3443 
3445  "Client canceled receiving peers from biased stream.\n");
3446  cli_ctx->stream_update = GNUNET_NO;
3447 
3448  GNUNET_assert (NULL != cli_ctx);
3450 }
3451 
3452 
3459 static void
3461  const struct GNUNET_RPS_CS_SubStartMessage *msg)
3462 {
3463  struct ClientContext *cli_ctx = cls;
3464 
3465  LOG (GNUNET_ERROR_TYPE_DEBUG, "Client requested start of a new sub.\n");
3466  if ((NULL != cli_ctx->sub) &&
3467  (0 != memcmp (&cli_ctx->sub->hash,
3468  &msg->hash,
3469  sizeof(struct GNUNET_HashCode))) )
3470  {
3472  "Already have a Sub with different share for this client. Remove old one, add new.\n");
3473  destroy_sub (cli_ctx->sub);
3474  cli_ctx->sub = NULL;
3475  }
3476  cli_ctx->sub = new_sub (&msg->hash,
3477  msub->sampler_size_est_min, // TODO make api input?
3480 }
3481 
3482 
3489 static void
3491  const struct GNUNET_RPS_CS_SubStopMessage *msg)
3492 {
3493  struct ClientContext *cli_ctx = cls;
3494 
3495  GNUNET_assert (NULL != cli_ctx->sub);
3496  if (0 != memcmp (&cli_ctx->sub->hash, &msg->hash, sizeof(struct
3497  GNUNET_HashCode)))
3498  {
3500  "Share of current sub and request differ!\n");
3501  }
3502  destroy_sub (cli_ctx->sub);
3503  cli_ctx->sub = NULL;
3505 }
3506 
3507 
3517 static void
3519  const struct GNUNET_MessageHeader *msg)
3520 {
3521  const struct ChannelCtx *channel_ctx = cls;
3522  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3523 
3524  (void) msg;
3525 
3527  "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer));
3528  if (channel_ctx->peer_ctx->sub == msub)
3529  {
3530  GNUNET_STATISTICS_update (stats,
3531  "# pending online checks",
3532  -1,
3533  GNUNET_NO);
3534  }
3535 
3536  GNUNET_CADET_receive_done (channel_ctx->channel);
3537 }
3538 
3539 
3549 static void
3550 handle_peer_push (void *cls,
3551  const struct GNUNET_MessageHeader *msg)
3552 {
3553  const struct ChannelCtx *channel_ctx = cls;
3554  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3555 
3556  (void) msg;
3557 
3558  // (check the proof of work (?))
3559 
3561  "Received PUSH (%s)\n",
3562  GNUNET_i2s (peer));
3563  if (channel_ctx->peer_ctx->sub == msub)
3564  {
3565  GNUNET_STATISTICS_update (stats, "# push message received", 1, GNUNET_NO);
3566  if ((NULL != map_single_hop) &&
3568  peer)))
3569  {
3570  GNUNET_STATISTICS_update (stats,
3571  "# push message received (multi-hop peer)",
3572  1,
3573  GNUNET_NO);
3574  }
3575  }
3576 
3577  #if ENABLE_MALICIOUS
3578  struct AttackedPeer *tmp_att_peer;
3579 
3580  if ((1 == mal_type) ||
3581  (3 == mal_type))
3582  { /* Try to maximise representation */
3583  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3584  tmp_att_peer->peer_id = *peer;
3585  if (NULL == att_peer_set)
3586  att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
3588  peer))
3589  {
3590  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3591  att_peers_tail,
3592  tmp_att_peer);
3593  add_peer_array_to_set (peer, 1, att_peer_set);
3594  }
3595  else
3596  {
3597  GNUNET_free (tmp_att_peer);
3598  }
3599  }
3600 
3601 
3602  else if (2 == mal_type)
3603  {
3604  /* We attack one single well-known peer - simply ignore */
3605  }
3606  #endif /* ENABLE_MALICIOUS */
3607 
3608  /* Add the sending peer to the push_map */
3609  CustomPeerMap_put (channel_ctx->peer_ctx->sub->push_map, peer);
3610 
3612  &channel_ctx->peer_ctx->peer_id));
3613  GNUNET_CADET_receive_done (channel_ctx->channel);
3614 }
3615 
3616 
3625 static void
3627  const struct GNUNET_MessageHeader *msg)
3628 {
3629  const struct ChannelCtx *channel_ctx = cls;
3630  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
3631  const struct GNUNET_PeerIdentity *peer = &peer_ctx->peer_id;
3632  const struct GNUNET_PeerIdentity *view_array;
3633 
3634  (void) msg;
3635 
3636  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (
3637  peer));
3638  if (peer_ctx->sub == msub)
3639  {
3640  GNUNET_STATISTICS_update (stats,
3641  "# pull request message received",
3642  1,
3643  GNUNET_NO);
3644  if ((NULL != map_single_hop) &&
3646  &peer_ctx->peer_id)))
3647  {
3648  GNUNET_STATISTICS_update (stats,
3649  "# pull request message received (multi-hop peer)",
3650  1,
3651  GNUNET_NO);
3652  }
3653  }
3654 
3655  #if ENABLE_MALICIOUS
3656  if ((1 == mal_type)
3657  || (3 == mal_type))
3658  { /* Try to maximise representation */
3659  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3660  }
3661 
3662  else if (2 == mal_type)
3663  { /* Try to partition network */
3664  if (0 == GNUNET_memcmp (&attacked_peer, peer))
3665  {
3666  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3667  }
3668  }
3669  #endif /* ENABLE_MALICIOUS */
3670 
3672  &channel_ctx->peer_ctx->peer_id));
3673  GNUNET_CADET_receive_done (channel_ctx->channel);
3674  view_array = View_get_as_array (channel_ctx->peer_ctx->sub->view);
3675  send_pull_reply (peer_ctx,
3676  view_array,
3677  View_size (channel_ctx->peer_ctx->sub->view));
3678 }
3679 
3680 
3688 static int
3690  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3691 {
3692  struct ChannelCtx *channel_ctx = cls;
3693  struct PeerContext *sender_ctx = channel_ctx->peer_ctx;
3694 
3695  if (sizeof(struct GNUNET_RPS_P2P_PullReplyMessage) > ntohs (msg->header.size))
3696  {
3697  GNUNET_break_op (0);
3698  return GNUNET_SYSERR;
3699  }
3700 
3701  if ((ntohs (msg->header.size) - sizeof(struct
3703  / sizeof(struct GNUNET_PeerIdentity) != ntohl (msg->num_peers))
3704  {
3706  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3707  ntohl (msg->num_peers),
3708  (ntohs (msg->header.size) - sizeof(struct
3710  / sizeof(struct GNUNET_PeerIdentity));
3711  GNUNET_break_op (0);
3712  return GNUNET_SYSERR;
3713  }
3714 
3715  if (GNUNET_YES != check_peer_flag (sender_ctx->sub->peer_map,
3716  &sender_ctx->peer_id,
3718  {
3720  "Received a pull reply from a peer (%s) we didn't request one from!\n",
3721  GNUNET_i2s (&sender_ctx->peer_id));
3722  if (sender_ctx->sub == msub)
3723  {
3724  GNUNET_STATISTICS_update (stats,
3725  "# unrequested pull replies",
3726  1,
3727  GNUNET_NO);
3728  }
3729  }
3730  return GNUNET_OK;
3731 }
3732 
3733 
3740 static void
3742  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3743 {
3744  const struct ChannelCtx *channel_ctx = cls;
3745  const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id;
3746  const struct GNUNET_PeerIdentity *peers;
3747  struct Sub *sub = channel_ctx->peer_ctx->sub;
3748  uint32_t i;
3749 
3750 #if ENABLE_MALICIOUS
3751  struct AttackedPeer *tmp_att_peer;
3752 #endif /* ENABLE_MALICIOUS */
3753 
3754  sub->pull_delays[sub->num_rounds - channel_ctx->peer_ctx->round_pull_req]++;
3755  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (
3756  sender));
3757  if (channel_ctx->peer_ctx->sub == msub)
3758  {
3759  GNUNET_STATISTICS_update (stats,
3760  "# pull reply messages received",
3761  1,
3762  GNUNET_NO);
3763  if ((NULL != map_single_hop) &&
3765  &channel_ctx->
3766  peer_ctx->peer_id)) )
3767  {
3768  GNUNET_STATISTICS_update (stats,
3769  "# pull reply messages received (multi-hop peer)",
3770  1,
3771  GNUNET_NO);
3772  }
3773  }
3774 
3775  #if ENABLE_MALICIOUS
3776  // We shouldn't even receive pull replies as we're not sending
3777  if (2 == mal_type)
3778  {
3779  }
3780  #endif /* ENABLE_MALICIOUS */
3781 
3782  /* Do actual logic */
3783  peers = (const struct GNUNET_PeerIdentity *) &msg[1];
3784 
3786  "PULL REPLY received, got following %u peers:\n",
3787  ntohl (msg->num_peers));
3788 
3789  for (i = 0; i < ntohl (msg->num_peers); i++)
3790  {
3792  "%u. %s\n",
3793  i,
3794  GNUNET_i2s (&peers[i]));
3795 
3796  #if ENABLE_MALICIOUS
3797  if ((NULL != att_peer_set) &&
3798  ((1 == mal_type) || (3 == mal_type) ))
3799  { /* Add attacked peer to local list */
3800  // TODO check if we sent a request and this was the first reply
3801  if ((GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (att_peer_set,
3802  &peers[i]))
3804  &peers[i])) )
3805  {
3806  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3807  tmp_att_peer->peer_id = peers[i];
3808  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3809  att_peers_tail,
3810  tmp_att_peer);
3811  add_peer_array_to_set (&peers[i], 1, att_peer_set);
3812  }
3813  continue;
3814  }
3815  #endif /* ENABLE_MALICIOUS */
3816  /* Make sure we 'know' about this peer */
3817  (void) insert_peer (channel_ctx->peer_ctx->sub,
3818  &peers[i]);
3819 
3820  if (GNUNET_YES == check_peer_valid (channel_ctx->peer_ctx->sub->valid_peers,
3821  &peers[i]))
3822  {
3823  CustomPeerMap_put (channel_ctx->peer_ctx->sub->pull_map,
3824  &peers[i]);
3825  }
3826  else
3827  {
3828  schedule_operation (channel_ctx->peer_ctx,
3830  channel_ctx->peer_ctx->sub); /* cls */
3831  (void) issue_peer_online_check (channel_ctx->peer_ctx->sub,
3832  &peers[i]);
3833  }
3834  }
3835 
3837  sender),
3839  clean_peer (channel_ctx->peer_ctx->sub,
3840  sender);
3841 
3843  sender));
3844  GNUNET_CADET_receive_done (channel_ctx->channel);
3845 }
3846 
3847 
3858 static struct GNUNET_TIME_Relative
3860  unsigned int spread)
3861 {
3862  struct GNUNET_TIME_Relative half_interval;
3863  struct GNUNET_TIME_Relative ret;
3864  unsigned int rand_delay;
3865  unsigned int max_rand_delay;
3866 
3867  if (0 == spread)
3868  {
3870  "Not accepting spread of 0\n");
3871  GNUNET_break (0);
3872  GNUNET_assert (0);
3873  }
3874  GNUNET_assert (0 != mean.rel_value_us);
3875 
3876  /* Compute random time value between spread * mean and spread * mean */
3877  half_interval = GNUNET_TIME_relative_divide (mean, spread);
3878 
3879  max_rand_delay = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us
3880  / mean.rel_value_us * (2 / spread);
3886  max_rand_delay);
3887  ret = GNUNET_TIME_relative_saturating_multiply (mean, rand_delay);
3888  ret = GNUNET_TIME_relative_divide (ret, max_rand_delay);
3889  ret = GNUNET_TIME_relative_add (ret, half_interval);
3890 
3891  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == ret.rel_value_us)
3893  "Returning FOREVER_REL\n");
3894 
3895  return ret;
3896 }
3897 
3898 
3904 static void
3905 send_pull_request (struct PeerContext *peer_ctx)
3906 {
3907  struct GNUNET_MQ_Envelope *ev;
3908 
3910  &peer_ctx->peer_id,
3912  SET_PEER_FLAG (peer_ctx,
3914  peer_ctx->round_pull_req = peer_ctx->sub->num_rounds;
3915 
3917  "Going to send PULL REQUEST to peer %s.\n",
3918  GNUNET_i2s (&peer_ctx->peer_id));
3919 
3921  send_message (peer_ctx,
3922  ev,
3923  "PULL REQUEST");
3924  if (peer_ctx->sub)
3925  {
3926  GNUNET_STATISTICS_update (stats,
3927  "# pull request send issued",
3928  1,
3929  GNUNET_NO);
3930  if ((NULL != map_single_hop) &&
3932  &peer_ctx->peer_id)))
3933  {
3934  GNUNET_STATISTICS_update (stats,
3935  "# pull request send issued (multi-hop peer)",
3936  1,
3937  GNUNET_NO);
3938  }
3939  }
3940 }
3941 
3942 
3948 static void
3949 send_push (struct PeerContext *peer_ctx)
3950 {
3951  struct GNUNET_MQ_Envelope *ev;
3952 
3954  "Going to send PUSH to peer %s.\n",
3955  GNUNET_i2s (&peer_ctx->peer_id));
3956 
3958  send_message (peer_ctx, ev, "PUSH");
3959  if (peer_ctx->sub)
3960  {
3961  GNUNET_STATISTICS_update (stats,
3962  "# push send issued",
3963  1,
3964  GNUNET_NO);
3965  if ((NULL != map_single_hop) &&
3967  &peer_ctx->peer_id)))
3968  {
3969  GNUNET_STATISTICS_update (stats,
3970  "# push send issued (multi-hop peer)",
3971  1,
3972  GNUNET_NO);
3973  }
3974  }
3975 }
3976 
3977 
3978 #if ENABLE_MALICIOUS
3979 
3980 
3989 static int
3990 check_client_act_malicious (void *cls,
3991  const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
3992 {
3993  struct ClientContext *cli_ctx = cls;
3994  uint16_t msize = ntohs (msg->header.size);
3995  uint32_t num_peers = ntohl (msg->num_peers);
3996 
3997  msize -= sizeof(struct GNUNET_RPS_CS_ActMaliciousMessage);
3998  if ((msize / sizeof(struct GNUNET_PeerIdentity) != num_peers) ||
3999  (msize % sizeof(struct GNUNET_PeerIdentity) != 0))
4000  {
4002  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
4003  ntohl (msg->num_peers),
4004  (msize / sizeof(struct GNUNET_PeerIdentity)));
4005  GNUNET_break (0);
4007  return GNUNET_SYSERR;
4008  }
4009  return GNUNET_OK;
4010 }
4011 
4012 
4020 static void
4021 handle_client_act_malicious (void *cls,
4022  const struct
4023  GNUNET_RPS_CS_ActMaliciousMessage *msg)
4024 {
4025  struct ClientContext *cli_ctx = cls;
4026  struct GNUNET_PeerIdentity *peers;
4027  uint32_t num_mal_peers_sent;
4028  uint32_t num_mal_peers_old;
4029  struct Sub *sub = cli_ctx->sub;
4030 
4031  if (NULL == sub)
4032  sub = msub;
4033  /* Do actual logic */
4034  peers = (struct GNUNET_PeerIdentity *) &msg[1];
4035  mal_type = ntohl (msg->type);
4036  if (NULL == mal_peer_set)
4037  mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
4038 
4040  "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
4041  mal_type,
4042  ntohl (msg->num_peers));
4043 
4044  if (1 == mal_type)
4045  { /* Try to maximise representation */
4046  /* Add other malicious peers to those we already know */
4047 
4048  num_mal_peers_sent = ntohl (msg->num_peers);
4049  num_mal_peers_old = num_mal_peers;
4050  GNUNET_array_grow (mal_peers,
4051  num_mal_peers,
4052  num_mal_peers + num_mal_peers_sent);
4053  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
4054  peers,
4055  num_mal_peers_sent * sizeof(struct GNUNET_PeerIdentity));
4056 
4057  /* Add all mal peers to mal_peer_set */
4058  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
4059  num_mal_peers_sent,
4060  mal_peer_set);
4061 
4062  /* Substitute do_round () with do_mal_round () */
4063  GNUNET_assert (NULL != sub->do_round_task);
4065  sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
4066  }
4067 
4068  else if ((2 == mal_type) ||
4069  (3 == mal_type))
4070  { /* Try to partition the network */
4071  /* Add other malicious peers to those we already know */
4072 
4073  num_mal_peers_sent = ntohl (msg->num_peers) - 1;
4074  num_mal_peers_old = num_mal_peers;
4075  GNUNET_assert (GNUNET_MAX_MALLOC_CHECKED > num_mal_peers_sent);
4076  GNUNET_array_grow (mal_peers,
4077  num_mal_peers,
4078  num_mal_peers + num_mal_peers_sent);
4079  if ((NULL != mal_peers) &&
4080  (0 != num_mal_peers) )
4081  {
4082  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
4083  peers,
4084  num_mal_peers_sent * sizeof(struct GNUNET_PeerIdentity));
4085 
4086  /* Add all mal peers to mal_peer_set */
4087  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
4088  num_mal_peers_sent,
4089  mal_peer_set);
4090  }
4091 
4092  /* Store the one attacked peer */
4093  GNUNET_memcpy (&attacked_peer,
4094  &msg->attacked_peer,
4095  sizeof(struct GNUNET_PeerIdentity));
4096  /* Set the flag of the attacked peer to valid to avoid problems */
4097  if (GNUNET_NO == check_peer_known (sub->peer_map, &attacked_peer))
4098  {
4099  (void) issue_peer_online_check (sub, &attacked_peer);
4100  }
4101 
4103  "Attacked peer is %s\n",
4104  GNUNET_i2s (&attacked_peer));
4105 
4106  /* Substitute do_round () with do_mal_round () */
4107  if (NULL != sub->do_round_task)
4108  {
4109  /* Probably in shutdown */
4111  sub->do_round_task = GNUNET_SCHEDULER_add_now (&do_mal_round, sub);
4112  }
4113  }
4114  else if (0 == mal_type)
4115  { /* Stop acting malicious */
4116  GNUNET_array_grow (mal_peers, num_mal_peers, 0);
4117 
4118  /* Substitute do_mal_round () with do_round () */
4121  }
4122  else
4123  {
4124  GNUNET_break (0);
4126  }
4128 }
4129 
4130 
4138 static void
4139 do_mal_round (void *cls)
4140 {
4141  uint32_t num_pushes;
4142  uint32_t i;
4143  struct GNUNET_TIME_Relative time_next_round;
4144  struct AttackedPeer *tmp_att_peer;
4145  struct Sub *sub = cls;
4146 
4148  "Going to execute next round maliciously type %" PRIu32 ".\n",
4149  mal_type);
4150  sub->do_round_task = NULL;
4151  GNUNET_assert (mal_type <= 3);
4152  /* Do malicious actions */
4153  if (1 == mal_type)
4154  { /* Try to maximise representation */
4155  /* The maximum of pushes we're going to send this round */
4156  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit,
4157  num_attacked_peers),
4159 
4161  "Going to send %" PRIu32 " pushes\n",
4162  num_pushes);
4163 
4164  /* Send PUSHes to attacked peers */
4165  for (i = 0; i < num_pushes; i++)
4166  {
4167  if (att_peers_tail == att_peer_index)
4168  att_peer_index = att_peers_head;
4169  else
4170  att_peer_index = att_peer_index->next;
4171 
4172  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4173  }
4174 
4175  /* Send PULLs to some peers to learn about additional peers to attack */
4176  tmp_att_peer = att_peer_index;
4177  for (i = 0; i < num_pushes * alpha; i++)
4178  {
4179  if (att_peers_tail == tmp_att_peer)
4180  tmp_att_peer = att_peers_head;
4181  else
4182  att_peer_index = tmp_att_peer->next;
4183 
4184  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4185  }
4186  }
4187 
4188 
4189  else if (2 == mal_type)
4190  {
4195  (void) issue_peer_online_check (sub, &attacked_peer);
4196  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4197  &attacked_peer,
4198  Peers_ONLINE))
4199  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4200  }
4201 
4202 
4203  if (3 == mal_type)
4204  { /* Combined attack */
4205  /* Send PUSH to attacked peers */
4206  if (GNUNET_YES == check_peer_known (sub->peer_map, &attacked_peer))
4207  {
4208  (void) issue_peer_online_check (sub, &attacked_peer);
4209  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4210  &attacked_peer,
4211  Peers_ONLINE))
4212  {
4214  "Goding to send push to attacked peer (%s)\n",
4215  GNUNET_i2s (&attacked_peer));
4216  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4217  }
4218  }
4219  (void) issue_peer_online_check (sub, &attacked_peer);
4220 
4221  /* The maximum of pushes we're going to send this round */
4222  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
4223  num_attacked_peers),
4225 
4227  "Going to send %" PRIu32 " pushes\n",
4228  num_pushes);
4229 
4230  for (i = 0; i < num_pushes; i++)
4231  {
4232  if (att_peers_tail == att_peer_index)
4233  att_peer_index = att_peers_head;
4234  else
4235  att_peer_index = att_peer_index->next;
4236 
4237  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4238  }
4239 
4240  /* Send PULLs to some peers to learn about additional peers to attack */
4241  tmp_att_peer = att_peer_index;
4242  for (i = 0; i < num_pushes * alpha; i++)
4243  {
4244  if (att_peers_tail == tmp_att_peer)
4245  tmp_att_peer = att_peers_head;
4246  else
4247  att_peer_index = tmp_att_peer->next;
4248 
4249  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4250  }
4251  }
4252 
4253  /* Schedule next round */
4254  time_next_round = compute_rand_delay (sub->round_interval, 2);
4255 
4256  GNUNET_assert (NULL == sub->do_round_task);
4257  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4258  &do_mal_round, sub);
4259  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4260 }
4261 
4262 
4263 #endif /* ENABLE_MALICIOUS */
4264 
4265 
4273 static void
4274 do_round (void *cls)
4275 {
4276  unsigned int i;
4277  const struct GNUNET_PeerIdentity *view_array;
4278  unsigned int *permut;
4279  unsigned int a_peers; /* Number of peers we send pushes to */
4280  unsigned int b_peers; /* Number of peers we send pull requests to */
4281  uint32_t first_border;
4282  uint32_t second_border;
4283  struct GNUNET_PeerIdentity peer;
4284  struct GNUNET_PeerIdentity *update_peer;
4285  struct Sub *sub = cls;
4286 
4287  sub->num_rounds++;
4289  "Going to execute next round.\n");
4290  if (sub == msub)
4291  {
4292  GNUNET_STATISTICS_update (stats, "# rounds", 1, GNUNET_NO);
4293  }
4294  sub->do_round_task = NULL;
4295 #ifdef TO_FILE_FULL
4296  to_file (sub->file_name_view_log,
4297  "___ new round ___");
4298 #endif /* TO_FILE_FULL */
4299  view_array = View_get_as_array (sub->view);
4300  for (i = 0; i < View_size (sub->view); i++)
4301  {
4303  "\t%s\n", GNUNET_i2s (&view_array[i]));
4304 #ifdef TO_FILE_FULL
4305  to_file (sub->file_name_view_log,
4306  "=%s\t(do round)",
4307  GNUNET_i2s_full (&view_array[i]));
4308 #endif /* TO_FILE_FULL */
4309  }
4310 
4311 
4312  /* Send pushes and pull requests */
4313  if (0 < View_size (sub->view))
4314  {
4316  View_size (sub->view));
4317 
4318  /* Send PUSHes */
4319  a_peers = ceil (alpha * View_size (sub->view));
4320 
4322  "Going to send pushes to %u (ceil (%f * %u)) peers.\n",
4323  a_peers, alpha, View_size (sub->view));
4324  for (i = 0; i < a_peers; i++)
4325  {
4326  peer = view_array[permut[i]];
4327  // FIXME if this fails schedule/loop this for later
4328  send_push (get_peer_ctx (sub->peer_map, &peer));
4329  }
4330 
4331  /* Send PULL requests */
4332  b_peers = ceil (beta * View_size (sub->view));
4333  first_border = a_peers;
4334  second_border = a_peers + b_peers;
4335  if (second_border > View_size (sub->view))
4336  {
4337  first_border = View_size (sub->view) - b_peers;
4338  second_border = View_size (sub->view);
4339  }
4341  "Going to send pulls to %u (ceil (%f * %u)) peers.\n",
4342  b_peers, beta, View_size (sub->view));
4343  for (i = first_border; i < second_border; i++)
4344  {
4345  peer = view_array[permut[i]];
4346  if (GNUNET_NO == check_peer_flag (sub->peer_map,
4347  &peer,
4349  { // FIXME if this fails schedule/loop this for later
4350  send_pull_request (get_peer_ctx (sub->peer_map, &peer));
4351  }
4352  }
4353 
4354  GNUNET_free (permut);
4355  permut = NULL;
4356  }
4357 
4358 
4359  /* Update view */
4360  /* TODO see how many peers are in push-/pull- list! */
4361 
4362  if ((CustomPeerMap_size (sub->push_map) <= alpha * sub->view_size_est_need) &&
4363  (0 < CustomPeerMap_size (sub->push_map)) &&
4364  (0 < CustomPeerMap_size (sub->pull_map)))
4365  { /* If conditions for update are fulfilled, update */
4366  LOG (GNUNET_ERROR_TYPE_DEBUG, "Update of the view.\n");
4367 
4368  uint32_t final_size;
4369  uint32_t peers_to_clean_size;
4370  struct GNUNET_PeerIdentity *peers_to_clean;
4371 
4372  peers_to_clean = NULL;
4373  peers_to_clean_size = 0;
4374  GNUNET_array_grow (peers_to_clean,
4375  peers_to_clean_size,
4376  View_size (sub->view));
4377  GNUNET_memcpy (peers_to_clean,
4378  view_array,
4379  View_size (sub->view) * sizeof(struct GNUNET_PeerIdentity));
4380 
4381  /* Seems like recreating is the easiest way of emptying the peermap */
4382  View_clear (sub->view);
4383 #ifdef TO_FILE_FULL
4384  to_file (sub->file_name_view_log,
4385  "--- emptied ---");
4386 #endif /* TO_FILE_FULL */
4387 
4388  first_border = GNUNET_MIN (ceil (alpha * sub->view_size_est_need),
4389  CustomPeerMap_size (sub->push_map));
4390  second_border = first_border
4391  + GNUNET_MIN (floor (beta * sub->view_size_est_need),
4392  CustomPeerMap_size (sub->pull_map));
4393  final_size = second_border
4394  + ceil ((1 - (alpha + beta)) * sub->view_size_est_need);
4396  "first border: %" PRIu32 ", second border: %" PRIu32 ", final size: %"
4397  PRIu32 "\n",
4398  first_border,
4399  second_border,
4400  final_size);
4401 
4402  /* Update view with peers received through PUSHes */
4404  CustomPeerMap_size (sub->push_map));
4405  for (i = 0; i < first_border; i++)
4406  {
4407  int inserted;
4408  inserted = insert_in_view (sub,
4410  permut[i]));
4411  if (GNUNET_OK == inserted)
4412  {
4414  1,
4416  sub->push_map, permut[i]));
4417  }
4418 #ifdef TO_FILE_FULL
4419  to_file (sub->file_name_view_log,
4420  "+%s\t(push list)",
4421  GNUNET_i2s_full (&view_array[i]));
4422 #endif /* TO_FILE_FULL */
4423  // TODO change the peer_flags accordingly
4424  }
4425  GNUNET_free (permut);
4426  permut = NULL;
4427 
4428  /* Update view with peers received through PULLs */
4430  CustomPeerMap_size (sub->pull_map));
4431  for (i = first_border; i < second_border; i++)
4432  {
4433  int inserted;
4434  inserted = insert_in_view (sub,
4436  permut[i
4437  -
4438  first_border
4439  ]));
4440  if (GNUNET_OK == inserted)
4441  {
4443  1,
4445  sub->pull_map,
4446  permut[i
4447  - first_border]));
4448  }
4449 #ifdef TO_FILE_FULL
4450  to_file (sub->file_name_view_log,
4451  "+%s\t(pull list)",
4452  GNUNET_i2s_full (&view_array[i]));
4453 #endif /* TO_FILE_FULL */
4454  // TODO change the peer_flags accordingly
4455  }
4456  GNUNET_free (permut);
4457  permut = NULL;
4458 
4459  /* Update view with peers from history */
4461  final_size - second_border,
4462  hist_update,
4463  sub);
4464  // TODO change the peer_flags accordingly
4465 
4466  for (i = 0; i < View_size (sub->view); i++)
4467  rem_from_list (&peers_to_clean, &peers_to_clean_size, &view_array[i]);
4468 
4469  /* Clean peers that were removed from the view */
4470  for (i = 0; i < peers_to_clean_size; i++)
4471  {
4472 #ifdef TO_FILE_FULL
4473  to_file (sub->file_name_view_log,
4474  "-%s",
4475  GNUNET_i2s_full (&peers_to_clean[i]));
4476 #endif /* TO_FILE_FULL */
4477  clean_peer (sub, &peers_to_clean[i]);
4478  }
4479 
4480  GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
4482  }
4483  else
4484  {
4485  LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
4486  if (sub == msub)
4487  {
4488  GNUNET_STATISTICS_update (stats, "# rounds blocked", 1, GNUNET_NO);
4489  if ((CustomPeerMap_size (sub->push_map) > alpha
4490  * sub->view_size_est_need) &&
4491  ! (0 >= CustomPeerMap_size (sub->pull_map)))
4492  GNUNET_STATISTICS_update (stats, "# rounds blocked - too many pushes",
4493  1, GNUNET_NO);
4494  if ((CustomPeerMap_size (sub->push_map) > alpha
4495  * sub->view_size_est_need) &&
4496  (0 >= CustomPeerMap_size (sub->pull_map)))
4497  GNUNET_STATISTICS_update (stats,
4498  "# rounds blocked - too many pushes, no pull replies",
4499  1, GNUNET_NO);
4500  if ((0 >= CustomPeerMap_size (sub->push_map)) &&
4501  ! (0 >= CustomPeerMap_size (sub->pull_map)))
4502  GNUNET_STATISTICS_update (stats, "# rounds blocked - no pushes", 1,
4503  GNUNET_NO);
4504  if ((0 >= CustomPeerMap_size (sub->push_map)) &&
4505  (0 >= CustomPeerMap_size (sub->pull_map)))
4506  GNUNET_STATISTICS_update (stats,
4507  "# rounds blocked - no pushes, no pull replies",
4508  1, GNUNET_NO);
4509  if ((0 >= CustomPeerMap_size (sub->pull_map)) &&
4511  * sub->view_size_est_need) &&
4512  (0 >= CustomPeerMap_size (sub->push_map)) )
4513  GNUNET_STATISTICS_update (stats, "# rounds blocked - no pull replies",
4514  1, GNUNET_NO);
4515  }
4516  }
4517  // TODO independent of that also get some peers from CADET_get_peers()?
4519  {
4520  sub->push_recv[CustomPeerMap_size (sub->push_map)]++;
4521  }
4522  else
4523  {
4525  "Push map size too big for histogram (%u, %u)\n",
4528  }
4529  // FIXME check bounds of histogram
4530  sub->push_delta[(int32_t) (CustomPeerMap_size (sub->push_map)
4531  - (alpha * sub->view_size_est_need))
4532  + (HISTOGRAM_FILE_SLOTS / 2)]++;
4533  if (sub == msub)
4534  {
4535  GNUNET_STATISTICS_set (stats,
4536  "# peers in push map at end of round",
4538  GNUNET_NO);
4539  GNUNET_STATISTICS_set (stats,
4540  "# peers in pull map at end of round",
4542  GNUNET_NO);
4543  GNUNET_STATISTICS_set (stats,
4544  "# peers in view at end of round",
4545  View_size (sub->view),
4546  GNUNET_NO);
4547  GNUNET_STATISTICS_set (stats,
4548  "# expected pushes",
4549  alpha * sub->view_size_est_need,
4550  GNUNET_NO);
4551  GNUNET_STATISTICS_set (stats,
4552  "delta expected - received pushes",
4554  * sub->
4555  view_size_est_need),
4556  GNUNET_NO);
4557  }
4558 
4560  "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (sub->view%u) = %.2f)\n",
4563  alpha,
4564  View_size (sub->view),
4565  alpha * View_size (sub->view));
4566 
4567  /* Update samplers */
4568  for (i = 0; i < CustomPeerMap_size (sub->push_map); i++)
4569  {
4570  update_peer = CustomPeerMap_get_peer_by_index (sub->push_map, i);
4572  "Updating with peer %s from push list\n",
4573  GNUNET_i2s (update_peer));
4574  insert_in_sampler (sub, update_peer);
4575  clean_peer (sub, update_peer); /* This cleans only if it is not in the view */
4576  }
4577 
4578  for (i = 0; i < CustomPeerMap_size (sub->pull_map); i++)
4579  {
4581  "Updating with peer %s from pull list\n",
4584  /* This cleans only if it is not in the view */
4586  }
4587 
4588 
4589  /* Empty push/pull lists */
4592 
4593  if (sub == msub)
4594  {
4595  GNUNET_STATISTICS_set (stats,
4596  "view size",
4597  View_size (sub->view),
4598  GNUNET_NO);
4599  }
4600 
4601  struct GNUNET_TIME_Relative time_next_round;
4602 
4603  time_next_round = compute_rand_delay (sub->round_interval, 2);
4604 
4605  /* Schedule next round */
4606  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4607  &do_round, sub);
4608  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4609 }
4610 
4611 
4627 void
4628 init_peer_cb (void *cls,
4629  const struct GNUNET_PeerIdentity *peer,
4630  int tunnel, /* "Do we have a tunnel towards this peer?" */
4631  unsigned int n_paths, /* "Number of known paths towards this peer" */
4632  unsigned int best_path) /* "How long is the best path?
4633  * (0 = unknown, 1 = ourselves, 2 = neighbor)" */
4634 {
4635  struct Sub *sub = cls;
4636 
4637  (void) tunnel;
4638  (void) n_paths;
4639  (void) best_path;
4640 
4641  if (NULL != peer)
4642  {
4644  "Got peer_id %s from cadet\n",
4645  GNUNET_i2s (peer));
4646  got_peer (sub, peer);
4647  }
4648 }
4649 
4650 
4662 static int
4664  const struct GNUNET_PeerIdentity *peer)
4665 {
4666  struct Sub *sub = cls;
4667 
4668  if (NULL != peer)
4669  {
4671  "Got stored, valid peer %s\n",
4672  GNUNET_i2s (peer));
4673  got_peer (sub, peer);
4674  }
4675  return GNUNET_YES;
4676 }
4677 
4678 
4687 void
4689  const struct GNUNET_PeerIdentity *peer,
4690  const struct GNUNET_HELLO_Message *hello,
4691  const char *err_msg)
4692 {
4693  struct Sub *sub = cls;
4694 
4695  (void) hello;
4696  (void) err_msg;
4697 
4698  if (NULL != peer)
4699  {
4701  "Got peer_id %s from peerinfo\n",
4702  GNUNET_i2s (peer));
4703  got_peer (sub, peer);
4704  }
4705 }
4706 
4707 
4713 static void
4714 shutdown_task (void *cls)
4715 {
4716  (void) cls;
4717  struct ClientContext *client_ctx;
4718 
4720  "RPS service is going down\n");
4721 
4722  /* Clean all clients */
4723  for (client_ctx = cli_ctx_head;
4724  NULL != cli_ctx_head;
4725  client_ctx = cli_ctx_head)
4726  {
4727  destroy_cli_ctx (client_ctx);
4728  }
4729  if (NULL != msub)
4730  {
4731  destroy_sub (msub);
4732  msub = NULL;
4733  }
4734 
4735  /* Disconnect from other services */
4736  GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
4737  GNUNET_PEERINFO_disconnect (peerinfo_handle);
4738  peerinfo_handle = NULL;
4739  GNUNET_NSE_disconnect (nse);
4740  if (NULL != map_single_hop)
4741  {
4742  /* core_init was called - core was initialised */
4743  /* disconnect first, so no callback tries to access missing peermap */
4744  GNUNET_CORE_disconnect (core_handle);
4745  core_handle = NULL;
4746  GNUNET_CONTAINER_multipeermap_destroy (map_single_hop);
4747  map_single_hop = NULL;
4748  }
4749 
4750  if (NULL != stats)
4751  {
4753  GNUNET_NO);
4754  stats = NULL;
4755  }
4756  GNUNET_CADET_disconnect (cadet_handle);
4757  cadet_handle = NULL;
4758 #if ENABLE_MALICIOUS
4759  struct AttackedPeer *tmp_att_peer;
4760  GNUNET_array_grow (mal_peers,
4761  num_mal_peers,
4762  0);
4763  if (NULL != mal_peer_set)
4765  if (NULL != att_peer_set)
4767  while (NULL != att_peers_head)
4768  {
4769  tmp_att_peer = att_peers_head;
4770  GNUNET_CONTAINER_DLL_remove (att_peers_head,
4771  att_peers_tail,
4772  tmp_att_peer);
4773  GNUNET_free (tmp_att_peer);
4774  }
4775 #endif /* ENABLE_MALICIOUS */
4776  close_all_files ();
4777 }
4778 
4779 
4788 static void *
4790  struct GNUNET_SERVICE_Client *client,
4791  struct GNUNET_MQ_Handle *mq)
4792 {
4793  struct ClientContext *cli_ctx;
4794 
4795  (void) cls;
4796 
4798  "Client connected\n");
4799  if (NULL == client)
4800  return client; /* Server was destroyed before a client connected. Shutting down */
4801  cli_ctx = GNUNET_new (struct ClientContext);
4802  cli_ctx->mq = mq;
4803  cli_ctx->view_updates_left = -1;
4804  cli_ctx->stream_update = GNUNET_NO;
4805  cli_ctx->client = client;
4806  GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
4807  cli_ctx_tail,
4808  cli_ctx);
4809  return cli_ctx;
4810 }
4811 
4812 
4820 static void
4822  struct GNUNET_SERVICE_Client *client,
4823  void *internal_cls)
4824 {
4825  struct ClientContext *cli_ctx = internal_cls;
4826 
4827  (void) cls;
4828  GNUNET_assert (client == cli_ctx->client);
4829  if (NULL == client)
4830  { /* shutdown task - destroy all clients */
4831  while (NULL != cli_ctx_head)
4832  destroy_cli_ctx (cli_ctx_head);
4833  }
4834  else
4835  { /* destroy this client */
4837  "Client disconnected. Destroy its context.\n");
4838  destroy_cli_ctx (cli_ctx);
4839  }
4840 }
4841 
4842 
4850 static void
4851 run (void *cls,
4852  const struct GNUNET_CONFIGURATION_Handle *c,
4854 {
4855  struct GNUNET_TIME_Relative round_interval;
4856  long long unsigned int sampler_size;
4857  char hash_port_string[] = GNUNET_APPLICATION_PORT_RPS;
4858  struct GNUNET_HashCode hash;
4859 
4860  (void) cls;
4861  (void) service;
4862 
4863  GNUNET_log_setup ("rps",
4865  NULL);
4866  cfg = c;
4867  /* Get own ID */
4869  &own_identity); // TODO check return value
4871  "STARTING SERVICE (rps) for peer [%s]\n",
4873 #if ENABLE_MALICIOUS
4875  "Malicious execution compiled in.\n");
4876 #endif /* ENABLE_MALICIOUS */
4877 
4878  /* Get time interval from the configuration */
4879  if (GNUNET_OK !=
4881  "RPS",
4882  "ROUNDINTERVAL",
4883  &round_interval))
4884  {
4886  "RPS", "ROUNDINTERVAL");
4888  return;
4889  }
4890 
4891  /* Get initial size of sampler/view from the configuration */
4892  if (GNUNET_OK !=
4894  "RPS",
4895  "MINSIZE",
4896  &sampler_size))
4897  {
4899  "RPS", "MINSIZE");
4901  return;
4902  }
4903 
4904  cadet_handle = GNUNET_CADET_connect (cfg);
4905  GNUNET_assert (NULL != cadet_handle);
4906  core_handle = GNUNET_CORE_connect (cfg,
4907  NULL, /* cls */
4908  core_init, /* init */
4909  core_connects, /* connects */
4910  core_disconnects, /* disconnects */
4911  NULL); /* handlers */
4912  GNUNET_assert (NULL != core_handle);
4913 
4914 
4915  alpha = 0.45;
4916  beta = 0.45;
4917 
4918 
4919  /* Set up main Sub */
4920  GNUNET_CRYPTO_hash (hash_port_string,
4921  strlen (hash_port_string),
4922  &hash);
4923  msub = new_sub (&hash,
4924  sampler_size, /* Will be overwritten by config */
4925  round_interval);
4926 
4927 
4928  peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
4929 
4930  /* connect to NSE */
4931  nse = GNUNET_NSE_connect (cfg, nse_callback, NULL);
4932 
4933  // LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
4934  // GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, msub);
4935  // TODO send push/pull to each of those peers?
4936  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
4937  restore_valid_peers (msub);
4939 
4940  peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
4941  GNUNET_NO,
4943  msub);
4944 
4945  LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
4946 
4948  stats = GNUNET_STATISTICS_create ("rps", cfg);
4949 }
4950 
4951 
4956  ("rps",
4958  &run,
4961  NULL,
4962  GNUNET_MQ_hd_var_size (client_seed,
4965  NULL),
4966 #if ENABLE_MALICIOUS
4967  GNUNET_MQ_hd_var_size (client_act_malicious,
4968  GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
4969  struct GNUNET_RPS_CS_ActMaliciousMessage,
4970  NULL),
4971 #endif /* ENABLE_MALICIOUS */
4972  GNUNET_MQ_hd_fixed_size (client_view_request,
4975  NULL),
4976  GNUNET_MQ_hd_fixed_size (client_view_cancel,
4978  struct GNUNET_MessageHeader,
4979  NULL),
4980  GNUNET_MQ_hd_fixed_size (client_stream_request,
4983  NULL),
4984  GNUNET_MQ_hd_fixed_size (client_stream_cancel,
4986  struct GNUNET_MessageHeader,
4987  NULL),
4988  GNUNET_MQ_hd_fixed_size (client_start_sub,
4991  NULL),
4992  GNUNET_MQ_hd_fixed_size (client_stop_sub,
4995  NULL),
4997 
4998 /* 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.
int 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:544
#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.
#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
int 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.
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.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1280
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.
int 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.
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:732
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 faciliating 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
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.
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.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
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...
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 incomming 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:48
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:820
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.
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:641
#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_.
int 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:399
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:579
#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
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.
int GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition: disk.c:206
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
int 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.
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:527
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.
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:1203
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:501
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
#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