paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / rps / gnunet-rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C)
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
19 /**
20  * @file rps/gnunet-rps.c
21  * @brief random peer sampling
22  * @author Julius Bünger
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_rps_service.h"
27 #include <inttypes.h>
28
29 static int ret;
30
31 /**
32  * RPS handle
33  */
34 static struct GNUNET_RPS_Handle *rps_handle;
35
36 /**
37  * Request handle
38  */
39 static struct GNUNET_RPS_Request_Handle *req_handle;
40
41 /**
42  * PeerID (Option --seed)
43  */
44 static struct GNUNET_PeerIdentity peer_id;
45
46 /**
47  * @brief Do we want to receive updates of the view? (Option --view)
48  */
49 static int view_update;
50
51 /**
52  * @brief Number of updates we want to receive
53  */
54 static uint64_t num_view_updates;
55
56
57 /**
58  * Task run when user presses CTRL-C to abort.
59  * Cancels pending request and disconnects.
60  *
61  * @param cls NULL
62  */
63 static void
64 do_shutdown (void *cls)
65 {
66   if (NULL != req_handle)
67     GNUNET_RPS_request_cancel (req_handle);
68   GNUNET_RPS_disconnect (rps_handle);
69 }
70
71
72 /**
73  * Callback called on receipt of reply.
74  * Prints replied PeerIDs.
75  *
76  * @param cls closure
77  * @param n number of peers
78  * @param recv_peers the received peers
79  */
80 static void
81 reply_handle (void *cls,
82               uint64_t n,
83               const struct GNUNET_PeerIdentity *recv_peers)
84 {
85   uint64_t i;
86
87   req_handle = NULL;
88   for (i = 0; i < n; i++)
89   {
90     FPRINTF (stdout, "%s\n",
91         GNUNET_i2s_full (&recv_peers[i]));
92   }
93   ret = 0;
94
95   GNUNET_SCHEDULER_shutdown ();
96 }
97
98 /**
99  * Callback called on receipt view update.
100  * Prints view.
101  *
102  * @param n number of peers
103  * @param recv_peers the received peers
104  */
105 static void
106 view_update_handle (void *cls,
107                     uint64_t n,
108                     const struct GNUNET_PeerIdentity *recv_peers)
109 {
110   uint64_t i;
111
112   if (0 == n)
113   {
114     FPRINTF (stdout, "Empty view\n");
115   }
116   req_handle = NULL;
117   for (i = 0; i < n; i++)
118   {
119     FPRINTF (stdout, "%s\n",
120         GNUNET_i2s_full (&recv_peers[i]));
121   }
122
123   if (1 == num_view_updates)
124   {
125     ret = 0;
126     GNUNET_SCHEDULER_shutdown ();
127   }
128   else if (1 < num_view_updates)
129   {
130     num_view_updates--;
131   }
132 }
133
134
135 /**
136  * Main function that will be run by the scheduler.
137  *
138  * @param cls closure
139  * @param args remaining command-line arguments
140  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
141  * @param cfg configuration
142  */
143 static void
144 run (void *cls,
145      char *const *args,
146      const char *cfgfile,
147      const struct GNUNET_CONFIGURATION_Handle *cfg)
148 {
149   static uint64_t num_peers;
150   static struct GNUNET_PeerIdentity zero_pid;
151
152   rps_handle = GNUNET_RPS_connect (cfg);
153
154   if ((0 == memcmp (&zero_pid, &peer_id, sizeof (peer_id))) &&
155       (!view_update))
156   { /* Request n PeerIDs */
157     /* If number was specified use it, else request single peer. */
158     num_peers = (NULL == args[0]) ? 1 : atoi (args[0]);
159     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
160         "Requesting %" PRIu64 " PeerIDs\n", num_peers);
161     req_handle = GNUNET_RPS_request_peers (rps_handle, num_peers, reply_handle, NULL);
162     GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
163   } else if (view_update)
164   {
165     /* Get updates of view */
166     num_view_updates = (NULL == args[0]) ? 0 : atoi (args[0]);
167     GNUNET_RPS_view_request (rps_handle, num_view_updates, view_update_handle, NULL);
168     if (0 != num_view_updates)
169       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
170           "Requesting %" PRIu64 " view updates\n", num_view_updates);
171     else
172       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
173           "Requesting contiuous view updates\n");
174     GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
175   }
176   else
177   { /* Seed PeerID */
178     GNUNET_RPS_seed_ids (rps_handle, 1, &peer_id);
179     FPRINTF (stdout, "Seeded PeerID %s\n", GNUNET_i2s_full (&peer_id));
180     ret = 0;
181     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
182   }
183 }
184
185 /**
186  * The main function to rps.
187  *
188  * @param argc number of arguments from the command line
189  * @param argv command line arguments
190  * @return 0 ok, 1 on error
191  */
192 int
193 main (int argc, char *const *argv)
194 {
195   const char helpstr[] =
196     "Get random GNUnet peers. If none is specified a single is requested.";
197   struct GNUNET_GETOPT_CommandLineOption options[] = {
198     GNUNET_GETOPT_option_base32_auto ('s',
199                                           "seed",
200                                           "PEER_ID",
201                                           gettext_noop ("Seed a PeerID"),
202                                           &peer_id),
203     GNUNET_GETOPT_option_flag ('V',
204                                "view",
205                                gettext_noop ("Get updates of view (0 for infinite updates)"),
206                                &view_update),
207     GNUNET_GETOPT_OPTION_END
208   };
209   return (GNUNET_OK ==
210           GNUNET_PROGRAM_run (argc,
211                               argv,
212                               "gnunet-rps [NUMBER_OF_PEERS]",
213                               gettext_noop
214                               (helpstr),
215                               options, &run, NULL)) ? ret : 1;
216 }
217
218 /* end of gnunet-rps.c */