Пример #1
0
/**
 * Handle the channel a peer opens to us.
 *
 * @param cls The closure
 * @param channel The channel the peer wants to establish
 * @param initiator The peer's peer ID
 * @param port The port the channel is being established over
 * @param options Further options
 *
 * @return initial channel context for the channel
 *         (can be NULL -- that's not an error)
 */
void *
Peers_handle_inbound_channel (void *cls,
                              struct GNUNET_CADET_Channel *channel,
                              const struct GNUNET_PeerIdentity *initiator,
                              const struct GNUNET_HashCode *port,
                              enum GNUNET_CADET_ChannelOption options)
{
  struct PeerContext *peer_ctx;

  LOG (GNUNET_ERROR_TYPE_DEBUG,
      "New channel was established to us (Peer %s).\n",
      GNUNET_i2s (initiator));
  GNUNET_assert (NULL != channel); /* according to cadet API */
  /* Make sure we 'know' about this peer */
  peer_ctx = create_or_get_peer_ctx (initiator);
  set_peer_live (peer_ctx);
  /* We only accept one incoming channel per peer */
  if (GNUNET_YES == Peers_check_peer_send_intention (initiator))
  {
    set_channel_flag (peer_ctx->recv_channel_flags,
                      Peers_CHANNEL_ESTABLISHED_TWICE);
    GNUNET_CADET_channel_destroy (channel);
    /* return the channel context */
    return peer_ctx->recv_channel_flags;
  }
  peer_ctx->recv_channel = channel;
  return peer_ctx->recv_channel_flags;
}
/**
 * Destroy a given client peer context
 *
 * @param cp client peer context
 */
static void
destroy_clientpeer (struct ClientPeerContext *cp)
{
  struct PendingMessage *pm;

  cp->destroying = GNUNET_YES;
  if (NULL != cp->th)
  {
    GNUNET_CADET_notify_transmit_ready_cancel (cp->th);
    cp->th = NULL;
  }
  pm = cp->pm_head;
  while (NULL != pm)
  {
    GNUNET_CONTAINER_DLL_remove (cp->pm_head, cp->pm_tail, pm);
    GNUNET_free (pm->msg);
    GNUNET_free (pm);
    pm = cp->pm_head;
  }
  if (NULL != cp->ch)
  {
    GNUNET_CADET_channel_destroy (cp->ch);
    cp->ch = NULL;
  }
  GNUNET_free (cp);
}
/**
 * Destroy incoming CADET session state, we are done with it.
 *
 * @param in the session to free elements from
 */
static void
destroy_cadet_session (struct CadetIncomingSession *in)
{
  struct BobServiceSession *s;

  if (GNUNET_YES == in->in_destroy)
    return;
  in->in_destroy = GNUNET_YES;
  if (NULL != (s = in->s))
  {
    in->s = NULL;
    destroy_service_session (s);
  }
  if (GNUNET_YES == in->in_map)
  {
    GNUNET_assert (GNUNET_YES ==
                   GNUNET_CONTAINER_multihashmap_remove (cadet_sessions,
                                                         &in->session_id,
                                                         in));
    in->in_map = GNUNET_NO;
  }
  if (NULL != in->cadet_mq)
  {
    GNUNET_MQ_destroy (in->cadet_mq);
    in->cadet_mq = NULL;
  }
  if (NULL != in->channel)
  {
    GNUNET_CADET_channel_destroy (in->channel);
    in->channel = NULL;
  }
  GNUNET_free (in);
}
Пример #4
0
/**
 * Destroy a channel.
 *
 * @param ch channel to destroy.
 */
static void
destroy_line_cadet_channels (struct Channel *ch)
{
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Destroying cadet channels\n");
  if (NULL != ch->mq)
  {
    GNUNET_MQ_destroy (ch->mq);
    ch->mq = NULL;
  }
  if (NULL != ch->channel)
    GNUNET_CADET_channel_destroy (ch->channel);
}
Пример #5
0
/**
 * Disconnect from cadet services af all peers, call shutdown.
 *
 * @param cls Closure (line number from which termination was requested).
 * @param tc Task Context.
 */
