GNUnet  0.11.x
scalarproduct_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2013, 2014, 2016 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  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
31 #include "gnunet_protocols.h"
32 #include "scalarproduct.h"
33 
34 #define LOG(kind, ...) GNUNET_log_from (kind, "scalarproduct-api", __VA_ARGS__)
35 
36 
44 typedef void
47  *h,
48  const struct
50  enum
52  status);
53 
54 
59 {
64 
69 
74 
79 
83  void *cont_cls;
84 
90 
95 };
96 
97 
106 static int
107 check_response (void *cls,
108  const struct ClientResponseMessage *message)
109 {
110  if (ntohs (message->header.size) !=
111  ntohl (message->product_length) + sizeof(struct ClientResponseMessage))
112  {
113  GNUNET_break (0);
114  return GNUNET_SYSERR;
115  }
116  return GNUNET_OK;
117 }
118 
119 
129 static void
131  const struct ClientResponseMessage *msg,
133 {
134  if (NULL != h->cont_status)
135  h->cont_status (h->cont_cls,
136  status);
138 }
139 
140 
149 static void
150 handle_response (void *cls,
151  const struct ClientResponseMessage *message)
152 {
155 
156  status = (enum GNUNET_SCALARPRODUCT_ResponseStatus) ntohl (message->status);
157  h->response_proc (h,
158  message,
159  status);
160 }
161 
162 
170 static int
172  uint32_t element_count)
173 {
175  uint32_t i;
176  int ok;
177 
178  ok = GNUNET_OK;
179  map = GNUNET_CONTAINER_multihashmap_create (2 * element_count,
180  GNUNET_YES);
181  for (i = 0; i < element_count; i++)
182  if (GNUNET_OK !=
184  &elements[i].key,
185  map,
187  {
189  _ ("Keys given to SCALARPRODUCT not unique!\n"));
190  ok = GNUNET_SYSERR;
191  }
193  return ok;
194 }
195 
196 
204 static void
205 mq_error_handler (void *cls,
206  enum GNUNET_MQ_Error error)
207 {
209 
211  "Disconnected from SCALARPRODUCT service.\n");
212  h->response_proc (h,
213  NULL,
215 }
216 
217 
232  const struct
234  const struct
236  uint32_t element_count,
238  cont,
239  void *cont_cls)
240 {
243  struct GNUNET_MQ_MessageHandler handlers[] = {
246  struct ClientResponseMessage,
247  h),
249  };
250  struct GNUNET_MQ_Envelope *env;
251  struct BobComputationMessage *msg;
253  uint32_t size;
254  uint16_t possible;
255  uint16_t todo;
256  uint32_t element_count_transfered;
257 
258 
259  if (GNUNET_SYSERR == check_unique (elements,
260  element_count))
261  return NULL;
262  h->cont_status = cont;
263  h->cont_cls = cont_cls;
265  h->cfg = cfg;
266  h->key = *session_key;
267  h->mq = GNUNET_CLIENT_connect (cfg,
268  "scalarproduct-bob",
269  handlers,
271  h);
272  if (NULL == h->mq)
273  {
274  /* scalarproduct configuration error */
275  GNUNET_break (0);
276  GNUNET_free (h);
277  return NULL;
278  }
279  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct
281  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
282  todo = GNUNET_MIN (possible,
283  element_count);
284  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
285  env = GNUNET_MQ_msg_extra (msg,
286  size,
288  msg->element_count_total = htonl (element_count);
289  msg->element_count_contained = htonl (todo);
290  msg->session_key = *session_key;
291  GNUNET_memcpy (&msg[1],
292  elements,
293  size);
294  element_count_transfered = todo;
295  GNUNET_MQ_send (h->mq,
296  env);
297  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
298  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
299  while (element_count_transfered < element_count)
300  {
301  todo = GNUNET_MIN (possible,
302  element_count - element_count_transfered);
303  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
304  env = GNUNET_MQ_msg_extra (mmsg,
305  size,
307  mmsg->element_count_contained = htonl (todo);
308  GNUNET_memcpy (&mmsg[1],
309  &elements[element_count_transfered],
310  size);
311  element_count_transfered += todo;
312  GNUNET_MQ_send (h->mq,
313  env);
314  }
315  return h;
316 }
317 
318 
328 static void
330  const struct ClientResponseMessage *msg,
332 {
333  uint32_t product_len;
334  gcry_mpi_t result = NULL;
335  gcry_error_t rc;
336  gcry_mpi_t num;
337  size_t rsize;
338 
340  {
341  result = gcry_mpi_new (0);
342 
343  product_len = ntohl (msg->product_length);
344  if (0 < product_len)
345  {
346  rsize = 0;
347  if (0 != (rc = gcry_mpi_scan (&num, GCRYMPI_FMT_STD,
348  &msg[1],
349  product_len,
350  &rsize)))
351  {
353  "gcry_mpi_scan",
354  rc);
355  gcry_mpi_release (result);
356  result = NULL;
358  }
359  else
360  {
361  if (0 < (int32_t) ntohl (msg->range))
362  gcry_mpi_add (result, result, num);
363  else
364  gcry_mpi_sub (result, result, num);
365  gcry_mpi_release (num);
366  }
367  }
368  }
369  if (NULL != h->cont_datum)
370  h->cont_datum (h->cont_cls,
371  status,
372  result);
373  if (NULL != result)
374  gcry_mpi_release (result);
376 }
377 
378 
394  const struct
396  const struct GNUNET_PeerIdentity *peer,
397  const struct
399  uint32_t element_count,
401  void *cont_cls)
402 {
405  struct GNUNET_MQ_MessageHandler handlers[] = {
408  struct ClientResponseMessage,
409  h),
411  };
412  struct GNUNET_MQ_Envelope *env;
415  uint32_t size;
416  uint16_t possible;
417  uint16_t todo;
418  uint32_t element_count_transfered;
419 
420  if (GNUNET_SYSERR == check_unique (elements,
421  element_count))
422  return NULL;
423  h->mq = GNUNET_CLIENT_connect (cfg,
424  "scalarproduct-alice",
425  handlers,
427  h);
428  if (NULL == h->mq)
429  {
430  /* missconfigured scalarproduct service */
431  GNUNET_break (0);
432  GNUNET_free (h);
433  return NULL;
434  }
435  h->cont_datum = cont;
436  h->cont_cls = cont_cls;
438  h->cfg = cfg;
439  h->key = *session_key;
440 
441  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct
443  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
444  todo = GNUNET_MIN (possible,
445  element_count);
446  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
447  env = GNUNET_MQ_msg_extra (msg,
448  size,
450  msg->element_count_total = htonl (element_count);
451  msg->element_count_contained = htonl (todo);
452  msg->reserved = htonl (0);
453  msg->peer = *peer;
454  msg->session_key = *session_key;
455  GNUNET_memcpy (&msg[1],
456  elements,
457  size);
458  GNUNET_MQ_send (h->mq,
459  env);
460  element_count_transfered = todo;
461  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
462  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
463  while (element_count_transfered < element_count)
464  {
465  todo = GNUNET_MIN (possible,
466  element_count - element_count_transfered);
467  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
468  env = GNUNET_MQ_msg_extra (mmsg,
469  size,
471  mmsg->element_count_contained = htonl (todo);
472  GNUNET_memcpy (&mmsg[1],
473  &elements[element_count_transfered],
474  size);
475  element_count_transfered += todo;
476  GNUNET_MQ_send (h->mq,
477  env);
478  }
479  return h;
480 }
481 
482 
489 void
491 {
492  if (NULL != h->mq)
493  {
494  GNUNET_MQ_destroy (h->mq);
495  h->mq = NULL;
496  }
497  GNUNET_free (h);
498 }
499 
500 
501 /* end of scalarproduct_api.c */
A handle returned for each computation.
Message type passed from service client to finalize a session as requester or responder.
static int check_response(void *cls, const struct ClientResponseMessage *message)
Called when a response is received from the service.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_ALICE
Client -> Alice multipart.
struct GNUNET_HashCode key
The shared session key identifying this computation.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
GNUNET_SCALARPRODUCT_DatumProcessor cont_datum
Function to call after transmission of the request (Alice).
uint32_t element_count_total
how many elements the vector in payload contains
Definition: scalarproduct.h:99
GNUNET_MQ_Error
Error codes for the queue.
static void handle_response(void *cls, const struct ClientResponseMessage *message)
Called when a response is received from the service.
int32_t range
Workaround for libgcrypt: -1 if negative, 0 if zero, else 1.
#define LOG_GCRY(level, cmd, rc)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
Definition: scalarproduct.h:35
static void process_result_message(struct GNUNET_SCALARPRODUCT_ComputationHandle *h, const struct ClientResponseMessage *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status)
Handles the RESULT received from the service for a request, should contain a result MPI value...
static int ok
Return value from &#39;main&#39; (0 == success)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_accept_computation(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *session_key, const struct GNUNET_SCALARPRODUCT_Element *elements, uint32_t element_count, GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, void *cont_cls)
Used by Bob&#39;s client to cooperate with Alice,.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB
Client -> Bob.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
uint32_t reserved
Always zero.
Definition: scalarproduct.h:66
Internal representation of the hash map.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:45
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
struct GNUNET_HashCode session_key
the transaction/session key used to identify a session
Definition: scalarproduct.h:71
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
void GNUNET_SCALARPRODUCT_cancel(struct GNUNET_SCALARPRODUCT_ComputationHandle *h)
Cancel an ongoing computation or revoke our collaboration offer.
uint32_t status
Status information about the outcome of this session, An enum GNUNET_SCALARPRODUCT_ResponseStatus (in...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
static struct GNUNET_HashCode session_key
the session key identifying this computation
struct GNUNET_MessageHeader header
GNUNET message header.
struct GNUNET_PeerIdentity peer
the identity of a remote peer we want to communicate with
Definition: scalarproduct.h:76
Scalar Product API Message Types.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
#define GNUNET_MIN(a, b)
Definition: gnunet_common.h:80
uint32_t element_count_total
how many elements the vector in payload contains
Definition: scalarproduct.h:56
uint16_t status
See PRISM_STATUS_*-constants.
void(* GNUNET_SCALARPRODUCT_ResponseMessageHandler)(struct GNUNET_SCALARPRODUCT_ComputationHandle *h, const struct ClientResponseMessage *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status)
The abstraction function for our internal callback.
static int result
Global testing status.
static void process_status_message(struct GNUNET_SCALARPRODUCT_ComputationHandle *h, const struct ClientResponseMessage *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status)
Handles the STATUS received from the service for a response, does not contain a payload.
We got disconnected from the SCALARPRODUCT service.
A 512-bit hashcode.
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
We encountered an error communicating with the set service while performing a set operation...
Message handler for a specific message type.
void(* GNUNET_SCALARPRODUCT_DatumProcessor)(void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status, gcry_mpi_t result)
Process a datum that was stored in the scalarproduct.
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE
Client -> Alice.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
uint32_t product_length
0 if no product attached
GNUNET_SCALARPRODUCT_ContinuationWithStatus cont_status
Function to call after transmission of the request (Bob).
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
uint32_t element_count_contained
contained elements the vector in payload contains
Handle to a message queue.
Definition: mq.c:85
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:85
#define GNUNET_log(kind,...)
uint32_t element_count_contained
contained elements the vector in payload contains
Definition: scalarproduct.h:61
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MULTIPART_BOB
Client -> Bob multipart.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
static struct MHD_Response * response
Our canonical response.
uint32_t element_count_contained
contained elements the vector in payload contains
multipart messages following struct ComputationMessage
Message type passed from client to service to initiate a request or responder role.
Definition: scalarproduct.h:88
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:824
#define GNUNET_YES
Definition: gnunet_common.h:77
void * cont_cls
Closure for cont_status or cont_datum.
struct GNUNET_HashCode session_key
the transaction/session key used to identify a session
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
#define LOG(kind,...)
GNUNET_SCALARPRODUCT_ResponseStatus
Result status values for the computation.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
GNUNET_SCALARPRODUCT_ResponseMessageHandler response_proc
API internal callback for results and failures to be forwarded to the client.
GNUNET_NETWORK_STRUCT_END typedef void(* GNUNET_SCALARPRODUCT_ContinuationWithStatus)(void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status)
Continuation called to notify client about result of the operation.
struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_start_computation(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *session_key, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_SCALARPRODUCT_Element *elements, uint32_t element_count, GNUNET_SCALARPRODUCT_DatumProcessor cont, void *cont_cls)
Request by Alice&#39;s client for computing a scalar product.
struct GNUNET_MQ_Handle * mq
Current connection to the scalarproduct service.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static int check_unique(const struct GNUNET_SCALARPRODUCT_Element *elements, uint32_t element_count)
Check if the keys for all given elements are unique.
An element key-value pair for scalarproduct.
#define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT
Alice/Bob -> Client Result.
#define GNUNET_free(ptr)
Wrapper around free.