Beispiel #1
0
/**
 * Remove an element to the given set.  After the element has been
 * removed (in the sense of the request being transmitted to the set
 * service), @a cont will be called.  Multiple calls to
 * GNUNET_SET_remove_element() can be queued
 *
 * @param set set to remove element from
 * @param element element to remove from the set
 * @param cont continuation called after the element has been removed
 * @param cont_cls closure for @a cont
 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the
 *         set is invalid (e.g. the set service crashed)
 */
int
GNUNET_SET_remove_element (struct GNUNET_SET_Handle *set,
                           const struct GNUNET_SET_Element *element,
                           GNUNET_SET_Continuation cont,
                           void *cont_cls)
{
  struct GNUNET_MQ_Envelope *mqm;
  struct GNUNET_SET_ElementMessage *msg;

  if (GNUNET_YES == set->invalid)
  {
    if (NULL != cont)
      cont (cont_cls);
    return GNUNET_SYSERR;
  }
  mqm = GNUNET_MQ_msg_extra (msg,
                             element->size,
                             GNUNET_MESSAGE_TYPE_SET_REMOVE);
  msg->element_type = htons (element->element_type);
  memcpy (&msg[1],
          element->data,
          element->size);
  GNUNET_MQ_notify_sent (mqm,
                         cont, cont_cls);
  GNUNET_MQ_send (set->mq, mqm);
  return GNUNET_OK;
}
/**
 * Bob generates the response message to be sent to Alice.
 *
 * @param s the associated requesting session with Alice
 */
static void
transmit_bobs_cryptodata_message (struct BobServiceSession *s)
{
  struct EccBobCryptodataMessage *msg;
  struct GNUNET_MQ_Envelope *e;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending response to Alice\n");
  e = GNUNET_MQ_msg (msg,
                     GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ECC_BOB_CRYPTODATA);
  msg->contained_element_count = htonl (2);
  if (NULL != s->prod_g_i_b_i)
    GNUNET_CRYPTO_ecc_point_to_bin (edc,
                                    s->prod_g_i_b_i,
                                    &msg->prod_g_i_b_i);
  if (NULL != s->prod_h_i_b_i)
    GNUNET_CRYPTO_ecc_point_to_bin (edc,
                                    s->prod_h_i_b_i,
                                    &msg->prod_h_i_b_i);
  GNUNET_MQ_notify_sent (e,
                         &bob_cadet_done_cb,
                         s);
  GNUNET_MQ_send (s->cadet->cadet_mq,
                  e);
}
Beispiel #3
0
static void
test_mq (struct GNUNET_CLIENT_Connection *client)
{
  struct GNUNET_MQ_Handle *mq;
  struct GNUNET_MQ_Envelope *mqm;

  /* FIXME: test handling responses */
  mq = GNUNET_MQ_queue_for_connection_client (client, NULL, NULL, NULL);

  mqm = GNUNET_MQ_msg_header (MY_TYPE);
  GNUNET_MQ_send (mq, mqm);

  mqm = GNUNET_MQ_msg_header (MY_TYPE);
  GNUNET_MQ_notify_sent (mqm, send_trap_cb, NULL);
  GNUNET_MQ_send (mq, mqm);
  GNUNET_MQ_send_cancel (mqm);

  mqm = GNUNET_MQ_msg_header (MY_TYPE);
  GNUNET_MQ_notify_sent (mqm, send_cb, NULL);
  GNUNET_MQ_send (mq, mqm);

}
/**
 * @brief Send a message to another peer.
 *
 * Keeps track about pending messages so they can be properly removed when the
 * peer is destroyed.
 *
 * @param peer receeiver of the message
 * @param ev envelope of the message
 * @param type type of the message
 */
void
Peers_send_message (const struct GNUNET_PeerIdentity *peer,
                    struct GNUNET_MQ_Envelope *ev,
                    const char *type)
{
  struct PendingMessage *pending_msg;
  struct GNUNET_MQ_Handle *mq;

  pending_msg = insert_pending_message (peer, ev, type);
  mq = get_mq (peer);
  GNUNET_MQ_notify_sent (ev,
                         mq_notify_sent_cb,
                         pending_msg);
  GNUNET_MQ_send (mq, ev);
}
/**
 * Issue a check whether peer is live
 *
 * @param peer_ctx the context of the peer
 */