static void
disconnect_cadet_peers (void *cls)
{
  long line = (long) cls;
  unsigned int i;

  disconnect_task = NULL;
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      "disconnecting cadet service of peers, called from line %ld\n",
	      line);
  for (i = 0; i < 2; i++)
  {
    GNUNET_TESTBED_operation_done (t_op[i]);
  }
  if (NULL != ch)
  {
    if (NULL != th)
    {
      GNUNET_CADET_notify_transmit_ready_cancel (th);
      th = NULL;
    }
    GNUNET_CADET_channel_destroy (ch);
    ch = NULL;
  }
  if (NULL != incoming_ch)
  {
    if (NULL != incoming_th)
    {
      GNUNET_CADET_notify_transmit_ready_cancel (incoming_th);
      incoming_th = NULL;
    }
    GNUNET_CADET_channel_destroy (incoming_ch);
    incoming_ch = NULL;
  }
  GNUNET_CADET_TEST_cleanup (test_ctx);
  GNUNET_SCHEDULER_shutdown ();
}
Пример #6
0
/**
 * @brief Destroy the send channel of a peer e.g. stop indicating a sending
 *        intention to another peer
 *
 * If there is also no channel to receive messages from that peer, remove it
 * from the peermap.
 * TODO really?
 *
 * @peer the peer identity of the peer whose sending channel to destroy
 * @return #GNUNET_YES if channel was destroyed
 *         #GNUNET_NO  otherwise
 */
int
Peers_destroy_sending_channel (const struct GNUNET_PeerIdentity *peer)
{
  struct PeerContext *peer_ctx;

  if (GNUNET_NO == Peers_check_peer_known (peer))
  {
    return GNUNET_NO;
  }
  peer_ctx = get_peer_ctx (peer);
  if (NULL != peer_ctx->send_channel)
  {
    set_channel_flag (peer_ctx->send_channel_flags, Peers_CHANNEL_CLEAN);
    GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
    peer_ctx->send_channel = NULL;
    (void) Peers_check_connected (peer);
    return GNUNET_YES;
  }
  return GNUNET_NO;
}
Пример #7
0
/**
 * Task to gather all statistics.
 *
 * @param cls Closure (NULL).
 */
static void
gather_stats_and_exit (void *cls)
{
  long l = (long) cls;

  disconnect_task = NULL;
  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
	      "gathering statistics from line %d\n",
	      (int) l);
  if (NULL != ch)
  {
    if (NULL != th)
    {
      GNUNET_CADET_notify_transmit_ready_cancel (th);
      th = NULL;
    }
    GNUNET_CADET_channel_destroy (ch);
    ch = NULL;
  }
  stats_op = GNUNET_TESTBED_get_statistics (peers_running, testbed_peers,
                                            "cadet", NULL,
                                            stats_iterator, stats_cont, cls);
}
Пример #8
0
/**
 * Shutdown nicely
 */
static void
do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n");
  if (NULL != abort_task)
  {
    GNUNET_SCHEDULER_cancel (abort_task);
  }
  if (NULL != ch)
  {
    GNUNET_CADET_channel_destroy (ch);
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n");
  if (NULL != cadet_peer_1)
  {
    GNUNET_CADET_disconnect (cadet_peer_1);
  }
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n");
  if (NULL != cadet_peer_2)
  {
    GNUNET_CADET_disconnect (cadet_peer_2);
  }
}
Пример #9
0
/**
 * This is called when a channel is destroyed.
 *
 * @param cls The closure
 * @param channel The channel being closed
 * @param channel_ctx The context associated with this channel
 */
