Exemplo n.º 1
0
/**
 * Client is done with ATS scheduling, release resources.
 *
 * @param sh handle to release
 */
void
GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh)
{
  struct GNUNET_ATS_AddressRecord *ar;
  unsigned int i;

  if (NULL != sh->mq)
  {
    GNUNET_MQ_destroy (sh->mq);
    sh->mq = NULL;
  }
  if (NULL != sh->client)
  {
    GNUNET_CLIENT_disconnect (sh->client);
    sh->client = NULL;
  }
  if (NULL != sh->task)
  {
    GNUNET_SCHEDULER_cancel (sh->task);
    sh->task = NULL;
  }
  for (i=0;i<sh->session_array_size;i++)
  {
    if (NULL != (ar = sh->session_array[i]))
    {
      GNUNET_HELLO_address_free (ar->address);
      GNUNET_free (ar);
      sh->session_array[i] = NULL;
    }
  }
  GNUNET_array_grow (sh->session_array,
                     sh->session_array_size,
                     0);
  GNUNET_free (sh);
}
/**
 * Release memory used by the given address data.
 *
 * @param ai the `struct AddressInfo`
 */
static void
destroy_ai (struct AddressInfo *ai)
{
  GNUNET_assert (NULL == ai->session);
  if (NULL != ai->unblock_task)
  {
    GNUNET_SCHEDULER_cancel (ai->unblock_task);
    ai->unblock_task = NULL;
    num_blocked--;
  }
  GNUNET_assert (GNUNET_YES ==
                 GNUNET_CONTAINER_multipeermap_remove (p2a,
                                                       &ai->address->peer,
                                                       ai));
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Telling ATS to destroy address from peer %s\n",
       GNUNET_i2s (&ai->address->peer));
  if (NULL != ai->ar)
  {
    GNUNET_ATS_address_destroy (ai->ar);
    ai->ar = NULL;
  }
  publish_p2a_stat_update ();
  GNUNET_HELLO_address_free (ai->address);
  GNUNET_free (ai);
}
/**
 * Add or remove an address from this peer's HELLO message.
 *
 * @param addremove GNUNET_YES to add, GNUNET_NO to remove
 * @param address address to add or remove
 */
void
GST_hello_modify_addresses (int addremove,
                            const struct GNUNET_HELLO_Address *address)
{
  struct OwnAddressList *al;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              (addremove ==
               GNUNET_YES) ? "Adding `%s' to the set of our addresses\n" :
              "Removing `%s' from the set of our addresses\n",
              GST_plugins_a2s (address));
  GNUNET_assert (address != NULL);
  if (GNUNET_NO == addremove)
  {
    for (al = oal_head; al != NULL; al = al->next)
      if (0 == GNUNET_HELLO_address_cmp (address, al->address))
      {
        GNUNET_CONTAINER_DLL_remove (oal_head, oal_tail, al);
        GNUNET_HELLO_address_free (al->address);
        GNUNET_free (al);
        refresh_hello ();
        return;
      }
    /* address to be removed not found!? */
    GNUNET_break (0);
    return;
  }
  al = GNUNET_malloc (sizeof (struct OwnAddressList));
  GNUNET_CONTAINER_DLL_insert (oal_head, oal_tail, al);
  al->address = GNUNET_HELLO_address_copy (address);
  refresh_hello ();
}
Exemplo n.º 4
0
/**
 * Release the session slot from the session table (ATS service is
 * also done using it).
 *
 * @param sh our handle
 * @param session_id identifies session that is no longer valid
 */
static void
release_session (struct GNUNET_ATS_SchedulingHandle *sh,
                 uint32_t session_id)
{
  struct GNUNET_ATS_AddressRecord *ar;

  if (NOT_FOUND == session_id)
    return;
  if (session_id >= sh->session_array_size)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  /* this slot should have been removed from remove_session before */
  ar = sh->session_array[session_id];
  if (NULL != ar->session)
  {
    GNUNET_break (0);
    force_reconnect (sh);
    return;
  }
  GNUNET_HELLO_address_free (ar->address);
  GNUNET_free (ar);
  sh->session_array[session_id] = NULL;
}
/**
 * Iterate over validation entries and free them.
 *
 * @param cls (unused)
 * @param key peer identity (unused)
 * @param value a 'struct ValidationEntry' to clean up
 * @return GNUNET_YES (continue to iterate)
 */
static int
cleanup_validation_entry (void *cls, const GNUNET_HashCode * key, void *value)
{
  struct ValidationEntry *ve = value;

  if (NULL != ve->bc)
  {
    GST_blacklist_test_cancel (ve->bc);
    ve->bc = NULL;
  }
  GNUNET_break (GNUNET_OK ==
                GNUNET_CONTAINER_multihashmap_remove (validation_map,
                                                      &ve->pid.hashPubKey, ve));
  GNUNET_HELLO_address_free (ve->address);
  if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
  {
    GNUNET_SCHEDULER_cancel (ve->timeout_task);
    ve->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  }
  if (GNUNET_SCHEDULER_NO_TASK != ve->revalidation_task)
  {
    GNUNET_SCHEDULER_cancel (ve->revalidation_task);
    ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK;
  }
  GNUNET_free (ve);
  return GNUNET_OK;
}
/**
 * Add or remove an address from this peer's HELLO message.
 *
 * @param addremove #GNUNET_YES to add, #GNUNET_NO to remove
 * @param address address to add or remove
 */
