GNUnet  0.10.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
46  const struct ClientResponseMessage *msg,
48 
49 
58 
63 
68 
73 
77  void *cont_cls;
78 
84 
89 };
90 
91 
100 static int
101 check_response(void *cls,
102  const struct ClientResponseMessage *message)
103 {
104  if (ntohs(message->header.size) !=
105  ntohl(message->product_length) + sizeof(struct ClientResponseMessage))
106  {
107  GNUNET_break(0);
108  return GNUNET_SYSERR;
109  }
110  return GNUNET_OK;
111 }
112 
113 
123 static void
125  const struct ClientResponseMessage *msg,
127 {
128  if (NULL != h->cont_status)
129  h->cont_status(h->cont_cls,
130  status);
132 }
133 
134 
143 static void
144 handle_response(void *cls,
145  const struct ClientResponseMessage *message)
146 {
149 
150  status = (enum GNUNET_SCALARPRODUCT_ResponseStatus)ntohl(message->status);
151  h->response_proc(h,
152  message,
153  status);
154 }
155 
156 
164 static int
166  uint32_t element_count)
167 {
169  uint32_t i;
170  int ok;
171 
172  ok = GNUNET_OK;
173  map = GNUNET_CONTAINER_multihashmap_create(2 * element_count,
174  GNUNET_YES);
175  for (i = 0; i < element_count; i++)
176  if (GNUNET_OK !=
178  &elements[i].key,
179  map,
181  {
183  _("Keys given to SCALARPRODUCT not unique!\n"));
184  ok = GNUNET_SYSERR;
185  }
187  return ok;
188 }
189 
190 
198 static void
200  enum GNUNET_MQ_Error error)
201 {
203 
205  "Disconnected from SCALARPRODUCT service.\n");
206  h->response_proc(h,
207  NULL,
209 }
210 
211 
225  const struct GNUNET_HashCode *session_key,
226  const struct GNUNET_SCALARPRODUCT_Element *elements,
227  uint32_t element_count,
229  void *cont_cls)
230 {
233  struct GNUNET_MQ_MessageHandler handlers[] = {
236  struct ClientResponseMessage,
237  h),
239  };
240  struct GNUNET_MQ_Envelope *env;
241  struct BobComputationMessage *msg;
243  uint32_t size;
244  uint16_t possible;
245  uint16_t todo;
246  uint32_t element_count_transfered;
247 
248 
249  if (GNUNET_SYSERR == check_unique(elements,
250  element_count))
251  return NULL;
252  h->cont_status = cont;
253  h->cont_cls = cont_cls;
255  h->cfg = cfg;
256  h->key = *session_key;
257  h->mq = GNUNET_CLIENT_connect(cfg,
258  "scalarproduct-bob",
259  handlers,
261  h);
262  if (NULL == h->mq)
263  {
264  /* scalarproduct configuration error */
265  GNUNET_break(0);
266  GNUNET_free(h);
267  return NULL;
268  }
269  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct BobComputationMessage))
270  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
271  todo = GNUNET_MIN(possible,
272  element_count);
273  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
274  env = GNUNET_MQ_msg_extra(msg,
275  size,
277  msg->element_count_total = htonl(element_count);
278  msg->element_count_contained = htonl(todo);
279  msg->session_key = *session_key;
280  GNUNET_memcpy(&msg[1],
281  elements,
282  size);
283  element_count_transfered = todo;
284  GNUNET_MQ_send(h->mq,
285  env);
286  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
287  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
288  while (element_count_transfered < element_count)
289  {
290  todo = GNUNET_MIN(possible,
291  element_count - element_count_transfered);
292  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
293  env = GNUNET_MQ_msg_extra(mmsg,
294  size,
296  mmsg->element_count_contained = htonl(todo);
297  GNUNET_memcpy(&mmsg[1],
298  &elements[element_count_transfered],
299  size);
300  element_count_transfered += todo;
301  GNUNET_MQ_send(h->mq,
302  env);
303  }
304  return h;
305 }
306 
307 
317 static void
319  const struct ClientResponseMessage *msg,
321 {
322  uint32_t product_len;
323  gcry_mpi_t result = NULL;
324  gcry_error_t rc;
325  gcry_mpi_t num;
326  size_t rsize;
327 
329  {
330  result = gcry_mpi_new(0);
331 
332  product_len = ntohl(msg->product_length);
333  if (0 < product_len)
334  {
335  rsize = 0;
336  if (0 != (rc = gcry_mpi_scan(&num, GCRYMPI_FMT_STD,
337  &msg[1],
338  product_len,
339  &rsize)))
340  {
342  "gcry_mpi_scan",
343  rc);
344  gcry_mpi_release(result);
345  result = NULL;
347  }
348  else
349  {
350  if (0 < (int32_t)ntohl(msg->range))
351  gcry_mpi_add(result, result, num);
352  else
353  gcry_mpi_sub(result, result, num);
354  gcry_mpi_release(num);
355  }
356  }
357  }
358  if (NULL != h->cont_datum)
359  h->cont_datum(h->cont_cls,
360  status,
361  result);
362  if (NULL != result)
363  gcry_mpi_release(result);
365 }
366 
367 
382  const struct GNUNET_HashCode *session_key,
383  const struct GNUNET_PeerIdentity *peer,
384  const struct GNUNET_SCALARPRODUCT_Element *elements,
385  uint32_t element_count,
387  void *cont_cls)
388 {
391  struct GNUNET_MQ_MessageHandler handlers[] = {
394  struct ClientResponseMessage,
395  h),
397  };
398  struct GNUNET_MQ_Envelope *env;
401  uint32_t size;
402  uint16_t possible;
403  uint16_t todo;
404  uint32_t element_count_transfered;
405 
406  if (GNUNET_SYSERR == check_unique(elements,
407  element_count))
408  return NULL;
409  h->mq = GNUNET_CLIENT_connect(cfg,
410  "scalarproduct-alice",
411  handlers,
413  h);
414  if (NULL == h->mq)
415  {
416  /* missconfigured scalarproduct service */
417  GNUNET_break(0);
418  GNUNET_free(h);
419  return NULL;
420  }
421  h->cont_datum = cont;
422  h->cont_cls = cont_cls;
424  h->cfg = cfg;
425  h->key = *session_key;
426 
427  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(struct AliceComputationMessage))
428  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
429  todo = GNUNET_MIN(possible,
430  element_count);
431  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
432  env = GNUNET_MQ_msg_extra(msg,
433  size,
435  msg->element_count_total = htonl(element_count);
436  msg->element_count_contained = htonl(todo);
437  msg->reserved = htonl(0);
438  msg->peer = *peer;
439  msg->session_key = *session_key;
440  GNUNET_memcpy(&msg[1],
441  elements,
442  size);
443  GNUNET_MQ_send(h->mq,
444  env);
445  element_count_transfered = todo;
446  possible = (GNUNET_MAX_MESSAGE_SIZE - 1 - sizeof(*mmsg))
447  / sizeof(struct GNUNET_SCALARPRODUCT_Element);
448  while (element_count_transfered < element_count)
449  {
450  todo = GNUNET_MIN(possible,
451  element_count - element_count_transfered);
452  size = todo * sizeof(struct GNUNET_SCALARPRODUCT_Element);
453  env = GNUNET_MQ_msg_extra(mmsg,
454  size,
456  mmsg->element_count_contained = htonl(todo);
457  GNUNET_memcpy(&mmsg[1],
458  &elements[element_count_transfered],
459  size);
460  element_count_transfered += todo;
461  GNUNET_MQ_send(h->mq,
462  env);
463  }
464  return h;
465 }
466 
467 
474 void
476 {
477  if (NULL != h->mq)
478  {
479  GNUNET_MQ_destroy(h->mq);
480  h->mq = NULL;
481  }
482  GNUNET_free(h);
483 }
484 
485 
486 /* 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:900
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:94
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:62
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:42
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:94
struct GNUNET_HashCode session_key
the transaction/session key used to identify a session
Definition: scalarproduct.h:67
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:72
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:52
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:66
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
Definition: scalarproduct.h:99
Handle to a message queue.
Definition: mq.c:84
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:83
#define GNUNET_log(kind,...)
uint32_t element_count_contained
contained elements the vector in payload contains
Definition: scalarproduct.h:57
#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:84
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:821
#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:351
#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.