- proper service-side error reporting for the SP API
[oweals/gnunet.git] / src / scalarproduct / gnunet-service-scalarproduct.c
index 5c702d5e10529399b33bd24898ad62849d0de683..e3a2d5513e9150e80ec60120bc3170c6c6ffdf07 100644 (file)
@@ -51,12 +51,29 @@ enum PeerRole
   BOB
 };
 
-
+/**
+ * DLL for sorting elements
+ */
 struct SortedValue
 {
+  /**
+   * Sorted Values are kept in a DLL
+   */
   struct SortedValue * next;
+  
+  /**
+   * Sorted Values are kept in a DLL
+   */
   struct SortedValue * prev;
+  
+  /**
+   * The element's id+integer-value
+   */
   struct GNUNET_SCALARPRODUCT_Element * elem;
+  
+  /**
+   * the element's value converted to MPI
+   */
   gcry_mpi_t val;
 };
 
@@ -94,7 +111,7 @@ struct ServiceSession
    * Alice or Bob's peerID
    */
   struct GNUNET_PeerIdentity peer;
-
+  
   /**
    * the client this request is related to
    */
@@ -150,7 +167,7 @@ struct ServiceSession
   /**
    * Public key of the remote service, only used by bob
    */
-  struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
+  struct GNUNET_CRYPTO_PaillierPublicKey remote_pubkey;
 
   /**
    * DLL for sorting elements after intersection
@@ -461,6 +478,10 @@ free_session_variables (struct ServiceSession * session)
     GNUNET_free (session->e_a);
     session->e_a = NULL;
   }
+  if (session->remote_pubkey){
+    GNUNET_free(session->remote_pubkey);
+    session->remote_pubkey=NULL;
+  }
   if (session->sorted_elements) {
     GNUNET_free (session->sorted_elements);
     session->sorted_elements = NULL;
@@ -482,6 +503,10 @@ free_session_variables (struct ServiceSession * session)
     GNUNET_SET_destroy (session->intersection_set);
     session->intersection_set = NULL;
   }
+  if (session->channel){
+    GNUNET_CADET_channel_destroy(session->channel);
+    session->channel = NULL;
+  }
   if (session->msg) {
     GNUNET_free (session->msg);
     session->msg = NULL;
@@ -726,10 +751,16 @@ prepare_bobs_cryptodata_message_multipart (void *cls)
   //disconnect our client
   if (NULL == session->service_transmit_handle) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via cadet!)\n"));
-
+    
+    GNUNET_free (msg);
+    session->msg = NULL;
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    
     session->response->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session->response);
+    free_session_variables(session);
+    GNUNET_free(session);
     return;
   }
   if (session->transferred_element_count != session->used_elements_count) {
@@ -815,9 +846,16 @@ prepare_bobs_cryptodata_message (void *cls,
   if (NULL == session->service_transmit_handle) {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via cadet!)\n"));
 
+    GNUNET_free (msg);
+    session->msg = NULL;
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    
     session->response->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session->response);
+    free_session_variables(session);
+    GNUNET_free(session);
+    return;
   }
   if (session->transferred_element_count != session->used_elements_count) {
     // multipart
@@ -895,13 +933,13 @@ compute_service_response (struct ServiceSession * session)
     // E(S - r_pi - b_pi)
     gcry_mpi_sub (tmp, my_offset, rand[p[i]]);
     gcry_mpi_sub (tmp, tmp, b[p[i]]);
-    GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
+    GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
                                     tmp,
                                     2,
                                     &r[i]);
 
     // E(S - r_pi - b_pi) * E(S + a_pi) ==  E(2*S + a - r - b)
-    GNUNET_CRYPTO_paillier_hom_add (&session->remote_pubkey,
+    GNUNET_CRYPTO_paillier_hom_add (session->remote_pubkey,
                                     &r[i],
                                     &a[p[i]],
                                     &r[i]);
@@ -911,13 +949,13 @@ compute_service_response (struct ServiceSession * session)
   for (i = 0; i < count; i++) {
     // E(S - r_qi)
     gcry_mpi_sub (tmp, my_offset, rand[q[i]]);
-    GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
+    GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
                                                         tmp,
                                                         2,
                                                         &r_prime[i]));
 
     // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi)
-    GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (&session->remote_pubkey,
+    GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (session->remote_pubkey,
                                                         &r_prime[i],
                                                         &a[q[i]],
                                                         &r_prime[i]));
@@ -925,7 +963,7 @@ compute_service_response (struct ServiceSession * session)
 
   // Calculate S' =  E(SUM( r_i^2 ))
   tmp = compute_square_sum (rand, count);
-  GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
+  GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
                                   tmp,
                                   1,
                                   s_prime);
@@ -934,7 +972,7 @@ compute_service_response (struct ServiceSession * session)
   for (i = 0; i < count; i++)
     gcry_mpi_add (rand[i], rand[i], b[i]);
   tmp = compute_square_sum (rand, count);
-  GNUNET_CRYPTO_paillier_encrypt (&session->remote_pubkey,
+  GNUNET_CRYPTO_paillier_encrypt (session->remote_pubkey,
                                   tmp,
                                   1,
                                   s);
@@ -1010,7 +1048,6 @@ cb_insert_element_sorted (void *cls,
   while (NULL != o);
   // broken DLL
   GNUNET_assert (0);
-  return GNUNET_NO;
 }
 
 
@@ -1058,25 +1095,20 @@ cb_intersection_element_removed (void *cls,
     session->sorted_elements = GNUNET_malloc (session->used_elements_count * sizeof (gcry_mpi_t));
     for (i = 0; NULL != session->a_head; i++) {
       struct SortedValue* a = session->a_head;
-      if (i > session->used_elements_count) {
-        GNUNET_assert (0);
-        return;
-      }
+      GNUNET_assert (i < session->used_elements_count);
+      
       session->sorted_elements[i] = a->val;
       GNUNET_CONTAINER_DLL_remove (session->a_head, session->a_tail, a);
       GNUNET_free (a->elem);
     }
-    if (i != session->used_elements_count)
-      GNUNET_assert (0);
+    GNUNET_assert (i == session->used_elements_count);
 
     if (ALICE == session->role) {
       prepare_alices_cyrptodata_message (session);
       return;
     }
-    else {
-      if (session->used_elements_count == session->transferred_element_count)
-        compute_service_response (session);
-
+    else if (session->used_elements_count == session->transferred_element_count) {
+      compute_service_response (session);
       return;
     }
   default:
@@ -1084,19 +1116,21 @@ cb_intersection_element_removed (void *cls,
   }
 
   //failed if we go here
+  GNUNET_break (0);
+
+  // and notify our client-session that we could not complete the session
   if (ALICE == session->role) {
     session->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session);
   }
   else {
-    //TODO: Fail service session, exit tunnel
-
-
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    free_session_variables (session);
     session->response->client_notification_task =
             GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                       session->response);
-
+    GNUNET_free(session);
   }
 }
 
@@ -1837,7 +1871,7 @@ handle_alices_cyrptodata_message_multipart (void *cls,
   session = (struct ServiceSession *) * channel_ctx;
   //we are not bob
   if ((NULL == session->e_a) || //or we did not expect this message yet 
-      (session->used_elements_count == session->transferred_element_count)) { //we not expecting multipart messages
+      (session->used_elements_count == session->transferred_element_count)) { //we are not expecting multipart messages
     goto except;
   }
   // shorter than minimum?
@@ -1869,15 +1903,24 @@ handle_alices_cyrptodata_message_multipart (void *cls,
 
   return GNUNET_OK;
 except:
+  session->channel = NULL;
   // and notify our client-session that we could not complete the session
-  GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
-  if (session->response)
-    // we just found the responder session in this queue
+  free_session_variables (session);
+  if (NULL != session->client){
+    //Alice
+    session->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session);
+  }
+  else {
+    //Bob
+    if (NULL != session->response)
     session->response->client_notification_task =
           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                     session->response);
-  free_session_variables (session);
-  GNUNET_free (session);
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    GNUNET_free(session);
+  }
   return GNUNET_SYSERR;
 }
 
@@ -1948,15 +1991,24 @@ handle_alices_cyrptodata_message (void *cls,
   return GNUNET_OK;
 invalid_msg:
   GNUNET_break_op (0);
-  if ((NULL != session->next) || (NULL != session->prev) || (from_service_head == session))
-    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+  session->channel = NULL;
   // and notify our client-session that we could not complete the session
-  if (session->response)
-    // we just found the responder session in this queue
+  free_session_variables (session);
+  if (NULL != session->client){
+    //Alice
+    session->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session);
+  }
+  else {
+    //Bob
+    if (NULL != session->response)
     session->response->client_notification_task =
           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                     session->response);
-  free_session_variables (session);
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    GNUNET_free(session);
+  }
   return GNUNET_SYSERR;
 }
 
@@ -2025,7 +2077,8 @@ handle_alices_computation_request (void *cls,
   memcpy (&session->session_id, &msg->session_id, sizeof (struct GNUNET_HashCode));
 
   // public key
-  memcpy (&session->remote_pubkey, &msg->public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
+  session->remote_pubkey = GNUNET_new (struct GNUNET_CRYPTO_PaillierPublicKey);
+  memcpy (session->remote_pubkey, &msg->public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
 
   //check if service queue contains a matching request
   client_session = find_matching_session (from_client_tail,
@@ -2062,15 +2115,24 @@ handle_alices_computation_request (void *cls,
   return GNUNET_OK;
 invalid_msg:
   GNUNET_break_op (0);
-  if ((NULL != session->next) || (NULL != session->prev) || (from_service_head == session))
-    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+  session->channel = NULL;
   // and notify our client-session that we could not complete the session
-  if (session->response)
-    // we just found the responder session in this queue
+  free_session_variables (session);
+  if (NULL != session->client){
+    //Alice
+    session->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session);
+  }
+  else {
+    //Bob
+    if (NULL != session->response)
     session->response->client_notification_task =
           GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
                                     session->response);
-  free_session_variables (session);
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    GNUNET_free(session);
+  }
   return GNUNET_SYSERR;
 }
 
@@ -2131,14 +2193,24 @@ handle_bobs_cryptodata_multipart (void *cls,
   session->product = compute_scalar_product (session); //never NULL
 
 invalid_msg:
-  GNUNET_break_op (NULL != session->product); //NULL if we never tried to compute it...
-
+  GNUNET_break_op (NULL != session->product);
+  session->channel = NULL;
   // send message with product to client
-  if (ALICE == session->role) {
-    session->channel = NULL;
+  if (NULL != session->client){
+    //Alice
     session->client_notification_task =
-            GNUNET_SCHEDULER_add_now (&prepare_client_response,
-                                      session);
+          GNUNET_SCHEDULER_add_now (&prepare_client_response,
+                                    session);
+  }
+  else {
+    //Bob
+    if (NULL != session->response)
+    session->response->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session->response);
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    free_session_variables (session);
+    GNUNET_free(session);
   }
   // the channel has done its job, terminate our connection and the channel
   // the peer will be notified that the channel was destroyed via channel_destruction_handler
@@ -2215,12 +2287,23 @@ handle_bobs_cryptodata_message (void *cls,
 
 invalid_msg:
   GNUNET_break_op (NULL != session->product);
+  session->channel = NULL;
   // send message with product to client
-  if (ALICE == session->role) {
-    session->channel = NULL;
+  if (NULL != session->client){
+    //Alice
     session->client_notification_task =
-            GNUNET_SCHEDULER_add_now (&prepare_client_response,
-                                      session);
+          GNUNET_SCHEDULER_add_now (&prepare_client_response,
+                                    session);
+  }
+  else {
+    //Bob
+    if (NULL != session->response)
+    session->response->client_notification_task =
+          GNUNET_SCHEDULER_add_now (&prepare_client_end_notification,
+                                    session->response);
+    GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session);
+    free_session_variables (session);
+    GNUNET_free(session);
   }
   // the channel has done its job, terminate our connection and the channel
   // the peer will be notified that the channel was destroyed via channel_destruction_handler
@@ -2328,7 +2411,7 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Mesh initialized\n"));
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("CADET initialized\n"));
   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                 &shutdown_task,
                                 NULL);