void
GST_hello_modify_addresses (int addremove,
                            const struct GNUNET_HELLO_Address *address)
{
  struct OwnAddressList *al;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              (GNUNET_YES == addremove)
              ? "Adding `%s' to the set of our addresses\n"
              : "Removing `%s' from the set of our addresses\n",
              GST_plugins_a2s (address));
  GNUNET_assert (NULL != address);
  for (al = oal_head; al != NULL; al = al->next)
    if (0 == GNUNET_HELLO_address_cmp (address, al->address))
      break;
  if (GNUNET_NO == addremove)
  {
    if (NULL == al)
    {
      /* address to be removed not found!? */
      GNUNET_break (0);
      return;
    }
    al->rc--;
    if (0 != al->rc)
      return; /* RC not yet zero */
    GNUNET_CONTAINER_DLL_remove (oal_head,
                                 oal_tail,
                                 al);
    GNUNET_HELLO_address_free (al->address);
    GNUNET_free (al);
    refresh_hello ();
    return;
  }
  if (NULL != al)
  {
    /* address added twice or more */
    al->rc++;
    return;
  }
  al = GNUNET_new (struct OwnAddressList);
  al->rc = 1;
  GNUNET_CONTAINER_DLL_insert (oal_head,
                               oal_tail,
                               al);
  al->address = GNUNET_HELLO_address_copy (address);
  refresh_hello ();
}
/**
 * Parse broadcast message received.
 *
 * @param cls the `struct Plugin`
 * @param client the `struct MstContext` with sender address
 * @param message the message we received
 * @return #GNUNET_OK (always)
 */
static int
broadcast_mst_cb (void *cls,
                  void *client,
                  const struct GNUNET_MessageHeader *message)
{
  struct Plugin *plugin = cls;
  struct MstContext *mc = client;
  struct GNUNET_HELLO_Address *address;
  const struct GNUNET_MessageHeader *hello;
  const struct UDP_Beacon_Message *msg;

  msg = (const struct UDP_Beacon_Message *) message;

  if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
      ntohs (msg->header.type))
    return GNUNET_OK;
  LOG (GNUNET_ERROR_TYPE_DEBUG,
       "Received beacon with %u bytes from peer `%s' via address `%s'\n",
       ntohs (msg->header.size),
       GNUNET_i2s (&msg->sender),
       udp_address_to_string (NULL,
                              mc->udp_addr,
                              mc->udp_addr_len));
  hello = (struct GNUNET_MessageHeader *) &msg[1];
  address = GNUNET_HELLO_address_allocate (&msg->sender,
                                           PLUGIN_NAME,
                                           mc->udp_addr,
                                           mc->udp_addr_len,
                                           GNUNET_HELLO_ADDRESS_INFO_NONE);
  plugin->env->receive (plugin->env->cls,
                        address,
                        NULL,
                        hello);
  GNUNET_HELLO_address_free (address);
  GNUNET_STATISTICS_update (plugin->env->stats,
                            _("# Multicast HELLO beacons received via UDP"),
                            1, GNUNET_NO);
  return GNUNET_OK;
}
/**
 * Function called with responses from the service.
 *
 * @param cls our `struct GNUNET_TRANSPORT_ValidationMonitoringContext *`
 * @param msg NULL on timeout or error, otherwise presumably a
 *        message with the human-readable address
 */
