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  const struct ClientResponseMessage *msg,
49 
50 
55 {
60 
65 
70 
75 
79  void *cont_cls;
80 
86 
91 };
92 
93 
102 static int
103 check_response (void *cls,
104  const struct ClientResponseMessage *message)
105 {
106  if (ntohs (message->header.size) !=
107  ntohl (message->product_length) + sizeof(struct ClientResponseMessage))
108  {
109  GNUNET_break (0);
110  return GNUNET_SYSERR;
111  }
112  return GNUNET_OK;
113 }
114 
115 
125 static void
127  const struct ClientResponseMessage *msg,
129 {
130  if (NULL != h->cont_status)
131  h->cont_status (h->cont_cls,
132  status);
134 }
135 
136 
145 static void
146 handle_response (void *cls,
147  const struct ClientResponseMessage *message)
148 {
151 
152  status = (enum GNUNET_SCALARPRODUCT_ResponseStatus) ntohl (message->status);
153  h->response_proc (h,
154  message,
155  status);
156 }
157 
158 
166 static int
168  uint32_t element_count)
169 {
171  int ok;
172 
173  ok = GNUNET_OK;
174  map = GNUNET_CONTAINER_multihashmap_create (2 * element_count,
175  GNUNET_YES);
176  for (uint32_t i = 0; i < element_count; i++)
177  if (GNUNET_OK !=
179  &elements[i].key,
180  map,
182  {
184  _ ("Keys given to SCALARPRODUCT not unique!\n"));
185  ok = GNUNET_SYSERR;
186  }
188  return ok;
189 }
190 
191 
199 static void
200 mq_error_handler (void *cls,
201  enum GNUNET_MQ_Error error)
202 {
204 
206  "Disconnected from SCALARPRODUCT service.\n");
207  h->response_proc (h,
208  NULL,
210 }
211 
212 
226  const struct GNUNET_CONFIGURATION_Handle *cfg,
227  const struct GNUNET_HashCode *session_key,
228  const struct GNUNET_SCALARPRODUCT_Element *elements,
229  uint32_t element_count,
231  void *cont_cls)
232 {
235  struct GNUNET_MQ_MessageHandler handlers[] = {
238  struct ClientResponseMessage,
239  h),
241  };
242  struct GNUNET_MQ_Envelope *env;
243  struct BobComputationMessage *msg;
245  uint32_t size;
246  uint16_t possible;
247  uint16_t todo;
248  uint32_t element_count_transfered;
249 
250 
251  if (GNUNET_SYSERR == check_unique (elements,
252  element_count))
253  return NULL;
254  h->cont_status = cont;
255  h->cont_cls = cont_cls;
257  h->cfg = cfg;
258  h->key = *session_key;
259  h->mq = GNUNET_CLIENT_connect (cfg,
260  "scalarproduct-bob",
261  handlers,
263  h);
264  if (NULL == h->mq)
265  {
266  /* scalarproduct configuration error */
267  GNUNET_break (0);
268  GNUNET_free (h);
269  return NULL;
270  }
271  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct
273  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
274  todo = GNUNET_MIN (possible,
275  element_count);
276  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
277  env = GNUNET_MQ_msg_extra (msg,
278  size,
280  msg->element_count_total = htonl (element_count);
281  msg->element_count_contained = htonl (todo);
282  msg->session_key = *session_key;
283  GNUNET_memcpy (&msg[1],
284  elements,
285  size);
286  element_count_transfered = todo;
287  GNUNET_MQ_send (h->mq,
288  env);
289  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
290  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
291  while (element_count_transfered < element_count)
292  {
293  todo = GNUNET_MIN (possible,
294  element_count - element_count_transfered);
295  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
296  env = GNUNET_MQ_msg_extra (mmsg,
297  size,
299  mmsg->element_count_contained = htonl (todo);
300  GNUNET_memcpy (&mmsg[1],
301  &elements[element_count_transfered],
302  size);
303  element_count_transfered += todo;
304  GNUNET_MQ_send (h->mq,
305  env);
306  }
307  return h;
308 }
309 
310 
320 static void
322  const struct ClientResponseMessage *msg,
324 {
325  uint32_t product_len;
326  gcry_mpi_t result = NULL;
327  gcry_error_t rc;
328  gcry_mpi_t num;
329  size_t rsize;
330 
332  {
333  result = gcry_mpi_new (0);
334 
335  product_len = ntohl (msg->product_length);
336  if (0 < product_len)
337  {
338  rsize = 0;
339  if (0 != (rc = gcry_mpi_scan (&num, GCRYMPI_FMT_STD,
340  &msg[1],
341  product_len,
342  &rsize)))
343  {
345  "gcry_mpi_scan",
346  rc);
347  gcry_mpi_release (result);
348  result = NULL;
350  }
351  else
352  {
353  if (0 < (int32_t) ntohl (msg->range))
354  gcry_mpi_add (result, result, num);
355  else
356  gcry_mpi_sub (result, result, num);
357  gcry_mpi_release (num);
358  }
359  }
360  }
361  if (NULL != h->cont_datum)
362  h->cont_datum (h->cont_cls,
363  status,
364  result);
365  if (NULL != result)
366  gcry_mpi_release (result);
368 }
369 
370 
385  const struct GNUNET_CONFIGURATION_Handle *cfg,
386  const struct GNUNET_HashCode *session_key,
387  const struct GNUNET_PeerIdentity *peer,
388  const struct GNUNET_SCALARPRODUCT_Element *elements,
389  uint32_t element_count,
391  void *cont_cls)
392 {
395  struct GNUNET_MQ_MessageHandler handlers[] = {
398  struct ClientResponseMessage,
399  h),
401  };
402  struct GNUNET_MQ_Envelope *env;
405  uint32_t size;
406  uint16_t possible;
407  uint16_t todo;
408  uint32_t element_count_transfered;
409 
410  if (GNUNET_SYSERR == check_unique (elements,
411  element_count))
412  return NULL;
413  h->mq = GNUNET_CLIENT_connect (cfg,
414  "scalarproduct-alice",
415  handlers,
417  h);
418  if (NULL == h->mq)
419  {
420  /* misconfigured scalarproduct service */
421  GNUNET_break (0);
422  GNUNET_free (h);
423  return NULL;
424  }
425  h->cont_datum = cont;
426  h->cont_cls = cont_cls;
428  h->cfg = cfg;
429  h->key = *session_key;
430 
431  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct
433  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
434  todo = GNUNET_MIN (possible,
435  element_count);
436  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
437  env = GNUNET_MQ_msg_extra (msg,
438  size,
440  msg->element_count_total = htonl (element_count);
441  msg->element_count_contained = htonl (todo);
442  msg->reserved = htonl (0);
443  msg->peer = *peer;
444  msg->session_key = *session_key;
445  GNUNET_memcpy (&msg[1],
446  elements,
447  size);
448  GNUNET_MQ_send (h->mq,
449  env);
450  element_count_transfered = todo;
451  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
452  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
453  while (element_count_transfered < element_count)
454  {
455  todo = GNUNET_MIN (possible,
456  element_count - element_count_transfered);
457  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
458  env = GNUNET_MQ_msg_extra (mmsg,
459  size,
461  mmsg->element_count_contained = htonl (todo);
462  GNUNET_memcpy (&mmsg[1],
463  &elements[element_count_transfered],
464  size);
465  element_count_transfered += todo;
466  GNUNET_MQ_send (h->mq,
467  env);
468  }
469  return h;
470 }
471 
472 
479 void
481 {
482  if (NULL != h->mq)
483  {
484  GNUNET_MQ_destroy (h->mq);
485  h->mq = NULL;
486  }
487  GNUNET_free (h);
488 }
489 
490 
491 /* 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:1063
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_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:178
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:93
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.
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
#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:837
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:355
#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.