static void
check_peer_live (struct PeerContext *peer_ctx)
{
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Get informed about peer %s getting live\n",
       GNUNET_i2s (&peer_ctx->peer_id));

  struct GNUNET_MQ_Handle *mq;
  struct GNUNET_MQ_Envelope *ev;

  ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_RPS_PP_CHECK_LIVE);
  peer_ctx->liveliness_check_pending = GNUNET_new (struct PendingMessage);
  peer_ctx->liveliness_check_pending->ev = ev;
  peer_ctx->liveliness_check_pending->peer_ctx = peer_ctx;
  peer_ctx->liveliness_check_pending->type = "Check liveliness";
  mq = get_mq (&peer_ctx->peer_id);
  GNUNET_MQ_notify_sent (ev,
                         mq_liveliness_check_successful,
                         peer_ctx);
  GNUNET_MQ_send (mq, ev);
}
Beispiel #6
0
/**
 * Store a new entry in the PEERSTORE.
 * Note that stored entries can be lost in some cases
 * such as power failure.
 *
 * @param h Handle to the PEERSTORE service
 * @param sub_system name of the sub system
 * @param peer Peer Identity
 * @param key entry key
 * @param value entry value BLOB
 * @param size size of @e value
 * @param expiry absolute time after which the entry is (possibly) deleted
 * @param options options specific to the storage operation
 * @param cont Continuation function after the store request is sent
 * @param cont_cls Closure for @a cont
 */
struct GNUNET_PEERSTORE_StoreContext *
GNUNET_PEERSTORE_store (struct GNUNET_PEERSTORE_Handle *h,
                        const char *sub_system,
                        const struct GNUNET_PeerIdentity *peer, const char *key,
                        const void *value, size_t size,
                        struct GNUNET_TIME_Absolute expiry,
                        enum GNUNET_PEERSTORE_StoreOption options,
                        GNUNET_PEERSTORE_Continuation cont, void *cont_cls)
{
  struct GNUNET_MQ_Envelope *ev;
  struct GNUNET_PEERSTORE_StoreContext *sc;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Storing value (size: %lu) for subsytem `%s', peer `%s', key `%s'\n",
       size, sub_system, GNUNET_i2s (peer), key);
  ev = PEERSTORE_create_record_mq_envelope (sub_system, peer, key, value, size,
                                            &expiry, options,
                                            GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
  sc = GNUNET_new (struct GNUNET_PEERSTORE_StoreContext);

  sc->sub_system = GNUNET_strdup (sub_system);
  sc->peer = *peer;
  sc->key = GNUNET_strdup (key);
  sc->value = GNUNET_memdup (value, size);
  sc->size = size;
  sc->expiry = expiry;
  sc->options = options;
  sc->cont = cont;
  sc->cont_cls = cont_cls;
  sc->h = h;

  GNUNET_CONTAINER_DLL_insert_tail (h->store_head, h->store_tail, sc);
  GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
  GNUNET_MQ_send (h->mq, ev);
  return sc;

}
/**
 * Function to handle audio data from the client
 *
 * @param cls the `struct Line` the message is about
 * @param msg the message from the client
 */
static void
handle_client_audio_message (void *cls,
                             const struct ClientAudioMessage *msg)
{
  struct Line *line = cls;
  struct ClientAudioMessage *mam;
  struct Channel *ch;
  size_t size;

  size = ntohs (msg->header.size) - sizeof (struct ClientAudioMessage);
  ch = find_channel_by_line (line,
                             msg->cid);
  if (NULL == ch)
  {
    /* could have been destroyed asynchronously, ignore message */
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Channel %u not found\n",
                msg->cid);
    GNUNET_SERVICE_client_continue (line->client);
    return;
  }

  switch (ch->status)
  {
  case CS_CALLEE_INIT:
  case CS_CALLEE_RINGING:
  case CS_CALLER_CALLING:
    GNUNET_break (0);
    GNUNET_SERVICE_client_drop (line->client);
    return;
  case CS_CALLEE_CONNECTED:
  case CS_CALLER_CONNECTED:
    /* common case, handled below */
    break;
  case CS_CALLEE_SHUTDOWN:
  case CS_CALLER_SHUTDOWN:
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                "Cadet audio channel in shutdown; audio data dropped\n");
    GNUNET_SERVICE_client_continue (line->client);
    return;
  }
  if (GNUNET_YES == ch->suspended_local)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "This channel is suspended locally\n");
    GNUNET_SERVICE_client_drop (line->client);
    return;
  }
  if (NULL != ch->env)
  {
    /* NOTE: we may want to not do this and instead combine the data */
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Bandwidth insufficient; dropping previous audio data segment\n");
    GNUNET_MQ_send_cancel (ch->env);
    ch->env = NULL;
  }

  ch->env = GNUNET_MQ_msg_extra (mam,
                                 size,
                                 GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO);
  GNUNET_memcpy (&mam[1],
                 &msg[1],
                 size);
  /* FIXME: set options for unreliable transmission */
  GNUNET_MQ_notify_sent (ch->env,
                         &channel_audio_sent_notify,
                         ch);
  GNUNET_MQ_send (ch->mq,
                  ch->env);
  GNUNET_SERVICE_client_continue (line->client);
}
/**
 * Function to handle a hangup request message from the client
 *
 * @param cls the `struct Line` the hangup is for
 * @param msg the message from the client
 */
