add some extra GNS-record well-formedness checks if logging is enabled
[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
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file rps/gnunet-rps.c
23  * @brief random peer sampling
24  * @author Julius Bünger
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_rps_service.h"
29 #include <inttypes.h>
30
31 static int ret;
32
33 /**
34  * RPS handle
35  */
36 static struct GNUNET_RPS_Handle *rps_handle;
37
38 /**
39  * Request handle
40  */
41 static struct GNUNET_RPS_Request_Handle *req_handle;
42
43 /**
44  * PeerID (Option --seed)
45  */
46 static struct GNUNET_PeerIdentity peer_id;
47
48 /**
49  * @brief Do we want to receive updates of the view? (Option --view)
50  */
51 static int view_update;
52
53 /**
54  * @brief Number of updates we want to receive
55  */
56 static uint64_t num_view_updates;
57
58
59 /**
60  * Task run when user presses CTRL-C to abort.
61  * Cancels pending request and disconnects.
62  *
63  * @param cls NULL
64  */
65 static void
66 do_shutdown (void *cls)
67 {
68   if (NULL != req_handle)
69     GNUNET_RPS_request_cancel (req_handle);
70   GNUNET_RPS_disconnect (rps_handle);
71 }
72
73
74 /**
75  * Callback called on receipt of reply.
76  * Prints replied PeerIDs.
77  *
78  * @param cls closure
79  * @param n number of peers
80  * @param recv_peers the received peers
81  */
82 static void
83 reply_handle (void *cls,
84               uint64_t n,
85               const struct GNUNET_PeerIdentity *recv_peers)
86 {
87   uint64_t i;
88
89   req_handle = NULL;
90   for (i = 0; i < n; i++)
91   {
92     FPRINTF (stdout, "%s\n",
93         GNUNET_i2s_full (&recv_peers[i]));
94   }
95   ret = 0;
96
97   GNUNET_SCHEDULER_shutdown ();
98 }
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  */
107 static void
108 view_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
136
137 /**
138  * Main function that will be run by the scheduler.
139  *
140  * @param cls closure
141  * @param args remaining command-line arguments
142  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
143  * @param cfg configuration
144  */
145 static void
146 run (void *cls,
147      char *const *args,
148      const char *cfgfile,
149      const struct GNUNET_CONFIGURATION_Handle *cfg)
150 {
151   static uint64_t num_peers;
152   static struct GNUNET_PeerIdentity zero_pid;
153
154   rps_handle = GNUNET_RPS_connect (cfg);
155
156   if ((0 == memcmp (&zero_pid, &peer_id, sizeof (peer_id))) &&
157       (!view_update))
158   { /* Request n PeerIDs */
159     /* If number was specified use it, else request single peer. */
160     num_peers = (NULL == args[0]) ? 1 : atoi (args[0]);
161     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162         "Requesting %" PRIu64 " PeerIDs\n", num_peers);
163     req_handle = GNUNET_RPS_request_peers (rps_handle, num_peers, reply_handle, 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);
177   }
178   else
179   { /* Seed PeerID */
180     GNUNET_RPS_seed_ids (rps_handle, 1, &peer_id);
181     FPRINTF (stdout, "Seeded PeerID %s\n", GNUNET_i2s_full (&peer_id));
182     ret = 0;
183     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
184   }
185 }
186
187 /**
188  * The main function to rps.
189  *
190  * @param argc number of arguments from the command line
191  * @param argv command line arguments
192  * @return 0 ok, 1 on error
193  */
194 int
195 main (int argc, char *const *argv)
196 {
197   const char helpstr[] =
198     "Get random GNUnet peers. If none is specified a single is requested.";
199   struct GNUNET_GETOPT_CommandLineOption options[] = {
200     GNUNET_GETOPT_option_base32_auto ('s',
201                                           "seed",
202                                           "PEER_ID",
203                                           gettext_noop ("Seed a PeerID"),
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),
209     GNUNET_GETOPT_OPTION_END
210   };
211   return (GNUNET_OK ==
212           GNUNET_PROGRAM_run (argc,
213                               argv,
214                               "gnunet-rps [NUMBER_OF_PEERS]",
215                               gettext_noop
216                               (helpstr),
217                               options, &run, NULL)) ? ret : 1;
218 }
219
220 /* end of gnunet-rps.c */