small API change: do no longer pass rarely needed GNUNET_SCHEDULER_TaskContext to...
[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
30 static int ret;
31
32 /**
33  * RPS handle
34  */
35 static struct GNUNET_RPS_Handle *rps_handle;
36
37 /**
38  * Request handle
39  */
40 static struct GNUNET_RPS_Request_Handle *req_handle;
41
42 /**
43  * PeerID (Option --seed)
44  */
45 static struct GNUNET_PeerIdentity *peer_id;
46
47
48 /**
49  * Shutdown task
50  */
51 static struct GNUNET_SCHEDULER_Task *shutdown_task;
52
53
54 /**
55  * Set an option of type 'struct GNUNET_PeerIdentity *' from the command line.
56  * A pointer to this function should be passed as part of the
57  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
58  * of this type.  It should be followed by a pointer to a value of
59  * type 'struct GNUNET_PeerIdentity *', which will be allocated with the requested string.
60  *
61  * @param ctx command line processing context
62  * @param scls additional closure (will point to the 'char *',
63  *             which will be allocated)
64  * @param option name of the option
65  * @param value actual value of the option (a PeerID)
66  * @return #GNUNET_OK
67  */
68 static int
69 GNUNET_GETOPT_set_peerid (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
70                           void *scls, const char *option, const char *value)
71 {
72   struct GNUNET_PeerIdentity **val = (struct GNUNET_PeerIdentity **) scls;
73
74   GNUNET_assert (NULL != value);
75   GNUNET_free_non_null (*val);
76   /* Not quite sure whether that is a sane way */
77   *val = GNUNET_new (struct GNUNET_PeerIdentity);
78   if (GNUNET_OK !=
79       GNUNET_CRYPTO_eddsa_public_key_from_string (value,
80                                                   strlen (value),
81                                                   &((*val)->public_key)))
82   {
83     FPRINTF (stderr, "Invalid peer ID %s\n", value);
84     return GNUNET_SYSERR;
85   }
86   return GNUNET_OK;
87 }
88
89
90 /**
91  * Task run when user presses CTRL-C to abort.
92  * Cancels pending request and disconnects.
93  *
94  * @param cls NULL
95  */
96 static void
97 do_shutdown (void *cls)
98 {
99   shutdown_task = NULL;
100   if (NULL != req_handle)
101     GNUNET_RPS_request_cancel (req_handle);
102   GNUNET_RPS_disconnect (rps_handle);
103 }
104
105
106 /**
107  * Callback called on receipt of reply.
108  * Prints replied PeerIDs.
109  *
110  * @param cls closure
111  * @param n number of peers
112  * @param recv_peers the received peers
113  */
114 static void
115 reply_handle (void *cls,
116               uint64_t n,
117               const struct GNUNET_PeerIdentity *recv_peers)
118 {
119   uint64_t i;
120
121   req_handle = NULL;
122   for (i = 0; i < n; i++)
123   {
124     FPRINTF (stdout, "%s\n",
125         GNUNET_i2s_full (&recv_peers[i]));
126   }
127   ret = 0;
128
129   GNUNET_SCHEDULER_cancel (shutdown_task);
130   GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
131 }
132
133
134 /**
135  * Main function that will be run by the scheduler.
136  *
137  * @param cls closure
138  * @param args remaining command-line arguments
139  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
140  * @param cfg configuration
141  */
142 static void
143 run (void *cls,
144      char *const *args,
145      const char *cfgfile,
146      const struct GNUNET_CONFIGURATION_Handle *cfg)
147 {
148   static uint64_t num_peers;
149
150   rps_handle = GNUNET_RPS_connect (cfg);
151
152   if (NULL == peer_id)
153   { /* Request n PeerIDs */
154     /* If number was specified use it, else request single peer. */
155     num_peers = (NULL == args[0]) ? 1 : atoi (args[0]);
156     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157         "Requesting %u PeerIDs\n", num_peers);
158     req_handle = GNUNET_RPS_request_peers (rps_handle, num_peers, reply_handle, NULL);
159     shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
160         &do_shutdown, NULL);
161   }
162   else
163   { /* Seed PeerID */
164     GNUNET_RPS_seed_ids (rps_handle, 1, peer_id);
165     FPRINTF (stdout, "Seeded PeerID %s\n", GNUNET_i2s_full (peer_id));
166     ret = 0;
167     GNUNET_SCHEDULER_add_now (do_shutdown, NULL);
168   }
169 }
170
171 /**
172  * The main function to rps.
173  *
174  * @param argc number of arguments from the command line
175  * @param argv command line arguments
176  * @return 0 ok, 1 on error
177  */
178 int
179 main (int argc, char *const *argv)
180 {
181   const char helpstr[] =
182     "Get random GNUnet peers. If none is specified a single is requested.";
183   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
184     {'s', "seed", "PEER_ID",
185       gettext_noop ("Seed a PeerID"),
186       GNUNET_YES, &GNUNET_GETOPT_set_peerid, &peer_id},
187     GNUNET_GETOPT_OPTION_END
188   };
189   return (GNUNET_OK ==
190           GNUNET_PROGRAM_run (argc,
191                               argv,
192                               "gnunet-rps [NUMBER_OF_PEERS]",
193                               gettext_noop
194                               (helpstr),
195                               options, &run, NULL)) ? ret : 1;
196 }
197
198 /* end of gnunet-rps.c */