/** * Function run on shutdown. * * @param cls closure */ static void do_shutdown (void *cls) { if (NULL != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = NULL; } if (NULL != oh1) { GNUNET_SET_operation_cancel (oh1); oh1 = NULL; } if (NULL != oh2) { GNUNET_SET_operation_cancel (oh2); oh2 = NULL; } if (NULL != set1) { GNUNET_SET_destroy (set1); set1 = NULL; } if (NULL != set2) { GNUNET_SET_destroy (set2); set2 = NULL; } if (NULL != listen_handle) { GNUNET_SET_listen_cancel (listen_handle); listen_handle = NULL; } }
/** * We encountered an error communicating with the set service while * performing a set operation. Report to the application. * * @param cls the `struct GNUNET_SET_Handle` * @param error error code */ static void handle_client_set_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SET_Handle *set = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling client set error %d\n", error); while (NULL != set->ops_head) { if (NULL != set->ops_head->result_cb) set->ops_head->result_cb (set->ops_head->result_cls, NULL, GNUNET_SET_STATUS_FAILURE); set_operation_destroy (set->ops_head); } set->invalid = GNUNET_YES; if (GNUNET_YES == set->destroy_requested) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying set after operation failure\n"); GNUNET_SET_destroy (set); } }
static void result_cb_set2 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_ADD_LOCAL: count_set2++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: failure\n"); ret = 1; GNUNET_SCHEDULER_shutdown (); break; case GNUNET_SET_STATUS_DONE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 2: done\n"); GNUNET_SET_destroy (set2); set2 = NULL; if (NULL == set1) GNUNET_SCHEDULER_shutdown (); break; case GNUNET_SET_STATUS_ADD_REMOTE: break; default: GNUNET_assert (0); } }
/** * We've paired up a client session with an incoming CADET request. * Initiate set intersection work. * * @param s client session to start intersection for */ static void start_intersection (struct BobServiceSession *s) { struct GNUNET_HashCode set_sid; GNUNET_CRYPTO_hash (&s->session_id, sizeof (struct GNUNET_HashCode), &set_sid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got session with key %s and %u elements, starting intersection.\n", GNUNET_h2s (&s->session_id), (unsigned int) s->total); s->intersection_op = GNUNET_SET_prepare (&s->cadet->peer, &set_sid, NULL, GNUNET_SET_RESULT_REMOVED, &cb_intersection_element_removed, s); if (GNUNET_OK != GNUNET_SET_commit (s->intersection_op, s->intersection_set)) { GNUNET_break (0); s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; prepare_client_end_notification (s); return; } GNUNET_SET_destroy (s->intersection_set); s->intersection_set = NULL; }
static int iter_cb (void *cls, const struct GNUNET_SET_Element *element) { if (NULL == element) { GNUNET_assert (iter_count == 3); GNUNET_SET_destroy (cls); return GNUNET_YES; } iter_count++; return GNUNET_YES; }
static int iter_cb (void *cls, const struct GNUNET_SET_Element *element) { if (NULL == element) { GNUNET_assert (iter_count == 3); GNUNET_SET_destroy (cls); return GNUNET_YES; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "iter: got element\n"); iter_count++; return GNUNET_YES; }
static void result_cb_set1 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_ADD_LOCAL: count_set1++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: failure\n"); oh1 = NULL; ret = 1; if (NULL != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = NULL; } GNUNET_SCHEDULER_shutdown (); break; case GNUNET_SET_STATUS_DONE: oh1 = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "set 1: done\n"); GNUNET_SET_destroy (set1); set1 = NULL; if (NULL == set2) { if (NULL != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = NULL; } GNUNET_SCHEDULER_shutdown (); } break; case GNUNET_SET_STATUS_ADD_REMOTE: break; default: GNUNET_assert (0); } }
/** * Cancel the given set operation. We need to send an explicit cancel * message, as all operations one one set communicate using one * handle. * * @param oh set operation to cancel */ void GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *oh) { struct GNUNET_SET_Handle *set = oh->set; struct GNUNET_SET_CancelMessage *m; struct GNUNET_MQ_Envelope *mqm; if (NULL != set) { mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SET_CANCEL); m->request_id = htonl (oh->request_id); GNUNET_MQ_send (set->mq, mqm); } set_operation_destroy (oh); if ( (NULL != set) && (GNUNET_YES == set->destroy_requested) && (NULL == set->ops_head) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying set after operation cancel\n"); GNUNET_SET_destroy (set); } }
static void result_cb_set2 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { static int count; switch (status) { case GNUNET_SET_STATUS_OK: count++; break; case GNUNET_SET_STATUS_FAILURE: ret = 1; break; case GNUNET_SET_STATUS_DONE: GNUNET_assert (1 == count); GNUNET_SET_destroy (set2); break; default: GNUNET_assert (0); } }
/** * Handle result message for a set operation. * * @param cls the set * @param mh the message */ static void handle_result (void *cls, const struct GNUNET_MessageHeader *mh) { struct GNUNET_SET_Handle *set = cls; const struct GNUNET_SET_ResultMessage *msg; struct GNUNET_SET_OperationHandle *oh; struct GNUNET_SET_Element e; enum GNUNET_SET_Status result_status; msg = (const struct GNUNET_SET_ResultMessage *) mh; GNUNET_assert (NULL != set->mq); result_status = ntohs (msg->result_status); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got result message with status %d\n", result_status); oh = GNUNET_MQ_assoc_get (set->mq, ntohl (msg->request_id)); if (NULL == oh) { /* 'oh' can be NULL if we canceled the operation, but the service did not get the cancel message yet. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ignoring result from canceled operation\n"); return; } switch (result_status) { case GNUNET_SET_STATUS_OK: case GNUNET_SET_STATUS_ADD_LOCAL: case GNUNET_SET_STATUS_ADD_REMOTE: goto do_element; case GNUNET_SET_STATUS_FAILURE: case GNUNET_SET_STATUS_DONE: goto do_final; case GNUNET_SET_STATUS_HALF_DONE: /* not used anymore */ GNUNET_assert (0); } do_final: LOG (GNUNET_ERROR_TYPE_DEBUG, "Treating result as final status\n"); GNUNET_MQ_assoc_remove (set->mq, ntohl (msg->request_id)); GNUNET_CONTAINER_DLL_remove (set->ops_head, set->ops_tail, oh); if (NULL != oh->result_cb) { oh->result_cb (oh->result_cls, NULL, result_status); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "No callback for final status\n"); } if ( (GNUNET_YES == set->destroy_requested) && (NULL == set->ops_head) ) GNUNET_SET_destroy (set); GNUNET_free (oh); return; do_element: LOG (GNUNET_ERROR_TYPE_DEBUG, "Treating result as element\n"); e.data = &msg[1]; e.size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ResultMessage); e.element_type = ntohs (msg->element_type); if (NULL != oh->result_cb) oh->result_cb (oh->result_cls, &e, result_status); }
/** * Callback for set operation results. Called for each element * that needs to be removed from the result set. * * @param cls closure with the `struct BobServiceSession` * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK * @param status what has happened with the set intersection? */ static void cb_intersection_element_removed (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { struct BobServiceSession *s = cls; struct GNUNET_SCALARPRODUCT_Element *se; switch (status) { case GNUNET_SET_STATUS_OK: /* this element has been removed from the set */ se = GNUNET_CONTAINER_multihashmap_get (s->intersected_elements, element->data); GNUNET_assert (NULL != se); LOG (GNUNET_ERROR_TYPE_DEBUG, "Removed element with key %s and value %lld\n", GNUNET_h2s (&se->key), (long long) GNUNET_ntohll (se->value)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (s->intersected_elements, element->data, se)); GNUNET_free (se); return; case GNUNET_SET_STATUS_DONE: s->intersection_op = NULL; GNUNET_break (NULL == s->intersection_set); GNUNET_CADET_receive_done (s->cadet->channel); LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished intersection, %d items remain\n", GNUNET_CONTAINER_multihashmap_size (s->intersected_elements)); if (s->client_received_element_count == GNUNET_CONTAINER_multihashmap_size (s->intersected_elements)) { /* CADET transmission from Alice is also already done, start with our own reply */ transmit_bobs_cryptodata_message (s); } return; case GNUNET_SET_STATUS_HALF_DONE: /* unexpected for intersection */ GNUNET_break (0); return; case GNUNET_SET_STATUS_FAILURE: /* unhandled status code */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Set intersection failed!\n"); s->intersection_op = NULL; if (NULL != s->intersection_set) { GNUNET_SET_destroy (s->intersection_set); s->intersection_set = NULL; } s->status = GNUNET_SCALARPRODUCT_STATUS_FAILURE; prepare_client_end_notification (s); return; default: GNUNET_break (0); return; } }
/** * Destroy session state, we are done with it. * * @param session the session to free elements from */ static void destroy_service_session (struct BobServiceSession *s) { struct CadetIncomingSession *in; unsigned int i; if (GNUNET_YES == s->in_destroy) return; s->in_destroy = GNUNET_YES; if (NULL != (in = s->cadet)) { s->cadet = NULL; destroy_cadet_session (in); } if (NULL != s->client) { struct GNUNET_SERVICE_Client *c = s->client; s->client = NULL; GNUNET_SERVICE_client_drop (c); } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (client_sessions, &s->session_id, s)); if (NULL != s->intersected_elements) { GNUNET_CONTAINER_multihashmap_iterate (s->intersected_elements, &free_element_cb, NULL); GNUNET_CONTAINER_multihashmap_destroy (s->intersected_elements); s->intersected_elements = NULL; } if (NULL != s->intersection_op) { GNUNET_SET_operation_cancel (s->intersection_op); s->intersection_op = NULL; } if (NULL != s->intersection_set) { GNUNET_SET_destroy (s->intersection_set); s->intersection_set = NULL; } if (NULL != s->sorted_elements) { for (i=0;i<s->used_element_count;i++) gcry_mpi_release (s->sorted_elements[i].value); GNUNET_free (s->sorted_elements); s->sorted_elements = NULL; } if (NULL != s->prod_g_i_b_i) { gcry_mpi_point_release (s->prod_g_i_b_i); s->prod_g_i_b_i = NULL; } if (NULL != s->prod_h_i_b_i) { gcry_mpi_point_release (s->prod_h_i_b_i); s->prod_h_i_b_i = NULL; } GNUNET_CADET_close_port (s->port); GNUNET_free (s); }