static void
handle_client_hangup_message (void *cls,
                              const struct ClientPhoneHangupMessage *msg)
{
  struct Line *line = cls;
  struct GNUNET_MQ_Envelope *e;
  struct CadetPhoneHangupMessage *mhum;
  struct Channel *ch;

  for (ch = line->channel_head; NULL != ch; ch = ch->next)
    if (msg->cid == ch->cid)
      break;
  if (NULL == ch)
  {
    /* could have been destroyed asynchronously, ignore message */
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Channel %u not found\n",
                msg->cid);
    GNUNET_SERVICE_client_continue (line->client);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Received HANGUP for channel %u which is in state %d\n",
              msg->cid,
              ch->status);
  switch (ch->status)
  {
  case CS_CALLEE_INIT:
    GNUNET_break (0);
    GNUNET_SERVICE_client_drop (line->client);
    return;
  case CS_CALLEE_RINGING:
    ch->status = CS_CALLEE_SHUTDOWN;
    break;
  case CS_CALLEE_CONNECTED:
    ch->status = CS_CALLEE_SHUTDOWN;
    break;
  case CS_CALLEE_SHUTDOWN:
    /* maybe the other peer closed asynchronously... */
    GNUNET_SERVICE_client_continue (line->client);
    return;
  case CS_CALLER_CALLING:
    ch->status = CS_CALLER_SHUTDOWN;
    break;
  case CS_CALLER_CONNECTED:
    ch->status = CS_CALLER_SHUTDOWN;
    break;
  case CS_CALLER_SHUTDOWN:
    /* maybe the other peer closed asynchronously... */
    GNUNET_SERVICE_client_continue (line->client);
    return;
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending HANG_UP message via cadet\n");
  e = GNUNET_MQ_msg (mhum,
                     GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
  GNUNET_MQ_notify_sent (e,
                         &mq_done_finish_caller_shutdown,
                         ch);
  GNUNET_MQ_send (ch->mq,
                  e);
  GNUNET_SERVICE_client_continue (line->client);
}
Beispiel #9
0
/**
 * Figure out when and how to transmit to the given peer.
 *
 * @param cls the `struct PeerPlan`
 */
static void
schedule_peer_transmission (void *cls)
{
  struct PeerPlan *pp = cls;
  struct GSF_RequestPlan *rp;
  struct GNUNET_TIME_Relative delay;

  if (NULL != pp->task)
  {
    pp->task = NULL;
  }
  else
  {
    GNUNET_assert (NULL != pp->env);
    pp->env = NULL;
  }
  /* move ready requests to priority queue */
  while ((NULL != (rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap))) &&
         (0 == GNUNET_TIME_absolute_get_remaining
          (rp->earliest_transmission).rel_value_us))
  {
    GNUNET_assert (rp == GNUNET_CONTAINER_heap_remove_root (pp->delay_heap));
    rp->hn = GNUNET_CONTAINER_heap_insert (pp->priority_heap,
                                           rp,
                                           rp->priority);
  }
  if (0 == GNUNET_CONTAINER_heap_get_size (pp->priority_heap))
  {
    /* priority heap (still) empty, check for delay... */
    rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap);
    if (NULL == rp)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "No active requests for plan %p.\n",
                  pp);
      return;                   /* both queues empty */
    }
    delay = GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission);
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Sleeping for %s before retrying requests on plan %p.\n",
                GNUNET_STRINGS_relative_time_to_string (delay,
							GNUNET_YES),
		pp);
    GNUNET_STATISTICS_set (GSF_stats,
                           gettext_noop ("# delay heap timeout (ms)"),
                           delay.rel_value_us / 1000LL, GNUNET_NO);

    pp->task =
        GNUNET_SCHEDULER_add_delayed (delay,
                                      &schedule_peer_transmission,
                                      pp);
    return;
  }
