2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
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.
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.
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
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",__VA_ARGS__)
37 #define INPUTSTRINGLENGTH 1024
40 * A primitive closure structure holding information about our session
42 struct ScalarProductCallbackClosure
45 * the session key identifying this computation
47 struct GNUNET_HashCode session_key;
50 * PeerID we want to compute a scalar product with
52 struct GNUNET_PeerIdentity peer_id;
56 * Option -p: destination peer identity for checking message-ids with
58 static char *input_peer_id;
61 * Option -p: destination peer identity for checking message-ids with
63 static char *input_session_key;
66 * Option -e: vector to calculate a scalarproduct with
68 static char *input_elements;
76 * our Scalarproduct Computation handle
78 struct GNUNET_SCALARPRODUCT_ComputationHandle * computation;
81 * Callback called if we are initiating a new computation session
84 * @param status if our job was successfully processed
87 responder_callback (void *cls,
88 enum GNUNET_SCALARPRODUCT_ResponseStatus status)
90 struct ScalarProductCallbackClosure * closure = cls;
94 case GNUNET_SCALARPRODUCT_Status_Success:
96 LOG (GNUNET_ERROR_TYPE_INFO,
97 "Session %s concluded.\n",
98 GNUNET_h2s (&closure->session_key));
100 case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
101 LOG (GNUNET_ERROR_TYPE_ERROR,
102 "Session %s failed: invalid response\n",
103 GNUNET_h2s (&closure->session_key));
105 case GNUNET_SCALARPRODUCT_Status_Failure:
106 LOG (GNUNET_ERROR_TYPE_ERROR,
107 "Session %s failed: service failure\n",
108 GNUNET_h2s (&closure->session_key));
110 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
111 LOG (GNUNET_ERROR_TYPE_ERROR,
112 "Session %s failed: service disconnect!\n",
113 GNUNET_h2s (&closure->session_key));
116 LOG (GNUNET_ERROR_TYPE_ERROR,
117 "Session %s failed: return code %d\n",
118 GNUNET_h2s (&closure->session_key),
122 GNUNET_SCHEDULER_shutdown();
127 * Callback called if we are initiating a new computation session
130 * @param status if our job was successfully processed
131 * @param result the result in gnu/gcry MPI format
134 requester_callback (void *cls,
135 enum GNUNET_SCALARPRODUCT_ResponseStatus status,
138 struct ScalarProductCallbackClosure * closure = cls;
144 case GNUNET_SCALARPRODUCT_Status_Success:
145 if (0 == (rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, result)))
151 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
155 case GNUNET_SCALARPRODUCT_Status_InvalidResponse:
156 LOG (GNUNET_ERROR_TYPE_ERROR,
157 "Session %s with peer %s failed: invalid response received\n",
158 GNUNET_h2s (&closure->session_key),
159 GNUNET_i2s (&closure->peer_id));
161 case GNUNET_SCALARPRODUCT_Status_Failure:
162 LOG (GNUNET_ERROR_TYPE_ERROR,
163 "Session %s with peer %s failed: API failure\n",
164 GNUNET_h2s (&closure->session_key),
165 GNUNET_i2s (&closure->peer_id));
167 case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected:
168 LOG (GNUNET_ERROR_TYPE_ERROR,
169 "Session %s with peer %s was disconnected from service.\n",
170 GNUNET_h2s (&closure->session_key),
171 GNUNET_i2s (&closure->peer_id));
174 LOG (GNUNET_ERROR_TYPE_ERROR,
175 "Session %s with peer %s failed: return code %d\n",
176 GNUNET_h2s (&closure->session_key),
177 GNUNET_i2s (&closure->peer_id),
181 GNUNET_SCHEDULER_shutdown();
186 * Task run during shutdown.
192 shutdown_task (void *cls,
193 const struct GNUNET_SCHEDULER_TaskContext *tc)
195 if (NULL != computation)
196 GNUNET_SCALARPRODUCT_cancel(computation);
201 * Main function that will be run by the scheduler.
204 * @param args remaining command-line arguments
205 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
206 * @param cfg configuration
212 const struct GNUNET_CONFIGURATION_Handle *cfg)
214 char *begin = input_elements;
217 struct GNUNET_SCALARPRODUCT_Element * elements;
218 uint32_t element_count = 0;
219 struct ScalarProductCallbackClosure * closure;
221 if (NULL == input_elements)
223 LOG (GNUNET_ERROR_TYPE_ERROR,
224 _ ("You must specify at least one message ID to check!\n"));
228 if (NULL == input_session_key)
230 LOG (GNUNET_ERROR_TYPE_ERROR,
231 _ ("This program needs a session identifier for comparing vectors.\n"));
235 if (1 > strnlen (input_session_key, sizeof (struct GNUNET_HashCode)))
237 LOG (GNUNET_ERROR_TYPE_ERROR,
238 _ ("Please give a session key for --input_key!\n"));
241 closure = GNUNET_new (struct ScalarProductCallbackClosure);
242 GNUNET_CRYPTO_hash (input_session_key, strlen (input_session_key), &closure->session_key);
246 GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id,
247 strlen (input_peer_id),
248 (struct GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer_id))) {
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"),
256 for (end = begin; 0 != *end; end++)
259 if (0 == element_count) {
260 LOG (GNUNET_ERROR_TYPE_ERROR,
261 _ ("Need elements to compute the vectorproduct, got none.\n"));
265 elements = (struct GNUNET_SCALARPRODUCT_Element *)
266 GNUNET_malloc(sizeof(struct GNUNET_SCALARPRODUCT_Element)*element_count);
268 for (i = 0; i < element_count;i++)
270 struct GNUNET_SCALARPRODUCT_Element element;
271 char* separator=NULL;
273 // get the length of the current key,value; tupel
274 for (end = begin; *end != ';'; end++)
279 if ((NULL == separator)
280 || (begin == separator)
281 || (separator == end - 1 )) {
282 LOG (GNUNET_ERROR_TYPE_ERROR,
283 _ ("Malformed input, could not parse `%s'\n"), begin);
284 GNUNET_free(elements);
288 // read the element's key
290 GNUNET_CRYPTO_hash (begin, strlen (begin), &element.key);
292 // read the element's value
293 if (1 != sscanf (separator+1, "%" SCNd32 ";", &element.value))
295 LOG (GNUNET_ERROR_TYPE_ERROR,
296 _ ("Could not convert `%s' to int32_t.\n"), begin);
297 GNUNET_free(elements);
305 if (((NULL != input_peer_id) &&
306 (NULL == (computation = GNUNET_SCALARPRODUCT_start_computation (cfg,
307 &closure->session_key,
309 elements, element_count,
311 (void *) &closure))))
313 ((NULL == input_peer_id) &&
314 (NULL == (computation = GNUNET_SCALARPRODUCT_accept_computation (cfg,
315 &closure->session_key,
316 elements, element_count,
318 (void *) &closure)))))
320 GNUNET_free (elements);
324 GNUNET_free (elements);
325 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
334 * The main function to the scalarproduct client.
336 * @param argc number of arguments from the command line
337 * @param argv command line arguments
338 * @return 0 ok, 1 on error
341 main (int argc, char *const *argv)
343 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
344 {'e', "elements", "\"key1,val1;key2,val2;...,keyn,valn;\"",
345 gettext_noop ("A comma separated list of elements to compare as vector with our remote peer."),
346 1, &GNUNET_GETOPT_set_string, &input_elements},
347 {'p', "peer", "PEERID",
348 gettext_noop ("[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."),
349 1, &GNUNET_GETOPT_set_string, &input_peer_id},
350 {'k', "key", "TRANSACTION_ID",
351 gettext_noop ("Transaction ID shared with peer."),
352 1, &GNUNET_GETOPT_set_string, &input_session_key},
353 GNUNET_GETOPT_OPTION_END
357 GNUNET_PROGRAM_run (argc,
359 "gnunet-scalarproduct",
360 gettext_noop ("Calculate the Vectorproduct with a GNUnet peer."),
361 options, &run, NULL)) ? ret : 1;