/**
 * Handle INDEX_LIST_GET-message.
 *
 * @param cls closure
 * @param client identification of the client
 * @param message the actual message
 */
void
GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client,
                                 const struct GNUNET_MessageHeader *message)
{
  struct GNUNET_SERVER_TransmitContext *tc;
  struct IndexInfoMessage *iim;
  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
  size_t slen;
  const char *fn;
  struct IndexInfo *pos;

  tc = GNUNET_SERVER_transmit_context_create (client);
  iim = (struct IndexInfoMessage *) buf;
  for (pos = indexed_files_head; NULL != pos; pos = pos->next)
  {
    fn = pos->filename;
    slen = strlen (fn) + 1;
    if (slen + sizeof (struct IndexInfoMessage) >=
        GNUNET_SERVER_MAX_MESSAGE_SIZE)
    {
      GNUNET_break (0);
      break;
    }
    iim->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY);
    iim->header.size = htons (slen + sizeof (struct IndexInfoMessage));
    iim->reserved = 0;
    iim->file_id = pos->file_id;
    memcpy (&iim[1], fn, slen);
    GNUNET_SERVER_transmit_context_append_message (tc, &iim->header);
  }
  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
                                              GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END);
  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES);
}
/**
 * Output information of validation entries to the given client.
 *
 * @param cls the 'struct IterationContext'
 * @param peer identity of the neighbour
 * @param address the address
 * @param last_validation point in time when last validation was performed
 * @param valid_until point in time how long address is valid
 * @param next_validation point in time when next validation will be performed
 * @param state state of validation notification
 */
static void
send_validation_information (void *cls,
    const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    struct GNUNET_TIME_Absolute last_validation,
    struct GNUNET_TIME_Absolute valid_until,
    struct GNUNET_TIME_Absolute next_validation,
    enum GNUNET_TRANSPORT_ValidationState state)
{
  struct IterationContext *pc = cls;
  struct ValidationIterateResponseMessage *msg;

  if ( (GNUNET_YES == pc->all) ||
       (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
        "Sending information about for validation entry for peer `%s' using address `%s'\n",
        GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
    msg = compose_validation_iterate_response_message (peer, address);
    msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
    msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
    msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
    msg->state = htonl ((uint32_t) state);
    GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
    GNUNET_free (msg);
  }
}
/**
 * Output information of neighbours to the given client.
 *
 * @param cls the 'struct PeerIterationContext'
 * @param peer identity of the neighbour
 * @param address the address
 * @param state current state this peer is in
 * @param state_timeout timeout for the current state of the peer
 * @param bandwidth_in inbound quota in NBO
 * @param bandwidth_out outbound quota in NBO
 */
static void
send_peer_information (void *cls,
    const struct GNUNET_PeerIdentity *peer,
    const struct GNUNET_HELLO_Address *address,
    enum GNUNET_TRANSPORT_PeerState state,
    struct GNUNET_TIME_Absolute state_timeout,
    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
{
  struct IterationContext *pc = cls;
  struct PeerIterateResponseMessage *msg;

  if ( (GNUNET_YES == pc->all) ||
       (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
        "Sending information about `%s' using address `%s' in state `%s'\n",
        GNUNET_i2s(peer),
        (address != NULL) ? GST_plugins_a2s (address) : "<none>",
        GNUNET_TRANSPORT_ps2s (state));
    msg = compose_address_iterate_response_message (peer, address);
    msg->state = htonl (state);
    msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout);
    GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
    GNUNET_free (msg);
  }
}
/**
 * Do transmit info about peer to given host.
 *
 * @param cls NULL to hit all hosts, otherwise specifies a particular target
 * @param key hostID
 * @param value information to transmit
 * @return GNUNET_YES (continue to iterate)
 */
static int
add_to_tc (void *cls, const GNUNET_HashCode * key, void *value)
{
  struct GNUNET_SERVER_TransmitContext *tc = cls;
  struct HostEntry *pos = value;
  struct InfoMessage *im;
  uint16_t hs;
  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;

  hs = 0;
  im = (struct InfoMessage *) buf;
  if (pos->hello != NULL)
  {
    hs = GNUNET_HELLO_size (pos->hello);
    GNUNET_assert (hs <
                   GNUNET_SERVER_MAX_MESSAGE_SIZE -
                   sizeof (struct InfoMessage));
    memcpy (&im[1], pos->hello, hs);
  }
  im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
  im->header.size = htons (sizeof (struct InfoMessage) + hs);
  im->reserved = htonl (0);
  im->peer = pos->identity;
  GNUNET_SERVER_transmit_context_append_message (tc, &im->header);
  return GNUNET_YES;
}