#if INSANE_STATISTICS
  GNUNET_STATISTICS_update (GSF_stats,
			    gettext_noop ("# query plans executed"),
                            1,
			    GNUNET_NO);
#endif
  /* process from priority heap */
  rp = GNUNET_CONTAINER_heap_remove_root (pp->priority_heap);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Executing query plan %p\n",
              rp);
  GNUNET_assert (NULL != rp);
  rp->hn = NULL;
  rp->last_transmission = GNUNET_TIME_absolute_get ();
  rp->transmission_counter++;
  total_delay++;
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Executing plan %p executed %u times, planning retransmission\n",
              rp,
	      rp->transmission_counter);
  GNUNET_assert (NULL == pp->env);
  pp->env = GSF_pending_request_get_message_ (get_latest (rp));
  GNUNET_MQ_notify_sent (pp->env,
			 &schedule_peer_transmission,
			 pp);
  GSF_peer_transmit_ (pp->cp,
		      GNUNET_YES,
		      rp->priority,
		      pp->env);
  GNUNET_STATISTICS_update (GSF_stats,
                            gettext_noop ("# query messages sent to other peers"),
                            1,
                            GNUNET_NO);
  plan (pp,
	rp);
}
Beispiel #10
0
/**
 * Close the existing connection to PEERSTORE and reconnect.
 *
 * @param h handle to the service
 */
static void
reconnect (struct GNUNET_PEERSTORE_Handle *h)
{
  struct GNUNET_PEERSTORE_IterateContext *ic;
  struct GNUNET_PEERSTORE_IterateContext *next;
  GNUNET_PEERSTORE_Processor icb;
  void *icb_cls;
  struct GNUNET_PEERSTORE_StoreContext *sc;
  struct GNUNET_MQ_Envelope *ev;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Reconnecting...\n");
  for (ic = h->iterate_head; NULL != ic; ic = next)
  {
    next = ic->next;
    if (GNUNET_YES == ic->iterating)
    {
      icb = ic->callback;
      icb_cls = ic->callback_cls;
      GNUNET_PEERSTORE_iterate_cancel (ic);
      if (NULL != icb)
        icb (icb_cls,
             NULL,
             "Iteration canceled due to reconnection");
    }
  }
  if (NULL != h->mq)
  {
    GNUNET_MQ_destroy (h->mq);
    h->mq = NULL;
  }
  if (NULL != h->client)
  {
    GNUNET_CLIENT_disconnect (h->client);
    h->client = NULL;
  }

  h->client = GNUNET_CLIENT_connect ("peerstore", h->cfg);
  GNUNET_assert (NULL != h->client);
  h->mq =
      GNUNET_MQ_queue_for_connection_client (h->client, mq_handlers,
                                             &handle_client_error, h);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Resending pending requests after reconnect.\n");
  if (NULL != h->watches)
    GNUNET_CONTAINER_multihashmap_iterate (h->watches, &rewatch_it, h);
  for (ic = h->iterate_head; NULL != ic; ic = ic->next)
  {
    ev =
      PEERSTORE_create_record_mq_envelope (ic->sub_system, &ic->peer, ic->key,
                                           NULL, 0, NULL, 0,
                                           GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
    GNUNET_MQ_send (h->mq, ev);
    ic->timeout_task =
        GNUNET_SCHEDULER_add_delayed (ic->timeout, &iterate_timeout, ic);
  }
  for (sc = h->store_head; NULL != sc; sc = sc->next)
  {
    ev =
      PEERSTORE_create_record_mq_envelope (sc->sub_system, &sc->peer, sc->key,
                                           sc->value, sc->size, &sc->expiry,
                                           sc->options,
                                           GNUNET_MESSAGE_TYPE_PEERSTORE_STORE);
    GNUNET_MQ_notify_sent (ev, &store_request_sent, sc);
    GNUNET_MQ_send (h->mq, ev);
  }
}