void
Peers_cleanup_destroyed_channel (void *cls,
                                 const struct GNUNET_CADET_Channel *channel,
                                 void *channel_ctx)
{
  struct GNUNET_PeerIdentity *peer;
  struct PeerContext *peer_ctx;

  peer = (struct GNUNET_PeerIdentity *) GNUNET_CADET_channel_get_info (
      (struct GNUNET_CADET_Channel *) channel, GNUNET_CADET_OPTION_PEER);
       // FIXME wait for cadet to change this function

  if (GNUNET_NO == Peers_check_peer_known (peer))
  {/* We don't want to implicitly create a context that we're about to kill */
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "channel (%s) without associated context was destroyed\n",
       GNUNET_i2s (peer));
    return;
  }
  peer_ctx = get_peer_ctx (peer);

  /* If our peer issued the destruction of the channel, the #Peers_TO_DESTROY
   * flag will be set. In this case simply make sure that the channels are
   * cleaned. */
  /* FIXME This distinction seems to be redundant */
  if (Peers_check_peer_flag (peer, Peers_TO_DESTROY))
  {/* We initiatad the destruction of this particular peer */
    if (channel == peer_ctx->send_channel)
      peer_ctx->send_channel = NULL;
    else if (channel == peer_ctx->recv_channel)
      peer_ctx->recv_channel = NULL;

    if (NULL != peer_ctx->send_channel)
    {
      GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
      peer_ctx->send_channel = NULL;
    }
    if (NULL != peer_ctx->recv_channel)
    {
      GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
      peer_ctx->recv_channel = NULL;
    }
    /* Set the #Peers_ONLINE flag accordingly */
    (void) Peers_check_connected (peer);
    return;
  }

  else
  { /* We did not initiate the destruction of this peer */
    if (channel == peer_ctx->send_channel)
    { /* Something (but us) killd the channel - clean up peer */
      LOG (GNUNET_ERROR_TYPE_DEBUG,
          "send channel (%s) was destroyed - cleaning up\n",
          GNUNET_i2s (peer));
      peer_ctx->send_channel = NULL;
    }
    else if (channel == peer_ctx->recv_channel)
    { /* Other peer doesn't want to send us messages anymore */
      LOG (GNUNET_ERROR_TYPE_DEBUG,
           "Peer %s destroyed recv channel - cleaning up channel\n",
           GNUNET_i2s (peer));
      peer_ctx->recv_channel = NULL;
    }
    else
    {
      LOG (GNUNET_ERROR_TYPE_WARNING,
           "unknown channel (%s) was destroyed\n",
           GNUNET_i2s (peer));
    }
  }
  (void) Peers_check_connected (peer);
}
Пример #10
0
/**
 * @brief Remove peer
 *
 * @param peer the peer to clean
 * @return #GNUNET_YES if peer was removed
 *         #GNUNET_NO  otherwise
 */
int
Peers_remove_peer (const struct GNUNET_PeerIdentity *peer)
{
  struct PeerContext *peer_ctx;

  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (peer_map, peer))
  {
    return GNUNET_NO;
  }

  peer_ctx = get_peer_ctx (peer);
  set_peer_flag (peer_ctx, Peers_TO_DESTROY);
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Going to remove peer %s\n",
       GNUNET_i2s (&peer_ctx->peer_id));
  Peers_unset_peer_flag (peer, Peers_ONLINE);

  GNUNET_array_grow (peer_ctx->pending_ops, peer_ctx->num_pending_ops, 0);
  while (NULL != peer_ctx->pending_messages_head)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Removing unsent %s\n",
        peer_ctx->pending_messages_head->type);
    remove_pending_message (peer_ctx->pending_messages_head);
  }
  /* If we are still waiting for notification whether this peer is live
   * cancel the according task */
  if (NULL != peer_ctx->liveliness_check_pending)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
         "Removing pending liveliness check for peer %s\n",
         GNUNET_i2s (&peer_ctx->peer_id));
    // TODO wait until cadet sets mq->cancel_impl
    //GNUNET_MQ_send_cancel (peer_ctx->liveliness_check_pending->ev);
    GNUNET_free (peer_ctx->liveliness_check_pending);
    peer_ctx->liveliness_check_pending = NULL;
  }
  if (NULL != peer_ctx->send_channel)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Destroying send channel\n");
    GNUNET_CADET_channel_destroy (peer_ctx->send_channel);
    peer_ctx->send_channel = NULL;
  }
  if (NULL != peer_ctx->recv_channel)
  {
    LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Destroying recv channel\n");
    GNUNET_CADET_channel_destroy (peer_ctx->recv_channel);
    peer_ctx->recv_channel = NULL;
  }
  if (NULL != peer_ctx->mq)
  {
    GNUNET_MQ_destroy (peer_ctx->mq);
    peer_ctx->mq = NULL;
  }

  GNUNET_free (peer_ctx->send_channel_flags);
  GNUNET_free (peer_ctx->recv_channel_flags);

  if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove_all (peer_map, &peer_ctx->peer_id))
  {
    LOG (GNUNET_ERROR_TYPE_WARNING, "removing peer from peer_map failed\n");
  }
  GNUNET_free (peer_ctx);
  return GNUNET_YES;
}
Пример #11
0
/**
 * Function is called whenever a message is received.
 *
 * @param cls closure (set from GNUNET_CADET_connect, peer number)
 * @param channel connection to the other end
 * @param channel_ctx place to store local state associated with the channel
 * @param message the actual message
 * @return GNUNET_OK to keep the connection open,
 *         GNUNET_SYSERR to close it (signal serious error)
 */
