+static void
+prepare_service_request_multipart (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct ServiceSession * session = cls;
+ unsigned char * current;
+ unsigned char * element_exported;
+ struct GNUNET_SCALARPRODUCT_multipart_message * msg;
+ unsigned int i;
+ unsigned int j;
+ uint32_t msg_length;
+ uint32_t todo_count;
+ size_t element_length = 0; // initialized by gcry_mpi_print, but the compiler doesn't know that
+ gcry_mpi_t a;
+ uint32_t value;
+
+ msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message);
+ todo_count = session->used - session->transferred;
+
+ if (todo_count > MULTIPART_ELEMENT_CAPACITY)
+ // send the currently possible maximum chunk
+ todo_count = MULTIPART_ELEMENT_CAPACITY;
+
+ msg_length += todo_count * PAILLIER_ELEMENT_LENGTH;
+ msg = GNUNET_malloc (msg_length);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART);
+ msg->header.size = htons (msg_length);
+ msg->multipart_element_count = htonl (todo_count);
+
+ element_exported = GNUNET_malloc (PAILLIER_ELEMENT_LENGTH);
+ a = gcry_mpi_new (KEYBITS * 2);
+ current = (unsigned char *) &msg[1];
+ // encrypt our vector and generate string representations
+ for (i = session->last_processed, j = 0; i < session->total; i++) {
+ // is this a used element?
+ if (session->mask[i / 8] & 1 << (i % 8)) {
+ if (todo_count <= j)
+ break; //reached end of this message, can't include more
+
+ memset (element_exported, 0, PAILLIER_ELEMENT_LENGTH);
+ value = session->vector[i] >= 0 ? session->vector[i] : -session->vector[i];
+
+ a = gcry_mpi_set_ui (a, 0);
+ // long to gcry_mpi_t
+ if (session->vector[i] < 0)
+ gcry_mpi_sub_ui (a, a, value);
+ else
+ gcry_mpi_add_ui (a, a, value);
+
+ session->a[session->transferred + j++] = gcry_mpi_set (NULL, a);
+ gcry_mpi_add (a, a, my_offset);
+ encrypt_element (a, a, my_g, my_n, my_nsquare);
+
+ // get representation as string
+ // we always supply some value, so gcry_mpi_print fails only if it can't reserve memory
+ GNUNET_assert (!gcry_mpi_print (GCRYMPI_FMT_USG,
+ element_exported, PAILLIER_ELEMENT_LENGTH,
+ &element_length,
+ a));
+
+ // move buffer content to the end of the buffer so it can easily be read by libgcrypt. also this now has fixed size
+ adjust (element_exported, element_length, PAILLIER_ELEMENT_LENGTH);
+
+ // copy over to the message
+ memcpy (current, element_exported, PAILLIER_ELEMENT_LENGTH);
+ current += PAILLIER_ELEMENT_LENGTH;
+ }
+ }
+ gcry_mpi_release (a);
+ GNUNET_free (element_exported);
+ session->transferred += todo_count;
+
+ session->msg = (struct GNUNET_MessageHeader *) msg;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n"));
+
+ //transmit via mesh messaging
+ session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->tunnel, GNUNET_YES,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ msg_length,
+ &do_send_message,
+ session);
+ if (!session->service_transmit_handle) {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-request multipart message to tunnel!\n"));
+ GNUNET_free (msg);
+ session->msg = NULL;
+ session->client_notification_task =
+ GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+ session);
+ return;
+ }
+ if (session->transferred != session->used) {
+ session->last_processed = i;
+ }
+ else
+ //final part
+ session->state = WAITING_FOR_SERVICE_RESPONSE;
+}