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/scalarproduct_api.c
23 * @brief API for the scalarproduct
24 * @author Christian Fuchs
25 * @author Gaurav Kukreja
29 #include "gnunet_util_lib.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet_scalarproduct_service.h"
32 #include "gnunet_protocols.h"
33 #include "scalarproduct.h"
35 #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-api",__VA_ARGS__)
37 /**************************************************************
38 *** Datatype Declarations **********
39 **************************************************************/
42 * Entry in the request queue per client
44 struct GNUNET_SCALARPRODUCT_ComputationHandle
47 * This is a linked list.
49 struct GNUNET_SCALARPRODUCT_ComputationHandle *next;
52 * This is a linked list.
54 struct GNUNET_SCALARPRODUCT_ComputationHandle *prev;
59 const struct GNUNET_CONFIGURATION_Handle *cfg;
62 * Current connection to the scalarproduct service.
64 struct GNUNET_CLIENT_Connection *client;
67 * Handle for statistics.
69 struct GNUNET_STATISTICS_Handle *stats;
72 * The shared session key identifying this computation
74 struct GNUNET_HashCode * key;
77 * Current transmit handle.
79 struct GNUNET_CLIENT_TransmitHandle *th;
84 uint16_t message_size;
87 * Message to be sent to the scalarproduct service
89 struct GNUNET_SCALARPRODUCT_client_request * msg;
94 * Function to call after transmission of the request.
96 GNUNET_SCALARPRODUCT_ContinuationWithStatus cont_status;
99 * Function to call after transmission of the request.
101 GNUNET_SCALARPRODUCT_DatumProcessor cont_datum;
105 * Closure for 'cont'.
110 * Response Processor for response from the service. This function calls the
111 * continuation function provided by the client.
113 GNUNET_SCALARPRODUCT_ResponseMessageHandler response_proc;
116 /**************************************************************
117 *** Global Variables **********
118 **************************************************************/
120 * Head of the active sessions queue
122 struct GNUNET_SCALARPRODUCT_ComputationHandle *head;
124 * Tail of the active sessions queue
126 struct GNUNET_SCALARPRODUCT_ComputationHandle *tail;
128 /**************************************************************
129 *** Function Declarations **********
130 **************************************************************/
133 * Called when a response is received from the service. After basic check
134 * handler in qe->response_proc is called. This functions handles the response
135 * to the client which used the API.
137 * @param cls Pointer to the Master Context
138 * @param msg Pointer to the data received in response
141 receive_cb (void *cls, const struct GNUNET_MessageHeader *msg);
144 * Transmits the request to the VectorProduct Sevice
147 * @param size Size of the buffer
148 * @param buf Pointer to the buffer
150 * @return Size of the message sent
152 static size_t transmit_request (void *cls, size_t size,
155 /**************************************************************
156 *** Static Function Declarations **********
157 **************************************************************/
160 * Handles the RESULT received in reply of prepare_response from the
163 * @param cls Handle to the Master Context
164 * @param msg Pointer to the response received
167 process_status_message (void *cls,
168 const struct GNUNET_MessageHeader *msg,
169 enum GNUNET_SCALARPRODUCT_ResponseStatus status)
171 struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls;
173 GNUNET_assert (qe != NULL);
175 if (qe->cont_status != NULL)
176 qe->cont_status (qe->cont_cls, &qe->msg->key, status);
181 * Handles the RESULT received in reply of prepare_response from the
184 * @param cls Handle to the Master Context
185 * @param msg Pointer to the response received
188 process_result_message (void *cls,
189 const struct GNUNET_MessageHeader *msg,
190 enum GNUNET_SCALARPRODUCT_ResponseStatus status)
192 struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls;
194 GNUNET_assert (qe != NULL);
196 if (msg == NULL && qe->cont_datum != NULL)
198 LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout reached or session terminated.\n");
200 if (qe->cont_datum != NULL)
202 qe->cont_datum (qe->cont_cls, &qe->msg->key, &qe->msg->peer, status, (struct GNUNET_SCALARPRODUCT_client_response *) msg);
208 * Called when a response is received from the service. After basic check
209 * handler in qe->response_proc is called. This functions handles the response
210 * to the client which used the API.
212 * @param cls Pointer to the Master Context
213 * @param msg Pointer to the data received in response
216 receive_cb (void *cls, const struct GNUNET_MessageHeader *msg)
218 struct GNUNET_SCALARPRODUCT_ComputationHandle *h = cls;
219 struct GNUNET_SCALARPRODUCT_ComputationHandle *qe;
220 int16_t was_transmitted;
221 struct GNUNET_SCALARPRODUCT_client_response *message =
222 (struct GNUNET_SCALARPRODUCT_client_response *) msg;
224 h->in_receive = GNUNET_NO;
225 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received reply from VectorProduct\n");
227 if (NULL == (qe = free_queue_head_entry (h)))
230 * The queue head will be NULL if the client disconnected,
231 * * In case of Alice, client disconnected after sending request, before receiving response
232 * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
238 if (h->client == NULL)
240 // GKUKREJA : handle this correctly
242 * The queue head will be NULL if the client disconnected,
243 * * In case of Alice, client disconnected after sending request, before receiving response
244 * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
250 was_transmitted = qe->was_transmitted;
251 // Control will only come here, when the request was transmitted to service,
252 // and service responded.
253 GNUNET_assert (was_transmitted == GNUNET_YES);
257 LOG (GNUNET_ERROR_TYPE_WARNING, "Service responded with NULL!\n");
258 qe->response_proc (qe, NULL, GNUNET_SCALARPRODUCT_Status_Failure);
260 else if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT))
262 LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid Message Received\n");
263 qe->response_proc (qe, msg, GNUNET_SCALARPRODUCT_Status_InvalidResponse);
265 else if (ntohl (message->product_length) == 0)
267 // response for the responder client, successful
268 GNUNET_STATISTICS_update (h->stats,
269 gettext_noop ("# SUC responder result messages received"), 1,
272 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from service without product attached.\n");
273 qe->response_proc (qe, msg, GNUNET_SCALARPRODUCT_Status_Success);
275 else if (ntohl (message->product_length) > 0)
277 // response for the requester client, successful
278 GNUNET_STATISTICS_update (h->stats,
279 gettext_noop ("# SUC requester result messages received"), 1,
282 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from requester service for requester client.\n");
283 qe->response_proc (qe, msg, GNUNET_SCALARPRODUCT_Status_Success);
292 * Transmits the request to the VectorProduct Sevice
295 * @param size Size of the buffer
296 * @param buf Pointer to the buffer
298 * @return Size of the message sent
301 transmit_request (void *cls, size_t size,
304 struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls;
309 LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to SCALARPRODUCT.\n");
310 GNUNET_STATISTICS_update (qe->stats,
311 gettext_noop ("# transmission request failures"),
313 GNUNET_SCALARPRODUCT_disconnect (qe);
316 LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u byte request to SCALARPRODUCT\n",
319 memcpy (buf, qe->msg, size);
320 GNUNET_free (qe->msg);
321 qe->was_transmitted = GNUNET_YES;
325 GNUNET_CLIENT_receive (h->client, &receive_cb, h,
326 GNUNET_TIME_UNIT_FOREVER_REL);
328 #if INSANE_STATISTICS
329 GNUNET_STATISTICS_update (h->stats,
330 gettext_noop ("# bytes sent to scalarproduct"), 1,
337 /**************************************************************
339 **************************************************************/
343 * Used by Bob's client to cooperate with Alice,
345 * @param h handle to the master context
346 * @param key Session key - unique to the requesting client
347 * @param elements Array of elements of the vector
348 * @param element_count Number of elements in the vector
349 * @param cont Callback function
350 * @param cont_cls Closure for the callback function
352 struct GNUNET_SCALARPRODUCT_ComputationHandle *
353 GNUNET_SCALARPRODUCT_response (const struct GNUNET_CONFIGURATION_Handle *cfg,
354 const struct GNUNET_HashCode * key,
355 const int32_t * elements,
356 uint32_t element_count,
357 GNUNET_SCALARPRODUCT_ContinuationWithStatus cont,
360 struct GNUNET_SCALARPRODUCT_ComputationHandle *h;
361 struct GNUNET_SCALARPRODUCT_client_request *msg;
367 GNUNET_assert(elements);
369 GNUNET_assert(element_count > 1);
370 GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_SCALARPRODUCT_client_request)
371 + element_count * sizeof (int32_t));
372 h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle);
373 h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg);
376 LOG (GNUNET_ERROR_TYPE_ERROR,
377 _ ("Failed to connect to the scalarproduct service\n"));
381 h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg);
383 LOG (GNUNET_ERROR_TYPE_ERROR,
384 _("Failed to send a message to the statistics service\n"));
385 GNUNET_CLIENT_disconnect(h->client);
390 size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * sizeof (int32_t);
392 h->cont_datum = cont;
393 h->cont_cls = cont_cls;
394 h->response_proc = &process_result_message;
396 h->msg = GNUNET_malloc (size);
397 memcpy (&h->key, key, sizeof (struct GNUNET_HashCode));
399 msg = (struct GNUNET_SCALARPRODUCT_client_request*) h->msg;
400 msg->header.size = htons (size);
401 msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE);
402 msg->element_count = htonl (element_count);
404 vector = (int32_t*) &msg[1];
405 // copy each element over to the message
406 for (i = 0; i < element_count; i++)
407 vector[i] = htonl(elements[i]);
409 memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode));
411 h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size,
412 GNUNET_TIME_UNIT_FOREVER_REL,
413 GNUNET_YES, // retry is OK in the initial stage
414 &transmit_request, h);
417 LOG (GNUNET_ERROR_TYPE_ERROR,
418 _ ("Failed to send a message to the scalarproduct service\n"));
419 GNUNET_STATISTICS_destroy(h->GNUNET_YES);
420 GNUNET_CLIENT_disconnect(h->client);
425 GNUNET_CONTAINER_DLL_insert (head, tail, h);
431 * Request by Alice's client for computing a scalar product
433 * @param h handle to the master context
434 * @param key Session key - unique to the requesting client
435 * @param peer PeerID of the other peer
436 * @param elements Array of elements of the vector
437 * @param element_count Number of elements in the vector
438 * @param mask Array of the mask
439 * @param mask_bytes number of bytes in the mask
440 * @param cont Callback function
441 * @param cont_cls Closure for the callback function
443 struct GNUNET_SCALARPRODUCT_ComputationHandle *
444 GNUNET_SCALARPRODUCT_request (const struct GNUNET_CONFIGURATION_Handle *cfg,
445 const struct GNUNET_HashCode * key,
446 const struct GNUNET_PeerIdentity *peer,
447 const int32_t * elements,
448 uint32_t element_count,
449 const unsigned char * mask,
451 GNUNET_SCALARPRODUCT_DatumProcessor cont,
454 struct GNUNET_SCALARPRODUCT_ComputationHandle *h;
455 struct GNUNET_SCALARPRODUCT_client_request *msg;
460 GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_SCALARPRODUCT_client_request)
461 + element_count * sizeof (int32_t)
464 h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle);
465 h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg);
468 LOG (GNUNET_ERROR_TYPE_ERROR,
469 _ ("Failed to connect to the scalarproduct service\n"));
473 h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg);
475 LOG (GNUNET_ERROR_TYPE_ERROR,
476 _("Failed to send a message to the statistics service\n"));
477 GNUNET_CLIENT_disconnect(h->client);
482 size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * sizeof (int32_t) + mask_length;
484 h->cont_datum = cont;
485 h->cont_cls = cont_cls;
486 h->response_proc = &process_status_message;
488 h->msg = GNUNET_malloc (size);
489 memcpy (&h->key, key, sizeof (struct GNUNET_HashCode));
491 msg = (struct GNUNET_SCALARPRODUCT_client_request*) h->msg;
492 msg->header.size = htons (size);
493 msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE);
494 msg->element_count = htons (element_count);
495 msg->mask_length = htons (mask_length);
497 vector = (int32_t*) &msg[1];
498 // copy each element over to the message
499 for (i = 0; i < element_count; i++)
500 vector[i] = htonl(elements[i]);
502 memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity));
503 memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode));
504 memcpy (&vector[element_count], mask, mask_length);
506 h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size,
507 GNUNET_TIME_UNIT_FOREVER_REL,
508 GNUNET_YES, // retry is OK in the initial stage
509 &transmit_request, h);
512 LOG (GNUNET_ERROR_TYPE_ERROR,
513 _ ("Failed to send a message to the scalarproduct service\n"));
514 GNUNET_STATISTICS_destroy(h->GNUNET_YES);
515 GNUNET_CLIENT_disconnect(h->client);
520 GNUNET_CONTAINER_DLL_insert (head, tail, h);
525 * Disconnect from the scalarproduct service.
527 * @param h handle to the scalarproduct
530 GNUNET_SCALARPRODUCT_disconnect (struct GNUNET_SCALARPRODUCT_ComputationHandle * h)
532 struct GNUNET_SCALARPRODUCT_ComputationHandle * qe;
534 LOG (GNUNET_ERROR_TYPE_INFO,
535 "Disconnecting from VectorProduct\n");
537 for (qe = head; head != NULL; qe = head)
539 GNUNET_CONTAINER_DLL_remove (head, tail, qe);
541 GNUNET_CLIENT_notify_transmit_ready_cancel(qe->th);
542 GNUNET_CLIENT_disconnect (h->client);
543 GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES);
544 qe->response_proc (qe, NULL, GNUNET_SCALARPRODUCT_Status_ServiceDisconnected);
545 GNUNET_free(qe->msg);
550 /* end of ext_api.c */