static void
val_response_processor (void *cls,
                        const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
  struct ValidationIterateResponseMessage *vr_msg;
  struct GNUNET_HELLO_Address *address;
  const char *addr;
  const char *transport_name;
  size_t size;
  size_t tlen;
  size_t alen;

  if (NULL == msg)
  {
    if (val_ctx->one_shot)
    {
      /* Disconnect */
      val_ctx->cb (val_ctx->cb_cls, NULL,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
    }
    else
    {
      reconnect_val_ctx (val_ctx);
    }
    return;
  }
  size = ntohs (msg->size);
  GNUNET_break (ntohs (msg->type) ==
      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);

  if (size == sizeof (struct GNUNET_MessageHeader))
  {
    /* Done! */
    if (val_ctx->one_shot)
    {
      val_ctx->cb (val_ctx->cb_cls, NULL,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
    }
    else
    {
      reconnect_val_ctx (val_ctx);
    }
    return;
  }

  if ((size < sizeof (struct ValidationIterateResponseMessage)) ||
      (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE))
  {
    GNUNET_break (0);
    if (val_ctx->one_shot)
    {
      val_ctx->cb (val_ctx->cb_cls, NULL,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
    }
    else
    {
      reconnect_val_ctx (val_ctx);
    }
    return;
  }

  vr_msg = (struct ValidationIterateResponseMessage *) msg;
  tlen = ntohl (vr_msg->pluginlen);
  alen = ntohl (vr_msg->addrlen);

  if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen)
  {
    GNUNET_break (0);
    if (val_ctx->one_shot)
    {
      val_ctx->cb (val_ctx->cb_cls, NULL,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
    }
    else
    {
      reconnect_val_ctx (val_ctx);
    }
    return;
  }
  if (0 == tlen)
  {
    GNUNET_break (0); /* This must not happen: address without plugin */
    return;
  }
  addr = (const char *) &vr_msg[1];
  transport_name = &addr[alen];
  
  if (transport_name[tlen - 1] != '\0')
  {
    /* Corrupt plugin name */
    GNUNET_break (0);
    if (val_ctx->one_shot)
    {
      val_ctx->cb (val_ctx->cb_cls,
		   NULL,
		   GNUNET_TIME_UNIT_ZERO_ABS,
		   GNUNET_TIME_UNIT_ZERO_ABS,
		   GNUNET_TIME_UNIT_ZERO_ABS,
		   GNUNET_TRANSPORT_VS_NONE);
      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
    }
    else
    {
      reconnect_val_ctx (val_ctx);
    }
    return;
  }
  
  /* notify client */
  address = GNUNET_HELLO_address_allocate (&vr_msg->peer,
					   transport_name,
					   addr, alen,
					   ntohl (vr_msg->local_address_info));
  val_ctx->cb (val_ctx->cb_cls,
	       address,
	       GNUNET_TIME_absolute_ntoh (vr_msg->last_validation),
	       GNUNET_TIME_absolute_ntoh (vr_msg->valid_until),
	       GNUNET_TIME_absolute_ntoh (vr_msg->next_validation),
	       ntohl(vr_msg->state));
  GNUNET_HELLO_address_free (address);
  /* expect more replies */
  GNUNET_CLIENT_receive (val_ctx->client,
                         &val_response_processor,
                         val_ctx,
                         GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
}
/**
 * Function called with responses from the service.
 *
 * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
 * @param msg NULL on timeout or error, otherwise presumably a
 *        message with the human-readable address
 */
static void
peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
{
  struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
  struct PeerIterateResponseMessage *pir_msg;
  struct GNUNET_HELLO_Address *address;
  const char *addr;
  const char *transport_name;
  uint16_t size;
  size_t alen;
  size_t tlen;

  if (msg == NULL)
  {
    if (pal_ctx->one_shot)
    {
      /* Disconnect */
      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
    }
    else
    {
      reconnect_peer_ctx (pal_ctx);
    }
    return;
  }
  size = ntohs (msg->size);
  GNUNET_break (ntohs (msg->type) ==
      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
  if (size == sizeof (struct GNUNET_MessageHeader))
  {
    /* Done! */
    if (pal_ctx->one_shot)
    {
      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
    }
    else
    {
      reconnect_peer_ctx (pal_ctx);
    }
    return;
  }

  if ((size < sizeof (struct PeerIterateResponseMessage)) ||
      (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
  {
    GNUNET_break (0);
    if (pal_ctx->one_shot)
    {
      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
    }
    else
    {
      reconnect_peer_ctx (pal_ctx);
    }
    return;
  }

  pir_msg = (struct PeerIterateResponseMessage *) msg;
  tlen = ntohl (pir_msg->pluginlen);
  alen = ntohl (pir_msg->addrlen);

  if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
  {
    GNUNET_break (0);
    if (pal_ctx->one_shot)
    {
      pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
      GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
    }
    else
    {
      reconnect_peer_ctx (pal_ctx);
    }
    return;
  }

  if ( (0 == tlen) && (0 == alen) )
  {
    /* No address available */
    pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
        ntohl(pir_msg->state),
        GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
  }
  else
  {
    if (0 == tlen)
    {
      GNUNET_break (0); /* This must not happen: address without plugin */
      return;
    }
    addr = (const char *) &pir_msg[1];
    transport_name = &addr[alen];

    if (transport_name[tlen - 1] != '\0')
    {
      /* Corrupt plugin name */
      GNUNET_break (0);
      if (pal_ctx->one_shot)
      {
        pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
            GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
        GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
      }
      else
      {
        reconnect_peer_ctx (pal_ctx);
      }
      return;
    }

    /* notify client */
    address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
        transport_name, addr, alen, ntohl(pir_msg->local_address_info));
    pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
        ntohl(pir_msg->state),
        GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
    GNUNET_HELLO_address_free (address);

  }

  /* expect more replies */
  GNUNET_CLIENT_receive (pal_ctx->client, &peer_response_processor,
                         pal_ctx,
                         GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout));
}