/**
 * 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;
  }
}
예제 #2
0
파일: set_api.c 프로젝트: muggenhor/GNUnet
/**
 * 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);
  }
}
예제 #3
0
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);
  }
}
예제 #8
0
파일: set_api.c 프로젝트: muggenhor/GNUnet
/**
 * 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);
  }
}
예제 #10
0
파일: set_api.c 프로젝트: muggenhor/GNUnet
/**
 * 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);
}