int
data_callback (void *cls, struct GNUNET_CADET_Channel *channel,
               void **channel_ctx,
               const struct GNUNET_MessageHeader *message)
{
  struct GNUNET_CADET_TransmitHandle **pth;
  long client = (long) cls;
  long expected_target_client;
  uint32_t *data;
  uint32_t payload;
  unsigned int counter;

  ok++;
  counter = get_expected_target () == client ? data_received : ack_received;

  GNUNET_CADET_receive_done (channel);

  if ((ok % 10) == 0)
  {
    if (NULL != disconnect_task)
    {
      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " reschedule timeout\n");
      GNUNET_SCHEDULER_cancel (disconnect_task);
      disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
                                                      &gather_stats_and_exit,
                                                      (void *) __LINE__);
    }
  }

  switch (client)
  {
  case 0L:
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n");
    GNUNET_assert (channel == ch);
    pth = &th;
    break;
  case 1L:
  case 4L:
    GNUNET_assert (client == peers_requested - 1);
    GNUNET_assert (channel == incoming_ch);
    pth = &incoming_th;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %ld got a message.\n",
                client);
    break;
  default:
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Client %ld not valid.\n", client);
    GNUNET_assert (0);
  }
  GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal);
  data = (uint32_t *) &message[1];
  payload = ntohl (*data);
  if (payload == counter)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload);
  }
  else
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " payload %u, expected: %u\n",
                payload, counter);
  }
  expected_target_client = get_expected_target ();

  if (GNUNET_NO == initialized)
  {
    initialized = GNUNET_YES;
    start_time = GNUNET_TIME_absolute_get ();
    if (SPEED == test)
    {
      GNUNET_assert (peers_requested - 1 == client);
      data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL);
      return GNUNET_OK;
    }
  }

  counter++;
  if (client == expected_target_client) /* Normally 4 */
  {
    data_received++;
    GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
    if (SPEED != test || (ok_goal - 2) == ok)
    {
      /* Send ACK */
      GNUNET_assert (NULL == *pth);
      *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
                                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                                 size_payload + ack_sent,
                                                 &tmt_rdy, (void *) client);
      return GNUNET_OK;
    }
    else
    {
      if (data_received < TOTAL_PACKETS)
        return GNUNET_OK;
    }
  }
  else /* Normally 0 */
  {
    if (SPEED_ACK == test || SPEED == test)
    {
      ack_received++;
      GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received);
      /* send more data */
      GNUNET_assert (NULL == *pth);
      *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO,
                                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                                 size_payload + data_sent,
                                                 &tmt_rdy, (void *) client);
      if (ack_received < TOTAL_PACKETS && SPEED != test)
        return GNUNET_OK;
      if (ok == 2 && SPEED == test)
        return GNUNET_OK;
      show_end_data();
    }
    if (test == P2P_SIGNAL)
    {
      if (NULL != incoming_th)
      {
        GNUNET_CADET_notify_transmit_ready_cancel (incoming_th);
        incoming_th = NULL;
      }
      GNUNET_CADET_channel_destroy (incoming_ch);
      incoming_ch = NULL;
    }
    else
    {
      if (NULL != th)
      {
        GNUNET_CADET_notify_transmit_ready_cancel (th);
        th = NULL;
      }
      GNUNET_CADET_channel_destroy (ch);
      ch = NULL;
    }
  }

  return GNUNET_OK;
}