GNUnet  0.10.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 
88 
96 {
101 
105  void *op_cls;
106 };
107 
115 {
121 
126 
131 
135  const char *type;
136 };
137 
141 struct ChannelCtx;
142 
152 {
156  struct Sub *sub;
157 
162 
167 
172 
177 
184 
188  unsigned int num_pending_ops;
189 
194 
198  uint32_t peer_flags;
199 
203  struct GNUNET_TIME_Absolute last_message_recv;
204 
208  struct GNUNET_TIME_Absolute last_keepalive;
209 
215 
221  uint32_t round_pull_req;
222 };
223 
228 {
233 
237  void *cls;
238 };
239 
244 {
249 
254 
261 };
262 
263 
264 #if ENABLE_MALICIOUS
265 
269 struct AttackedPeer
270 {
274  struct AttackedPeer *next;
275  struct AttackedPeer *prev;
276 
280  struct GNUNET_PeerIdentity peer_id;
281 };
282 
283 #endif /* ENABLE_MALICIOUS */
284 
289 #define HISTOGRAM_FILE_SLOTS 32
290 
297 #define SIZE_DUMP_FILE (HISTOGRAM_FILE_SLOTS * 5) + 1
298 
305 struct Sub
306 {
310  struct GNUNET_HashCode hash;
311 
316 
321 
326 
331 
337  unsigned int sampler_size_est_min;
338 
345  unsigned int sampler_size_est_need;
346 
350  struct GNUNET_TIME_Relative round_interval;
351 
356 
357 #ifdef TO_FILE_FULL
358 
361  char *file_name_view_log;
362 #endif /* TO_FILE_FULL */
363 
364 #ifdef TO_FILE
365 #ifdef TO_FILE_FULL
366 
369  char *file_name_observed_log;
370 #endif /* TO_FILE_FULL */
371 
376 
381 #endif /* TO_FILE */
382 
387 
392 
398  unsigned int view_size_est_need;
399 
405  unsigned int view_size_est_min;
406 
410  struct View *view;
411 
416 
417  /* === stats === */
418 
422  uint32_t num_rounds;
423 
429  uint32_t push_recv[HISTOGRAM_FILE_SLOTS];
430 
438  uint32_t push_delta[HISTOGRAM_FILE_SLOTS];
439 
446  uint32_t pull_delays[HISTOGRAM_FILE_SLOTS];
447 };
448 
449 
450 /***********************************************************************
451  * Globals
452 ***********************************************************************/
453 
457 static const struct GNUNET_CONFIGURATION_Handle *cfg;
458 
463 
468 
473 
478 
483 
488 static float alpha;
489 
494 static float beta;
495 
499 static struct GNUNET_NSE_Handle *nse;
500 
505 
510 
511 
512 #if ENABLE_MALICIOUS
513 
521 static uint32_t mal_type;
522 
526 static struct GNUNET_PeerIdentity *mal_peers;
527 
532 static struct GNUNET_CONTAINER_MultiPeerMap *mal_peer_set;
533 
537 static uint32_t num_mal_peers;
538 
539 
543 static struct AttackedPeer *att_peers_head;
544 static struct AttackedPeer *att_peers_tail;
545 
550 static struct AttackedPeer *att_peer_index;
551 
556 static struct GNUNET_CONTAINER_MultiPeerMap *att_peer_set;
557 
561 static uint32_t num_attacked_peers;
562 
566 static struct GNUNET_PeerIdentity attacked_peer;
567 
575 static uint32_t push_limit = 10000;
576 #endif /* ENABLE_MALICIOUS */
577 
584 static struct Sub *msub;
585 
590 static const uint32_t num_valid_peers_max = UINT32_MAX;
591 
592 /***********************************************************************
593  * /Globals
594 ***********************************************************************/
595 
596 
597 static void
598 do_round (void *cls);
599 
600 static void
601 do_mal_round (void *cls);
602 
603 
612 static struct PeerContext *
614  const struct GNUNET_PeerIdentity *peer)
615 {
616  struct PeerContext *ctx;
617  int ret;
618 
619  ret = GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
620  GNUNET_assert (GNUNET_YES == ret);
621  ctx = GNUNET_CONTAINER_multipeermap_get (peer_map, peer);
622  GNUNET_assert (NULL != ctx);
623  return ctx;
624 }
625 
637 static int
639  const struct GNUNET_PeerIdentity *peer)
640 {
641  if (NULL != peer_map)
642  {
643  return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
644  }
645  else
646  {
647  return GNUNET_NO;
648  }
649 }
650 
651 
660 static struct PeerContext *
662  const struct GNUNET_PeerIdentity *peer)
663 {
664  struct PeerContext *ctx;
665  int ret;
666 
668 
669  ctx = GNUNET_new (struct PeerContext);
670  ctx->peer_id = *peer;
671  ctx->sub = sub;
672  ret = GNUNET_CONTAINER_multipeermap_put (sub->peer_map, peer, ctx,
674  GNUNET_assert (GNUNET_OK == ret);
675  if (sub == msub)
676  {
677  GNUNET_STATISTICS_set (stats,
678  "# known peers",
680  GNUNET_NO);
681  }
682  return ctx;
683 }
684 
685 
694 static struct PeerContext *
696  const struct GNUNET_PeerIdentity *peer)
697 {
698  if (GNUNET_NO == check_peer_known (sub->peer_map, peer))
699  {
700  return create_peer_ctx (sub, peer);
701  }
702  return get_peer_ctx (sub->peer_map, peer);
703 }
704 
705 
716 static int
717 check_connected (struct PeerContext *peer_ctx)
718 {
719  /* If we don't know about this peer we don't know whether it's online */
720  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
721  &peer_ctx->peer_id))
722  {
723  return GNUNET_NO;
724  }
725  /* Get the context */
726  peer_ctx = get_peer_ctx (peer_ctx->sub->peer_map, &peer_ctx->peer_id);
727  /* If we have no channel to this peer we don't know whether it's online */
728  if ( (NULL == peer_ctx->send_channel_ctx) &&
729  (NULL == peer_ctx->recv_channel_ctx) )
730  {
731  UNSET_PEER_FLAG (peer_ctx, Peers_ONLINE);
732  return GNUNET_NO;
733  }
734  /* Otherwise (if we have a channel, we know that it's online */
735  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
736  return GNUNET_YES;
737 }
738 
739 
744 {
750  uint32_t index;
751 
755  const struct GNUNET_PeerIdentity *peer;
756 };
757 
758 
774 static int
776  const struct GNUNET_PeerIdentity *peer,
777  void *value)
778 {
779  struct GetRandPeerIteratorCls *iterator_cls = cls;
780  (void) value;
781 
782  if (0 >= iterator_cls->index)
783  {
784  iterator_cls->peer = peer;
785  return GNUNET_NO;
786  }
787  iterator_cls->index--;
788  return GNUNET_YES;
789 }
790 
791 
800 static const struct GNUNET_PeerIdentity *
802 {
803  struct GetRandPeerIteratorCls *iterator_cls;
804  const struct GNUNET_PeerIdentity *ret;
805 
806  iterator_cls = GNUNET_new (struct GetRandPeerIteratorCls);
808  GNUNET_CONTAINER_multipeermap_size (valid_peers));
809  (void) GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
811  iterator_cls);
812  ret = iterator_cls->peer;
813  GNUNET_free (iterator_cls);
814  return ret;
815 }
816 
817 
829 static int
831  struct GNUNET_CONTAINER_MultiPeerMap *valid_peers)
832 {
833  const struct GNUNET_PeerIdentity *rand_peer;
834  int ret;
835 
836  ret = GNUNET_YES;
837  /* Remove random peers until there is space for a new one */
838  while (num_valid_peers_max <=
840  {
841  rand_peer = get_random_peer_from_peermap (valid_peers);
842  GNUNET_CONTAINER_multipeermap_remove_all (valid_peers, rand_peer);
843  ret = GNUNET_NO;
844  }
845  (void) GNUNET_CONTAINER_multipeermap_put (valid_peers, peer, NULL,
847  if (valid_peers == msub->valid_peers)
848  {
849  GNUNET_STATISTICS_set (stats,
850  "# valid peers",
852  GNUNET_NO);
853  }
854  return ret;
855 }
856 
857 static void
858 remove_pending_message (struct PendingMessage *pending_msg, int cancel);
859 
868 static void
869 set_peer_online (struct PeerContext *peer_ctx)
870 {
871  struct GNUNET_PeerIdentity *peer;
872  unsigned int i;
873 
874  peer = &peer_ctx->peer_id;
876  "Peer %s is online and valid, calling %i pending operations on it\n",
877  GNUNET_i2s (peer),
878  peer_ctx->num_pending_ops);
879 
880  if (NULL != peer_ctx->online_check_pending)
881  {
883  "Removing pending online check for peer %s\n",
884  GNUNET_i2s (&peer_ctx->peer_id));
885  // TODO wait until cadet sets mq->cancel_impl
886  //GNUNET_MQ_send_cancel (peer_ctx->online_check_pending->ev);
888  peer_ctx->online_check_pending = NULL;
889  }
890 
891  SET_PEER_FLAG (peer_ctx, Peers_ONLINE);
892 
893  /* Call pending operations */
894  for (i = 0; i < peer_ctx->num_pending_ops; i++)
895  {
896  peer_ctx->pending_ops[i].op (peer_ctx->pending_ops[i].op_cls, peer);
897  }
898  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
899 }
900 
901 static void
902 cleanup_destroyed_channel (void *cls,
903  const struct GNUNET_CADET_Channel *channel);
904 
905 /* Declaration of handlers */
906 static void
907 handle_peer_check (void *cls,
908  const struct GNUNET_MessageHeader *msg);
909 
910 static void
911 handle_peer_push (void *cls,
912  const struct GNUNET_MessageHeader *msg);
913 
914 static void
915 handle_peer_pull_request (void *cls,
916  const struct GNUNET_MessageHeader *msg);
917 
918 static int
919 check_peer_pull_reply (void *cls,
920  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
921 
922 static void
923 handle_peer_pull_reply (void *cls,
924  const struct GNUNET_RPS_P2P_PullReplyMessage *msg);
925 
926 /* End declaration of handlers */
927 
935 static struct ChannelCtx *
937 {
938  struct ChannelCtx *channel_ctx;
939  channel_ctx = GNUNET_new (struct ChannelCtx);
940  channel_ctx->peer_ctx = peer_ctx;
941  return channel_ctx;
942 }
943 
944 
950 static void
951 remove_channel_ctx (struct ChannelCtx *channel_ctx)
952 {
953  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
954 
955  if (NULL != channel_ctx->destruction_task)
956  {
958  channel_ctx->destruction_task = NULL;
959  }
960 
961  GNUNET_free (channel_ctx);
962 
963  if (NULL == peer_ctx) return;
964  if (channel_ctx == peer_ctx->send_channel_ctx)
965  {
966  peer_ctx->send_channel_ctx = NULL;
967  peer_ctx->mq = NULL;
968  }
969  else if (channel_ctx == peer_ctx->recv_channel_ctx)
970  {
971  peer_ctx->recv_channel_ctx = NULL;
972  }
973 }
974 
975 
982 struct GNUNET_CADET_Channel *
983 get_channel (struct PeerContext *peer_ctx)
984 {
985  /* There exists a copy-paste-clone in run() */
986  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
987  GNUNET_MQ_hd_fixed_size (peer_check,
989  struct GNUNET_MessageHeader,
990  NULL),
991  GNUNET_MQ_hd_fixed_size (peer_push,
993  struct GNUNET_MessageHeader,
994  NULL),
995  GNUNET_MQ_hd_fixed_size (peer_pull_request,
997  struct GNUNET_MessageHeader,
998  NULL),
999  GNUNET_MQ_hd_var_size (peer_pull_reply,
1002  NULL),
1004  };
1005 
1006 
1007  if (NULL == peer_ctx->send_channel_ctx)
1008  {
1010  "Trying to establish channel to peer %s\n",
1011  GNUNET_i2s (&peer_ctx->peer_id));
1012  peer_ctx->send_channel_ctx = add_channel_ctx (peer_ctx);
1013  peer_ctx->send_channel_ctx->channel =
1014  GNUNET_CADET_channel_create (cadet_handle,
1015  peer_ctx->send_channel_ctx, /* context */
1016  &peer_ctx->peer_id,
1017  &peer_ctx->sub->hash,
1019  NULL, /* WindowSize handler */
1020  &cleanup_destroyed_channel, /* Disconnect handler */
1021  cadet_handlers);
1022  }
1023  GNUNET_assert (NULL != peer_ctx->send_channel_ctx);
1024  GNUNET_assert (NULL != peer_ctx->send_channel_ctx->channel);
1025  return peer_ctx->send_channel_ctx->channel;
1026 }
1027 
1028 
1038 static struct GNUNET_MQ_Handle *
1039 get_mq (struct PeerContext *peer_ctx)
1040 {
1041  if (NULL == peer_ctx->mq)
1042  {
1043  peer_ctx->mq = GNUNET_CADET_get_mq (get_channel (peer_ctx));
1044  }
1045  return peer_ctx->mq;
1046 }
1047 
1056 static struct PendingMessage *
1058  struct GNUNET_MQ_Envelope *ev,
1059  const char *type)
1060 {
1061  struct PendingMessage *pending_msg;
1062 
1063  pending_msg = GNUNET_new (struct PendingMessage);
1064  pending_msg->ev = ev;
1065  pending_msg->peer_ctx = peer_ctx;
1066  pending_msg->type = type;
1068  peer_ctx->pending_messages_tail,
1069  pending_msg);
1070  return pending_msg;
1071 }
1072 
1073 
1080 static void
1081 remove_pending_message (struct PendingMessage *pending_msg, int cancel)
1082 {
1083  struct PeerContext *peer_ctx;
1084  (void) cancel;
1085 
1086  peer_ctx = pending_msg->peer_ctx;
1087  GNUNET_assert (NULL != peer_ctx);
1089  peer_ctx->pending_messages_tail,
1090  pending_msg);
1091  // TODO wait for the cadet implementation of message cancellation
1092  //if (GNUNET_YES == cancel)
1093  //{
1094  // GNUNET_MQ_send_cancel (pending_msg->ev);
1095  //}
1096  GNUNET_free (pending_msg);
1097 }
1098 
1099 
1106 static void
1108 {
1109  struct PeerContext *peer_ctx = cls;
1110 
1111  if (NULL != peer_ctx->online_check_pending)
1112  {
1114  "Online check for peer %s was successfull\n",
1115  GNUNET_i2s (&peer_ctx->peer_id));
1117  peer_ctx->online_check_pending = NULL;
1118  set_peer_online (peer_ctx);
1119  (void) add_valid_peer (&peer_ctx->peer_id, peer_ctx->sub->valid_peers);
1120  }
1121 }
1122 
1128 static void
1129 check_peer_online (struct PeerContext *peer_ctx)
1130 {
1132  "Get informed about peer %s getting online\n",
1133  GNUNET_i2s (&peer_ctx->peer_id));
1134 
1135  struct GNUNET_MQ_Handle *mq;
1136  struct GNUNET_MQ_Envelope *ev;
1137 
1139  peer_ctx->online_check_pending =
1140  insert_pending_message (peer_ctx, ev, "Check online");
1141  mq = get_mq (peer_ctx);
1144  peer_ctx);
1145  GNUNET_MQ_send (mq, ev);
1146  if (peer_ctx->sub == msub)
1147  {
1148  GNUNET_STATISTICS_update (stats,
1149  "# pending online checks",
1150  1,
1151  GNUNET_NO);
1152  }
1153 }
1154 
1155 
1168 static int
1169 check_operation_scheduled (const struct PeerContext *peer_ctx,
1170  const PeerOp peer_op)
1171 {
1172  unsigned int i;
1173 
1174  for (i = 0; i < peer_ctx->num_pending_ops; i++)
1175  if (peer_op == peer_ctx->pending_ops[i].op)
1176  return GNUNET_YES;
1177  return GNUNET_NO;
1178 }
1179 
1180 
1186 static void
1187 destroy_channel (struct ChannelCtx *channel_ctx)
1188 {
1189  struct GNUNET_CADET_Channel *channel;
1190 
1191  if (NULL != channel_ctx->destruction_task)
1192  {
1194  channel_ctx->destruction_task = NULL;
1195  }
1196  GNUNET_assert (channel_ctx->channel != NULL);
1197  channel = channel_ctx->channel;
1198  channel_ctx->channel = NULL;
1199  GNUNET_CADET_channel_destroy (channel);
1200  remove_channel_ctx (channel_ctx);
1201 }
1202 
1203 
1211 static void
1213 {
1214  struct ChannelCtx *channel_ctx = cls;
1215 
1216  channel_ctx->destruction_task = NULL;
1217  destroy_channel (channel_ctx);
1218 }
1219 
1220 
1231 static void
1233 {
1234  GNUNET_assert (NULL ==
1235  channel_ctx->destruction_task);
1236  GNUNET_assert (NULL !=
1237  channel_ctx->channel);
1238  channel_ctx->destruction_task =
1240  channel_ctx);
1241 }
1242 
1243 
1257 static int
1259 {
1260  GNUNET_assert (NULL != peer_ctx);
1261  GNUNET_assert (NULL != peer_ctx->sub->peer_map);
1262  if (GNUNET_NO ==
1264  &peer_ctx->peer_id))
1265  {
1266  return GNUNET_NO;
1267  }
1268  SET_PEER_FLAG (peer_ctx, Peers_TO_DESTROY);
1270  "Going to remove peer %s\n",
1271  GNUNET_i2s (&peer_ctx->peer_id));
1272  UNSET_PEER_FLAG (peer_ctx, Peers_ONLINE);
1273 
1274  /* Clear list of pending operations */
1275  // TODO this probably leaks memory
1276  // ('only' the cls to the function. Not sure what to do with it)
1277  GNUNET_array_grow (peer_ctx->pending_ops,
1278  peer_ctx->num_pending_ops,
1279  0);
1280  /* Remove all pending messages */
1281  while (NULL != peer_ctx->pending_messages_head)
1282  {
1284  "Removing unsent %s\n",
1285  peer_ctx->pending_messages_head->type);
1286  /* Cancle pending message, too */
1287  if ( (NULL != peer_ctx->online_check_pending) &&
1288  (0 == memcmp (peer_ctx->pending_messages_head,
1289  peer_ctx->online_check_pending,
1290  sizeof (struct PendingMessage))) )
1291  {
1292  peer_ctx->online_check_pending = NULL;
1293  if (peer_ctx->sub == msub)
1294  {
1295  GNUNET_STATISTICS_update (stats,
1296  "# pending online checks",
1297  -1,
1298  GNUNET_NO);
1299  }
1300  }
1302  GNUNET_YES);
1303  }
1304 
1305  /* If we are still waiting for notification whether this peer is online
1306  * cancel the according task */
1307  if (NULL != peer_ctx->online_check_pending)
1308  {
1310  "Removing pending online check for peer %s\n",
1311  GNUNET_i2s (&peer_ctx->peer_id));
1312  // TODO wait until cadet sets mq->cancel_impl
1313  //GNUNET_MQ_send_cancel (peer_ctx->online_check_pending->ev);
1315  GNUNET_YES);
1316  peer_ctx->online_check_pending = NULL;
1317  }
1318 
1319  if (NULL != peer_ctx->send_channel_ctx)
1320  {
1321  /* This is possibly called from within channel destruction */
1322  peer_ctx->send_channel_ctx->peer_ctx = NULL;
1324  peer_ctx->send_channel_ctx = NULL;
1325  peer_ctx->mq = NULL;
1326  }
1327  if (NULL != peer_ctx->recv_channel_ctx)
1328  {
1329  /* This is possibly called from within channel destruction */
1330  peer_ctx->recv_channel_ctx->peer_ctx = NULL;
1332  peer_ctx->recv_channel_ctx = NULL;
1333  }
1334 
1335  if (GNUNET_YES !=
1337  &peer_ctx->peer_id))
1338  {
1340  "removing peer from peer_ctx->sub->peer_map failed\n");
1341  }
1342  if (peer_ctx->sub == msub)
1343  {
1344  GNUNET_STATISTICS_set (stats,
1345  "# known peers",
1347  GNUNET_NO);
1348  }
1349  GNUNET_free (peer_ctx);
1350  return GNUNET_YES;
1351 }
1352 
1353 
1363 static int
1365  const struct GNUNET_PeerIdentity *key,
1366  void *value)
1367 {
1368  struct Sub *sub = cls;
1369  (void) value;
1370 
1371  destroy_peer (get_peer_ctx (sub->peer_map, key));
1372  return GNUNET_YES;
1373 }
1374 
1375 
1383 static void
1385 {
1386  struct PendingMessage *pending_msg = (struct PendingMessage *) cls;
1388  "%s was sent.\n",
1389  pending_msg->type);
1390  if (pending_msg->peer_ctx->sub == msub)
1391  {
1392  if (0 == strncmp ("PULL REPLY", pending_msg->type, 10))
1393  GNUNET_STATISTICS_update(stats, "# pull replys sent", 1, GNUNET_NO);
1394  if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12))
1395  GNUNET_STATISTICS_update(stats, "# pull requests sent", 1, GNUNET_NO);
1396  if (0 == strncmp ("PUSH", pending_msg->type, 4))
1397  GNUNET_STATISTICS_update(stats, "# pushes sent", 1, GNUNET_NO);
1398  if (0 == strncmp ("PULL REQUEST", pending_msg->type, 12) &&
1399  NULL != map_single_hop &&
1401  &pending_msg->peer_ctx->peer_id))
1403  "# pull requests sent (multi-hop peer)",
1404  1,
1405  GNUNET_NO);
1406  }
1407  /* Do not cancle message */
1408  remove_pending_message (pending_msg, GNUNET_NO);
1409 }
1410 
1411 
1426 static int
1428  const struct GNUNET_PeerIdentity *peer,
1429  void *value)
1430 {
1431  const struct GNUNET_DISK_FileHandle *fh = cls;
1432  char peer_string[128];
1433  int size;
1434  ssize_t ret;
1435  (void) value;
1436 
1437  if (NULL == peer)
1438  {
1439  return GNUNET_YES;
1440  }
1441  size = GNUNET_snprintf (peer_string,
1442  sizeof (peer_string),
1443  "%s\n",
1444  GNUNET_i2s_full (peer));
1445  GNUNET_assert (53 == size);
1446  ret = GNUNET_DISK_file_write (fh,
1447  peer_string,
1448  size);
1449  GNUNET_assert (size == ret);
1450  return GNUNET_YES;
1451 }
1452 
1453 
1459 static void
1460 store_valid_peers (const struct Sub *sub)
1461 {
1462  struct GNUNET_DISK_FileHandle *fh;
1463  uint32_t number_written_peers;
1464  int ret;
1465 
1466  if (0 == strncmp ("DISABLE", sub->filename_valid_peers, 7))
1467  {
1468  return;
1469  }
1470 
1472  if (GNUNET_SYSERR == ret)
1473  {
1475  "Not able to create directory for file `%s'\n",
1476  sub->filename_valid_peers);
1477  GNUNET_break (0);
1478  }
1479  else if (GNUNET_NO == ret)
1480  {
1482  "Directory for file `%s' exists but is not writable for us\n",
1483  sub->filename_valid_peers);
1484  GNUNET_break (0);
1485  }
1491  if (NULL == fh)
1492  {
1494  "Not able to write valid peers to file `%s'\n",
1495  sub->filename_valid_peers);
1496  return;
1497  }
1499  "Writing %u valid peers to disk\n",
1501  number_written_peers =
1504  fh);
1506  GNUNET_assert (number_written_peers ==
1508 }
1509 
1510 
1520 static const struct GNUNET_PeerIdentity *
1521 s2i_full (const char *string_repr)
1522 {
1523  struct GNUNET_PeerIdentity *peer;
1524  size_t len;
1525  int ret;
1526 
1527  peer = GNUNET_new (struct GNUNET_PeerIdentity);
1528  len = strlen (string_repr);
1529  if (52 > len)
1530  {
1532  "Not able to convert string representation of PeerID to PeerID\n"
1533  "Sting representation: %s (len %lu) - too short\n",
1534  string_repr,
1535  len);
1536  GNUNET_break (0);
1537  }
1538  else if (52 < len)
1539  {
1540  len = 52;
1541  }
1542  ret = GNUNET_CRYPTO_eddsa_public_key_from_string (string_repr,
1543  len,
1544  &peer->public_key);
1545  if (GNUNET_OK != ret)
1546  {
1548  "Not able to convert string representation of PeerID to PeerID\n"
1549  "Sting representation: %s\n",
1550  string_repr);
1551  GNUNET_break (0);
1552  }
1553  return peer;
1554 }
1555 
1556 
1562 static void
1563 restore_valid_peers (const struct Sub *sub)
1564 {
1565  off_t file_size;
1566  uint32_t num_peers;
1567  struct GNUNET_DISK_FileHandle *fh;
1568  char *buf;
1569  ssize_t size_read;
1570  char *iter_buf;
1571  char *str_repr;
1572  const struct GNUNET_PeerIdentity *peer;
1573 
1574  if (0 == strncmp ("DISABLE", sub->filename_valid_peers, 7))
1575  {
1576  return;
1577  }
1578 
1580  {
1581  return;
1582  }
1586  GNUNET_assert (NULL != fh);
1588  num_peers = file_size / 53;
1589  buf = GNUNET_malloc (file_size);
1590  size_read = GNUNET_DISK_file_read (fh, buf, file_size);
1591  GNUNET_assert (size_read == file_size);
1593  "Restoring %" PRIu32 " peers from file `%s'\n",
1594  num_peers,
1595  sub->filename_valid_peers);
1596  for (iter_buf = buf; iter_buf < buf + file_size - 1; iter_buf += 53)
1597  {
1598  str_repr = GNUNET_strndup (iter_buf, 53);
1599  peer = s2i_full (str_repr);
1600  GNUNET_free (str_repr);
1601  add_valid_peer (peer, sub->valid_peers);
1603  "Restored valid peer %s from disk\n",
1604  GNUNET_i2s_full (peer));
1605  }
1606  iter_buf = NULL;
1607  GNUNET_free (buf);
1609  "num_peers: %" PRIu32 ", _size (sub->valid_peers): %u\n",
1610  num_peers,
1612  if (num_peers != GNUNET_CONTAINER_multipeermap_size (sub->valid_peers))
1613  {
1615  "Number of restored peers does not match file size. Have probably duplicates.\n");
1616  }
1619  "Restored %u valid peers from disk\n",
1621 }
1622 
1623 
1629 static void
1630 peers_terminate (struct Sub *sub)
1631 {
1632  if (GNUNET_SYSERR ==
1635  sub))
1636  {
1638  "Iteration destroying peers was aborted.\n");
1639  }
1641  sub->peer_map = NULL;
1642  store_valid_peers (sub);
1644  sub->filename_valid_peers = NULL;
1646  sub->valid_peers = NULL;
1647 }
1648 
1649 
1660 static int
1662  const struct GNUNET_PeerIdentity *peer,
1663  void *value)
1664 {
1665  struct PeersIteratorCls *it_cls = cls;
1666  (void) value;
1667 
1668  return it_cls->iterator (it_cls->cls, peer);
1669 }
1670 
1671 
1681 static int
1684  void *it_cls)
1685 {
1686  struct PeersIteratorCls *cls;
1687  int ret;
1688 
1689  cls = GNUNET_new (struct PeersIteratorCls);
1690  cls->iterator = iterator;
1691  cls->cls = it_cls;
1692  ret = GNUNET_CONTAINER_multipeermap_iterate (valid_peers,
1694  cls);
1695  GNUNET_free (cls);
1696  return ret;
1697 }
1698 
1699 
1712 static int
1713 insert_peer (struct Sub *sub,
1714  const struct GNUNET_PeerIdentity *peer)
1715 {
1716  if (GNUNET_YES == check_peer_known (sub->peer_map, peer))
1717  {
1718  return GNUNET_NO; /* We already know this peer - nothing to do */
1719  }
1720  (void) create_peer_ctx (sub, peer);
1721  return GNUNET_YES;
1722 }
1723 
1724 
1736 static int
1738  const struct GNUNET_PeerIdentity *peer,
1739  enum Peers_PeerFlags flags)
1740 {
1741  struct PeerContext *peer_ctx;
1742 
1743  if (GNUNET_NO == check_peer_known (peer_map, peer))
1744  {
1745  return GNUNET_SYSERR;
1746  }
1747  peer_ctx = get_peer_ctx (peer_map, peer);
1748  return check_peer_flag_set (peer_ctx, flags);
1749 }
1750 
1761 static int
1763  const struct GNUNET_PeerIdentity *peer)
1764 {
1765  struct PeerContext *peer_ctx;
1766 
1767  (void) insert_peer (sub, peer); // TODO even needed?
1768  peer_ctx = get_peer_ctx (sub->peer_map, peer);
1769  if ( (GNUNET_NO == check_peer_flag (sub->peer_map, peer, Peers_ONLINE)) &&
1770  (NULL == peer_ctx->online_check_pending) )
1771  {
1772  check_peer_online (peer_ctx);
1773  return GNUNET_YES;
1774  }
1775  return GNUNET_NO;
1776 }
1777 
1778 
1792 static int
1793 check_removable (const struct PeerContext *peer_ctx)
1794 {
1796  &peer_ctx->peer_id))
1797  {
1798  return GNUNET_SYSERR;
1799  }
1800 
1801  if ( (NULL != peer_ctx->recv_channel_ctx) ||
1802  (NULL != peer_ctx->pending_messages_head) ||
1804  {
1805  return GNUNET_NO;
1806  }
1807  return GNUNET_YES;
1808 }
1809 
1810 
1822 static int
1824  const struct GNUNET_PeerIdentity *peer)
1825 {
1826  return GNUNET_CONTAINER_multipeermap_contains (valid_peers, peer);
1827 }
1828 
1829 
1837 static void
1839 {
1841  &peer_ctx->peer_id));
1842  (void) get_channel (peer_ctx);
1843 }
1844 
1845 
1855 static int
1856 check_peer_send_intention (const struct PeerContext *peer_ctx)
1857 {
1858  if (NULL != peer_ctx->recv_channel_ctx)
1859  {
1860  return GNUNET_YES;
1861  }
1862  return GNUNET_NO;
1863 }
1864 
1865 
1876 static void *
1878  struct GNUNET_CADET_Channel *channel,
1879  const struct GNUNET_PeerIdentity *initiator)
1880 {
1881  struct PeerContext *peer_ctx;
1882  struct ChannelCtx *channel_ctx;
1883  struct Sub *sub = cls;
1884 
1886  "New channel was established to us (Peer %s).\n",
1887  GNUNET_i2s (initiator));
1888  GNUNET_assert (NULL != channel); /* according to cadet API */
1889  /* Make sure we 'know' about this peer */
1890  peer_ctx = create_or_get_peer_ctx (sub, initiator);
1891  set_peer_online (peer_ctx);
1892  (void) add_valid_peer (&peer_ctx->peer_id, peer_ctx->sub->valid_peers);
1893  channel_ctx = add_channel_ctx (peer_ctx);
1894  channel_ctx->channel = channel;
1895  /* We only accept one incoming channel per peer */
1897  initiator)))
1898  {
1900  "Already got one receive channel. Destroying old one.\n");
1901  GNUNET_break_op (0);
1902  destroy_channel (peer_ctx->recv_channel_ctx);
1903  peer_ctx->recv_channel_ctx = channel_ctx;
1904  /* return the channel context */
1905  return channel_ctx;
1906  }
1907  peer_ctx->recv_channel_ctx = channel_ctx;
1908  return channel_ctx;
1909 }
1910 
1911 
1920 static int
1922 {
1923  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
1924  &peer_ctx->peer_id))
1925  { /* If no such peer exists, there is no channel */
1926  return GNUNET_NO;
1927  }
1928  if (NULL == peer_ctx->send_channel_ctx)
1929  {
1930  return GNUNET_NO;
1931  }
1932  return GNUNET_YES;
1933 }
1934 
1935 
1944 static int
1946 {
1947  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
1948  &peer_ctx->peer_id))
1949  {
1950  return GNUNET_NO;
1951  }
1952  if (NULL != peer_ctx->send_channel_ctx)
1953  {
1954  destroy_channel (peer_ctx->send_channel_ctx);
1955  (void) check_connected (peer_ctx);
1956  return GNUNET_YES;
1957  }
1958  return GNUNET_NO;
1959 }
1960 
1971 static void
1972 send_message (struct PeerContext *peer_ctx,
1973  struct GNUNET_MQ_Envelope *ev,
1974  const char *type)
1975 {
1976  struct PendingMessage *pending_msg;
1977  struct GNUNET_MQ_Handle *mq;
1978 
1980  "Sending message to %s of type %s\n",
1981  GNUNET_i2s (&peer_ctx->peer_id),
1982  type);
1983  pending_msg = insert_pending_message (peer_ctx, ev, type);
1984  mq = get_mq (peer_ctx);
1987  pending_msg);
1988  GNUNET_MQ_send (mq, ev);
1989 }
1990 
2003 static int
2005  const PeerOp peer_op,
2006  void *cls)
2007 {
2008  struct PeerPendingOp pending_op;
2009 
2011  &peer_ctx->peer_id));
2012 
2013  //TODO if ONLINE execute immediately
2014 
2015  if (GNUNET_NO == check_operation_scheduled (peer_ctx, peer_op))
2016  {
2017  pending_op.op = peer_op;
2018  pending_op.op_cls = cls;
2019  GNUNET_array_append (peer_ctx->pending_ops,
2020  peer_ctx->num_pending_ops,
2021  pending_op);
2022  return GNUNET_YES;
2023  }
2024  return GNUNET_NO;
2025 }
2026 
2027 /***********************************************************************
2028  * /Old gnunet-service-rps_peers.c
2029 ***********************************************************************/
2030 
2031 
2032 /***********************************************************************
2033  * Housekeeping with clients
2034 ***********************************************************************/
2035 
2040 struct ReplyCls
2041 {
2045  struct ReplyCls *next;
2046  struct ReplyCls *prev;
2047 
2051  uint32_t id;
2052 
2057 
2062 };
2063 
2064 
2069 {
2075 
2080 
2085 
2091 
2096 
2100  struct Sub *sub;
2101 };
2102 
2108 
2109 /***********************************************************************
2110  * /Housekeeping with clients
2111 ***********************************************************************/
2112 
2113 
2114 
2115 
2116 
2117 /***********************************************************************
2118  * Util functions
2119 ***********************************************************************/
2120 
2121 
2125 static void
2127  unsigned int len)
2128 {
2129  unsigned int i;
2130 
2132  "Printing peer list of length %u at %p:\n",
2133  len,
2134  list);
2135  for (i = 0 ; i < len ; i++)
2136  {
2138  "%u. peer: %s\n",
2139  i, GNUNET_i2s (&list[i]));
2140  }
2141 }
2142 
2143 
2147 static void
2149  unsigned int *list_size,
2150  const struct GNUNET_PeerIdentity *peer)
2151 {
2152  unsigned int i;
2153  struct GNUNET_PeerIdentity *tmp;
2154 
2155  tmp = *peer_list;
2156 
2158  "Removing peer %s from list at %p\n",
2159  GNUNET_i2s (peer),
2160  tmp);
2161 
2162  for ( i = 0 ; i < *list_size ; i++ )
2163  {
2164  if (0 == GNUNET_memcmp (&tmp[i], peer))
2165  {
2166  if (i < *list_size -1)
2167  { /* Not at the last entry -- shift peers left */
2168  memmove (&tmp[i], &tmp[i +1],
2169  ((*list_size) - i -1) * sizeof (struct GNUNET_PeerIdentity));
2170  }
2171  /* Remove last entry (should be now useless PeerID) */
2172  GNUNET_array_grow (tmp, *list_size, (*list_size) -1);
2173  }
2174  }
2175  *peer_list = tmp;
2176 }
2177 
2178 
2188 static void
2189 insert_in_view_op (void *cls,
2190  const struct GNUNET_PeerIdentity *peer);
2191 
2203 static int
2204 insert_in_view (struct Sub *sub,
2205  const struct GNUNET_PeerIdentity *peer)
2206 {
2207  struct PeerContext *peer_ctx;
2208  int online;
2209  int ret;
2210 
2211  online = check_peer_flag (sub->peer_map, peer, Peers_ONLINE);
2212  peer_ctx = get_peer_ctx (sub->peer_map, peer); // TODO indirection needed?
2213  if ( (GNUNET_NO == online) ||
2214  (GNUNET_SYSERR == online) ) /* peer is not even known */
2215  {
2216  (void) issue_peer_online_check (sub, peer);
2217  (void) schedule_operation (peer_ctx, insert_in_view_op, sub);
2218  return GNUNET_NO;
2219  }
2220  /* Open channel towards peer to keep connection open */
2221  indicate_sending_intention (peer_ctx);
2222  ret = View_put (sub->view, peer);
2223  if (peer_ctx->sub == msub)
2224  {
2225  GNUNET_STATISTICS_set (stats,
2226  "view size",
2227  View_size (peer_ctx->sub->view),
2228  GNUNET_NO);
2229  }
2230  return ret;
2231 }
2232 
2233 
2241 static void
2242 send_view (const struct ClientContext *cli_ctx,
2243  const struct GNUNET_PeerIdentity *view_array,
2244  uint64_t view_size)
2245 {
2246  struct GNUNET_MQ_Envelope *ev;
2247  struct GNUNET_RPS_CS_DEBUG_ViewReply *out_msg;
2248  struct Sub *sub;
2249 
2250  if (NULL == view_array)
2251  {
2252  if (NULL == cli_ctx->sub) sub = msub;
2253  else sub = cli_ctx->sub;
2254  view_size = View_size (sub->view);
2255  view_array = View_get_as_array (sub->view);
2256  }
2257 
2258  ev = GNUNET_MQ_msg_extra (out_msg,
2259  view_size * sizeof (struct GNUNET_PeerIdentity),
2261  out_msg->num_peers = htonl (view_size);
2262 
2263  GNUNET_memcpy (&out_msg[1],
2264  view_array,
2265  view_size * sizeof (struct GNUNET_PeerIdentity));
2266  GNUNET_MQ_send (cli_ctx->mq, ev);
2267 }
2268 
2269 
2279 static void
2280 send_stream_peers (const struct ClientContext *cli_ctx,
2281  uint64_t num_peers,
2282  const struct GNUNET_PeerIdentity *peers)
2283 {
2284  struct GNUNET_MQ_Envelope *ev;
2285  struct GNUNET_RPS_CS_DEBUG_StreamReply *out_msg;
2286 
2287  GNUNET_assert (NULL != peers);
2288 
2289  ev = GNUNET_MQ_msg_extra (out_msg,
2290  num_peers * sizeof (struct GNUNET_PeerIdentity),
2292  out_msg->num_peers = htonl (num_peers);
2293 
2294  GNUNET_memcpy (&out_msg[1],
2295  peers,
2296  num_peers * sizeof (struct GNUNET_PeerIdentity));
2297  GNUNET_MQ_send (cli_ctx->mq, ev);
2298 }
2299 
2300 
2306 static void
2307 clients_notify_view_update (const struct Sub *sub)
2308 {
2309  struct ClientContext *cli_ctx_iter;
2310  uint64_t num_peers;
2311  const struct GNUNET_PeerIdentity *view_array;
2312 
2313  num_peers = View_size (sub->view);
2314  view_array = View_get_as_array(sub->view);
2315  /* check size of view is small enough */
2316  if (GNUNET_MAX_MESSAGE_SIZE < num_peers)
2317  {
2319  "View is too big to send\n");
2320  return;
2321  }
2322 
2323  for (cli_ctx_iter = cli_ctx_head;
2324  NULL != cli_ctx_iter;
2325  cli_ctx_iter = cli_ctx_iter->next)
2326  {
2327  if (1 < cli_ctx_iter->view_updates_left)
2328  {
2329  /* Client wants to receive limited amount of updates */
2330  cli_ctx_iter->view_updates_left -= 1;
2331  } else if (1 == cli_ctx_iter->view_updates_left)
2332  {
2333  /* Last update of view for client */
2334  cli_ctx_iter->view_updates_left = -1;
2335  } else if (0 > cli_ctx_iter->view_updates_left) {
2336  /* Client is not interested in updates */
2337  continue;
2338  }
2339  /* else _updates_left == 0 - infinite amount of updates */
2340 
2341  /* send view */
2342  send_view (cli_ctx_iter, view_array, num_peers);
2343  }
2344 }
2345 
2346 
2353 static void
2354 clients_notify_stream_peer (const struct Sub *sub,
2355  uint64_t num_peers,
2356  const struct GNUNET_PeerIdentity *peers)
2357  // TODO enum StreamPeerSource)
2358 {
2359  struct ClientContext *cli_ctx_iter;
2360 
2362  "Got peer (%s) from biased stream - update all clients\n",
2363  GNUNET_i2s (peers));
2364 
2365  for (cli_ctx_iter = cli_ctx_head;
2366  NULL != cli_ctx_iter;
2367  cli_ctx_iter = cli_ctx_iter->next)
2368  {
2369  if (GNUNET_YES == cli_ctx_iter->stream_update &&
2370  (sub == cli_ctx_iter->sub || sub == msub))
2371  {
2372  send_stream_peers (cli_ctx_iter, num_peers, peers);
2373  }
2374  }
2375 }
2376 
2377 
2385 static void
2387  uint32_t num_peers,
2388  void *cls)
2389 {
2390  unsigned int i;
2391  struct Sub *sub = cls;
2392 
2393  for (i = 0; i < num_peers; i++)
2394  {
2395  int inserted;
2396  if (GNUNET_YES != check_peer_known (sub->peer_map, &ids[i]))
2397  {
2399  "Peer in history update not known!\n");
2400  continue;
2401  }
2402  inserted = insert_in_view (sub, &ids[i]);
2403  if (GNUNET_OK == inserted)
2404  {
2405  clients_notify_stream_peer (sub, 1, &ids[i]);
2406  }
2407 #ifdef TO_FILE_FULL
2408  to_file (sub->file_name_view_log,
2409  "+%s\t(hist)",
2410  GNUNET_i2s_full (ids));
2411 #endif /* TO_FILE_FULL */
2412  }
2414 }
2415 
2416 
2426 static void
2427 resize_wrapper (struct RPS_Sampler *sampler, uint32_t new_size)
2428 {
2429  unsigned int sampler_size;
2430 
2431  // TODO statistics
2432  // TODO respect the min, max
2433  sampler_size = RPS_sampler_get_size (sampler);
2434  if (sampler_size > new_size * 4)
2435  { /* Shrinking */
2436  RPS_sampler_resize (sampler, sampler_size / 2);
2437  }
2438  else if (sampler_size < new_size)
2439  { /* Growing */
2440  RPS_sampler_resize (sampler, sampler_size * 2);
2441  }
2442  LOG (GNUNET_ERROR_TYPE_DEBUG, "sampler_size is now %u\n", sampler_size);
2443 }
2444 
2445 
2453 static void
2454 add_peer_array_to_set (const struct GNUNET_PeerIdentity *peer_array,
2455  unsigned int num_peers,
2457 {
2458  unsigned int i;
2459  if (NULL == peer_map)
2460  {
2462  "Trying to add peers to non-existing peermap.\n");
2463  return;
2464  }
2465 
2466  for (i = 0; i < num_peers; i++)
2467  {
2469  &peer_array[i],
2470  NULL,
2472  if (msub->peer_map == peer_map)
2473  {
2474  GNUNET_STATISTICS_set (stats,
2475  "# known peers",
2477  GNUNET_NO);
2478  }
2479  }
2480 }
2481 
2482 
2490 static void
2491 send_pull_reply (struct PeerContext *peer_ctx,
2492  const struct GNUNET_PeerIdentity *peer_ids,
2493  unsigned int num_peer_ids)
2494 {
2495  uint32_t send_size;
2496  struct GNUNET_MQ_Envelope *ev;
2497  struct GNUNET_RPS_P2P_PullReplyMessage *out_msg;
2498 
2499  /* Compute actual size */
2500  send_size = sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) +
2501  num_peer_ids * sizeof (struct GNUNET_PeerIdentity);
2502 
2504  /* Compute number of peers to send
2505  * If too long, simply truncate */
2506  // TODO select random ones via permutation
2507  // or even better: do good protocol design
2508  send_size =
2510  sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
2511  sizeof (struct GNUNET_PeerIdentity);
2512  else
2513  send_size = num_peer_ids;
2514 
2516  "Going to send PULL REPLY with %u peers to %s\n",
2517  send_size, GNUNET_i2s (&peer_ctx->peer_id));
2518 
2519  ev = GNUNET_MQ_msg_extra (out_msg,
2520  send_size * sizeof (struct GNUNET_PeerIdentity),
2522  out_msg->num_peers = htonl (send_size);
2523  GNUNET_memcpy (&out_msg[1], peer_ids,
2524  send_size * sizeof (struct GNUNET_PeerIdentity));
2525 
2526  send_message (peer_ctx, ev, "PULL REPLY");
2527  if (peer_ctx->sub == msub)
2528  {
2529  GNUNET_STATISTICS_update(stats, "# pull reply send issued", 1, GNUNET_NO);
2530  }
2531  // TODO check with send intention: as send_channel is used/opened we indicate
2532  // a sending intention without intending it.
2533  // -> clean peer afterwards?
2534  // -> use recv_channel?
2535 }
2536 
2537 
2546 static void
2548  const struct GNUNET_PeerIdentity *peer)
2549 {
2550  struct Sub *sub = cls;
2551 
2552  CustomPeerMap_put (sub->pull_map, peer);
2553 }
2554 
2555 
2565 static void
2567  const struct GNUNET_PeerIdentity *peer)
2568 {
2569  struct Sub *sub = cls;
2570  int inserted;
2571 
2572  inserted = insert_in_view (sub, peer);
2573  if (GNUNET_OK == inserted)
2574  {
2575  clients_notify_stream_peer (sub, 1, peer);
2576  }
2577 }
2578 
2579 
2587 static void
2589  const struct GNUNET_PeerIdentity *peer)
2590 {
2591  struct Sub *sub = cls;
2592 
2594  "Updating samplers with peer %s from insert_in_sampler()\n",
2595  GNUNET_i2s (peer));
2596  RPS_sampler_update (sub->sampler, peer);
2597  if (0 < RPS_sampler_count_id (sub->sampler, peer))
2598  {
2599  /* Make sure we 'know' about this peer */
2600  (void) issue_peer_online_check (sub, peer);
2601  /* Establish a channel towards that peer to indicate we are going to send
2602  * messages to it */
2603  //indicate_sending_intention (peer);
2604  }
2605  if (sub == msub)
2606  {
2607  GNUNET_STATISTICS_update (stats,
2608  "# observed peers in gossip",
2609  1,
2610  GNUNET_NO);
2611  }
2612 #ifdef TO_FILE
2613  sub->num_observed_peers++;
2615  (sub->observed_unique_peers,
2616  peer,
2617  NULL,
2619  uint32_t num_observed_unique_peers =
2621  GNUNET_STATISTICS_set (stats,
2622  "# unique peers in gossip",
2623  num_observed_unique_peers,
2624  GNUNET_NO);
2625 #ifdef TO_FILE_FULL
2626  to_file (sub->file_name_observed_log,
2627  "%" PRIu32 " %" PRIu32 " %f\n",
2628  sub->num_observed_peers,
2629  num_observed_unique_peers,
2630  1.0*num_observed_unique_peers/sub->num_observed_peers)
2631 #endif /* TO_FILE_FULL */
2632 #endif /* TO_FILE */
2633 }
2634 
2635 
2646 static void
2647 got_peer (struct Sub *sub,
2648  const struct GNUNET_PeerIdentity *peer)
2649 {
2650  /* If we did not know this peer already, insert it into sampler and view */
2651  if (GNUNET_YES == issue_peer_online_check (sub, peer))
2652  {
2654  &insert_in_sampler, sub);
2656  &insert_in_view_op, sub);
2657  }
2658  if (sub == msub)
2659  {
2660  GNUNET_STATISTICS_update (stats,
2661  "# learnd peers",
2662  1,
2663  GNUNET_NO);
2664  }
2665 }
2666 
2667 
2675 static int
2677 {
2678  /* struct GNUNET_CADET_Channel *channel; */
2679  if (GNUNET_NO == check_peer_known (peer_ctx->sub->peer_map,
2680  &peer_ctx->peer_id))
2681  {
2682  return GNUNET_NO;
2683  }
2684  if (GNUNET_YES == check_sending_channel_exists (peer_ctx))
2685  {
2686  if ( (0 < RPS_sampler_count_id (peer_ctx->sub->sampler,
2687  &peer_ctx->peer_id)) ||
2688  (GNUNET_YES == View_contains_peer (peer_ctx->sub->view,
2689  &peer_ctx->peer_id)) ||
2691  &peer_ctx->peer_id)) ||
2693  &peer_ctx->peer_id)) ||
2694  (GNUNET_YES == check_peer_flag (peer_ctx->sub->peer_map,
2695  &peer_ctx->peer_id,
2697  { /* If we want to keep the connection to peer open */
2698  return GNUNET_YES;
2699  }
2700  return GNUNET_NO;
2701  }
2702  return GNUNET_NO;
2703 }
2704 
2705 
2713 static void
2714 remove_peer (struct Sub *sub,
2715  const struct GNUNET_PeerIdentity *peer)
2716 {
2717  (void) View_remove_peer (sub->view,
2718  peer);
2720  peer);
2722  peer);
2724  peer);
2725  /* We want to destroy the peer now.
2726  * Sometimes, it just seems that it's already been removed from the peer_map,
2727  * so check the peer_map first. */
2728  if (GNUNET_YES == check_peer_known (sub->peer_map,
2729  peer))
2730  {
2732  peer));
2733  }
2734 }
2735 
2736 
2745 static void
2746 clean_peer (struct Sub *sub,
2747  const struct GNUNET_PeerIdentity *peer)
2748 {
2750  peer)))
2751  {
2753  "Going to remove send channel to peer %s\n",
2754  GNUNET_i2s (peer));
2755  #if ENABLE_MALICIOUS
2756  if (0 != GNUNET_memcmp (&attacked_peer,
2757  peer))
2759  peer));
2760  #else /* ENABLE_MALICIOUS */
2762  peer));
2763  #endif /* ENABLE_MALICIOUS */
2764  }
2765 
2767  peer))
2768  {
2769  /* Peer was already removed by callback on destroyed channel */
2771  "Peer was removed from our knowledge during cleanup\n");
2772  return;
2773  }
2774 
2776  peer))) &&
2777  (GNUNET_NO == View_contains_peer (sub->view, peer)) &&
2778  (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2779  (GNUNET_NO == CustomPeerMap_contains_peer (sub->push_map, peer)) &&
2780  (0 == RPS_sampler_count_id (sub->sampler, peer)) &&
2781  (GNUNET_YES == check_removable (get_peer_ctx (sub->peer_map, peer))) )
2782  { /* We can safely remove this peer */
2784  "Going to remove peer %s\n",
2785  GNUNET_i2s (peer));
2786  remove_peer (sub, peer);
2787  return;
2788  }
2789 }
2790 
2791 
2803 static void
2805  const struct GNUNET_CADET_Channel *channel)
2806 {
2807  struct ChannelCtx *channel_ctx = cls;
2808  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
2809  (void) channel;
2810 
2811  channel_ctx->channel = NULL;
2812  remove_channel_ctx (channel_ctx);
2813  if (NULL != peer_ctx &&
2814  peer_ctx->send_channel_ctx == channel_ctx &&
2816  {
2817  remove_peer (peer_ctx->sub, &peer_ctx->peer_id);
2818  }
2819 }
2820 
2821 /***********************************************************************
2822  * /Util functions
2823 ***********************************************************************/
2824 
2825 
2826 
2827 /***********************************************************************
2828  * Sub
2829 ***********************************************************************/
2830 
2841 struct Sub *
2843  uint32_t sampler_size,
2845 {
2846  struct Sub *sub;
2847 
2848  sub = GNUNET_new (struct Sub);
2849 
2850  /* With the hash generated from the secret value this service only connects
2851  * to rps instances that share the value */
2852  struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
2853  GNUNET_MQ_hd_fixed_size (peer_check,
2855  struct GNUNET_MessageHeader,
2856  NULL),
2857  GNUNET_MQ_hd_fixed_size (peer_push,
2859  struct GNUNET_MessageHeader,
2860  NULL),
2861  GNUNET_MQ_hd_fixed_size (peer_pull_request,
2863  struct GNUNET_MessageHeader,
2864  NULL),
2865  GNUNET_MQ_hd_var_size (peer_pull_reply,
2868  NULL),
2870  };
2871  sub->hash = *hash;
2872  sub->cadet_port =
2873  GNUNET_CADET_open_port (cadet_handle,
2874  &sub->hash,
2875  &handle_inbound_channel, /* Connect handler */
2876  sub, /* cls */
2877  NULL, /* WindowSize handler */
2878  &cleanup_destroyed_channel, /* Disconnect handler */
2879  cadet_handlers);
2880  if (NULL == sub->cadet_port)
2881  {
2883  "Cadet port `%s' is already in use.\n",
2885  GNUNET_assert (0);
2886  }
2887 
2888  /* Set up general data structure to keep track about peers */
2890  if (GNUNET_OK !=
2892  "rps",
2893  "FILENAME_VALID_PEERS",
2894  &sub->filename_valid_peers))
2895  {
2897  "rps",
2898  "FILENAME_VALID_PEERS");
2899  }
2900  if (0 != strncmp ("DISABLE", sub->filename_valid_peers, 7))
2901  {
2902  char *tmp_filename_valid_peers;
2903  char str_hash[105];
2904 
2905  GNUNET_snprintf (str_hash,
2906  sizeof (str_hash),
2907  GNUNET_h2s_full (hash));
2908  tmp_filename_valid_peers = sub->filename_valid_peers;
2910  "%s%s",
2911  tmp_filename_valid_peers,
2912  str_hash);
2913  GNUNET_free (tmp_filename_valid_peers);
2914  }
2916 
2917  /* Set up the sampler */
2918  sub->sampler_size_est_min = sampler_size;
2919  sub->sampler_size_est_need = sampler_size;;
2920  LOG (GNUNET_ERROR_TYPE_DEBUG, "MINSIZE is %u\n", sub->sampler_size_est_min);
2921  GNUNET_assert (0 != round_interval.rel_value_us);
2922  sub->round_interval = round_interval;
2923  sub->sampler = RPS_sampler_init (sampler_size,
2924  round_interval);
2925 
2926  /* Logging of internals */
2927 #ifdef TO_FILE_FULL
2928  sub->file_name_view_log = store_prefix_file_name (&own_identity, "view");
2929 #endif /* TO_FILE_FULL */
2930 #ifdef TO_FILE
2931 #ifdef TO_FILE_FULL
2932  sub->file_name_observed_log = store_prefix_file_name (&own_identity,
2933  "observed");
2934 #endif /* TO_FILE_FULL */
2935  sub->num_observed_peers = 0;
2937  GNUNET_NO);
2938 #endif /* TO_FILE */
2939 
2940  /* Set up data structures for gossip */
2941  sub->push_map = CustomPeerMap_create (4);
2942  sub->pull_map = CustomPeerMap_create (4);
2943  sub->view_size_est_min = sampler_size;;
2944  sub->view = View_create (sub->view_size_est_min);
2945  if (sub == msub)
2946  {
2947  GNUNET_STATISTICS_set (stats,
2948  "view size aim",
2949  sub->view_size_est_min,
2950  GNUNET_NO);
2951  }
2952 
2953  /* Start executing rounds */
2955 
2956  return sub;
2957 }
2958 
2959 
2960 #ifdef TO_FILE
2961 
2969 static void
2970 write_histogram_to_file (const uint32_t hist_array[],
2971  const char *file_name)
2972 {
2973  char collect_str[SIZE_DUMP_FILE + 1] = "";
2974  char *recv_str_iter;
2975  char *file_name_full;
2976 
2977  recv_str_iter = collect_str;
2978  file_name_full = store_prefix_file_name (&own_identity,
2979  file_name);
2980  for (uint32_t i = 0; i < HISTOGRAM_FILE_SLOTS; i++)
2981  {
2982  char collect_str_tmp[8];
2983 
2984  GNUNET_snprintf (collect_str_tmp,
2985  sizeof (collect_str_tmp),
2986  "%" PRIu32 "\n",
2987  hist_array[i]);
2988  recv_str_iter = stpncpy (recv_str_iter,
2989  collect_str_tmp,
2990  6);
2991  }
2992  (void) stpcpy (recv_str_iter,
2993  "\n");
2995  "Writing push stats to disk\n");
2996  to_file_w_len (file_name_full,
2998  collect_str);
2999  GNUNET_free (file_name_full);
3000 }
3001 #endif /* TO_FILE */
3002 
3003 
3009 static void
3010 destroy_sub (struct Sub *sub)
3011 {
3012  GNUNET_assert (NULL != sub);
3013  GNUNET_assert (NULL != sub->do_round_task);
3015  sub->do_round_task = NULL;
3016 
3017  /* Disconnect from cadet */
3019  sub->cadet_port= NULL;
3020 
3021  /* Clean up data structures for peers */
3023  sub->sampler = NULL;
3024  View_destroy (sub->view);
3025  sub->view = NULL;
3027  sub->push_map = NULL;
3029  sub->pull_map = NULL;
3030  peers_terminate (sub);
3031 
3032  /* Free leftover data structures */
3033 #ifdef TO_FILE_FULL
3034  GNUNET_free (sub->file_name_view_log);
3035  sub->file_name_view_log = NULL;
3036 #endif /* TO_FILE_FULL */
3037 #ifdef TO_FILE
3038 #ifdef TO_FILE_FULL
3039  GNUNET_free (sub->file_name_observed_log);
3040  sub->file_name_observed_log = NULL;
3041 #endif /* TO_FILE_FULL */
3042 
3043  /* Write push frequencies to disk */
3045  "push_recv");
3046 
3047  /* Write push deltas to disk */
3049  "push_delta");
3050 
3051  /* Write pull delays to disk */
3053  "pull_delays");
3054 
3056  sub->observed_unique_peers = NULL;
3057 #endif /* TO_FILE */
3058 
3059  GNUNET_free (sub);
3060 }
3061 
3062 
3063 /***********************************************************************
3064  * /Sub
3065 ***********************************************************************/
3066 
3067 
3068 /***********************************************************************
3069  * Core handlers
3070 ***********************************************************************/
3071 
3078 void
3080  const struct GNUNET_PeerIdentity *my_identity)
3081 {
3082  (void) cls;
3083  (void) my_identity;
3084 
3085  map_single_hop = GNUNET_CONTAINER_multipeermap_create (4, GNUNET_NO);
3086 }
3087 
3088 
3097 void *
3099  const struct GNUNET_PeerIdentity *peer,
3100  struct GNUNET_MQ_Handle *mq)
3101 {
3102  (void) cls;
3103  (void) mq;
3104 
3106  GNUNET_CONTAINER_multipeermap_put (map_single_hop,
3107  peer,
3108  NULL,
3110  return NULL;
3111 }
3112 
3113 
3122 void
3124  const struct GNUNET_PeerIdentity *peer,
3125  void *peer_cls)
3126 {
3127  (void) cls;
3128  (void) peer_cls;
3129 
3130  GNUNET_CONTAINER_multipeermap_remove_all (map_single_hop, peer);
3131 }
3132 
3133 /***********************************************************************
3134  * /Core handlers
3135 ***********************************************************************/
3136 
3137 
3143 static void
3145 {
3146  GNUNET_assert (NULL != cli_ctx);
3147  GNUNET_CONTAINER_DLL_remove (cli_ctx_head,
3148  cli_ctx_tail,
3149  cli_ctx);
3150  if (NULL != cli_ctx->sub)
3151  {
3152  destroy_sub (cli_ctx->sub);
3153  cli_ctx->sub = NULL;
3154  }
3155  GNUNET_free (cli_ctx);
3156 }
3157 
3158 
3166 static void
3167 adapt_sizes (struct Sub *sub, double logestimate, double std_dev)
3168 {
3169  double estimate;
3170  //double scale; // TODO this might go gloabal/config
3171 
3173  "Received a ns estimate - logest: %f, std_dev: %f (old_size: %u)\n",
3174  logestimate, std_dev, RPS_sampler_get_size (sub->sampler));
3175  //scale = .01;
3176  estimate = GNUNET_NSE_log_estimate_to_n (logestimate);
3177  // GNUNET_NSE_log_estimate_to_n (logestimate);
3178  estimate = pow (estimate, 1.0 / 3);
3179  // TODO add if std_dev is a number
3180  // estimate += (std_dev * scale);
3181  if (sub->view_size_est_min < ceil (estimate))
3182  {
3183  LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing estimate to %f\n", estimate);
3184  sub->sampler_size_est_need = estimate;
3185  sub->view_size_est_need = estimate;
3186  } else
3187  {
3188  LOG (GNUNET_ERROR_TYPE_DEBUG, "Not using estimate %f\n", estimate);
3189  //sub->sampler_size_est_need = sub->view_size_est_min;
3191  }
3192  if (sub == msub)
3193  {
3194  GNUNET_STATISTICS_set (stats,
3195  "view size aim",
3196  sub->view_size_est_need,
3197  GNUNET_NO);
3198  }
3199 
3200  /* If the NSE has changed adapt the lists accordingly */
3203 }
3204 
3205 
3219 static void
3221  struct GNUNET_TIME_Absolute timestamp,
3222  double logestimate, double std_dev)
3223 {
3224  (void) cls;
3225  (void) timestamp;
3226  struct ClientContext *cli_ctx_iter;
3227 
3228  adapt_sizes (msub, logestimate, std_dev);
3229  for (cli_ctx_iter = cli_ctx_head;
3230  NULL != cli_ctx_iter;
3231  cli_ctx_iter = cli_ctx_iter->next)
3232  {
3233  if (NULL != cli_ctx_iter->sub)
3234  {
3235  adapt_sizes (cli_ctx_iter->sub, logestimate, std_dev);
3236  }
3237  }
3238 }
3239 
3240 
3250 static int
3251 check_client_seed (void *cls, const struct GNUNET_RPS_CS_SeedMessage *msg)
3252 {
3253  struct ClientContext *cli_ctx = cls;
3254  uint16_t msize = ntohs (msg->header.size);
3255  uint32_t num_peers = ntohl (msg->num_peers);
3256 
3257  msize -= sizeof (struct GNUNET_RPS_CS_SeedMessage);
3258  if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
3259  (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
3260  {
3262  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3263  ntohl (msg->num_peers),
3264  (msize / sizeof (struct GNUNET_PeerIdentity)));
3265  GNUNET_break (0);
3267  return GNUNET_SYSERR;
3268  }
3269  return GNUNET_OK;
3270 }
3271 
3272 
3279 static void
3281  const struct GNUNET_RPS_CS_SeedMessage *msg)
3282 {
3283  struct ClientContext *cli_ctx = cls;
3284  struct GNUNET_PeerIdentity *peers;
3285  uint32_t num_peers;
3286  uint32_t i;
3287 
3288  num_peers = ntohl (msg->num_peers);
3289  peers = (struct GNUNET_PeerIdentity *) &msg[1];
3290 
3292  "Client seeded peers:\n");
3293  print_peer_list (peers, num_peers);
3294 
3295  for (i = 0; i < num_peers; i++)
3296  {
3298  "Updating samplers with seed %" PRIu32 ": %s\n",
3299  i,
3300  GNUNET_i2s (&peers[i]));
3301 
3302  if (NULL != msub) got_peer (msub, &peers[i]); /* Condition needed? */
3303  if (NULL != cli_ctx->sub) got_peer (cli_ctx->sub, &peers[i]);
3304  }
3306 }
3307 
3308 
3316 static void
3318  const struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg)
3319 {
3320  struct ClientContext *cli_ctx = cls;
3321  uint64_t num_updates;
3322 
3323  num_updates = ntohl (msg->num_updates);
3324 
3326  "Client requested %" PRIu64 " updates of view.\n",
3327  num_updates);
3328 
3329  GNUNET_assert (NULL != cli_ctx);
3330  cli_ctx->view_updates_left = num_updates;
3331  send_view (cli_ctx, NULL, 0);
3333 }
3334 
3335 
3342 static void
3344  const struct GNUNET_MessageHeader *msg)
3345 {
3346  struct ClientContext *cli_ctx = cls;
3347  (void) msg;
3348 
3350  "Client does not want to receive updates of view any more.\n");
3351 
3352  GNUNET_assert (NULL != cli_ctx);
3353  cli_ctx->view_updates_left = 0;
3355  if (GNUNET_YES == cli_ctx->stream_update)
3356  {
3357  destroy_cli_ctx (cli_ctx);
3358  }
3359 }
3360 
3361 
3368 static void
3370  const struct GNUNET_RPS_CS_DEBUG_StreamRequest *msg)
3371 {
3372  struct ClientContext *cli_ctx = cls;
3373  (void) msg;
3374 
3376  "Client requested peers from biased stream.\n");
3377  cli_ctx->stream_update = GNUNET_YES;
3378 
3379  GNUNET_assert (NULL != cli_ctx);
3381 }
3382 
3383 
3390 static void
3392  const struct GNUNET_MessageHeader *msg)
3393 {
3394  struct ClientContext *cli_ctx = cls;
3395  (void) msg;
3396 
3398  "Client canceled receiving peers from biased stream.\n");
3399  cli_ctx->stream_update = GNUNET_NO;
3400 
3401  GNUNET_assert (NULL != cli_ctx);
3403 }
3404 
3405 
3412 static void
3414  const struct GNUNET_RPS_CS_SubStartMessage *msg)
3415 {
3416  struct ClientContext *cli_ctx = cls;
3417 
3418  LOG (GNUNET_ERROR_TYPE_DEBUG, "Client requested start of a new sub.\n");
3419  if (NULL != cli_ctx->sub &&
3420  0 != memcmp (&cli_ctx->sub->hash,
3421  &msg->hash,
3422  sizeof (struct GNUNET_HashCode)))
3423  {
3424  LOG (GNUNET_ERROR_TYPE_WARNING, "Already have a Sub with different share for this client. Remove old one, add new.\n");
3425  destroy_sub (cli_ctx->sub);
3426  cli_ctx->sub = NULL;
3427  }
3428  cli_ctx->sub = new_sub (&msg->hash,
3429  msub->sampler_size_est_min, // TODO make api input?
3432 }
3433 
3434 
3441 static void
3443  const struct GNUNET_RPS_CS_SubStopMessage *msg)
3444 {
3445  struct ClientContext *cli_ctx = cls;
3446 
3447  GNUNET_assert (NULL != cli_ctx->sub);
3448  if (0 != memcmp (&cli_ctx->sub->hash, &msg->hash, sizeof (struct GNUNET_HashCode)))
3449  {
3450  LOG (GNUNET_ERROR_TYPE_WARNING, "Share of current sub and request differ!\n");
3451  }
3452  destroy_sub (cli_ctx->sub);
3453  cli_ctx->sub = NULL;
3455 }
3456 
3457 
3467 static void
3469  const struct GNUNET_MessageHeader *msg)
3470 {
3471  const struct ChannelCtx *channel_ctx = cls;
3472  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3473  (void) msg;
3474 
3476  "Received CHECK_LIVE (%s)\n", GNUNET_i2s (peer));
3477  if (channel_ctx->peer_ctx->sub == msub)
3478  {
3479  GNUNET_STATISTICS_update (stats,
3480  "# pending online checks",
3481  -1,
3482  GNUNET_NO);
3483  }
3484 
3485  GNUNET_CADET_receive_done (channel_ctx->channel);
3486 }
3487 
3488 
3498 static void
3499 handle_peer_push (void *cls,
3500  const struct GNUNET_MessageHeader *msg)
3501 {
3502  const struct ChannelCtx *channel_ctx = cls;
3503  const struct GNUNET_PeerIdentity *peer = &channel_ctx->peer_ctx->peer_id;
3504  (void) msg;
3505 
3506  // (check the proof of work (?))
3507 
3509  "Received PUSH (%s)\n",
3510  GNUNET_i2s (peer));
3511  if (channel_ctx->peer_ctx->sub == msub)
3512  {
3513  GNUNET_STATISTICS_update(stats, "# push message received", 1, GNUNET_NO);
3514  if (NULL != map_single_hop &&
3516  peer))
3517  {
3518  GNUNET_STATISTICS_update (stats,
3519  "# push message received (multi-hop peer)",
3520  1,
3521  GNUNET_NO);
3522  }
3523  }
3524 
3525  #if ENABLE_MALICIOUS
3526  struct AttackedPeer *tmp_att_peer;
3527 
3528  if ( (1 == mal_type) ||
3529  (3 == mal_type) )
3530  { /* Try to maximise representation */
3531  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3532  tmp_att_peer->peer_id = *peer;
3533  if (NULL == att_peer_set)
3534  att_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
3536  peer))
3537  {
3538  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3539  att_peers_tail,
3540  tmp_att_peer);
3541  add_peer_array_to_set (peer, 1, att_peer_set);
3542  }
3543  else
3544  {
3545  GNUNET_free (tmp_att_peer);
3546  }
3547  }
3548 
3549 
3550  else if (2 == mal_type)
3551  {
3552  /* We attack one single well-known peer - simply ignore */
3553  }
3554  #endif /* ENABLE_MALICIOUS */
3555 
3556  /* Add the sending peer to the push_map */
3557  CustomPeerMap_put (channel_ctx->peer_ctx->sub->push_map, peer);
3558 
3560  &channel_ctx->peer_ctx->peer_id));
3561  GNUNET_CADET_receive_done (channel_ctx->channel);
3562 }
3563 
3564 
3573 static void
3575  const struct GNUNET_MessageHeader *msg)
3576 {
3577  const struct ChannelCtx *channel_ctx = cls;
3578  struct PeerContext *peer_ctx = channel_ctx->peer_ctx;
3579  const struct GNUNET_PeerIdentity *peer = &peer_ctx->peer_id;
3580  const struct GNUNET_PeerIdentity *view_array;
3581  (void) msg;
3582 
3583  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REQUEST (%s)\n", GNUNET_i2s (peer));
3584  if (peer_ctx->sub == msub)
3585  {
3587  "# pull request message received",
3588  1,
3589  GNUNET_NO);
3590  if (NULL != map_single_hop &&
3592  &peer_ctx->peer_id))
3593  {
3594  GNUNET_STATISTICS_update (stats,
3595  "# pull request message received (multi-hop peer)",
3596  1,
3597  GNUNET_NO);
3598  }
3599  }
3600 
3601  #if ENABLE_MALICIOUS
3602  if (1 == mal_type
3603  || 3 == mal_type)
3604  { /* Try to maximise representation */
3605  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3606  }
3607 
3608  else if (2 == mal_type)
3609  { /* Try to partition network */
3610  if (0 == GNUNET_memcmp (&attacked_peer, peer))
3611  {
3612  send_pull_reply (peer_ctx, mal_peers, num_mal_peers);
3613  }
3614  }
3615  #endif /* ENABLE_MALICIOUS */
3616 
3618  &channel_ctx->peer_ctx->peer_id));
3619  GNUNET_CADET_receive_done (channel_ctx->channel);
3620  view_array = View_get_as_array (channel_ctx->peer_ctx->sub->view);
3621  send_pull_reply (peer_ctx,
3622  view_array,
3623  View_size (channel_ctx->peer_ctx->sub->view));
3624 }
3625 
3626 
3634 static int
3636  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3637 {
3638  struct ChannelCtx *channel_ctx = cls;
3639  struct PeerContext *sender_ctx = channel_ctx->peer_ctx;
3640 
3641  if (sizeof (struct GNUNET_RPS_P2P_PullReplyMessage) > ntohs (msg->header.size))
3642  {
3643  GNUNET_break_op (0);
3644  return GNUNET_SYSERR;
3645  }
3646 
3647  if ((ntohs (msg->header.size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
3648  sizeof (struct GNUNET_PeerIdentity) != ntohl (msg->num_peers))
3649  {
3651  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3652  ntohl (msg->num_peers),
3653  (ntohs (msg->header.size) - sizeof (struct GNUNET_RPS_P2P_PullReplyMessage)) /
3654  sizeof (struct GNUNET_PeerIdentity));
3655  GNUNET_break_op (0);
3656  return GNUNET_SYSERR;
3657  }
3658 
3659  if (GNUNET_YES != check_peer_flag (sender_ctx->sub->peer_map,
3660  &sender_ctx->peer_id,
3662  {
3664  "Received a pull reply from a peer (%s) we didn't request one from!\n",
3665  GNUNET_i2s (&sender_ctx->peer_id));
3666  if (sender_ctx->sub == msub)
3667  {
3668  GNUNET_STATISTICS_update (stats,
3669  "# unrequested pull replies",
3670  1,
3671  GNUNET_NO);
3672  }
3673  }
3674  return GNUNET_OK;
3675 }
3676 
3677 
3684 static void
3686  const struct GNUNET_RPS_P2P_PullReplyMessage *msg)
3687 {
3688  const struct ChannelCtx *channel_ctx = cls;
3689  const struct GNUNET_PeerIdentity *sender = &channel_ctx->peer_ctx->peer_id;
3690  const struct GNUNET_PeerIdentity *peers;
3691  struct Sub *sub = channel_ctx->peer_ctx->sub;
3692  uint32_t i;
3693 #if ENABLE_MALICIOUS
3694  struct AttackedPeer *tmp_att_peer;
3695 #endif /* ENABLE_MALICIOUS */
3696 
3697  sub->pull_delays[sub->num_rounds - channel_ctx->peer_ctx->round_pull_req]++;
3698  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PULL REPLY (%s)\n", GNUNET_i2s (sender));
3699  if (channel_ctx->peer_ctx->sub == msub)
3700  {
3701  GNUNET_STATISTICS_update (stats,
3702  "# pull reply messages received",
3703  1,
3704  GNUNET_NO);
3705  if (NULL != map_single_hop &&
3707  &channel_ctx->peer_ctx->peer_id))
3708  {
3709  GNUNET_STATISTICS_update (stats,
3710  "# pull reply messages received (multi-hop peer)",
3711  1,
3712  GNUNET_NO);
3713  }
3714  }
3715 
3716  #if ENABLE_MALICIOUS
3717  // We shouldn't even receive pull replies as we're not sending
3718  if (2 == mal_type)
3719  {
3720  }
3721  #endif /* ENABLE_MALICIOUS */
3722 
3723  /* Do actual logic */
3724  peers = (const struct GNUNET_PeerIdentity *) &msg[1];
3725 
3727  "PULL REPLY received, got following %u peers:\n",
3728  ntohl (msg->num_peers));
3729 
3730  for (i = 0; i < ntohl (msg->num_peers); i++)
3731  {
3733  "%u. %s\n",
3734  i,
3735  GNUNET_i2s (&peers[i]));
3736 
3737  #if ENABLE_MALICIOUS
3738  if ((NULL != att_peer_set) &&
3739  (1 == mal_type || 3 == mal_type))
3740  { /* Add attacked peer to local list */
3741  // TODO check if we sent a request and this was the first reply
3743  &peers[i])
3745  &peers[i]))
3746  {
3747  tmp_att_peer = GNUNET_new (struct AttackedPeer);
3748  tmp_att_peer->peer_id = peers[i];
3749  GNUNET_CONTAINER_DLL_insert (att_peers_head,
3750  att_peers_tail,
3751  tmp_att_peer);
3752  add_peer_array_to_set (&peers[i], 1, att_peer_set);
3753  }
3754  continue;
3755  }
3756  #endif /* ENABLE_MALICIOUS */
3757  /* Make sure we 'know' about this peer */
3758  (void) insert_peer (channel_ctx->peer_ctx->sub,
3759  &peers[i]);
3760 
3761  if (GNUNET_YES == check_peer_valid (channel_ctx->peer_ctx->sub->valid_peers,
3762  &peers[i]))
3763  {
3764  CustomPeerMap_put (channel_ctx->peer_ctx->sub->pull_map,
3765  &peers[i]);
3766  }
3767  else
3768  {
3769  schedule_operation (channel_ctx->peer_ctx,
3771  channel_ctx->peer_ctx->sub); /* cls */
3772  (void) issue_peer_online_check (channel_ctx->peer_ctx->sub,
3773  &peers[i]);
3774  }
3775  }
3776 
3778  sender),
3780  clean_peer (channel_ctx->peer_ctx->sub,
3781  sender);
3782 
3784  sender));
3785  GNUNET_CADET_receive_done (channel_ctx->channel);
3786 }
3787 
3788 
3799 static struct GNUNET_TIME_Relative
3801  unsigned int spread)
3802 {
3803  struct GNUNET_TIME_Relative half_interval;
3804  struct GNUNET_TIME_Relative ret;
3805  unsigned int rand_delay;
3806  unsigned int max_rand_delay;
3807 
3808  if (0 == spread)
3809  {
3811  "Not accepting spread of 0\n");
3812  GNUNET_break (0);
3813  GNUNET_assert (0);
3814  }
3815  GNUNET_assert (0 != mean.rel_value_us);
3816 
3817  /* Compute random time value between spread * mean and spread * mean */
3818  half_interval = GNUNET_TIME_relative_divide (mean, spread);
3819 
3820  max_rand_delay = GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us / mean.rel_value_us * (2/spread);
3825  rand_delay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_rand_delay);
3826  ret = GNUNET_TIME_relative_saturating_multiply (mean, rand_delay);
3827  ret = GNUNET_TIME_relative_divide (ret, max_rand_delay);
3828  ret = GNUNET_TIME_relative_add (ret, half_interval);
3829 
3830  if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == ret.rel_value_us)
3832  "Returning FOREVER_REL\n");
3833 
3834  return ret;
3835 }
3836 
3837 
3843 static void
3844 send_pull_request (struct PeerContext *peer_ctx)
3845 {
3846  struct GNUNET_MQ_Envelope *ev;
3847 
3849  &peer_ctx->peer_id,
3851  SET_PEER_FLAG (peer_ctx,
3853  peer_ctx->round_pull_req = peer_ctx->sub->num_rounds;
3854 
3856  "Going to send PULL REQUEST to peer %s.\n",
3857  GNUNET_i2s (&peer_ctx->peer_id));
3858 
3860  send_message (peer_ctx,
3861  ev,
3862  "PULL REQUEST");
3863  if (peer_ctx->sub)
3864  {
3865  GNUNET_STATISTICS_update (stats,
3866  "# pull request send issued",
3867  1,
3868  GNUNET_NO);
3869  if (NULL != map_single_hop &&
3871  &peer_ctx->peer_id))
3872  {
3873  GNUNET_STATISTICS_update (stats,
3874  "# pull request send issued (multi-hop peer)",
3875  1,
3876  GNUNET_NO);
3877  }
3878  }
3879 }
3880 
3881 
3887 static void
3888 send_push (struct PeerContext *peer_ctx)
3889 {
3890  struct GNUNET_MQ_Envelope *ev;
3891 
3893  "Going to send PUSH to peer %s.\n",
3894  GNUNET_i2s (&peer_ctx->peer_id));
3895 
3897  send_message (peer_ctx, ev, "PUSH");
3898  if (peer_ctx->sub)
3899  {
3900  GNUNET_STATISTICS_update (stats,
3901  "# push send issued",
3902  1,
3903  GNUNET_NO);
3904  if (NULL != map_single_hop &&
3906  &peer_ctx->peer_id))
3907  {
3908  GNUNET_STATISTICS_update (stats,
3909  "# push send issued (multi-hop peer)",
3910  1,
3911  GNUNET_NO);
3912  }
3913  }
3914 }
3915 
3916 
3917 #if ENABLE_MALICIOUS
3918 
3919 
3928 static int
3929 check_client_act_malicious (void *cls,
3930  const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
3931 {
3932  struct ClientContext *cli_ctx = cls;
3933  uint16_t msize = ntohs (msg->header.size);
3934  uint32_t num_peers = ntohl (msg->num_peers);
3935 
3936  msize -= sizeof (struct GNUNET_RPS_CS_ActMaliciousMessage);
3937  if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
3938  (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
3939  {
3941  "message says it sends %" PRIu32 " peers, have space for %lu peers\n",
3942  ntohl (msg->num_peers),
3943  (msize / sizeof (struct GNUNET_PeerIdentity)));
3944  GNUNET_break (0);
3946  return GNUNET_SYSERR;
3947  }
3948  return GNUNET_OK;
3949 }
3950 
3958 static void
3959 handle_client_act_malicious (void *cls,
3960  const struct GNUNET_RPS_CS_ActMaliciousMessage *msg)
3961 {
3962  struct ClientContext *cli_ctx = cls;
3963  struct GNUNET_PeerIdentity *peers;
3964  uint32_t num_mal_peers_sent;
3965  uint32_t num_mal_peers_old;
3966  struct Sub *sub = cli_ctx->sub;
3967 
3968  if (NULL == sub) sub = msub;
3969  /* Do actual logic */
3970  peers = (struct GNUNET_PeerIdentity *) &msg[1];
3971  mal_type = ntohl (msg->type);
3972  if (NULL == mal_peer_set)
3973  mal_peer_set = GNUNET_CONTAINER_multipeermap_create (1, GNUNET_NO);
3974 
3976  "Now acting malicious type %" PRIu32 ", got %" PRIu32 " peers.\n",
3977  mal_type,
3978  ntohl (msg->num_peers));
3979 
3980  if (1 == mal_type)
3981  { /* Try to maximise representation */
3982  /* Add other malicious peers to those we already know */
3983 
3984  num_mal_peers_sent = ntohl (msg->num_peers);
3985  num_mal_peers_old = num_mal_peers;
3986  GNUNET_array_grow (mal_peers,
3987  num_mal_peers,
3988  num_mal_peers + num_mal_peers_sent);
3989  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
3990  peers,
3991  num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
3992 
3993  /* Add all mal peers to mal_peer_set */
3994  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
3995  num_mal_peers_sent,
3996  mal_peer_set);
3997 
3998  /* Substitute do_round () with do_mal_round () */
3999  GNUNET_assert (NULL != sub->do_round_task);
4002  }
4003 
4004  else if ( (2 == mal_type) ||
4005  (3 == mal_type) )
4006  { /* Try to partition the network */
4007  /* Add other malicious peers to those we already know */
4008 
4009  num_mal_peers_sent = ntohl (msg->num_peers) - 1;
4010  num_mal_peers_old = num_mal_peers;
4011  GNUNET_assert (GNUNET_MAX_MALLOC_CHECKED > num_mal_peers_sent);
4012  GNUNET_array_grow (mal_peers,
4013  num_mal_peers,
4014  num_mal_peers + num_mal_peers_sent);
4015  if (NULL != mal_peers &&
4016  0 != num_mal_peers)
4017  {
4018  GNUNET_memcpy (&mal_peers[num_mal_peers_old],
4019  peers,
4020  num_mal_peers_sent * sizeof (struct GNUNET_PeerIdentity));
4021 
4022  /* Add all mal peers to mal_peer_set */
4023  add_peer_array_to_set (&mal_peers[num_mal_peers_old],
4024  num_mal_peers_sent,
4025  mal_peer_set);
4026  }
4027 
4028  /* Store the one attacked peer */
4029  GNUNET_memcpy (&attacked_peer,
4030  &msg->attacked_peer,
4031  sizeof (struct GNUNET_PeerIdentity));
4032  /* Set the flag of the attacked peer to valid to avoid problems */
4033  if (GNUNET_NO == check_peer_known (sub->peer_map, &attacked_peer))
4034  {
4035  (void) issue_peer_online_check (sub, &attacked_peer);
4036  }
4037 
4039  "Attacked peer is %s\n",
4040  GNUNET_i2s (&attacked_peer));
4041 
4042  /* Substitute do_round () with do_mal_round () */
4043  if (NULL != sub->do_round_task)
4044  {
4045  /* Probably in shutdown */
4048  }
4049  }
4050  else if (0 == mal_type)
4051  { /* Stop acting malicious */
4052  GNUNET_array_grow (mal_peers, num_mal_peers, 0);
4053 
4054  /* Substitute do_mal_round () with do_round () */
4057  }
4058  else
4059  {
4060  GNUNET_break (0);
4062  }
4064 }
4065 
4066 
4074 static void
4075 do_mal_round (void *cls)
4076 {
4077  uint32_t num_pushes;
4078  uint32_t i;
4079  struct GNUNET_TIME_Relative time_next_round;
4080  struct AttackedPeer *tmp_att_peer;
4081  struct Sub *sub = cls;
4082 
4084  "Going to execute next round maliciously type %" PRIu32 ".\n",
4085  mal_type);
4086  sub->do_round_task = NULL;
4087  GNUNET_assert (mal_type <= 3);
4088  /* Do malicious actions */
4089  if (1 == mal_type)
4090  { /* Try to maximise representation */
4091 
4092  /* The maximum of pushes we're going to send this round */
4093  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit,
4094  num_attacked_peers),
4096 
4098  "Going to send %" PRIu32 " pushes\n",
4099  num_pushes);
4100 
4101  /* Send PUSHes to attacked peers */
4102  for (i = 0 ; i < num_pushes ; i++)
4103  {
4104  if (att_peers_tail == att_peer_index)
4105  att_peer_index = att_peers_head;
4106  else
4107  att_peer_index = att_peer_index->next;
4108 
4109  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4110  }
4111 
4112  /* Send PULLs to some peers to learn about additional peers to attack */
4113  tmp_att_peer = att_peer_index;
4114  for (i = 0 ; i < num_pushes * alpha ; i++)
4115  {
4116  if (att_peers_tail == tmp_att_peer)
4117  tmp_att_peer = att_peers_head;
4118  else
4119  att_peer_index = tmp_att_peer->next;
4120 
4121  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4122  }
4123  }
4124 
4125 
4126  else if (2 == mal_type)
4127  {
4132  (void) issue_peer_online_check (sub, &attacked_peer);
4133  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4134  &attacked_peer,
4135  Peers_ONLINE))
4136  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4137  }
4138 
4139 
4140  if (3 == mal_type)
4141  { /* Combined attack */
4142 
4143  /* Send PUSH to attacked peers */
4144  if (GNUNET_YES == check_peer_known (sub->peer_map, &attacked_peer))
4145  {
4146  (void) issue_peer_online_check (sub, &attacked_peer);
4147  if (GNUNET_YES == check_peer_flag (sub->peer_map,
4148  &attacked_peer,
4149  Peers_ONLINE))
4150  {
4152  "Goding to send push to attacked peer (%s)\n",
4153  GNUNET_i2s (&attacked_peer));
4154  send_push (get_peer_ctx (sub->peer_map, &attacked_peer));
4155  }
4156  }
4157  (void) issue_peer_online_check (sub, &attacked_peer);
4158 
4159  /* The maximum of pushes we're going to send this round */
4160  num_pushes = GNUNET_MIN (GNUNET_MIN (push_limit - 1,
4161  num_attacked_peers),
4163 
4165  "Going to send %" PRIu32 " pushes\n",
4166  num_pushes);
4167 
4168  for (i = 0; i < num_pushes; i++)
4169  {
4170  if (att_peers_tail == att_peer_index)
4171  att_peer_index = att_peers_head;
4172  else
4173  att_peer_index = att_peer_index->next;
4174 
4175  send_push (get_peer_ctx (sub->peer_map, &att_peer_index->peer_id));
4176  }
4177 
4178  /* Send PULLs to some peers to learn about additional peers to attack */
4179  tmp_att_peer = att_peer_index;
4180  for (i = 0; i < num_pushes * alpha; i++)
4181  {
4182  if (att_peers_tail == tmp_att_peer)
4183  tmp_att_peer = att_peers_head;
4184  else
4185  att_peer_index = tmp_att_peer->next;
4186 
4187  send_pull_request (get_peer_ctx (sub->peer_map, &tmp_att_peer->peer_id));
4188  }
4189  }
4190 
4191  /* Schedule next round */
4192  time_next_round = compute_rand_delay (sub->round_interval, 2);
4193 
4194  GNUNET_assert (NULL == sub->do_round_task);
4195  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4196  &do_mal_round, sub);
4197  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4198 }
4199 #endif /* ENABLE_MALICIOUS */
4200 
4201 
4209 static void
4210 do_round (void *cls)
4211 {
4212  unsigned int i;
4213  const struct GNUNET_PeerIdentity *view_array;
4214  unsigned int *permut;
4215  unsigned int a_peers; /* Number of peers we send pushes to */
4216  unsigned int b_peers; /* Number of peers we send pull requests to */
4217  uint32_t first_border;
4218  uint32_t second_border;
4219  struct GNUNET_PeerIdentity peer;
4220  struct GNUNET_PeerIdentity *update_peer;
4221  struct Sub *sub = cls;
4222 
4223  sub->num_rounds++;
4225  "Going to execute next round.\n");
4226  if (sub == msub)
4227  {
4228  GNUNET_STATISTICS_update (stats, "# rounds", 1, GNUNET_NO);
4229  }
4230  sub->do_round_task = NULL;
4231 #ifdef TO_FILE_FULL
4232  to_file (sub->file_name_view_log,
4233  "___ new round ___");
4234 #endif /* TO_FILE_FULL */
4235  view_array = View_get_as_array (sub->view);
4236  for (i = 0; i < View_size (sub->view); i++)
4237  {
4239  "\t%s\n", GNUNET_i2s (&view_array[i]));
4240 #ifdef TO_FILE_FULL
4241  to_file (sub->file_name_view_log,
4242  "=%s\t(do round)",
4243  GNUNET_i2s_full (&view_array[i]));
4244 #endif /* TO_FILE_FULL */
4245  }
4246 
4247 
4248  /* Send pushes and pull requests */
4249  if (0 < View_size (sub->view))
4250  {
4252  View_size (sub->view));
4253 
4254  /* Send PUSHes */
4255  a_peers = ceil (alpha * View_size (sub->view));
4256 
4258  "Going to send pushes to %u (ceil (%f * %u)) peers.\n",
4259  a_peers, alpha, View_size (sub->view));
4260  for (i = 0; i < a_peers; i++)
4261  {
4262  peer = view_array[permut[i]];
4263  // FIXME if this fails schedule/loop this for later
4264  send_push (get_peer_ctx (sub->peer_map, &peer));
4265  }
4266 
4267  /* Send PULL requests */
4268  b_peers = ceil (beta * View_size (sub->view));
4269  first_border = a_peers;
4270  second_border = a_peers + b_peers;
4271  if (second_border > View_size (sub->view))
4272  {
4273  first_border = View_size (sub->view) - b_peers;
4274  second_border = View_size (sub->view);
4275  }
4277  "Going to send pulls to %u (ceil (%f * %u)) peers.\n",
4278  b_peers, beta, View_size (sub->view));
4279  for (i = first_border; i < second_border; i++)
4280  {
4281  peer = view_array[permut[i]];
4282  if ( GNUNET_NO == check_peer_flag (sub->peer_map,
4283  &peer,
4285  { // FIXME if this fails schedule/loop this for later
4286  send_pull_request (get_peer_ctx (sub->peer_map, &peer));
4287  }
4288  }
4289 
4290  GNUNET_free (permut);
4291  permut = NULL;
4292  }
4293 
4294 
4295  /* Update view */
4296  /* TODO see how many peers are in push-/pull- list! */
4297 
4298  if ((CustomPeerMap_size (sub->push_map) <= alpha * sub->view_size_est_need) &&
4299  (0 < CustomPeerMap_size (sub->push_map)) &&
4300  (0 < CustomPeerMap_size (sub->pull_map)))
4301  { /* If conditions for update are fulfilled, update */
4302  LOG (GNUNET_ERROR_TYPE_DEBUG, "Update of the view.\n");
4303 
4304  uint32_t final_size;
4305  uint32_t peers_to_clean_size;
4306  struct GNUNET_PeerIdentity *peers_to_clean;
4307 
4308  peers_to_clean = NULL;
4309  peers_to_clean_size = 0;
4310  GNUNET_array_grow (peers_to_clean,
4311  peers_to_clean_size,
4312  View_size (sub->view));
4313  GNUNET_memcpy (peers_to_clean,
4314  view_array,
4315  View_size (sub->view) * sizeof (struct GNUNET_PeerIdentity));
4316 
4317  /* Seems like recreating is the easiest way of emptying the peermap */
4318  View_clear (sub->view);
4319 #ifdef TO_FILE_FULL
4320  to_file (sub->file_name_view_log,
4321  "--- emptied ---");
4322 #endif /* TO_FILE_FULL */
4323 
4324  first_border = GNUNET_MIN (ceil (alpha * sub->view_size_est_need),
4325  CustomPeerMap_size (sub->push_map));
4326  second_border = first_border +
4327  GNUNET_MIN (floor (beta * sub->view_size_est_need),
4328  CustomPeerMap_size (sub->pull_map));
4329  final_size = second_border +
4330  ceil ((1 - (alpha + beta)) * sub->view_size_est_need);
4332  "first border: %" PRIu32 ", second border: %" PRIu32 ", final size: %"PRIu32 "\n",
4333  first_border,
4334  second_border,
4335  final_size);
4336 
4337  /* Update view with peers received through PUSHes */
4339  CustomPeerMap_size (sub->push_map));
4340  for (i = 0; i < first_border; i++)
4341  {
4342  int inserted;
4343  inserted = insert_in_view (sub,
4345  permut[i]));
4346  if (GNUNET_OK == inserted)
4347  {
4349  1,
4350  CustomPeerMap_get_peer_by_index (sub->push_map, permut[i]));
4351  }
4352 #ifdef TO_FILE_FULL
4353  to_file (sub->file_name_view_log,
4354  "+%s\t(push list)",
4355  GNUNET_i2s_full (&view_array[i]));
4356 #endif /* TO_FILE_FULL */
4357  // TODO change the peer_flags accordingly
4358  }
4359  GNUNET_free (permut);
4360  permut = NULL;
4361 
4362  /* Update view with peers received through PULLs */
4364  CustomPeerMap_size (sub->pull_map));
4365  for (i = first_border; i < second_border; i++)
4366  {
4367  int inserted;
4368  inserted = insert_in_view (sub,
4370  permut[i - first_border]));
4371  if (GNUNET_OK == inserted)
4372  {
4374  1,
4376  permut[i - first_border]));
4377  }
4378 #ifdef TO_FILE_FULL
4379  to_file (sub->file_name_view_log,
4380  "+%s\t(pull list)",
4381  GNUNET_i2s_full (&view_array[i]));
4382 #endif /* TO_FILE_FULL */
4383  // TODO change the peer_flags accordingly
4384  }
4385  GNUNET_free (permut);
4386  permut = NULL;
4387 
4388  /* Update view with peers from history */
4390  final_size - second_border,
4391  hist_update,
4392  sub);
4393  // TODO change the peer_flags accordingly
4394 
4395  for (i = 0; i < View_size (sub->view); i++)
4396  rem_from_list (&peers_to_clean, &peers_to_clean_size, &view_array[i]);
4397 
4398  /* Clean peers that were removed from the view */
4399  for (i = 0; i < peers_to_clean_size; i++)
4400  {
4401 #ifdef TO_FILE_FULL
4402  to_file (sub->file_name_view_log,
4403  "-%s",
4404  GNUNET_i2s_full (&peers_to_clean[i]));
4405 #endif /* TO_FILE_FULL */
4406  clean_peer (sub, &peers_to_clean[i]);
4407  }
4408 
4409  GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
4411  } else {
4412  LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
4413  if (sub == msub)
4414  {
4415  GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO);
4416  if (CustomPeerMap_size (sub->push_map) > alpha * sub->view_size_est_need &&
4417  !(0 >= CustomPeerMap_size (sub->pull_map)))
4418  GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO);
4419  if (CustomPeerMap_size (sub->push_map) > alpha * sub->view_size_est_need &&
4420  (0 >= CustomPeerMap_size (sub->pull_map)))
4421  GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes, no pull replies", 1, GNUNET_NO);
4422  if (0 >= CustomPeerMap_size (sub->push_map) &&
4423  !(0 >= CustomPeerMap_size (sub->pull_map)))
4424  GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO);
4425  if (0 >= CustomPeerMap_size (sub->push_map) &&
4426  (0 >= CustomPeerMap_size (sub->pull_map)))
4427  GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes, no pull replies", 1, GNUNET_NO);
4428  if (0 >= CustomPeerMap_size (sub->pull_map) &&
4430  0 >= CustomPeerMap_size (sub->push_map))
4431  GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO);
4432  }
4433  }
4434  // TODO independent of that also get some peers from CADET_get_peers()?
4436  {
4437  sub->push_recv[CustomPeerMap_size (sub->push_map)]++;
4438  }
4439  else
4440  {
4442  "Push map size too big for histogram (%u, %u)\n",
4445  }
4446  // FIXME check bounds of histogram
4447  sub->push_delta[(int32_t) (CustomPeerMap_size (sub->push_map) -
4448  (alpha * sub->view_size_est_need)) +
4449  (HISTOGRAM_FILE_SLOTS/2)]++;
4450  if (sub == msub)
4451  {
4452  GNUNET_STATISTICS_set (stats,
4453  "# peers in push map at end of round",
4455  GNUNET_NO);
4456  GNUNET_STATISTICS_set (stats,
4457  "# peers in pull map at end of round",
4459  GNUNET_NO);
4460  GNUNET_STATISTICS_set (stats,
4461  "# peers in view at end of round",
4462  View_size (sub->view),
4463  GNUNET_NO);
4464  GNUNET_STATISTICS_set (stats,
4465  "# expected pushes",
4466  alpha * sub->view_size_est_need,
4467  GNUNET_NO);
4468  GNUNET_STATISTICS_set (stats,
4469  "delta expected - received pushes",
4471  GNUNET_NO);
4472  }
4473 
4475  "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (sub->view%u) = %.2f)\n",
4478  alpha,
4479  View_size (sub->view),
4480  alpha * View_size (sub->view));
4481 
4482  /* Update samplers */
4483  for (i = 0; i < CustomPeerMap_size (sub->push_map); i++)
4484  {
4485  update_peer = CustomPeerMap_get_peer_by_index (sub->push_map, i);
4487  "Updating with peer %s from push list\n",
4488  GNUNET_i2s (update_peer));
4489  insert_in_sampler (sub, update_peer);
4490  clean_peer (sub, update_peer); /* This cleans only if it is not in the view */
4491  }
4492 
4493  for (i = 0; i < CustomPeerMap_size (sub->pull_map); i++)
4494  {
4496  "Updating with peer %s from pull list\n",
4499  /* This cleans only if it is not in the view */
4501  }
4502 
4503 
4504  /* Empty push/pull lists */
4507 
4508  if (sub == msub)
4509  {
4510  GNUNET_STATISTICS_set (stats,
4511  "view size",
4512  View_size(sub->view),
4513  GNUNET_NO);
4514  }
4515 
4516  struct GNUNET_TIME_Relative time_next_round;
4517 
4518  time_next_round = compute_rand_delay (sub->round_interval, 2);
4519 
4520  /* Schedule next round */
4521  sub->do_round_task = GNUNET_SCHEDULER_add_delayed (time_next_round,
4522  &do_round, sub);
4523  LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished round\n");
4524 }
4525 
4526 
4542 void
4543 init_peer_cb (void *cls,
4544  const struct GNUNET_PeerIdentity *peer,
4545  int tunnel, /* "Do we have a tunnel towards this peer?" */
4546  unsigned int n_paths, /* "Number of known paths towards this peer" */
4547  unsigned int best_path) /* "How long is the best path?
4548  * (0 = unknown, 1 = ourselves, 2 = neighbor)" */
4549 {
4550  struct Sub *sub = cls;
4551  (void) tunnel;
4552  (void) n_paths;
4553  (void) best_path;
4554 
4555  if (NULL != peer)
4556  {
4558  "Got peer_id %s from cadet\n",
4559  GNUNET_i2s (peer));
4560  got_peer (sub, peer);
4561  }
4562 }
4563 
4564 
4576 static int
4578  const struct GNUNET_PeerIdentity *peer)
4579 {
4580  struct Sub *sub = cls;
4581 
4582  if (NULL != peer)
4583  {
4585  "Got stored, valid peer %s\n",
4586  GNUNET_i2s (peer));
4587  got_peer (sub, peer);
4588  }
4589  return GNUNET_YES;
4590 }
4591 
4592 
4601 void
4603  const struct GNUNET_PeerIdentity *peer,
4604  const struct GNUNET_HELLO_Message *hello,
4605  const char *err_msg)
4606 {
4607  struct Sub *sub = cls;
4608  (void) hello;
4609  (void) err_msg;
4610 
4611  if (NULL != peer)
4612  {
4614  "Got peer_id %s from peerinfo\n",
4615  GNUNET_i2s (peer));
4616  got_peer (sub, peer);
4617  }
4618 }
4619 
4620 
4626 static void
4627 shutdown_task (void *cls)
4628 {
4629  (void) cls;
4630  struct ClientContext *client_ctx;
4631 
4633  "RPS service is going down\n");
4634 
4635  /* Clean all clients */
4636  for (client_ctx = cli_ctx_head;
4637  NULL != cli_ctx_head;
4638  client_ctx = cli_ctx_head)
4639  {
4640  destroy_cli_ctx (client_ctx);
4641  }
4642  if (NULL != msub)
4643  {
4644  destroy_sub (msub);
4645  msub = NULL;
4646  }
4647 
4648  /* Disconnect from other services */
4649  GNUNET_PEERINFO_notify_cancel (peerinfo_notify_handle);
4650  GNUNET_PEERINFO_disconnect (peerinfo_handle);
4651  peerinfo_handle = NULL;
4652  GNUNET_NSE_disconnect (nse);
4653  if (NULL != map_single_hop)
4654  {
4655  /* core_init was called - core was initialised */
4656  /* disconnect first, so no callback tries to access missing peermap */
4657  GNUNET_CORE_disconnect (core_handle);
4658  core_handle = NULL;
4659  GNUNET_CONTAINER_multipeermap_destroy (map_single_hop);
4660  map_single_hop = NULL;
4661  }
4662 
4663  if (NULL != stats)
4664  {
4666  GNUNET_NO);
4667  stats = NULL;
4668  }
4669  GNUNET_CADET_disconnect (cadet_handle);
4670  cadet_handle = NULL;
4671 #if ENABLE_MALICIOUS
4672  struct AttackedPeer *tmp_att_peer;
4673  GNUNET_array_grow (mal_peers,
4674  num_mal_peers,
4675  0);
4676  if (NULL != mal_peer_set)
4678  if (NULL != att_peer_set)
4680  while (NULL != att_peers_head)
4681  {
4682  tmp_att_peer = att_peers_head;
4683  GNUNET_CONTAINER_DLL_remove (att_peers_head,
4684  att_peers_tail,
4685  tmp_att_peer);
4686  GNUNET_free (tmp_att_peer);
4687  }
4688 #endif /* ENABLE_MALICIOUS */
4689  close_all_files();
4690 }
4691 
4692 
4701 static void *
4703  struct GNUNET_SERVICE_Client *client,
4704  struct GNUNET_MQ_Handle *mq)
4705 {
4706  struct ClientContext *cli_ctx;
4707  (void) cls;
4708 
4710  "Client connected\n");
4711  if (NULL == client)
4712  return client; /* Server was destroyed before a client connected. Shutting down */
4713  cli_ctx = GNUNET_new (struct ClientContext);
4714  cli_ctx->mq = mq;
4715  cli_ctx->view_updates_left = -1;
4716  cli_ctx->stream_update = GNUNET_NO;
4717  cli_ctx->client = client;
4718  GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
4719  cli_ctx_tail,
4720  cli_ctx);
4721  return cli_ctx;
4722 }
4723 
4731 static void
4733  struct GNUNET_SERVICE_Client *client,
4734  void *internal_cls)
4735 {
4736  struct ClientContext *cli_ctx = internal_cls;
4737 
4738  (void) cls;
4739  GNUNET_assert (client == cli_ctx->client);
4740  if (NULL == client)
4741  {/* shutdown task - destroy all clients */
4742  while (NULL != cli_ctx_head)
4743  destroy_cli_ctx (cli_ctx_head);
4744  }
4745  else
4746  { /* destroy this client */
4748  "Client disconnected. Destroy its context.\n");
4749  destroy_cli_ctx (cli_ctx);
4750  }
4751 }
4752 
4753 
4761 static void
4762 run (void *cls,
4763  const struct GNUNET_CONFIGURATION_Handle *c,
4765 {
4766  struct GNUNET_TIME_Relative round_interval;
4767  long long unsigned int sampler_size;
4768  char hash_port_string[] = GNUNET_APPLICATION_PORT_RPS;
4769  struct GNUNET_HashCode hash;
4770 
4771  (void) cls;
4772  (void) service;
4773 
4774  GNUNET_log_setup ("rps",
4776  NULL);
4777  cfg = c;
4778  /* Get own ID */
4780  &own_identity); // TODO check return value
4782  "STARTING SERVICE (rps) for peer [%s]\n",
4784 #if ENABLE_MALICIOUS
4786  "Malicious execution compiled in.\n");
4787 #endif /* ENABLE_MALICIOUS */
4788 
4789  /* Get time interval from the configuration */
4790  if (GNUNET_OK !=
4792  "RPS",
4793  "ROUNDINTERVAL",
4794  &round_interval))
4795  {
4797  "RPS", "ROUNDINTERVAL");
4799  return;
4800  }
4801 
4802  /* Get initial size of sampler/view from the configuration */
4803  if (GNUNET_OK !=
4805  "RPS",
4806  "MINSIZE",
4807  &sampler_size))
4808  {
4810  "RPS", "MINSIZE");
4812  return;
4813  }
4814 
4815  cadet_handle = GNUNET_CADET_connect (cfg);
4816  GNUNET_assert (NULL != cadet_handle);
4817  core_handle = GNUNET_CORE_connect (cfg,
4818  NULL, /* cls */
4819  core_init, /* init */
4820  core_connects, /* connects */
4821  core_disconnects, /* disconnects */
4822  NULL); /* handlers */
4823  GNUNET_assert (NULL != core_handle);
4824 
4825 
4826  alpha = 0.45;
4827  beta = 0.45;
4828 
4829 
4830  /* Set up main Sub */
4831  GNUNET_CRYPTO_hash (hash_port_string,
4832  strlen (hash_port_string),
4833  &hash);
4834  msub = new_sub (&hash,
4835  sampler_size, /* Will be overwritten by config */
4836  round_interval);
4837 
4838 
4839  peerinfo_handle = GNUNET_PEERINFO_connect (cfg);
4840 
4841  /* connect to NSE */
4842  nse = GNUNET_NSE_connect (cfg, nse_callback, NULL);
4843 
4844  //LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting peers from CADET\n");
4845  //GNUNET_CADET_get_peers (cadet_handle, &init_peer_cb, msub);
4846  // TODO send push/pull to each of those peers?
4847  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting stored valid peers\n");
4848  restore_valid_peers (msub);
4850 
4851  peerinfo_notify_handle = GNUNET_PEERINFO_notify (cfg,
4852  GNUNET_NO,
4854  msub);
4855 
4856  LOG (GNUNET_ERROR_TYPE_INFO, "Ready to receive requests from clients\n");
4857 
4859  stats = GNUNET_STATISTICS_create ("rps", cfg);
4860 }
4861 
4862 
4867 ("rps",
4869  &run,
4872  NULL,
4873  GNUNET_MQ_hd_var_size (client_seed,
4876  NULL),
4877 #if ENABLE_MALICIOUS
4878  GNUNET_MQ_hd_var_size (client_act_malicious,
4879  GNUNET_MESSAGE_TYPE_RPS_ACT_MALICIOUS,
4880  struct GNUNET_RPS_CS_ActMaliciousMessage,
4881  NULL),
4882 #endif /* ENABLE_MALICIOUS */
4883  GNUNET_MQ_hd_fixed_size (client_view_request,
4886  NULL),
4887  GNUNET_MQ_hd_fixed_size (client_view_cancel,
4889  struct GNUNET_MessageHeader,
4890  NULL),
4891  GNUNET_MQ_hd_fixed_size (client_stream_request,
4894  NULL),
4895  GNUNET_MQ_hd_fixed_size (client_stream_cancel,
4897  struct GNUNET_MessageHeader,
4898  NULL),
4899  GNUNET_MQ_hd_fixed_size (client_start_sub,
4902  NULL),
4903  GNUNET_MQ_hd_fixed_size (client_stop_sub,
4906  NULL),
4908 
4909 /* 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 do_mal_round(void *cls)
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:669
#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:849
static void destroy_sub(struct Sub *sub)
Destroy Sub.
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:86
Message from service to client containing current update of view.
Definition: rps.h:186
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:209
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:1817
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.
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:78
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:180
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:133
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.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
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:169
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:881
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:1293
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:330
#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.
static char * file_name
Dump file name.
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.
Enable channel reliability, lost messages will be retransmitted.
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_MQ_hd_fixed_size(name, code, str, ctx)
unsigned int RPS_sampler_get_size(struct RPS_Sampler *sampler)
Get the size of the sampler.
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:833
static unsigned int mal_type
Type of malicious peer to test.
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
#define GNUNET_NO
Definition: gnunet_common.h:81
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_api.c:80
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
Peers_PeerFlags
Different flags indicating the status of another peer.
Definition: rps.h:246
#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:524
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).
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:995
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:67
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.
#define to_file_w_len(file_name, len,...)
Definition: rps-test_util.h:83
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:249
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.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#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:1246
If we are waiting for a reply from that peer (sent a pull request).
Definition: rps.h:251
static void add_peer_array_to_set(const struct GNUNET_PeerIdentity *peer_array, unsigned int num_peers, struct GNUNET_CONTAINER_MultiPeerMap *peer_map)
Add all peers in peer_array to peer_map used as set.
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:230
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:1029
#define GNUNET_memcpy(dst, src, n)
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(* 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:318
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:774
static char * value
Value of the record to add/remove.
static struct GNUNET_PeerIdentity * peer_ids
char * store_prefix_file_name(const unsigned int index, const char *prefix)
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:44
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:1049
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:1273
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:159
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:83
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:149
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:638
#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:2618
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.
Message from service to client containing peer from biased stream.
Definition: rps.h:220
#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_STREAM_CANCEL
Cancel getting biased strem.
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:122
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:267
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:694
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:732
struct GNUNET_MessageHeader header
Header including size and type in NBO.
Definition: rps.h:72
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:77
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:137
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:501
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
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:576
#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:973
const struct GNUNET_PeerIdentity * peer
Pointer to peer to return.
configuration data
Definition: configuration.c:85
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:208
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.
#define SIZE_DUMP_FILE
The size (in bytes) a file needs to store the histogram.
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:151
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:159
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:525
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:882
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
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:353
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 void write_histogram_to_file(const uint32_t hist_array[], const char *file_name)
Write all numbers in the given array into the given file.
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:1673
uint64_t num_peers
Number of peers in the view.
Definition: rps.h:201
#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:911
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:499
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:2533
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:64
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:260
#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...
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, enum GNUNET_CADET_ChannelOption options, 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:1088
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:1142
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
High-quality operations are desired.
struct GNUNET_HashCode hash
Length of the shared value represented as string.
Definition: rps.h:142