From 31536a9bb75502f4c090472f188e1eec138515f7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 24 May 2014 19:57:15 +0000 Subject: [PATCH] cleaning up scalar product client API --- src/include/gnunet_crypto_lib.h | 6 +- src/include/gnunet_scalarproduct_service.h | 86 ++- src/scalarproduct/gnunet-scalarproduct.c | 22 +- .../gnunet-service-scalarproduct.c | 267 +++++--- src/scalarproduct/scalarproduct.h | 142 +---- src/scalarproduct/scalarproduct_api.c | 589 ++++++++---------- 6 files changed, 545 insertions(+), 567 deletions(-) diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 18e49ee93..0d18e1185 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -374,7 +374,7 @@ struct GNUNET_CRYPTO_PaillierCiphertext * guaranteed minimum number of homomorphic operations with this ciphertext */ int32_t remaining_ops GNUNET_PACKED; - + /** * The bits of the ciphertext. */ @@ -1334,7 +1334,7 @@ GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_ke * @param m Plaintext to encrypt. * @param desired_ops How many homomorphic ops the caller intends to use * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. - * @return guaranteed number of supported homomorphic operations >= 1, + * @return guaranteed number of supported homomorphic operations >= 1, * or desired_ops, in case that is lower, * or -1 if less than one homomorphic operation is possible */ @@ -1381,7 +1381,7 @@ GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *pu /** - * Get the number of remaining supported homomorphic operations. + * Get the number of remaining supported homomorphic operations. * * @param c Paillier cipher text. * @return the number of remaining homomorphic operations diff --git a/src/include/gnunet_scalarproduct_service.h b/src/include/gnunet_scalarproduct_service.h index 63bc29f0e..c96c280c4 100644 --- a/src/include/gnunet_scalarproduct_service.h +++ b/src/include/gnunet_scalarproduct_service.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2013 Christian Grothoff (and other contributing authors) + (C) 2013, 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -39,13 +39,31 @@ extern "C" { /** * Version of the scalarproduct API. */ -#define GNUNET_SCALARPRODUCT_VERSION 0x00000043 +#define GNUNET_SCALARPRODUCT_VERSION 0x00000044 +/** + * Result status values for the computation. + */ enum GNUNET_SCALARPRODUCT_ResponseStatus { + /** + * The computation was successful. + */ GNUNET_SCALARPRODUCT_Status_Success = 0, + + /** + * We encountered some error. + */ GNUNET_SCALARPRODUCT_Status_Failure, + + /** + * We got an invalid response. + */ GNUNET_SCALARPRODUCT_Status_InvalidResponse, + + /** + * We got disconnected from the SCALARPRODUCT service. + */ GNUNET_SCALARPRODUCT_Status_ServiceDisconnected }; @@ -55,14 +73,27 @@ enum GNUNET_SCALARPRODUCT_ResponseStatus */ struct GNUNET_SCALARPRODUCT_Handle; + +GNUNET_NETWORK_STRUCT_BEGIN + /** * An element key-value pair for scalarproduct */ -struct GNUNET_SCALARPRODUCT_Element { - int32_t value; - struct GNUNET_HashCode key; +struct GNUNET_SCALARPRODUCT_Element +{ + /** + * Key used to identify matching pairs of values to multiply. + */ + struct GNUNET_HashCode key; + + /** + * Value to multiply in scalar product. + */ + int64_t value GNUNET_PACKED; }; +GNUNET_NETWORK_STRUCT_END + /** * Continuation called to notify client about result of the @@ -71,8 +102,9 @@ struct GNUNET_SCALARPRODUCT_Element { * @param cls closure * @param status Status of the request */ -typedef void (*GNUNET_SCALARPRODUCT_ContinuationWithStatus) (void *cls, - enum GNUNET_SCALARPRODUCT_ResponseStatus status); +typedef void +(*GNUNET_SCALARPRODUCT_ContinuationWithStatus) (void *cls, + enum GNUNET_SCALARPRODUCT_ResponseStatus status); /** @@ -82,15 +114,18 @@ typedef void (*GNUNET_SCALARPRODUCT_ContinuationWithStatus) (void *cls, * @param status Status of the request * @param result result of the computation */ -typedef void (*GNUNET_SCALARPRODUCT_DatumProcessor) (void *cls, - enum GNUNET_SCALARPRODUCT_ResponseStatus status, - gcry_mpi_t result); +typedef void +(*GNUNET_SCALARPRODUCT_DatumProcessor) (void *cls, + enum GNUNET_SCALARPRODUCT_ResponseStatus status, + gcry_mpi_t result); + /** * Entry in the request queue per client */ struct GNUNET_SCALARPRODUCT_ComputationHandle; + /** * Request by Alice's client for computing a scalar product * @@ -98,20 +133,20 @@ struct GNUNET_SCALARPRODUCT_ComputationHandle; * @param session_key Session key should be unique to the requesting client * @param peer PeerID of the other peer * @param elements Array of elements of the vector - * @param element_count Number of elements in the vector + * @param element_count Number of elements in the @a elements vector * @param cont Callback function - * @param cont_cls Closure for the callback function - * + * @param cont_cls Closure for the @a cont callback function * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_start_computation (const struct GNUNET_CONFIGURATION_Handle * cfg, - const struct GNUNET_HashCode * session_key, +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, + const struct GNUNET_SCALARPRODUCT_Element *elements, uint32_t element_count, GNUNET_SCALARPRODUCT_DatumProcessor cont, - void * cont_cls); + void *cont_cls); + /** * Used by Bob's client to cooperate with Alice, @@ -119,19 +154,18 @@ GNUNET_SCALARPRODUCT_start_computation (const struct GNUNET_CONFIGURATION_Handle * @param cfg the gnunet configuration handle * @param session_key Session key unique to the requesting client * @param elements Array of elements of the vector - * @param element_count Number of elements in the vector + * @param element_count Number of elements in the @a elements vector * @param cont Callback function - * @param cont_cls Closure for the callback function - * + * @param cont_cls Closure for the @a cont callback function * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * -GNUNET_SCALARPRODUCT_accept_computation (const struct GNUNET_CONFIGURATION_Handle * cfg, - const struct GNUNET_HashCode * key, - const struct GNUNET_SCALARPRODUCT_Element * elements, - uint32_t element_count, - GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, - void * cont_cls); +GNUNET_SCALARPRODUCT_accept_computation (const struct GNUNET_CONFIGURATION_Handle *cfg, + const struct GNUNET_HashCode *key, + const struct GNUNET_SCALARPRODUCT_Element *elements, + uint32_t element_count, + GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, + void *cont_cls); /** diff --git a/src/scalarproduct/gnunet-scalarproduct.c b/src/scalarproduct/gnunet-scalarproduct.c index 2bb708fc9..88069d41d 100644 --- a/src/scalarproduct/gnunet-scalarproduct.c +++ b/src/scalarproduct/gnunet-scalarproduct.c @@ -261,22 +261,22 @@ run (void *cls, _ ("Need elements to compute the vectorproduct, got none.\n")); return; } - - elements = (struct GNUNET_SCALARPRODUCT_Element *) + + elements = (struct GNUNET_SCALARPRODUCT_Element *) GNUNET_malloc(sizeof(struct GNUNET_SCALARPRODUCT_Element)*element_count); - + for (i = 0; i < element_count;i++) { struct GNUNET_SCALARPRODUCT_Element element; char* separator=NULL; - + // get the length of the current key,value; tupel for (end = begin; *end != ';'; end++) if (*end == ',') separator = end; - + // final element - if ((NULL == separator) + if ((NULL == separator) || (begin == separator) || (separator == end - 1 )) { LOG (GNUNET_ERROR_TYPE_ERROR, @@ -284,20 +284,20 @@ run (void *cls, GNUNET_free(elements); return; } - + // read the element's key *separator = 0; GNUNET_CRYPTO_hash (begin, strlen (begin), &element.key); - + // read the element's value - if (1 != sscanf (separator+1, "%" SCNd32 ";", &element.value)) + if (1 != sscanf (separator+1, "%" SCNd64 ";", &element.value)) { LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Could not convert `%s' to int32_t.\n"), begin); + _ ("Could not convert `%s' to int64_t.\n"), begin); GNUNET_free(elements); return; } - + elements[i]=element; begin = end+1; } diff --git a/src/scalarproduct/gnunet-service-scalarproduct.c b/src/scalarproduct/gnunet-service-scalarproduct.c index 568f68ffc..7758d7046 100644 --- a/src/scalarproduct/gnunet-service-scalarproduct.c +++ b/src/scalarproduct/gnunet-service-scalarproduct.c @@ -37,9 +37,119 @@ #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct", __VA_ARGS__) -/////////////////////////////////////////////////////////////////////////////// -// Service Structure Definitions -/////////////////////////////////////////////////////////////////////////////// + +/** + * Maximum count of elements we can put into a multipart message + */ +#define MULTIPART_ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct MultipartMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)) + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Message type passed from requesting service Alice to responding + * service Bob to initiate a request and make Bob participate in our + * protocol + */ +struct ServiceRequestMessage +{ + /** + * GNUNET message header + */ + struct GNUNET_MessageHeader header; + + /** + * the transaction/session key used to identify a session + */ + struct GNUNET_HashCode session_id; + + /** + * Alice's public key + */ + struct GNUNET_CRYPTO_PaillierPublicKey public_key; + +}; + + +/** + * FIXME. + */ +struct AliceCryptodataMessage +{ + /** + * GNUNET message header + */ + struct GNUNET_MessageHeader header; + + /** + * how many elements we appended to this message + */ + uint32_t contained_element_count GNUNET_PACKED; + + /** + * struct GNUNET_CRYPTO_PaillierCiphertext[contained_element_count] + */ +}; + + +/** + * Multipart Message type passed between to supply additional elements + * for the peer + */ +struct MultipartMessage +{ + /** + * GNUNET message header + */ + struct GNUNET_MessageHeader header; + + /** + * how many elements we supply within this message + */ + uint32_t contained_element_count GNUNET_PACKED; + + // struct GNUNET_CRYPTO_PaillierCiphertext[multipart_element_count] +}; + + +/** + * Message type passed from responding service Bob to responding service Alice + * to complete a request and allow Alice to compute the result + */ +struct ServiceResponseMessage +{ + /** + * GNUNET message header + */ + struct GNUNET_MessageHeader header; + + /** + * how many elements the session input had + */ + uint32_t total_element_count GNUNET_PACKED; + + /** + * how many elements were included after the mask was applied + * including all multipart msgs. + */ + uint32_t used_element_count GNUNET_PACKED; + + /** + * how many elements this individual message delivers + */ + uint32_t contained_element_count GNUNET_PACKED; + + /** + * the transaction/session key used to identify a session + */ + struct GNUNET_HashCode key; + + /** + * followed by s | s' | k[i][perm] + */ +}; + +GNUNET_NETWORK_STRUCT_END /** @@ -599,15 +709,13 @@ prepare_client_end_notification (void * cls, const struct GNUNET_SCHEDULER_TaskContext * tc) { struct ServiceSession * s = cls; - struct GNUNET_SCALARPRODUCT_client_response * msg; + struct ClientResponseMessage * msg; s->client_notification_task = GNUNET_SCHEDULER_NO_TASK; - msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_client_response); + msg = GNUNET_new (struct ClientResponseMessage); + msg->header.size = htons (sizeof (struct ClientResponseMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_RESULT); - memcpy (&msg->key, &s->session_id, sizeof (struct GNUNET_HashCode)); - memcpy (&msg->peer, &s->peer, sizeof ( struct GNUNET_PeerIdentity)); - msg->header.size = htons (sizeof (struct GNUNET_SCALARPRODUCT_client_response)); // signal error if not signalized, positive result-range field but zero length. msg->product_length = htonl (0); msg->status = htonl(s->active); @@ -615,23 +723,28 @@ prepare_client_end_notification (void * cls, s->msg = &msg->header; //transmit this message to our client - s->client_transmit_handle = - GNUNET_SERVER_notify_transmit_ready (s->client, - sizeof (struct GNUNET_SCALARPRODUCT_client_response), - GNUNET_TIME_UNIT_FOREVER_REL, - &cb_transfer_message, - s); + s->client_transmit_handle + = GNUNET_SERVER_notify_transmit_ready (s->client, + sizeof (struct ClientResponseMessage), + GNUNET_TIME_UNIT_FOREVER_REL, + &cb_transfer_message, + s); // if we could not even queue our request, something is wrong - if (NULL == s->client_transmit_handle) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not send message to client (%p)!\n"), s->client); + if (NULL == s->client_transmit_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Could not send message to client (%p)!\n"), s->client); GNUNET_SERVER_client_disconnect(s->client); free_session_variables(s); GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, s); GNUNET_free(s); } else - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sending session-end notification to client (%p) for session %s\n"), &s->client, GNUNET_h2s (&s->session_id)); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Sending session-end notification to client (%p) for session %s\n"), + s->client, + GNUNET_h2s (&s->session_id)); } @@ -644,15 +757,17 @@ static void prepare_alices_cyrptodata_message (void *cls) { struct ServiceSession * s = cls; - struct GNUNET_SCALARPRODUCT_alices_cryptodata_message * msg; + struct AliceCryptodataMessage * msg; struct GNUNET_CRYPTO_PaillierCiphertext * payload; unsigned int i; uint32_t msg_length; gcry_mpi_t a; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to peer (%s)!\n"), GNUNET_i2s (&s->peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _ ("Successfully created new channel to peer (%s)!\n"), + GNUNET_i2s (&s->peer)); - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message) + msg_length = sizeof (struct AliceCryptodataMessage) +s->used_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length) { @@ -660,9 +775,9 @@ prepare_alices_cyrptodata_message (void *cls) } else { //create a multipart msg, first we calculate a new msg size for the head msg - s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message)) + s->transferred_element_count = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct AliceCryptodataMessage)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message) + msg_length = sizeof (struct AliceCryptodataMessage) +s->transferred_element_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); } @@ -715,13 +830,13 @@ prepare_bobs_cryptodata_message_multipart (void *cls) { struct ServiceSession * s = cls; struct GNUNET_CRYPTO_PaillierCiphertext * payload; - struct GNUNET_SCALARPRODUCT_multipart_message * msg; + struct MultipartMessage * msg; unsigned int i; unsigned int j; uint32_t msg_length; uint32_t todo_count; - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message); + msg_length = sizeof (struct MultipartMessage); todo_count = s->used_element_count - s->transferred_element_count; if (todo_count > MULTIPART_ELEMENT_CAPACITY / 2) @@ -793,13 +908,13 @@ prepare_bobs_cryptodata_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) { - struct ServiceSession * s = (struct ServiceSession *) cls; - struct GNUNET_SCALARPRODUCT_service_response * msg; + struct ServiceSession * s = cls; + struct ServiceResponseMessage * msg; uint32_t msg_length = 0; struct GNUNET_CRYPTO_PaillierCiphertext * payload; int i; - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + msg_length = sizeof (struct ServiceResponseMessage) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // s, stick if (GNUNET_SERVER_MAX_MESSAGE_SIZE > @@ -885,7 +1000,7 @@ prepare_bobs_cryptodata_message (void *cls, * @param request the requesting session + bob's requesting peer */ static void -compute_service_response (struct ServiceSession * session) +compute_service_response (struct ServiceSession *session) { int i; unsigned int * p; @@ -1022,13 +1137,15 @@ cb_insert_element_sorted (void *cls, struct ServiceSession * s = (struct ServiceSession*) cls; struct SortedValue * e = GNUNET_new (struct SortedValue); struct SortedValue * o = s->a_head; + int64_t val; e->elem = value; e->val = gcry_mpi_new (0); - if (0 > e->elem->value) - gcry_mpi_sub_ui (e->val, e->val, abs (e->elem->value)); + val = (int64_t) GNUNET_ntohll (e->elem->value); + if (0 > val) + gcry_mpi_sub_ui (e->val, e->val, - val); else - gcry_mpi_add_ui (e->val, e->val, e->elem->value); + gcry_mpi_add_ui (e->val, e->val, val); // insert as first element with the lowest key if (NULL == s->a_head @@ -1208,7 +1325,7 @@ prepare_client_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceSession * s = cls; - struct GNUNET_SCALARPRODUCT_client_response * msg; + struct ClientResponseMessage *msg; unsigned char * product_exported = NULL; size_t product_length = 0; uint32_t msg_length = 0; @@ -1250,10 +1367,8 @@ prepare_client_response (void *cls, gcry_mpi_release (value); } - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_client_response) +product_length; + msg_length = sizeof (struct ClientResponseMessage) + product_length; msg = GNUNET_malloc (msg_length); - msg->key = s->session_id; - msg->peer = s->peer; if (product_exported != NULL) { memcpy (&msg[1], product_exported, product_length); GNUNET_free (product_exported); @@ -1285,27 +1400,31 @@ prepare_client_response (void *cls, static void prepare_alices_computation_request (struct ServiceSession * s) { - struct GNUNET_SCALARPRODUCT_service_request * msg; + struct ServiceRequestMessage * msg; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to peer (%s)!\n"), GNUNET_i2s (&s->peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Successfully created new channel to peer (%s)!\n"), + GNUNET_i2s (&s->peer)); - msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_service_request); + msg = GNUNET_new (struct ServiceRequestMessage); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_CRYPTODATA); memcpy (&msg->session_id, &s->session_id, sizeof (struct GNUNET_HashCode)); - msg->header.size = htons (sizeof (struct GNUNET_SCALARPRODUCT_service_request)); + msg->header.size = htons (sizeof (struct ServiceRequestMessage)); s->msg = (struct GNUNET_MessageHeader *) msg; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n")); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Transmitting service request.\n")); //transmit via cadet messaging - s->service_transmit_handle = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES, - GNUNET_TIME_UNIT_FOREVER_REL, - sizeof (struct GNUNET_SCALARPRODUCT_service_request), - &cb_transfer_message, - s); + s->service_transmit_handle + = GNUNET_CADET_notify_transmit_ready (s->channel, GNUNET_YES, + GNUNET_TIME_UNIT_FOREVER_REL, + sizeof (struct ServiceRequestMessage), + &cb_transfer_message, + s); if (!s->service_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ ("Could not send message to channel!\n")); + _("Could not send message to channel!\n")); GNUNET_free (msg); s->msg = NULL; s->active = GNUNET_SYSERR; @@ -1330,14 +1449,14 @@ static void prepare_alices_cyrptodata_message_multipart (void *cls) { struct ServiceSession * s = cls; - struct GNUNET_SCALARPRODUCT_multipart_message * msg; + struct MultipartMessage * msg; struct GNUNET_CRYPTO_PaillierCiphertext * payload; unsigned int i; uint32_t msg_length; uint32_t todo_count; gcry_mpi_t a; - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message); + msg_length = sizeof (struct MultipartMessage); todo_count = s->used_element_count - s->transferred_element_count; if (todo_count > MULTIPART_ELEMENT_CAPACITY) @@ -1472,7 +1591,7 @@ handle_client_message_multipart (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - const struct GNUNET_SCALARPRODUCT_computation_message_multipart * msg = (const struct GNUNET_SCALARPRODUCT_computation_message_multipart *) message; + const struct ComputationMultipartMessage * msg = (const struct ComputationMultipartMessage *) message; struct ServiceSession * s; uint32_t contained_count; struct GNUNET_SCALARPRODUCT_Element * elements; @@ -1488,8 +1607,9 @@ handle_client_message_multipart (void *cls, contained_count = ntohl (msg->element_count_contained); //sanity check: is the message as long as the message_count fields suggests? - if ((ntohs (msg->header.size) != (sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart) +contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) - || (0 == contained_count) || (s->total < s->transferred_element_count + contained_count)) { + if ((ntohs (msg->header.size) != (sizeof (struct ComputationMultipartMessage) +contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) + || (0 == contained_count) || (s->total < s->transferred_element_count + contained_count)) + { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -1501,7 +1621,7 @@ handle_client_message_multipart (void *cls, struct GNUNET_SET_Element set_elem; struct GNUNET_SCALARPRODUCT_Element * elem; - if (0 == ntohl (elements[i].value)) + if (0 == GNUNET_ntohll (elements[i].value)) continue; elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element); @@ -1549,7 +1669,7 @@ handle_client_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - const struct GNUNET_SCALARPRODUCT_computation_message * msg = (const struct GNUNET_SCALARPRODUCT_computation_message *) message; + const struct ComputationMessage * msg = (const struct ComputationMessage *) message; struct ServiceSession * s; uint32_t contained_count; uint32_t total_count; @@ -1577,8 +1697,10 @@ handle_client_message (void *cls, } //sanity check: is the message as long as the message_count fields suggests? - if ((ntohs (msg->header.size) != (sizeof (struct GNUNET_SCALARPRODUCT_computation_message) +contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) - || (0 == total_count)) { + if ((ntohs (msg->header.size) != + (sizeof (struct ComputationMessage) + contained_count * sizeof (struct GNUNET_SCALARPRODUCT_Element))) + || (0 == total_count)) + { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; @@ -1611,7 +1733,7 @@ handle_client_message (void *cls, struct GNUNET_SET_Element set_elem; struct GNUNET_SCALARPRODUCT_Element * elem; - if (0 == ntohl (elements[i].value)) + if (0 == GNUNET_ntohll (elements[i].value)) continue; elem = GNUNET_new (struct GNUNET_SCALARPRODUCT_Element); @@ -1862,7 +1984,7 @@ handle_alices_cyrptodata_message_multipart (void *cls, const struct GNUNET_MessageHeader * message) { struct ServiceSession * s; - const struct GNUNET_SCALARPRODUCT_multipart_message * msg = (const struct GNUNET_SCALARPRODUCT_multipart_message *) message; + const struct MultipartMessage * msg = (const struct MultipartMessage *) message; struct GNUNET_CRYPTO_PaillierCiphertext *payload; uint32_t contained_elements; uint32_t msg_length; @@ -1875,11 +1997,11 @@ handle_alices_cyrptodata_message_multipart (void *cls, goto except; } // shorter than minimum? - if (ntohs (msg->header.size) <= sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)) { + if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage)) { goto except; } contained_elements = ntohl (msg->contained_element_count); - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + msg_length = sizeof (struct MultipartMessage) +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check if ((ntohs (msg->header.size) != msg_length) @@ -1946,7 +2068,7 @@ handle_alices_cyrptodata_message (void *cls, const struct GNUNET_MessageHeader * message) { struct ServiceSession * s; - const struct GNUNET_SCALARPRODUCT_alices_cryptodata_message * msg = (const struct GNUNET_SCALARPRODUCT_alices_cryptodata_message *) message; + const struct AliceCryptodataMessage * msg = (const struct AliceCryptodataMessage *) message; struct GNUNET_CRYPTO_PaillierCiphertext *payload; uint32_t contained_elements = 0; uint32_t msg_length; @@ -1966,12 +2088,13 @@ handle_alices_cyrptodata_message (void *cls, } // shorter than minimum? - if (ntohs (msg->header.size) <= sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)) { + if (ntohs (msg->header.size) <= sizeof (struct MultipartMessage)) + { goto invalid_msg; } contained_elements = ntohl (msg->contained_element_count); - msg_length = sizeof (struct GNUNET_SCALARPRODUCT_alices_cryptodata_message) + msg_length = sizeof (struct AliceCryptodataMessage) +contained_elements * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? @@ -2039,7 +2162,7 @@ handle_alices_computation_request (void *cls, { struct ServiceSession * s; struct ServiceSession * client_session; - const struct GNUNET_SCALARPRODUCT_service_request * msg = (const struct GNUNET_SCALARPRODUCT_service_request *) message; + const struct ServiceRequestMessage * msg = (const struct ServiceRequestMessage *) message; s = (struct ServiceSession *) * channel_ctx; if ((BOB != s->role) || (s->total != 0)) { @@ -2053,7 +2176,7 @@ handle_alices_computation_request (void *cls, return GNUNET_SYSERR; } // shorter than expected? - if (ntohs (msg->header.size) != sizeof (struct GNUNET_SCALARPRODUCT_service_request)) { + if (ntohs (msg->header.size) != sizeof (struct ServiceRequestMessage)) { GNUNET_free (s); GNUNET_break_op (0); return GNUNET_SYSERR; @@ -2155,7 +2278,7 @@ handle_bobs_cryptodata_multipart (void *cls, const struct GNUNET_MessageHeader * message) { struct ServiceSession * s; - const struct GNUNET_SCALARPRODUCT_multipart_message * msg = (const struct GNUNET_SCALARPRODUCT_multipart_message *) message; + const struct MultipartMessage * msg = (const struct MultipartMessage *) message; struct GNUNET_CRYPTO_PaillierCiphertext * payload; size_t i; uint32_t contained = 0; @@ -2169,14 +2292,14 @@ handle_bobs_cryptodata_multipart (void *cls, goto invalid_msg; } msg_size = ntohs (msg->header.size); - required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + required_size = sizeof (struct MultipartMessage) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // shorter than minimum? if (required_size > msg_size) { goto invalid_msg; } contained = ntohl (msg->contained_element_count); - required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + required_size = sizeof (struct MultipartMessage) + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? if ((required_size != msg_size) || (s->used_element_count < s->transferred_element_count + contained)) { @@ -2239,12 +2362,12 @@ invalid_msg: */ static int handle_bobs_cryptodata_message (void *cls, - struct GNUNET_CADET_Channel * channel, + struct GNUNET_CADET_Channel *channel, void **channel_ctx, - const struct GNUNET_MessageHeader * message) + const struct GNUNET_MessageHeader *message) { struct ServiceSession * s; - const struct GNUNET_SCALARPRODUCT_service_response * msg = (const struct GNUNET_SCALARPRODUCT_service_response *) message; + const struct ServiceResponseMessage *msg = (const struct ServiceResponseMessage *) message; struct GNUNET_CRYPTO_PaillierCiphertext * payload; size_t i; uint32_t contained = 0; @@ -2261,13 +2384,13 @@ handle_bobs_cryptodata_message (void *cls, } //we need at least a full message without elements attached msg_size = ntohs (msg->header.size); - required_size = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); + required_size = sizeof (struct ServiceResponseMessage) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); if (required_size > msg_size) { goto invalid_msg; } contained = ntohl (msg->contained_element_count); - required_size = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + required_size = sizeof (struct ServiceResponseMessage) + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? diff --git a/src/scalarproduct/scalarproduct.h b/src/scalarproduct/scalarproduct.h index 6837b3abc..4bafb18fb 100644 --- a/src/scalarproduct/scalarproduct.h +++ b/src/scalarproduct/scalarproduct.h @@ -33,14 +33,8 @@ extern "C" { #endif -/////////////////////////////////////////////////////////////////////////////// -// Defines -/////////////////////////////////////////////////////////////////////////////// -/** - * Maximum count of elements we can put into a multipart message - */ -#define MULTIPART_ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)) +GNUNET_NETWORK_STRUCT_BEGIN /** * Log an error message at log-level 'level' that indicates @@ -49,15 +43,12 @@ extern "C" */ #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) -/////////////////////////////////////////////////////////////////////////////// -// Scalar Product Message Types -/////////////////////////////////////////////////////////////////////////////// /** * Message type passed from client to service * to initiate a request or responder role */ -struct GNUNET_SCALARPRODUCT_computation_message +struct ComputationMessage { /** * GNUNET message header @@ -68,12 +59,17 @@ struct GNUNET_SCALARPRODUCT_computation_message * how many elements the vector in payload contains */ uint32_t element_count_total GNUNET_PACKED; - + /** * contained elements the vector in payload contains */ uint32_t element_count_contained GNUNET_PACKED; + /** + * Always zero. + */ + uint32_t reserved GNUNET_PACKED; + /** * the transaction/session key used to identify a session */ @@ -89,16 +85,17 @@ struct GNUNET_SCALARPRODUCT_computation_message */ }; + /** - * multipart messages following GNUNET_SCALARPRODUCT_client_request + * multipart messages following `struct ComputationMessage` */ -struct GNUNET_SCALARPRODUCT_computation_message_multipart +struct ComputationMultipartMessage { /** * GNUNET message header */ struct GNUNET_MessageHeader header; - + /** * contained elements the vector in payload contains */ @@ -110,106 +107,11 @@ struct GNUNET_SCALARPRODUCT_computation_message_multipart }; -/** - * Message type passed from requesting service Alice to responding service Bob - * to initiate a request and make bob participate in our protocol - */ -struct GNUNET_SCALARPRODUCT_service_request { - /** - * GNUNET message header - */ - struct GNUNET_MessageHeader header; - - /** - * the transaction/session key used to identify a session - */ - struct GNUNET_HashCode session_id; - - /** - * Alice's public key - */ - struct GNUNET_CRYPTO_PaillierPublicKey public_key; - -}; - - -/** - * Message type passed from requesting service Alice to responding service Bob - * to initiate a request and make bob participate in our protocol - */ -struct GNUNET_SCALARPRODUCT_alices_cryptodata_message { - /** - * GNUNET message header - */ - struct GNUNET_MessageHeader header; - - /** - * how many elements we appended to this message - */ - uint32_t contained_element_count GNUNET_PACKED; - - /** - * struct GNUNET_CRYPTO_PaillierCiphertext[contained_element_count] - */ -}; - -/** - * Multipart Message type passed between to supply additional elements for the peer - */ -struct GNUNET_SCALARPRODUCT_multipart_message { - /** - * GNUNET message header - */ - struct GNUNET_MessageHeader header; - - /** - * how many elements we supply within this message - */ - uint32_t contained_element_count GNUNET_PACKED; - - // struct GNUNET_CRYPTO_PaillierCiphertext[multipart_element_count] -}; - -/** - * Message type passed from responding service Bob to responding service Alice - * to complete a request and allow Alice to compute the result - */ -struct GNUNET_SCALARPRODUCT_service_response { - /** - * GNUNET message header - */ - struct GNUNET_MessageHeader header; - - /** - * how many elements the session input had - */ - uint32_t total_element_count GNUNET_PACKED; - - /** - * how many elements were included after the mask was applied including all multipart msgs. - */ - uint32_t used_element_count GNUNET_PACKED; - - /** - * how many elements this individual message delivers - */ - uint32_t contained_element_count GNUNET_PACKED; - - /** - * the transaction/session key used to identify a session - */ - struct GNUNET_HashCode key; - - /** - * followed by s | s' | k[i][perm] - */ -}; - /** * Message type passed from service client * to finalize a session as requester or responder */ -struct GNUNET_SCALARPRODUCT_client_response +struct ClientResponseMessage { /** * GNUNET message header @@ -221,31 +123,23 @@ struct GNUNET_SCALARPRODUCT_client_response */ uint32_t product_length GNUNET_PACKED; - /** - * the transaction/session key used to identify a session - */ - struct GNUNET_HashCode key; - - /** - * the identity of a remote peer we want to communicate with - */ - struct GNUNET_PeerIdentity peer; - /** * status information about the outcome of this session */ - int32_t status; - + int32_t status GNUNET_PACKED; + /** * Workaround for libgcrypt: -1 if negative, 0 if zero, else 1 */ - int8_t range; + int32_t range GNUNET_PACKED; /** * followed by product of length product_length (or nothing) */ }; +GNUNET_NETWORK_STRUCT_END + #ifdef __cplusplus } #endif diff --git a/src/scalarproduct/scalarproduct_api.c b/src/scalarproduct/scalarproduct_api.c index 3b92af579..ea62027ab 100644 --- a/src/scalarproduct/scalarproduct_api.c +++ b/src/scalarproduct/scalarproduct_api.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2013 Christian Grothoff (and other contributing authors) + (C) 2013, 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -23,7 +23,7 @@ * @brief API for the scalarproduct * @author Christian Fuchs * @author Gaurav Kukreja - * + * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" @@ -34,16 +34,19 @@ #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-api",__VA_ARGS__) -/************************************************************** - *** Datatype Declarations ********** - **************************************************************/ /** - * the abstraction function for our internal callback + * The abstraction function for our internal callback + * + * @param h computation handle + * @param msg response we got, NULL on errors + * @param status processing status code */ -typedef void (*GNUNET_SCALARPRODUCT_ResponseMessageHandler) (void *cls, - const struct GNUNET_MessageHeader *msg, - enum GNUNET_SCALARPRODUCT_ResponseStatus status); +typedef void +(*GNUNET_SCALARPRODUCT_ResponseMessageHandler) (struct GNUNET_SCALARPRODUCT_ComputationHandle *h, + const struct ClientResponseMessage *msg, + enum GNUNET_SCALARPRODUCT_ResponseStatus status); + /** * A handle returned for each computation @@ -60,11 +63,6 @@ struct GNUNET_SCALARPRODUCT_ComputationHandle */ struct GNUNET_CLIENT_Connection *client; - /** - * Handle for statistics. - */ - struct GNUNET_STATISTICS_Handle *stats; - /** * The shared session key identifying this computation */ @@ -76,30 +74,25 @@ struct GNUNET_SCALARPRODUCT_ComputationHandle struct GNUNET_CLIENT_TransmitHandle *th; /** - * count of all elements we offer for computation + * count of all @e elements we offer for computation */ uint32_t element_count_total; /** - * count of the transfered elements we offer for computation + * count of the transfered @e elements we offer for computation */ uint32_t element_count_transfered; - + /** - * the client's elements which + * the client's elements which */ - struct GNUNET_SCALARPRODUCT_Element * elements; - + struct GNUNET_SCALARPRODUCT_Element *elements; + /** * Message to be sent to the scalarproduct service */ - void * msg; + struct GNUNET_MessageHeader *msg; - /** - * The client's msg handler callback - */ - union - { /** * Function to call after transmission of the request (Bob). */ @@ -109,101 +102,99 @@ struct GNUNET_SCALARPRODUCT_ComputationHandle * Function to call after transmission of the request (Alice). */ GNUNET_SCALARPRODUCT_DatumProcessor cont_datum; - }; /** - * Closure for 'cont'. + * Closure for @e cont_status or @e cont_datum. */ void *cont_cls; /** - * API internal callback for results and failures to be forwarded to the client + * API internal callback for results and failures to be forwarded to + * the client. */ GNUNET_SCALARPRODUCT_ResponseMessageHandler response_proc; - - /** - * - */ - GNUNET_SCHEDULER_TaskIdentifier cont_multipart; -}; - -/************************************************************** - *** Forward Function Declarations ********** - **************************************************************/ - -void -GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * h); -static size_t do_send_message (void *cls, size_t size, void *buf); -/************************************************************** - *** Static Function Declarations ********** - **************************************************************/ +}; /** - * Handles the STATUS received from the service for a response, does not contain a payload + * Handles the STATUS received from the service for a response, does + * not contain a payload. * - * @param cls our Handle + * @param h our Handle * @param msg Pointer to the response received * @param status the condition the request was terminated with (eg: disconnect) */ static void -process_status_message (void *cls, - const struct GNUNET_MessageHeader *msg, +process_status_message (struct GNUNET_SCALARPRODUCT_ComputationHandle *h, + const struct ClientResponseMessage *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status) { - struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; - - qe->cont_status (qe->cont_cls, status); + if (NULL != h->cont_status) + h->cont_status (h->cont_cls, + status); + GNUNET_SCALARPRODUCT_cancel (h); } /** - * Handles the RESULT received from the service for a request, should contain a result MPI value + * Handles the RESULT received from the service for a request, should + * contain a result MPI value * - * @param cls our Handle + * @param h our Handle * @param msg Pointer to the response received * @param status the condition the request was terminated with (eg: disconnect) */ static void -process_result_message (void *cls, - const struct GNUNET_MessageHeader *msg, +process_result_message (struct GNUNET_SCALARPRODUCT_ComputationHandle *h, + const struct ClientResponseMessage *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status) { - struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; - const struct GNUNET_SCALARPRODUCT_client_response *message = - (const struct GNUNET_SCALARPRODUCT_client_response *) msg; + size_t product_len = ntohl (msg->product_length); gcry_mpi_t result = NULL; gcry_error_t rc; + gcry_mpi_t num; + size_t rsize; + if (ntohs (msg->header.size) - sizeof (struct ClientResponseMessage) + != product_len) + { + GNUNET_break (0); + status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; + } if (GNUNET_SCALARPRODUCT_Status_Success == status) + { + result = gcry_mpi_new (0); + + if (0 < product_len) { - size_t product_len = ntohl (message->product_length); - result = gcry_mpi_new (0); - - if (0 < product_len) - { - gcry_mpi_t num; - size_t read = 0; - - if (0 != (rc = gcry_mpi_scan (&num, GCRYMPI_FMT_STD, &message[1], product_len, &read))) - { - LOG_GCRY(GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (result); - result = NULL; - status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; - } - else - { - if (0 < message->range) - gcry_mpi_add (result, result, num); - else if (0 > message->range) - gcry_mpi_sub (result, result, num); - gcry_mpi_release (num); - } - } + rsize = 0; + if (0 != (rc = gcry_mpi_scan (&num, GCRYMPI_FMT_STD, + &msg[1], + product_len, + &rsize))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, + "gcry_mpi_scan", + rc); + gcry_mpi_release (result); + result = NULL; + status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; + } + else + { + if (0 < ntohl (msg->range)) + gcry_mpi_add (result, result, num); + else if (0 > ntohl (msg->range)) + gcry_mpi_sub (result, result, num); + gcry_mpi_release (num); + } } - qe->cont_datum (qe->cont_cls, status, result); + } + h->cont_datum (h->cont_cls, status, result); + if (NULL != result) + gcry_mpi_release (result); + GNUNET_SCALARPRODUCT_cancel (h); } @@ -216,144 +207,114 @@ process_result_message (void *cls, * @param msg Pointer to the data received in response */ static void -receive_cb (void *cls, const struct GNUNET_MessageHeader *msg) +receive_cb (void *cls, + const struct GNUNET_MessageHeader *msg) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h = cls; - const struct GNUNET_SCALARPRODUCT_client_response *message = - (const struct GNUNET_SCALARPRODUCT_client_response *) msg; - enum GNUNET_SCALARPRODUCT_ResponseStatus status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; + const struct ClientResponseMessage *message; if (NULL == msg) - { - LOG (GNUNET_ERROR_TYPE_WARNING, "Disconnected by Service.\n"); - status = GNUNET_SCALARPRODUCT_Status_ServiceDisconnected; - } - else if ((GNUNET_SYSERR != message->status) && (0 < message->product_length )) - { - // response for the responder client, successful - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# SUC responder result messages received"), 1, - GNUNET_NO); - - status = GNUNET_SCALARPRODUCT_Status_Success; - } - else if (message->status == GNUNET_SYSERR){ - // service signaled an error - status = GNUNET_SCALARPRODUCT_Status_Failure; + { + LOG (GNUNET_ERROR_TYPE_INFO, + "Disconnected from SCALARPRODUCT service.\n"); + h->response_proc (h, + NULL, + GNUNET_SCALARPRODUCT_Status_ServiceDisconnected); + return; } - - if (h->cont_status != NULL) - h->response_proc (h, msg, status); - - GNUNET_free (h); -} - - -static void -send_multipart (void * cls, const struct GNUNET_SCHEDULER_TaskContext * tc) -{ - struct GNUNET_SCALARPRODUCT_ComputationHandle *h = (struct GNUNET_SCALARPRODUCT_ComputationHandle *) cls; - struct GNUNET_SCALARPRODUCT_computation_message_multipart *msg; - uint32_t size; - uint32_t todo; - - h->cont_multipart = GNUNET_SCHEDULER_NO_TASK; - - todo = h->element_count_total - h->element_count_transfered; - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart) +todo * sizeof (struct GNUNET_SCALARPRODUCT_Element); - if (GNUNET_SERVER_MAX_MESSAGE_SIZE <= size) { - //create a multipart msg, first we calculate a new msg size for the head msg - todo = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart)) / sizeof (struct GNUNET_SCALARPRODUCT_Element); - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message_multipart) +todo * sizeof (struct GNUNET_SCALARPRODUCT_Element); + if (ntohs (msg->size) != sizeof (struct ClientResponseMessage)) + { + GNUNET_break (0); + h->response_proc (h, + NULL, + GNUNET_SCALARPRODUCT_Status_InvalidResponse); + return; } - - msg = (struct GNUNET_SCALARPRODUCT_computation_message_multipart*) GNUNET_malloc (size); - h->msg = msg; - msg->header.size = htons (size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART); - msg->element_count_contained = htonl (todo); - - memcpy (&msg[1], &h->elements[h->element_count_transfered], todo * sizeof (struct GNUNET_SCALARPRODUCT_Element)); - h->element_count_transfered += todo; - - h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, // retry is OK in the initial stage - &do_send_message, h); - - if (!h->th) { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to send a multipart message to the scalarproduct service\n")); - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# transmission request failures"), - 1, GNUNET_NO); - GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_free (h->msg); - h->msg = NULL; - if (h->cont_status != NULL) - h->response_proc (h, NULL, GNUNET_SCALARPRODUCT_Status_Failure); - - GNUNET_SCALARPRODUCT_cancel (cls); + message = (const struct ClientResponseMessage *) msg; + if (GNUNET_SYSERR == ntohl (message->status)) + { + h->response_proc (h, + NULL, + GNUNET_SCALARPRODUCT_Status_Failure); + return; } + h->response_proc (h, + message, + GNUNET_SCALARPRODUCT_Status_Success); } + /** - * Transmits the request to the VectorProduct Service + * Transmits the request to the SCALARPRODUCT service * - * @param cls Closure - * @param size Size of the buffer + * @param cls Closure with the `struct GNUNET_SCALARPRODUCT_ComputationHandle` + * @param size Size of the buffer @a buf * @param buf Pointer to the buffer - * * @return Size of the message sent */ static size_t -do_send_message (void *cls, size_t size, +do_send_message (void *cls, + size_t size, void *buf) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h = cls; + struct ComputationMultipartMessage *msg; + size_t ret; + uint32_t nsize; + uint32_t todo; - if (NULL == buf) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to SCALARPRODUCT.\n"); - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# transmission request failures"), - 1, GNUNET_NO); - - // notify caller about the error, done here. - if (h->cont_status != NULL) - h->response_proc (h, NULL, GNUNET_SCALARPRODUCT_Status_Failure); - - GNUNET_SCALARPRODUCT_cancel (cls); + h->th = NULL; + if (NULL == buf) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Failed to transmit request to SCALARPRODUCT.\n"); + /* notify caller about the error, done here */ + h->response_proc (h, NULL, + GNUNET_SCALARPRODUCT_Status_Failure); return 0; } - memcpy (buf, h->msg, size); - + ret = ntohs (h->msg->size); + memcpy (buf, h->msg, ret); GNUNET_free (h->msg); h->msg = NULL; - h->th = NULL; - -#if INSANE_STATISTICS - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# bytes sent to scalarproduct"), 1, - GNUNET_NO); -#endif - /* done sending */ - if (h->element_count_total == h->element_count_transfered) { - GNUNET_CLIENT_receive (h->client, &receive_cb, h, + /* done sending? */ + if (h->element_count_total == h->element_count_transfered) + { + GNUNET_CLIENT_receive (h->client, + &receive_cb, h, GNUNET_TIME_UNIT_FOREVER_REL); - return size; + return ret; } - - h->cont_multipart = GNUNET_SCHEDULER_add_now (&send_multipart, h); - - return size; -} + todo = h->element_count_total - h->element_count_transfered; + nsize = sizeof (struct ComputationMultipartMessage) + + todo * sizeof (struct GNUNET_SCALARPRODUCT_Element); + if (GNUNET_SERVER_MAX_MESSAGE_SIZE <= size) + { + /* cannot do all of them, limit to what is possible in one message */ + todo = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct ComputationMultipartMessage)) + / sizeof (struct GNUNET_SCALARPRODUCT_Element); + nsize = sizeof (struct ComputationMultipartMessage) + + todo * sizeof (struct GNUNET_SCALARPRODUCT_Element); + } -/************************************************************** - *** API ********** - **************************************************************/ + msg = GNUNET_malloc (nsize); + h->msg = &msg->header; + msg->header.size = htons (nsize); + msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_MUTLIPART); + msg->element_count_contained = htonl (todo); + memcpy (&msg[1], + &h->elements[h->element_count_transfered], + todo * sizeof (struct GNUNET_SCALARPRODUCT_Element)); + h->element_count_transfered += todo; + h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, nsize, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &do_send_message, h); + GNUNET_assert (NULL != h->th); + return ret; +} /** @@ -362,96 +323,75 @@ do_send_message (void *cls, size_t size, * @param cfg the gnunet configuration handle * @param key Session key unique to the requesting client * @param elements Array of elements of the vector - * @param element_count Number of elements in the vector + * @param element_count Number of elements in the @a elements vector * @param cont Callback function - * @param cont_cls Closure for the callback function - * + * @param cont_cls Closure for @a cont * @return a new handle for this computation */ 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) +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) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h; - struct GNUNET_SCALARPRODUCT_computation_message *msg; + struct ComputationMessage *msg; uint32_t size; uint16_t possible; - GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_SCALARPRODUCT_computation_message) - + element_count * sizeof (int32_t)); h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); + h->cont_status = cont; + h->cont_cls = cont_cls; + h->response_proc = &process_status_message; + h->cfg = cfg; + h->key = *session_key; h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg); - if (!h->client) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to connect to the scalarproduct service\n")); - GNUNET_free (h); - return NULL; - } - h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg); - if (!h->stats) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to send a message to the statistics service\n")); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_free (h); - return NULL; - } - h->element_count_total = element_count; - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element); - if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) { + if (NULL == h->client) + { + /* scalarproduct configuration error */ + GNUNET_break (0); + GNUNET_free (h); + return NULL; + } + size = sizeof (struct ComputationMessage) + + element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element); + if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) + { possible = element_count; h->element_count_transfered = element_count; } - else { - //create a multipart msg, first we calculate a new msg size for the head msg - possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_computation_message)) / sizeof (struct GNUNET_SCALARPRODUCT_Element); + else + { + /* create a multipart msg, first we calculate a new msg size for the head msg */ + possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct ComputationMessage)) + / sizeof (struct GNUNET_SCALARPRODUCT_Element); h->element_count_transfered = possible; - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + possible*sizeof (struct GNUNET_SCALARPRODUCT_Element); - h->elements = (struct GNUNET_SCALARPRODUCT_Element*) - GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * element_count); - memcpy (h->elements, elements, sizeof (struct GNUNET_SCALARPRODUCT_Element)*element_count); + size = sizeof (struct ComputationMessage) + + possible * sizeof (struct GNUNET_SCALARPRODUCT_Element); + h->elements = GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * element_count); + memcpy (h->elements, + elements, + sizeof (struct GNUNET_SCALARPRODUCT_Element) * element_count); } - h->cont_status = cont; - h->cont_cls = cont_cls; - h->response_proc = &process_status_message; - h->cfg = cfg; - memcpy (&h->key, session_key, sizeof (struct GNUNET_HashCode)); - - msg = (struct GNUNET_SCALARPRODUCT_computation_message*) GNUNET_malloc (size); - h->msg = msg; + msg = GNUNET_malloc (size); + h->msg = &msg->header; msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB); msg->element_count_total = htonl (element_count); msg->element_count_contained = htonl (possible); - - memcpy (&msg->session_key, session_key, sizeof (struct GNUNET_HashCode)); - memcpy (&msg[1], elements, possible); - + msg->session_key = *session_key; + memcpy (&msg[1], + elements, + possible); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, // retry is OK in the initial stage + GNUNET_YES, /* retry is OK in the initial stage */ &do_send_message, h); - if (!h->th) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to send a message to the scalarproduct service\n")); - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# transmission request failures"), - 1, GNUNET_NO); - GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_free (h->msg); - GNUNET_free_non_null (h->elements); - GNUNET_free (h); - return NULL; - } + GNUNET_assert (NULL != h->th); return h; } @@ -463,99 +403,82 @@ GNUNET_SCALARPRODUCT_accept_computation (const struct GNUNET_CONFIGURATION_Handl * @param session_key Session key should be unique to the requesting client * @param peer PeerID of the other peer * @param elements Array of elements of the vector - * @param element_count Number of elements in the vector + * @param element_count Number of elements in the @a elements vector * @param cont Callback function - * @param cont_cls Closure for the callback function - * + * @param cont_cls Closure for @a cont * @return a new handle for this computation */ 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) +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) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h; - struct GNUNET_SCALARPRODUCT_computation_message *msg; + struct ComputationMessage *msg; uint32_t size; - uint16_t possible; + uint32_t possible; h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg); - if (!h->client) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to connect to the scalarproduct service\n")); - GNUNET_free (h); - return NULL; - } - h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg); - if (!h->stats) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to send a message to the statistics service\n")); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_free (h); - return NULL; - } - + if (NULL == h->client) + { + /* missconfigured scalarproduct service */ + GNUNET_break (0); + GNUNET_free (h); + return NULL; + } h->element_count_total = element_count; - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element); - if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) { + h->cont_datum = cont; + h->cont_cls = cont_cls; + h->response_proc = &process_result_message; + h->cfg = cfg; + h->key = *session_key; + size = sizeof (struct ComputationMessage) + + element_count * sizeof (struct GNUNET_SCALARPRODUCT_Element); + if (GNUNET_SERVER_MAX_MESSAGE_SIZE > size) + { possible = element_count; h->element_count_transfered = element_count; } - else { - //create a multipart msg, first we calculate a new msg size for the head msg - possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_computation_message)) / sizeof (struct GNUNET_SCALARPRODUCT_Element); + else + { + /* create a multipart msg, first we calculate a new msg size for the head msg */ + possible = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct ComputationMessage)) + / sizeof (struct GNUNET_SCALARPRODUCT_Element); h->element_count_transfered = possible; - size = sizeof (struct GNUNET_SCALARPRODUCT_computation_message) + possible*sizeof (struct GNUNET_SCALARPRODUCT_Element); - h->elements = (struct GNUNET_SCALARPRODUCT_Element*) - GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * element_count); - memcpy (h->elements, elements, sizeof (struct GNUNET_SCALARPRODUCT_Element) * element_count); + size = sizeof (struct ComputationMessage) + + possible * sizeof (struct GNUNET_SCALARPRODUCT_Element); + h->elements = GNUNET_malloc (sizeof(struct GNUNET_SCALARPRODUCT_Element) * element_count); + memcpy (h->elements, + elements, + sizeof (struct GNUNET_SCALARPRODUCT_Element) * element_count); } - - h->cont_datum = cont; - h->cont_cls = cont_cls; - h->response_proc = &process_result_message; - h->cfg = cfg; - memcpy (&h->key, session_key, sizeof (struct GNUNET_HashCode)); - msg = (struct GNUNET_SCALARPRODUCT_computation_message*) GNUNET_malloc (size); - h->msg = msg; + msg = GNUNET_malloc (size); + h->msg = &msg->header; msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE); msg->element_count_total = htonl (element_count); msg->element_count_contained = htonl (possible); - - memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity)); - memcpy (&msg->session_key, session_key, sizeof (struct GNUNET_HashCode)); - memcpy (&msg[1], elements, sizeof (struct GNUNET_SCALARPRODUCT_Element) * possible); - + msg->reserved = htonl (0); + msg->peer = *peer; + msg->session_key = *session_key; + memcpy (&msg[1], + elements, + sizeof (struct GNUNET_SCALARPRODUCT_Element) * possible); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, // retry is OK in the initial stage + GNUNET_YES, /* retry is OK in the initial stage */ &do_send_message, h); - if (!h->th) - { - LOG (GNUNET_ERROR_TYPE_ERROR, - _ ("Failed to send a message to the scalarproduct service\n")); - GNUNET_STATISTICS_update (h->stats, - gettext_noop ("# transmission request failures"), - 1, GNUNET_NO); - GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_free (h->msg); - GNUNET_free_non_null (h->elements); - GNUNET_free (h); - return NULL; - } + GNUNET_assert (NULL != h->th); return h; } + /** * Cancel an ongoing computation or revoke our collaboration offer. * Closes the connection to the service @@ -563,16 +486,20 @@ GNUNET_SCALARPRODUCT_start_computation (const struct GNUNET_CONFIGURATION_Handle * @param h computation handle to terminate */ void -GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * h) +GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle *h) { if (NULL != h->th) + { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); - if (GNUNET_SCHEDULER_NO_TASK != h->cont_multipart) - GNUNET_SCHEDULER_cancel (h->cont_multipart); + h->th = NULL; + } GNUNET_free_non_null (h->elements); GNUNET_free_non_null (h->msg); - GNUNET_CLIENT_disconnect (h->client); - GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); + if (NULL != h->client) + { + GNUNET_CLIENT_disconnect (h->client); + h->client = NULL; + } GNUNET_free (h); } -- 2.25.1