aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_protocols.h26
-rw-r--r--src/include/gnunet_rps_service.h26
-rw-r--r--src/rps/gnunet-rps.c67
-rw-r--r--src/rps/gnunet-service-rps.c136
-rw-r--r--src/rps/gnunet-service-rps_custommap.c5
-rw-r--r--src/rps/rps.h43
-rw-r--r--src/rps/rps_api.c95
-rw-r--r--src/rps/test_rps.c132
8 files changed, 519 insertions, 11 deletions
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 436adc5a4..d692b28ff 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -2621,6 +2621,8 @@ extern "C"
2621 2621
2622#endif /* ENABLE_MALICIOUS */ 2622#endif /* ENABLE_MALICIOUS */
2623 2623
2624/* Debugging API continues at 1130 */
2625
2624/******************************************************************************/ 2626/******************************************************************************/
2625 2627
2626 2628
@@ -2944,8 +2946,30 @@ extern "C"
2944#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_OUTCOME 1112 2946#define GNUNET_MESSAGE_TYPE_AUCTION_CLIENT_OUTCOME 1112
2945 2947
2946 2948
2949
2950/******************************************************************************/
2951/********************************* RPS DEBUG ********************************/
2952/******************************************************************************/
2953
2954/**
2955 * @brief Request updates of the view
2956 */
2957#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REQUEST 1130
2958
2959/**
2960 * @brief Send update of the view
2961 */
2962#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REPLY 1131
2963
2964/**
2965 * @brief Cancel getting updates of the view
2966 */
2967#define GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_CANCEL 1132
2968
2969
2970
2947/** 2971/**
2948 * Next available: 1130 2972 * Next available: 1200
2949 */ 2973 */
2950 2974
2951 2975
diff --git a/src/include/gnunet_rps_service.h b/src/include/gnunet_rps_service.h
index c91804a60..8267e28b2 100644
--- a/src/include/gnunet_rps_service.h
+++ b/src/include/gnunet_rps_service.h
@@ -66,6 +66,16 @@ typedef void (* GNUNET_RPS_NotifyReadyCB) (void *cls,
66 const struct GNUNET_PeerIdentity *peers); 66 const struct GNUNET_PeerIdentity *peers);
67 67
68/** 68/**
69 * Callback called when view was updated
70 *
71 * @param num_peers the number of peers returned
72 * @param peers array with num_peers PeerIDs
73 */
74typedef void (* GNUNET_RPS_ViewUpdateCB) (void *cls,
75 uint64_t num_peers,
76 const struct GNUNET_PeerIdentity *peers);
77
78/**
69 * Connect to the rps service 79 * Connect to the rps service
70 * 80 *
71 * @param cfg configuration to use 81 * @param cfg configuration to use
@@ -136,6 +146,22 @@ GNUNET_RPS_act_malicious (struct GNUNET_RPS_Handle *h,
136 const struct GNUNET_PeerIdentity *target_peer); 146 const struct GNUNET_PeerIdentity *target_peer);
137#endif /* ENABLE_MALICIOUS */ 147#endif /* ENABLE_MALICIOUS */
138 148
149/* Get internals for debugging/profiling purposes */
150
151/**
152 * Request updates of view
153 *
154 * @param rps_handle handle to the rps service
155 * @param num_req_peers number of peers we want to receive
156 * (0 for infinite updates)
157 * @param cls a closure that will be given to the callback
158 * @param ready_cb the callback called when the peers are available
159 */
160void
161GNUNET_RPS_view_request (struct GNUNET_RPS_Handle *rps_handle,
162 uint32_t num_updates,
163 GNUNET_RPS_ViewUpdateCB view_update_cb,
164 void *cls);
139 165
140/** 166/**
141 * Disconnect from the rps service 167 * Disconnect from the rps service
diff --git a/src/rps/gnunet-rps.c b/src/rps/gnunet-rps.c
index bbac0d634..8de588568 100644
--- a/src/rps/gnunet-rps.c
+++ b/src/rps/gnunet-rps.c
@@ -45,6 +45,16 @@ static struct GNUNET_RPS_Request_Handle *req_handle;
45 */ 45 */
46static struct GNUNET_PeerIdentity peer_id; 46static struct GNUNET_PeerIdentity peer_id;
47 47
48/**
49 * @brief Do we want to receive updates of the view? (Option --view)
50 */
51static int view_update;
52
53/**
54 * @brief Number of updates we want to receive
55 */
56static uint64_t num_view_updates;
57
48 58
49/** 59/**
50 * Task run when user presses CTRL-C to abort. 60 * Task run when user presses CTRL-C to abort.
@@ -87,6 +97,42 @@ reply_handle (void *cls,
87 GNUNET_SCHEDULER_shutdown (); 97 GNUNET_SCHEDULER_shutdown ();
88} 98}
89 99
100/**
101 * Callback called on receipt view update.
102 * Prints view.
103 *
104 * @param n number of peers
105 * @param recv_peers the received peers
106 */
107static void
108view_update_handle (void *cls,
109 uint64_t n,
110 const struct GNUNET_PeerIdentity *recv_peers)
111{
112 uint64_t i;
113
114 if (0 == n)
115 {
116 FPRINTF (stdout, "Empty view\n");
117 }
118 req_handle = NULL;
119 for (i = 0; i < n; i++)
120 {
121 FPRINTF (stdout, "%s\n",
122 GNUNET_i2s_full (&recv_peers[i]));
123 }
124
125 if (1 == num_view_updates)
126 {
127 ret = 0;
128 GNUNET_SCHEDULER_shutdown ();
129 }
130 else if (1 < num_view_updates)
131 {
132 num_view_updates--;
133 }
134}
135
90 136
91/** 137/**
92 * Main function that will be run by the scheduler. 138 * Main function that will be run by the scheduler.
@@ -107,9 +153,8 @@ run (void *cls,
107 153
108 rps_handle = GNUNET_RPS_connect (cfg); 154 rps_handle = GNUNET_RPS_connect (cfg);
109 155
110 if (0 == memcmp (&zero_pid, 156 if ((0 == memcmp (&zero_pid, &peer_id, sizeof (peer_id))) &&
111 &peer_id, 157 (!view_update))
112 sizeof (peer_id)))
113 { /* Request n PeerIDs */ 158 { /* Request n PeerIDs */
114 /* If number was specified use it, else request single peer. */ 159 /* If number was specified use it, else request single peer. */
115 num_peers = (NULL == args[0]) ? 1 : atoi (args[0]); 160 num_peers = (NULL == args[0]) ? 1 : atoi (args[0]);
@@ -117,6 +162,18 @@ run (void *cls,
117 "Requesting %" PRIu64 " PeerIDs\n", num_peers); 162 "Requesting %" PRIu64 " PeerIDs\n", num_peers);
118 req_handle = GNUNET_RPS_request_peers (rps_handle, num_peers, reply_handle, NULL); 163 req_handle = GNUNET_RPS_request_peers (rps_handle, num_peers, reply_handle, NULL);
119 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 164 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
165 } else if (view_update)
166 {
167 /* Get updates of view */
168 num_view_updates = (NULL == args[0]) ? 0 : atoi (args[0]);
169 GNUNET_RPS_view_request (rps_handle, num_view_updates, view_update_handle, NULL);
170 if (0 != num_view_updates)
171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
172 "Requesting %" PRIu64 " view updates\n", num_view_updates);
173 else
174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175 "Requesting contiuous view updates\n");
176 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
120 } 177 }
121 else 178 else
122 { /* Seed PeerID */ 179 { /* Seed PeerID */
@@ -145,6 +202,10 @@ main (int argc, char *const *argv)
145 "PEER_ID", 202 "PEER_ID",
146 gettext_noop ("Seed a PeerID"), 203 gettext_noop ("Seed a PeerID"),
147 &peer_id), 204 &peer_id),
205 GNUNET_GETOPT_option_flag ('V',
206 "view",
207 gettext_noop ("Get updates of view (0 for infinite updates)"),
208 &view_update),
148 GNUNET_GETOPT_OPTION_END 209 GNUNET_GETOPT_OPTION_END
149 }; 210 };
150 return (GNUNET_OK == 211 return (GNUNET_OK ==
diff --git a/src/rps/gnunet-service-rps.c b/src/rps/gnunet-service-rps.c
index 56c3c52b6..12e5b1b3e 100644
--- a/src/rps/gnunet-service-rps.c
+++ b/src/rps/gnunet-service-rps.c
@@ -1072,6 +1072,7 @@ Peers_terminate ()
1072 "Iteration destroying peers was aborted.\n"); 1072 "Iteration destroying peers was aborted.\n");
1073 } 1073 }
1074 GNUNET_CONTAINER_multipeermap_destroy (peer_map); 1074 GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1075 peer_map = NULL;
1075 store_valid_peers (); 1076 store_valid_peers ();
1076 GNUNET_free (filename_valid_peers); 1077 GNUNET_free (filename_valid_peers);
1077 GNUNET_CONTAINER_multipeermap_destroy (valid_peers); 1078 GNUNET_CONTAINER_multipeermap_destroy (valid_peers);
@@ -1439,7 +1440,13 @@ Peers_get_channel_flag (const struct GNUNET_PeerIdentity *peer,
1439int 1440int
1440Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer) 1441Peers_check_peer_known (const struct GNUNET_PeerIdentity *peer)
1441{ 1442{
1442 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer); 1443 if (NULL != peer_map)
1444 {
1445 return GNUNET_CONTAINER_multipeermap_contains (peer_map, peer);
1446 } else
1447 {
1448 return GNUNET_NO;
1449 }
1443} 1450}
1444 1451
1445 1452
@@ -1514,6 +1521,7 @@ Peers_handle_inbound_channel (void *cls,
1514 const struct GNUNET_PeerIdentity *initiator) 1521 const struct GNUNET_PeerIdentity *initiator)
1515{ 1522{
1516 struct PeerContext *peer_ctx; 1523 struct PeerContext *peer_ctx;
1524 struct GNUNET_PeerIdentity *ctx_peer;
1517 1525
1518 LOG (GNUNET_ERROR_TYPE_DEBUG, 1526 LOG (GNUNET_ERROR_TYPE_DEBUG,
1519 "New channel was established to us (Peer %s).\n", 1527 "New channel was established to us (Peer %s).\n",
@@ -1522,6 +1530,8 @@ Peers_handle_inbound_channel (void *cls,
1522 /* Make sure we 'know' about this peer */ 1530 /* Make sure we 'know' about this peer */
1523 peer_ctx = create_or_get_peer_ctx (initiator); 1531 peer_ctx = create_or_get_peer_ctx (initiator);
1524 set_peer_live (peer_ctx); 1532 set_peer_live (peer_ctx);
1533 ctx_peer = GNUNET_new (struct GNUNET_PeerIdentity);
1534 *ctx_peer = *initiator;
1525 /* We only accept one incoming channel per peer */ 1535 /* We only accept one incoming channel per peer */
1526 if (GNUNET_YES == Peers_check_peer_send_intention (initiator)) 1536 if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
1527 { 1537 {
@@ -1531,10 +1541,10 @@ Peers_handle_inbound_channel (void *cls,
1531 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel); 1541 GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
1532 peer_ctx->recv_channel = channel; 1542 peer_ctx->recv_channel = channel;
1533 /* return the channel context */ 1543 /* return the channel context */
1534 return &peer_ctx->peer_id; 1544 return ctx_peer;
1535 } 1545 }
1536 peer_ctx->recv_channel = channel; 1546 peer_ctx->recv_channel = channel;
1537 return &peer_ctx->peer_id; 1547 return ctx_peer;
1538} 1548}
1539 1549
1540 1550
@@ -1629,6 +1639,7 @@ Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
1629 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN); 1639 set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
1630 GNUNET_CADET_channel_destroy (peer_ctx->send_channel); 1640 GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
1631 peer_ctx->send_channel = NULL; 1641 peer_ctx->send_channel = NULL;
1642 peer_ctx->mq = NULL;
1632 (void) Peers_check_connected (peer); 1643 (void) Peers_check_connected (peer);
1633 return GNUNET_YES; 1644 return GNUNET_YES;
1634 } 1645 }
@@ -1856,6 +1867,11 @@ struct ClientContext
1856 struct ReplyCls *rep_cls_tail; 1867 struct ReplyCls *rep_cls_tail;
1857 1868
1858 /** 1869 /**
1870 * @brief How many updates this client expects to receive.
1871 */
1872 int64_t view_updates_left;
1873
1874 /**
1859 * The client handle to send the reply to 1875 * The client handle to send the reply to
1860 */ 1876 */
1861 struct GNUNET_SERVICE_Client *client; 1877 struct GNUNET_SERVICE_Client *client;
@@ -2610,6 +2626,7 @@ cleanup_destroyed_channel (void *cls,
2610 to_file (file_name_view_log, 2626 to_file (file_name_view_log,
2611 "-%s\t(cleanup channel, ourself)", 2627 "-%s\t(cleanup channel, ourself)",
2612 GNUNET_i2s_full (peer)); 2628 GNUNET_i2s_full (peer));
2629 //GNUNET_free (peer);
2613 return; 2630 return;
2614 } 2631 }
2615 2632
@@ -2625,6 +2642,7 @@ cleanup_destroyed_channel (void *cls,
2625 { /* We are about to clean the sending channel. Clean the respective 2642 { /* We are about to clean the sending channel. Clean the respective
2626 * context */ 2643 * context */
2627 Peers_cleanup_destroyed_channel (cls, channel); 2644 Peers_cleanup_destroyed_channel (cls, channel);
2645 //GNUNET_free (peer);
2628 return; 2646 return;
2629 } 2647 }
2630 else 2648 else
@@ -2632,6 +2650,7 @@ cleanup_destroyed_channel (void *cls,
2632 * open. It probably went down. Remove it from our knowledge. */ 2650 * open. It probably went down. Remove it from our knowledge. */
2633 Peers_cleanup_destroyed_channel (cls, channel); 2651 Peers_cleanup_destroyed_channel (cls, channel);
2634 remove_peer (peer); 2652 remove_peer (peer);
2653 //GNUNET_free (peer);
2635 return; 2654 return;
2636 } 2655 }
2637 } 2656 }
@@ -2648,6 +2667,7 @@ cleanup_destroyed_channel (void *cls,
2648 { /* Other peer tried to establish a channel to us twice. We do not accept 2667 { /* Other peer tried to establish a channel to us twice. We do not accept
2649 * that. Clean the context. */ 2668 * that. Clean the context. */
2650 Peers_cleanup_destroyed_channel (cls, channel); 2669 Peers_cleanup_destroyed_channel (cls, channel);
2670 //GNUNET_free (peer);
2651 return; 2671 return;
2652 } 2672 }
2653 else 2673 else
@@ -2655,6 +2675,7 @@ cleanup_destroyed_channel (void *cls,
2655 * it. */ 2675 * it. */
2656 Peers_cleanup_destroyed_channel (cls, channel); 2676 Peers_cleanup_destroyed_channel (cls, channel);
2657 clean_peer (peer); 2677 clean_peer (peer);
2678 //GNUNET_free (peer);
2658 return; 2679 return;
2659 } 2680 }
2660 } 2681 }
@@ -2663,6 +2684,7 @@ cleanup_destroyed_channel (void *cls,
2663 LOG (GNUNET_ERROR_TYPE_WARNING, 2684 LOG (GNUNET_ERROR_TYPE_WARNING,
2664 "Destroyed channel is neither sending nor receiving channel\n"); 2685 "Destroyed channel is neither sending nor receiving channel\n");
2665 } 2686 }
2687 //GNUNET_free (peer);
2666} 2688}
2667 2689
2668/*********************************************************************** 2690/***********************************************************************
@@ -2940,6 +2962,107 @@ handle_client_seed (void *cls,
2940} 2962}
2941 2963
2942/** 2964/**
2965 * @brief Send view to client
2966 *
2967 * @param cli_ctx the context of the client
2968 * @param view_array the peerids of the view as array (can be empty)
2969 * @param view_size the size of the view array (can be 0)
2970 */
2971void
2972send_view (const struct ClientContext *cli_ctx,
2973 const struct GNUNET_PeerIdentity *view_array,
2974 uint64_t view_size)
2975{
2976 struct GNUNET_MQ_Envelope *ev;
2977 struct GNUNET_RPS_CS_DEBUG_ViewReply *out_msg;
2978
2979 if (NULL == view_array)
2980 {
2981 view_size = View_size ();
2982 view_array = View_get_as_array();
2983 }
2984
2985 ev = GNUNET_MQ_msg_extra (out_msg,
2986 view_size * sizeof (struct GNUNET_PeerIdentity),
2987 GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REPLY);
2988 out_msg->num_peers = htonl (view_size);
2989
2990 GNUNET_memcpy (&out_msg[1],
2991 view_array,
2992 view_size * sizeof (struct GNUNET_PeerIdentity));
2993 GNUNET_MQ_send (cli_ctx->mq, ev);
2994}
2995
2996/**
2997 * @brief sends updates to clients that are interested
2998 */
2999static void
3000clients_notify_view_update (void)
3001{
3002 struct ClientContext *cli_ctx_iter;
3003 uint64_t num_peers;
3004 const struct GNUNET_PeerIdentity *view_array;
3005
3006 num_peers = View_size ();
3007 view_array = View_get_as_array();
3008 /* check size of view is small enough */
3009 if (GNUNET_MAX_MESSAGE_SIZE < num_peers)
3010 {
3011 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3012 "View is too big to send\n");
3013 return;
3014 }
3015
3016 for (cli_ctx_iter = cli_ctx_head;
3017 NULL != cli_ctx_iter;
3018 cli_ctx_iter = cli_ctx_head->next)
3019 {
3020 if (1 < cli_ctx_iter->view_updates_left)
3021 {
3022 /* Client wants to receive limited amount of updates */
3023 cli_ctx_iter->view_updates_left -= 1;
3024 } else if (1 == cli_ctx_iter->view_updates_left)
3025 {
3026 /* Last update of view for client */
3027 cli_ctx_iter->view_updates_left = -1;
3028 } else if (0 > cli_ctx_iter->view_updates_left) {
3029 /* Client is not interested in updates */
3030 continue;
3031 }
3032 /* else _updates_left == 0 - infinite amount of updates */
3033
3034 /* send view */
3035 send_view (cli_ctx_iter, view_array, num_peers);
3036 }
3037}
3038
3039
3040/**
3041 * Handle RPS request from the client.
3042 *
3043 * @param cls closure
3044 * @param message the actual message
3045 */
3046static void
3047handle_client_view_request (void *cls,
3048 const struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg)
3049{
3050 struct ClientContext *cli_ctx = cls;
3051 uint64_t num_updates;
3052
3053 num_updates = ntohl (msg->num_updates);
3054
3055 LOG (GNUNET_ERROR_TYPE_DEBUG,
3056 "Client requested %" PRIu64 " updates of view.\n",
3057 num_updates);
3058
3059 GNUNET_assert (NULL != cli_ctx);
3060 cli_ctx->view_updates_left = num_updates;
3061 send_view (cli_ctx, NULL, 0);
3062 GNUNET_SERVICE_client_continue (cli_ctx->client);
3063}
3064
3065/**
2943 * Handle a CHECK_LIVE message from another peer. 3066 * Handle a CHECK_LIVE message from another peer.
2944 * 3067 *
2945 * This does nothing. But without calling #GNUNET_CADET_receive_done() 3068 * This does nothing. But without calling #GNUNET_CADET_receive_done()
@@ -3554,7 +3677,6 @@ do_mal_round (void *cls)
3554} 3677}
3555#endif /* ENABLE_MALICIOUS */ 3678#endif /* ENABLE_MALICIOUS */
3556 3679
3557
3558/** 3680/**
3559 * Send out PUSHes and PULLs, possibly update #view, samplers. 3681 * Send out PUSHes and PULLs, possibly update #view, samplers.
3560 * 3682 *
@@ -3724,6 +3846,7 @@ do_round (void *cls)
3724 } 3846 }
3725 3847
3726 GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0); 3848 GNUNET_array_grow (peers_to_clean, peers_to_clean_size, 0);
3849 clients_notify_view_update();
3727 } else { 3850 } else {
3728 LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n"); 3851 LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
3729 GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO); 3852 GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO);
@@ -3973,6 +4096,7 @@ client_connect_cb (void *cls,
3973 return client; /* Server was destroyed before a client connected. Shutting down */ 4096 return client; /* Server was destroyed before a client connected. Shutting down */
3974 cli_ctx = GNUNET_new (struct ClientContext); 4097 cli_ctx = GNUNET_new (struct ClientContext);
3975 cli_ctx->mq = GNUNET_SERVICE_client_get_mq (client); 4098 cli_ctx->mq = GNUNET_SERVICE_client_get_mq (client);
4099 cli_ctx->view_updates_left = -1;
3976 cli_ctx->client = client; 4100 cli_ctx->client = client;
3977 GNUNET_CONTAINER_DLL_insert (cli_ctx_head, 4101 GNUNET_CONTAINER_DLL_insert (cli_ctx_head,
3978 cli_ctx_tail, 4102 cli_ctx_tail,
@@ -4216,6 +4340,10 @@ GNUNET_SERVICE_MAIN
4216 struct GNUNET_RPS_CS_ActMaliciousMessage, 4340 struct GNUNET_RPS_CS_ActMaliciousMessage,
4217 NULL), 4341 NULL),
4218#endif /* ENABLE_MALICIOUS */ 4342#endif /* ENABLE_MALICIOUS */
4343 GNUNET_MQ_hd_fixed_size (client_view_request,
4344 GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REQUEST,
4345 struct GNUNET_RPS_CS_DEBUG_ViewRequest,
4346 NULL),
4219 GNUNET_MQ_handler_end()); 4347 GNUNET_MQ_handler_end());
4220 4348
4221/* end of gnunet-service-rps.c */ 4349/* end of gnunet-service-rps.c */
diff --git a/src/rps/gnunet-service-rps_custommap.c b/src/rps/gnunet-service-rps_custommap.c
index 064192d08..aef081a00 100644
--- a/src/rps/gnunet-service-rps_custommap.c
+++ b/src/rps/gnunet-service-rps_custommap.c
@@ -128,7 +128,9 @@ CustomPeerMap_put (const struct CustomPeerMap *c_peer_map,
128 *index = CustomPeerMap_size (c_peer_map); 128 *index = CustomPeerMap_size (c_peer_map);
129 p = GNUNET_new (struct GNUNET_PeerIdentity); 129 p = GNUNET_new (struct GNUNET_PeerIdentity);
130 *p = *peer; 130 *p = *peer;
131 GNUNET_CONTAINER_multipeermap_put (c_peer_map->peer_map, peer, index, 131 GNUNET_assert (p != peer);
132 GNUNET_assert (0 == memcmp (p, peer, sizeof(struct GNUNET_PeerIdentity)));
133 GNUNET_CONTAINER_multipeermap_put (c_peer_map->peer_map, p, index,
132 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 134 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
133 GNUNET_CONTAINER_multihashmap32_put (c_peer_map->hash_map, *index, p, 135 GNUNET_CONTAINER_multihashmap32_put (c_peer_map->hash_map, *index, p,
134 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
@@ -218,7 +220,6 @@ CustomPeerMap_remove_peer (const struct CustomPeerMap *c_peer_map,
218 *last_index = *index; 220 *last_index = *index;
219 } 221 }
220 GNUNET_free (index); 222 GNUNET_free (index);
221 GNUNET_free (p);
222 GNUNET_assert (GNUNET_CONTAINER_multihashmap32_size (c_peer_map->hash_map) == 223 GNUNET_assert (GNUNET_CONTAINER_multihashmap32_size (c_peer_map->hash_map) ==
223 GNUNET_CONTAINER_multipeermap_size (c_peer_map->peer_map)); 224 GNUNET_CONTAINER_multipeermap_size (c_peer_map->peer_map));
224 return GNUNET_OK; 225 return GNUNET_OK;
diff --git a/src/rps/rps.h b/src/rps/rps.h
index f5cc2e8d1..6a7fa3e14 100644
--- a/src/rps/rps.h
+++ b/src/rps/rps.h
@@ -176,6 +176,49 @@ struct GNUNET_RPS_CS_ActMaliciousMessage
176#endif /* ENABLE_MALICIOUS */ 176#endif /* ENABLE_MALICIOUS */
177 177
178 178
179/* Debug messages */
180
181/**
182 * Message from client to service indicating that
183 * clients wants to get updates of the view
184 */
185struct GNUNET_RPS_CS_DEBUG_ViewRequest
186{
187 /**
188 * Header including size and type in NBO
189 */
190 struct GNUNET_MessageHeader header;
191
192 /**
193 * Number of updates
194 * 0 for sending updates until cancellation
195 */
196 uint32_t num_updates GNUNET_PACKED;
197};
198
199/**
200 * Message from service to client containing current update of view
201 */
202struct GNUNET_RPS_CS_DEBUG_ViewReply
203{
204 /**
205 * Header including size and type in NBO
206 */
207 struct GNUNET_MessageHeader header;
208
209 /**
210 * Identifyer of the message.
211 */
212 uint32_t id GNUNET_PACKED;
213
214 /**
215 * Number of peers in the view
216 */
217 uint64_t num_peers GNUNET_PACKED;
218};
219 /* Followed by num_peers * GNUNET_PeerIdentity */
220
221
179/*********************************************************************** 222/***********************************************************************
180 * Defines from old gnunet-service-rps_peers.h 223 * Defines from old gnunet-service-rps_peers.h
181***********************************************************************/ 224***********************************************************************/
diff --git a/src/rps/rps_api.c b/src/rps/rps_api.c
index ccd480086..62ba9e226 100644
--- a/src/rps/rps_api.c
+++ b/src/rps/rps_api.c
@@ -56,6 +56,16 @@ struct GNUNET_RPS_Handle
56 * The id of the last request. 56 * The id of the last request.
57 */ 57 */
58 uint32_t current_request_id; 58 uint32_t current_request_id;
59
60 /**
61 * @brief Callback called on each update of the view
62 */
63 GNUNET_RPS_ViewUpdateCB view_update_cb;
64
65 /**
66 * @brief Callback called on each update of the view
67 */
68 void *view_update_cls;
59}; 69};
60 70
61 71
@@ -236,6 +246,86 @@ handle_reply (void *cls,
236} 246}
237 247
238 248
249/* Get internals for debugging/profiling purposes */
250
251/**
252 * Request updates of view
253 *
254 * @param rps_handle handle to the rps service
255 * @param num_req_peers number of peers we want to receive
256 * (0 for infinite updates)
257 * @param cls a closure that will be given to the callback
258 * @param ready_cb the callback called when the peers are available
259 */
260void
261GNUNET_RPS_view_request (struct GNUNET_RPS_Handle *rps_handle,
262 uint32_t num_updates,
263 GNUNET_RPS_ViewUpdateCB view_update_cb,
264 void *cls)
265{
266 struct GNUNET_MQ_Envelope *ev;
267 struct GNUNET_RPS_CS_DEBUG_ViewRequest *msg;
268
269 rps_handle->view_update_cb = view_update_cb;
270 rps_handle->view_update_cls = cls;
271
272 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REQUEST);
273 msg->num_updates = htonl (num_updates);
274 GNUNET_MQ_send (rps_handle->mq, ev);
275}
276
277/**
278 * This function is called, when the service updates the view.
279 * It verifies that @a msg is well-formed.
280 *
281 * @param cls the closure
282 * @param msg the message
283 * @return #GNUNET_OK if @a msg is well-formed
284 */
285static int
286check_view_update (void *cls,
287 const struct GNUNET_RPS_CS_DEBUG_ViewReply *msg)
288{
289 uint16_t msize = ntohs (msg->header.size);
290 uint32_t num_peers = ntohl (msg->num_peers);
291
292 msize -= sizeof (struct GNUNET_RPS_CS_DEBUG_ViewReply);
293 if ( (msize / sizeof (struct GNUNET_PeerIdentity) != num_peers) ||
294 (msize % sizeof (struct GNUNET_PeerIdentity) != 0) )
295 {
296 GNUNET_break (0);
297 return GNUNET_SYSERR;
298 }
299 return GNUNET_OK;
300}
301
302/**
303 * This function is called, when the service updated its view.
304 * It calls the callback the caller provided
305 * and disconnects afterwards.
306 *
307 * @param msg the message
308 */
309static void
310handle_view_update (void *cls,
311 const struct GNUNET_RPS_CS_DEBUG_ViewReply *msg)
312{
313 struct GNUNET_RPS_Handle *h = cls;
314 struct GNUNET_PeerIdentity *peers;
315
316 /* Give the peers back */
317 LOG (GNUNET_ERROR_TYPE_DEBUG,
318 "New view of %" PRIu32 " peers:\n",
319 ntohl (msg->num_peers));
320
321 peers = (struct GNUNET_PeerIdentity *) &msg[1];
322 GNUNET_assert (NULL != h);
323 GNUNET_assert (NULL != h->view_update_cb);
324 h->view_update_cb (h->view_update_cls, ntohl (msg->num_peers), peers);
325}
326
327
328
239/** 329/**
240 * Reconnect to the service 330 * Reconnect to the service
241 */ 331 */
@@ -281,6 +371,10 @@ reconnect (struct GNUNET_RPS_Handle *h)
281 GNUNET_MESSAGE_TYPE_RPS_CS_REPLY, 371 GNUNET_MESSAGE_TYPE_RPS_CS_REPLY,
282 struct GNUNET_RPS_CS_ReplyMessage, 372 struct GNUNET_RPS_CS_ReplyMessage,
283 h), 373 h),
374 GNUNET_MQ_hd_var_size (view_update,
375 GNUNET_MESSAGE_TYPE_RPS_CS_DEBUG_VIEW_REPLY,
376 struct GNUNET_RPS_CS_DEBUG_ViewReply,
377 h),
284 GNUNET_MQ_handler_end () 378 GNUNET_MQ_handler_end ()
285 }; 379 };
286 380
@@ -306,6 +400,7 @@ GNUNET_RPS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
306 struct GNUNET_RPS_Handle *h; 400 struct GNUNET_RPS_Handle *h;
307 401
308 h = GNUNET_new (struct GNUNET_RPS_Handle); 402 h = GNUNET_new (struct GNUNET_RPS_Handle);
403 h->current_request_id = 0;
309 h->cfg = cfg; 404 h->cfg = cfg;
310 reconnect (h); 405 reconnect (h);
311 if (NULL == h->mq) 406 if (NULL == h->mq)
diff --git a/src/rps/test_rps.c b/src/rps/test_rps.c
index 4ef97ad92..e0f87652b 100644
--- a/src/rps/test_rps.c
+++ b/src/rps/test_rps.c
@@ -258,6 +258,16 @@ struct RPSPeer
258 * @brief File name of the file the stats are finally written to 258 * @brief File name of the file the stats are finally written to
259 */ 259 */
260 char *file_name_stats; 260 char *file_name_stats;
261
262 /**
263 * @brief The current view
264 */
265 struct GNUNET_PeerIdentity *cur_view;
266
267 /**
268 * @brief Number of peers in the #cur_view.
269 */
270 uint32_t cur_view_count;
261}; 271};
262 272
263enum STAT_TYPE 273enum STAT_TYPE
@@ -419,6 +429,21 @@ enum OPTION_COLLECT_STATISTICS {
419}; 429};
420 430
421/** 431/**
432 * @brief Do we collect views during run?
433 */
434enum OPTION_COLLECT_VIEW {
435 /**
436 * @brief We collect view during run
437 */
438 COLLECT_VIEW,
439
440 /**
441 * @brief We do not collect the view during run
442 */
443 NO_COLLECT_VIEW,
444};
445
446/**
422 * Structure to define a single test 447 * Structure to define a single test
423 */ 448 */
424struct SingleTestRun 449struct SingleTestRun
@@ -484,6 +509,11 @@ struct SingleTestRun
484 enum OPTION_COLLECT_STATISTICS have_collect_statistics; 509 enum OPTION_COLLECT_STATISTICS have_collect_statistics;
485 510
486 /** 511 /**
512 * Collect view during run?
513 */
514 enum OPTION_COLLECT_VIEW have_collect_view;
515
516 /**
487 * @brief Mark which values from the statistics service to collect at the end 517 * @brief Mark which values from the statistics service to collect at the end
488 * of the run 518 * of the run
489 */ 519 */
@@ -1788,6 +1818,91 @@ store_stats_file_name (struct RPSPeer *rps_peer)
1788 rps_peer->file_name_stats = file_name; 1818 rps_peer->file_name_stats = file_name;
1789} 1819}
1790 1820
1821void compute_diversity ()
1822{
1823 uint32_t i, j, k;
1824 /* ith entry represents the numer of occurrences in other peer's views */
1825 uint32_t *count_peers = GNUNET_new_array (num_peers, uint32_t);
1826 uint32_t views_total_size;
1827 double expected;
1828 /* deviation from expected number of peers */
1829 double *deviation = GNUNET_new_array (num_peers, double);
1830
1831 views_total_size = 0;
1832 expected = 0;
1833
1834 /* For each peer count its representation in other peer's views*/
1835 for (i = 0; i < num_peers; i++) /* Peer to count */
1836 {
1837 views_total_size += rps_peers[i].cur_view_count;
1838 for (j = 0; j < num_peers; j++) /* Peer in which view is counted */
1839 {
1840 for (k = 0; k < rps_peers[j].cur_view_count; k++) /* entry in view */
1841 {
1842 if (0 == memcmp (rps_peers[i].peer_id,
1843 &rps_peers[j].cur_view[k],
1844 sizeof (struct GNUNET_PeerIdentity)))
1845 {
1846 count_peers[i]++;
1847 }
1848 }
1849 }
1850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1851 "Counted representation of %" PRIu32 "th peer: %" PRIu32"\n",
1852 i,
1853 count_peers[i]);
1854 }
1855
1856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1857 "size of all views combined: %" PRIu32 "\n",
1858 views_total_size);
1859 expected = ((double) 1/num_peers) * views_total_size;
1860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1861 "Expected number of occurrences of each peer in all views: %f\n",
1862 expected);
1863 for (i = 0; i < num_peers; i++) /* Peer to count */
1864 {
1865 deviation[i] = expected - count_peers[i];
1866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1867 "Deviation from expectation: %f\n", deviation[i]);
1868 }
1869 GNUNET_free (count_peers);
1870 GNUNET_free (deviation);
1871}
1872
1873void all_views_updated_cb ()
1874{
1875 compute_diversity ();
1876}
1877
1878void view_update_cb (void *cls,
1879 uint64_t num_peers,
1880 const struct GNUNET_PeerIdentity *peers)
1881{
1882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1883 "View was updated (%" PRIu64 ")\n", num_peers);
1884 struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
1885 for (int i = 0; i < num_peers; i++)
1886 {
1887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1888 "\t%s\n", GNUNET_i2s (&peers[i]));
1889 }
1890 GNUNET_array_grow (rps_peer->cur_view,
1891 rps_peer->cur_view_count,
1892 num_peers);
1893 //*rps_peer->cur_view = *peers;
1894 memcpy (rps_peer->cur_view,
1895 peers,
1896 num_peers * sizeof (struct GNUNET_PeerIdentity));
1897 all_views_updated_cb();
1898}
1899
1900static void
1901pre_profiler (struct RPSPeer *rps_peer, struct GNUNET_RPS_Handle *h)
1902{
1903 GNUNET_RPS_view_request (h, 0, view_update_cb, rps_peer);
1904}
1905
1791/** 1906/**
1792 * Continuation called by #GNUNET_STATISTICS_get() functions. 1907 * Continuation called by #GNUNET_STATISTICS_get() functions.
1793 * 1908 *
@@ -2009,6 +2124,11 @@ run (void *cls,
2009 rps_peers[i].index = i; 2124 rps_peers[i].index = i;
2010 if (NULL != cur_test_run.init_peer) 2125 if (NULL != cur_test_run.init_peer)
2011 cur_test_run.init_peer (&rps_peers[i]); 2126 cur_test_run.init_peer (&rps_peers[i]);
2127 if (NO_COLLECT_VIEW == cur_test_run.have_collect_view)
2128 {
2129 rps_peers->cur_view_count = 0;
2130 rps_peers->cur_view = NULL;
2131 }
2012 entry->op = GNUNET_TESTBED_peer_get_information (peers[i], 2132 entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
2013 GNUNET_TESTBED_PIT_IDENTITY, 2133 GNUNET_TESTBED_PIT_IDENTITY,
2014 &info_cb, 2134 &info_cb,
@@ -2067,6 +2187,7 @@ main (int argc, char *argv[])
2067{ 2187{
2068 int ret_value; 2188 int ret_value;
2069 2189
2190 /* Defaults for tests */
2070 num_peers = 5; 2191 num_peers = 5;
2071 cur_test_run.name = "test-rps-default"; 2192 cur_test_run.name = "test-rps-default";
2072 cur_test_run.init_peer = default_init_peer; 2193 cur_test_run.init_peer = default_init_peer;
@@ -2077,6 +2198,7 @@ main (int argc, char *argv[])
2077 cur_test_run.have_churn = HAVE_CHURN; 2198 cur_test_run.have_churn = HAVE_CHURN;
2078 cur_test_run.have_collect_statistics = NO_COLLECT_STATISTICS; 2199 cur_test_run.have_collect_statistics = NO_COLLECT_STATISTICS;
2079 cur_test_run.stat_collect_flags = 0; 2200 cur_test_run.stat_collect_flags = 0;
2201 cur_test_run.have_collect_view = NO_COLLECT_VIEW;
2080 churn_task = NULL; 2202 churn_task = NULL;
2081 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); 2203 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
2082 2204
@@ -2190,7 +2312,8 @@ main (int argc, char *argv[])
2190 num_peers = 10; 2312 num_peers = 10;
2191 mal_type = 3; 2313 mal_type = 3;
2192 cur_test_run.init_peer = profiler_init_peer; 2314 cur_test_run.init_peer = profiler_init_peer;
2193 cur_test_run.pre_test = mal_pre; 2315 //cur_test_run.pre_test = mal_pre;
2316 cur_test_run.pre_test = pre_profiler;
2194 cur_test_run.main_test = profiler_cb; 2317 cur_test_run.main_test = profiler_cb;
2195 cur_test_run.reply_handle = profiler_reply_handle; 2318 cur_test_run.reply_handle = profiler_reply_handle;
2196 cur_test_run.eval_cb = profiler_eval; 2319 cur_test_run.eval_cb = profiler_eval;
@@ -2216,6 +2339,7 @@ main (int argc, char *argv[])
2216 STAT_TYPE_RECV_PUSH_SEND | 2339 STAT_TYPE_RECV_PUSH_SEND |
2217 STAT_TYPE_RECV_PULL_REQ | 2340 STAT_TYPE_RECV_PULL_REQ |
2218 STAT_TYPE_RECV_PULL_REP; 2341 STAT_TYPE_RECV_PULL_REP;
2342 cur_test_run.have_collect_view = COLLECT_VIEW;
2219 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300); 2343 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300);
2220 2344
2221 /* 'Clean' directory */ 2345 /* 'Clean' directory */
@@ -2249,6 +2373,12 @@ main (int argc, char *argv[])
2249 } 2373 }
2250 2374
2251 ret_value = cur_test_run.eval_cb(); 2375 ret_value = cur_test_run.eval_cb();
2376 if (NO_COLLECT_VIEW == cur_test_run.have_collect_view)
2377 {
2378 GNUNET_array_grow (rps_peers->cur_view,
2379 rps_peers->cur_view_count,
2380 0);
2381 }
2252 GNUNET_free (rps_peers); 2382 GNUNET_free (rps_peers);
2253 GNUNET_free (rps_peer_ids); 2383 GNUNET_free (rps_peer_ids);
2254 GNUNET_CONTAINER_multipeermap_destroy (peer_map); 2384 GNUNET_CONTAINER_multipeermap_destroy (peer_map);