/**
 * Delete an address
 *
 * If session != 0, just the session is deleted, the address itself still exists
 * If session == 0, remove full address
 * If session == 0 and addrlen == 0, destroy inbound address
 *
 * @param cls unused
 * @param key unused
 * @param value the 'struct ATS_Address'
 * @return GNUNET_OK (continue to iterate)
 */
static int
destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *value)
{
  const struct ATS_Address *info = cls;
  struct ATS_Address *aa = value;

  GNUNET_assert (0 ==
                 memcmp (&aa->peer, &info->peer,
                         sizeof (struct GNUNET_PeerIdentity)));
  /* session == 0, remove full address  */
  if ((info->session_id == 0) && (0 == strcmp (info->plugin, aa->plugin)) &&
      (aa->addr_len == info->addr_len) &&
      (0 == memcmp (info->addr, aa->addr, aa->addr_len)))
  {

    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Deleting address for peer `%s': `%s' %u\n",
                GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);

    if (GNUNET_YES == destroy_address (aa))
      recalculate_assigned_bw ();
    return GNUNET_OK;
  }
  /* session != 0, just remove session */
  if (aa->session_id != info->session_id)
    return GNUNET_OK;           /* irrelevant */
  if (aa->session_id != 0)
    GNUNET_break (0 == strcmp (info->plugin, aa->plugin));
  /* session died */
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Deleting session for peer `%s': `%s' %u\n",
              GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);
  aa->session_id = 0;

  if (GNUNET_YES == aa->active)
  {
    aa->active = GNUNET_NO;
    active_addr_count--;
    recalculate_assigned_bw ();
  }

  /* session == 0 and addrlen == 0 : destroy address */
  if (aa->addr_len == 0)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Deleting session and address for peer `%s': `%s' %u\n",
                GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id);
    (void) destroy_address (aa);
  }
  else
  {
    /* session was set to 0, update address */
#if HAVE_LIBGLPK
  if (ats_mode == MLP)
    GAS_mlp_address_update (mlp, addresses, aa);
#endif
  }

  return GNUNET_OK;
}
/**
 * Free memory of address.
 *
 * @param cls NULL
 * @param key peer identity (unused)
 * @param value the 'struct ATS_Address' to free
 * @return GNUNET_OK (continue to iterate)
 */
static int
free_address_it (void *cls, const GNUNET_HashCode * key, void *value)
{
  struct ATS_Address *aa = value;

  destroy_address (aa);
  return GNUNET_OK;
}