aboutsummaryrefslogtreecommitdiff
path: root/src/contrib/service/scalarproduct/gnunet-scalarproduct.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/service/scalarproduct/gnunet-scalarproduct.c')
-rw-r--r--src/contrib/service/scalarproduct/gnunet-scalarproduct.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/src/contrib/service/scalarproduct/gnunet-scalarproduct.c b/src/contrib/service/scalarproduct/gnunet-scalarproduct.c
new file mode 100644
index 000000000..5ebab5baf
--- /dev/null
+++ b/src/contrib/service/scalarproduct/gnunet-scalarproduct.c
@@ -0,0 +1,401 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2014 GNUnet e.V.
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file scalarproduct/gnunet-scalarproduct.c
23 * @brief scalarproduct client
24 * @author Christian M. Fuchs
25 */
26#define GCRYPT_NO_DEPRECATED
27#include "platform.h"
28#include <gcrypt.h>
29#include <inttypes.h>
30
31#include "gnunet_util_lib.h"
32#include "gnunet_scalarproduct_service.h"
33#include "gnunet_protocols.h"
34#include "scalarproduct.h"
35
36#define LOG(kind, ...) GNUNET_log_from (kind, "gnunet-scalarproduct", \
37 __VA_ARGS__)
38
39
40/**
41 * the session key identifying this computation
42 */
43static struct GNUNET_HashCode session_key;
44
45/**
46 * PeerID we want to compute a scalar product with
47 */
48static struct GNUNET_PeerIdentity peer_id;
49
50/**
51 * Option -p: destination peer identity for checking message-ids with
52 */
53static char *input_peer_id;
54
55/**
56 * Option -p: destination peer identity for checking message-ids with
57 */
58static char *input_session_key;
59
60/**
61 * Option -e: vector to calculate a scalarproduct with
62 */
63static char *input_elements;
64
65/**
66 * Global return value
67 */
68static int ret = -1;
69
70/**
71 * our Scalarproduct Computation handle
72 */
73static struct GNUNET_SCALARPRODUCT_ComputationHandle *computation;
74
75
76/**
77 * Callback called if we are initiating a new computation session
78 *
79 * @param cls unused
80 * @param status if our job was successfully processed
81 */
82static void
83responder_callback (void *cls,
84 enum GNUNET_SCALARPRODUCT_ResponseStatus status)
85{
86 switch (status)
87 {
88 case GNUNET_SCALARPRODUCT_STATUS_SUCCESS:
89 ret = 0;
90 LOG (GNUNET_ERROR_TYPE_INFO,
91 "Session %s concluded.\n",
92 GNUNET_h2s (&session_key));
93 break;
94
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));
99 break;
100
101 case GNUNET_SCALARPRODUCT_STATUS_FAILURE:
102 LOG (GNUNET_ERROR_TYPE_ERROR,
103 "Session %s failed: service failure\n",
104 GNUNET_h2s (&session_key));
105 break;
106
107 case GNUNET_SCALARPRODUCT_STATUS_DISCONNECTED:
108 LOG (GNUNET_ERROR_TYPE_ERROR,
109 "Session %s failed: service disconnect!\n",
110 GNUNET_h2s (&session_key));
111 break;
112
113 default:
114 LOG (GNUNET_ERROR_TYPE_ERROR,
115 "Session %s failed: return code %d\n",
116 GNUNET_h2s (&session_key),
117 status);
118 }
119 computation = NULL;
120 GNUNET_SCHEDULER_shutdown ();
121}
122
123
124/**
125 * Callback called if we are initiating a new computation session
126 *
127 * @param cls unused
128 * @param status if our job was successfully processed
129 * @param result the result in gnu/gcry MPI format
130 */
131static void
132requester_callback (void *cls,
133 enum GNUNET_SCALARPRODUCT_ResponseStatus status,
134 gcry_mpi_t result)
135{
136 unsigned char *buf;
137 gcry_error_t rc;
138
139 switch (status)
140 {
141 case GNUNET_SCALARPRODUCT_STATUS_SUCCESS:
142 if (0 == (rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, result)))
143 {
144 ret = 0;
145 fprintf (stdout,
146 "%s\n",
147 buf);
148 fflush (stdout);
149 }
150 else
151 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
152 "gcry_mpi_aprint",
153 rc);
154 break;
155
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));
161 break;
162
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));
168 break;
169
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));
175 break;
176
177 default:
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),
182 status);
183 }
184 computation = NULL;
185 GNUNET_SCHEDULER_shutdown ();
186}
187
188
189/**
190 * Task run during shutdown.
191 *
192 * @param cls unused
193 */
194static void
195shutdown_task (void *cls)
196{
197 if (NULL != computation)
198 {
199 GNUNET_SCALARPRODUCT_cancel (computation);
200 ret = 1; /* aborted */
201 }
202}
203
204
205/**
206 * Main function that will be run by the scheduler.
207 *
208 * @param cls closure
209 * @param args remaining command-line arguments
210 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
211 * @param cfg configuration
212 */
213static void
214run (void *cls,
215 char *const *args,
216 const char *cfgfile,
217 const struct GNUNET_CONFIGURATION_Handle *cfg)
218{
219 char *begin = input_elements;
220 char *end;
221 unsigned int i;
222 struct GNUNET_SCALARPRODUCT_Element *elements;
223 uint32_t element_count = 0;
224
225 if (NULL == input_elements)
226 {
227 LOG (GNUNET_ERROR_TYPE_ERROR,
228 _ ("You must specify at least one message ID to check!\n"));
229 return;
230 }
231 if ((NULL == input_session_key) ||
232 (0 == strlen (input_session_key)))
233 {
234 LOG (GNUNET_ERROR_TYPE_ERROR,
235 _ (
236 "This program needs a session identifier for comparing vectors.\n"));
237 return;
238 }
239 GNUNET_CRYPTO_hash (input_session_key,
240 strlen (input_session_key),
241 &session_key);
242 if ((NULL != input_peer_id) &&
243 (GNUNET_OK !=
244 GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id,
245 strlen (input_peer_id),
246 &peer_id.public_key)))
247 {
248 LOG (GNUNET_ERROR_TYPE_ERROR,
249 _ ("Tried to set initiator mode, as peer ID was given. "
250 "However, `%s' is not a valid peer identifier.\n"),
251 input_peer_id);
252 return;
253 }
254 if (('\'' == *begin) &&
255 ('\'' == begin[strlen (begin) - 1]))
256 {
257 begin[strlen (begin) - 1] = '\0';
258 if (strlen (begin) > 0)
259 begin++;
260 }
261 for (end = begin; 0 != *end; end++)
262 if (*end == ';')
263 element_count++;
264 if (0 == element_count)
265 {
266 LOG (GNUNET_ERROR_TYPE_ERROR,
267 _ ("Need elements to compute the scalarproduct, got none.\n"));
268 return;
269 }
270
271 elements = GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element)
272 * element_count);
273
274 for (i = 0; i < element_count; i++)
275 {
276 struct GNUNET_SCALARPRODUCT_Element element;
277 char*separator = NULL;
278
279 /* get the length of the current key,value; tuple */
280 for (end = begin; *end != ';'; end++)
281 if (*end == ',')
282 separator = end;
283
284 /* final element */
285 if ((NULL == separator) ||
286 (begin == separator) ||
287 (separator == end - 1))
288 {
289 LOG (GNUNET_ERROR_TYPE_ERROR,
290 _ ("Malformed input, could not parse `%s'\n"),
291 begin);
292 GNUNET_free (elements);
293 return;
294 }
295 *separator = 0;
296 /* read the element's key */
297 GNUNET_CRYPTO_hash (begin,
298 strlen (begin),
299 &element.key);
300
301 /* read the element's value */
302 if (1 !=
303 sscanf (separator + 1,
304 "%" SCNd64 ";",
305 &element.value))
306 {
307 LOG (GNUNET_ERROR_TYPE_ERROR,
308 _ ("Could not convert `%s' to int64_t.\n"),
309 begin);
310 GNUNET_free (elements);
311 return;
312 }
313 element.value = GNUNET_htonll (element.value);
314 elements[i] = element;
315 begin = end + 1;
316 }
317
318 if (((NULL != input_peer_id) &&
319 (NULL == (computation
320 = GNUNET_SCALARPRODUCT_start_computation (cfg,
321 &session_key,
322 &peer_id,
323 elements,
324 element_count,
325 &requester_callback,
326 NULL)))) ||
327 ((NULL == input_peer_id) &&
328 (NULL == (computation
329 = GNUNET_SCALARPRODUCT_accept_computation (cfg,
330 &session_key,
331 elements,
332 element_count,
333 &
334 responder_callback,
335 NULL)))))
336 {
337 fprintf (stderr,
338 _ ("Failed to initiate computation, were all keys unique?\n"));
339 GNUNET_free (elements);
340 return;
341 }
342 GNUNET_free (elements);
343 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
344 NULL);
345 ret = 0;
346}
347
348
349/**
350 * The main function to the scalarproduct client.
351 *
352 * @param argc number of arguments from the command line
353 * @param argv command line arguments
354 * @return 0 ok, 1 on error
355 */
356int
357main (int argc, char *const *argv)
358{
359 struct GNUNET_GETOPT_CommandLineOption options[] = {
360 GNUNET_GETOPT_option_string ('e',
361 "elements",
362 "\"key1,val1;key2,val2;...,keyn,valn;\"",
363 gettext_noop (
364 "A comma separated list of elements to compare as vector with our remote peer."),
365 &input_elements),
366
367 GNUNET_GETOPT_option_string ('e',
368 "elements",
369 "\"key1,val1;key2,val2;...,keyn,valn;\"",
370 gettext_noop (
371 "A comma separated list of elements to compare as vector with our remote peer."),
372 &input_elements),
373
374 GNUNET_GETOPT_option_string ('p',
375 "peer",
376 "PEERID",
377 gettext_noop (
378 "[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."),
379 &input_peer_id),
380
381 GNUNET_GETOPT_option_string ('k',
382 "key",
383 "TRANSACTION_ID",
384 gettext_noop (
385 "Transaction ID shared with peer."),
386 &input_session_key),
387
388 GNUNET_GETOPT_OPTION_END
389 };
390
391 return (GNUNET_OK ==
392 GNUNET_PROGRAM_run (argc,
393 argv,
394 "gnunet-scalarproduct",
395 gettext_noop (
396 "Calculate the Vectorproduct with a GNUnet peer."),
397 options, &run, NULL)) ? ret : 1;
398}
399
400
401/* end of gnunet-scalarproduct.c */