2 This file is part of GNUnet.
3 Copyright (C) 2013, 2014 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file scalarproduct/gnunet-scalarproduct.c
23 * @brief scalarproduct client
24 * @author Christian M. Fuchs
26 #define GCRYPT_NO_DEPRECATED
31 #include "gnunet_util_lib.h"
32 #include "gnunet_scalarproduct_service.h"
33 #include "gnunet_protocols.h"
34 #include "scalarproduct.h"
36 #define LOG(kind, ...) GNUNET_log_from (kind, "gnunet-scalarproduct", \
41 * the session key identifying this computation
43 static struct GNUNET_HashCode session_key;
46 * PeerID we want to compute a scalar product with
48 static struct GNUNET_PeerIdentity peer_id;
51 * Option -p: destination peer identity for checking message-ids with
53 static char *input_peer_id;
56 * Option -p: destination peer identity for checking message-ids with
58 static char *input_session_key;
61 * Option -e: vector to calculate a scalarproduct with
63 static char *input_elements;
71 * our Scalarproduct Computation handle
73 static struct GNUNET_SCALARPRODUCT_ComputationHandle *computation;
77 * Callback called if we are initiating a new computation session
80 * @param status if our job was successfully processed
83 responder_callback (void *cls,
84 enum GNUNET_SCALARPRODUCT_ResponseStatus status)
88 case GNUNET_SCALARPRODUCT_STATUS_SUCCESS:
90 LOG (GNUNET_ERROR_TYPE_INFO,
91 "Session %s concluded.\n",
92 GNUNET_h2s (&session_key));
95 case GNUNET_SCALARPRODUCT_STATUS_INVALID_RESPONSE:
96 LOG (GNUNET_ERROR_TYPE_ERROR,
97 "Session %s failed: invalid response\n",
98 GNUNET_h2s (&session_key));
101 case GNUNET_SCALARPRODUCT_STATUS_FAILURE:
102 LOG (GNUNET_ERROR_TYPE_ERROR,
103 "Session %s failed: service failure\n",
104 GNUNET_h2s (&session_key));
107 case GNUNET_SCALARPRODUCT_STATUS_DISCONNECTED:
108 LOG (GNUNET_ERROR_TYPE_ERROR,
109 "Session %s failed: service disconnect!\n",
110 GNUNET_h2s (&session_key));
114 LOG (GNUNET_ERROR_TYPE_ERROR,
115 "Session %s failed: return code %d\n",
116 GNUNET_h2s (&session_key),
120 GNUNET_SCHEDULER_shutdown ();
125 * Callback called if we are initiating a new computation session
128 * @param status if our job was successfully processed
129 * @param result the result in gnu/gcry MPI format
132 requester_callback (void *cls,
133 enum GNUNET_SCALARPRODUCT_ResponseStatus status,
141 case GNUNET_SCALARPRODUCT_STATUS_SUCCESS:
142 if (0 == (rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, result)))
151 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
156 case GNUNET_SCALARPRODUCT_STATUS_INVALID_RESPONSE:
157 LOG (GNUNET_ERROR_TYPE_ERROR,
158 "Session %s with peer %s failed: invalid response received\n",
159 GNUNET_h2s (&session_key),
160 GNUNET_i2s (&peer_id));
163 case GNUNET_SCALARPRODUCT_STATUS_FAILURE:
164 LOG (GNUNET_ERROR_TYPE_ERROR,
165 "Session %s with peer %s failed: API failure\n",
166 GNUNET_h2s (&session_key),
167 GNUNET_i2s (&peer_id));
170 case GNUNET_SCALARPRODUCT_STATUS_DISCONNECTED:
171 LOG (GNUNET_ERROR_TYPE_ERROR,
172 "Session %s with peer %s was disconnected from service.\n",
173 GNUNET_h2s (&session_key),
174 GNUNET_i2s (&peer_id));
178 LOG (GNUNET_ERROR_TYPE_ERROR,
179 "Session %s with peer %s failed: return code %d\n",
180 GNUNET_h2s (&session_key),
181 GNUNET_i2s (&peer_id),
185 GNUNET_SCHEDULER_shutdown ();
190 * Task run during shutdown.
196 shutdown_task (void *cls)
198 if (NULL != computation)
200 GNUNET_SCALARPRODUCT_cancel (computation);
201 ret = 1; /* aborted */
207 * Main function that will be run by the scheduler.
210 * @param args remaining command-line arguments
211 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
212 * @param cfg configuration
218 const struct GNUNET_CONFIGURATION_Handle *cfg)
220 char *begin = input_elements;
223 struct GNUNET_SCALARPRODUCT_Element *elements;
224 uint32_t element_count = 0;
226 if (NULL == input_elements)
228 LOG (GNUNET_ERROR_TYPE_ERROR,
229 _ ("You must specify at least one message ID to check!\n"));
232 if ((NULL == input_session_key) ||
233 (0 == strlen (input_session_key)))
235 LOG (GNUNET_ERROR_TYPE_ERROR,
237 "This program needs a session identifier for comparing vectors.\n"));
240 GNUNET_CRYPTO_hash (input_session_key,
241 strlen (input_session_key),
243 if ((NULL != input_peer_id) &&
245 GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id,
246 strlen (input_peer_id),
247 &peer_id.public_key)))
249 LOG (GNUNET_ERROR_TYPE_ERROR,
250 _ ("Tried to set initiator mode, as peer ID was given. "
251 "However, `%s' is not a valid peer identifier.\n"),
255 if (('\'' == *begin) &&
256 ('\'' == begin[strlen (begin) - 1]))
258 begin[strlen (begin) - 1] = '\0';
259 if (strlen (begin) > 0)
262 for (end = begin; 0 != *end; end++)
265 if (0 == element_count)
267 LOG (GNUNET_ERROR_TYPE_ERROR,
268 _ ("Need elements to compute the scalarproduct, got none.\n"));
272 elements = GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element)
275 for (i = 0; i < element_count; i++)
277 struct GNUNET_SCALARPRODUCT_Element element;
278 char*separator = NULL;
280 /* get the length of the current key,value; tupel */
281 for (end = begin; *end != ';'; end++)
286 if ((NULL == separator) ||
287 (begin == separator) ||
288 (separator == end - 1))
290 LOG (GNUNET_ERROR_TYPE_ERROR,
291 _ ("Malformed input, could not parse `%s'\n"),
293 GNUNET_free (elements);
297 /* read the element's key */
298 GNUNET_CRYPTO_hash (begin,
302 /* read the element's value */
304 sscanf (separator + 1,
308 LOG (GNUNET_ERROR_TYPE_ERROR,
309 _ ("Could not convert `%s' to int64_t.\n"),
311 GNUNET_free (elements);
314 element.value = GNUNET_htonll (element.value);
315 elements[i] = element;
319 if (((NULL != input_peer_id) &&
320 (NULL == (computation
321 = GNUNET_SCALARPRODUCT_start_computation (cfg,
328 ((NULL == input_peer_id) &&
329 (NULL == (computation
330 = GNUNET_SCALARPRODUCT_accept_computation (cfg,
339 _ ("Failed to initiate computation, were all keys unique?\n"));
340 GNUNET_free (elements);
343 GNUNET_free (elements);
344 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
351 * The main function to the scalarproduct client.
353 * @param argc number of arguments from the command line
354 * @param argv command line arguments
355 * @return 0 ok, 1 on error
358 main (int argc, char *const *argv)
360 struct GNUNET_GETOPT_CommandLineOption options[] = {
361 GNUNET_GETOPT_option_string ('e',
363 "\"key1,val1;key2,val2;...,keyn,valn;\"",
365 "A comma separated list of elements to compare as vector with our remote peer."),
368 GNUNET_GETOPT_option_string ('e',
370 "\"key1,val1;key2,val2;...,keyn,valn;\"",
372 "A comma separated list of elements to compare as vector with our remote peer."),
375 GNUNET_GETOPT_option_string ('p',
379 "[Optional] peer to calculate our scalarproduct with. If this parameter is not given, the service will wait for a remote peer to compute the request."),
382 GNUNET_GETOPT_option_string ('k',
386 "Transaction ID shared with peer."),
389 GNUNET_GETOPT_OPTION_END
393 GNUNET_PROGRAM_run (argc,
395 "gnunet-scalarproduct",
397 "Calculate the Vectorproduct with a GNUnet peer."),
398 options, &run, NULL)) ? ret : 1;
402 /* end of gnunet-scalarproduct.c */