/**
 * Convert a given address to a human-readable format.  Note that the
 * return value will be overwritten on the next call to this function.
 *
 * @param address the address to convert
 * @return statically allocated (!) human-readable address
 */
const char *
GST_plugins_a2s (const struct GNUNET_HELLO_Address *address)
{
  struct GNUNET_TRANSPORT_PluginFunctions *api;
  static char unable_to_show[1024];
  static const char *s;

  if (NULL == address)
    return "<NULL>";
  if (0 == address->address_length)
    return TRANSPORT_SESSION_INBOUND_STRING; /* Addresse with length 0 are inbound, address->address itself may be NULL */
  api = GST_plugins_printer_find (address->transport_name);
  if (NULL == api)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Failed to find transport plugin `%s'\n",
                address->transport_name);
    return "<plugin unknown>";
  }
  if (0 == address->address_length)
  {
    GNUNET_snprintf (unable_to_show,
                     sizeof (unable_to_show),
                     "<unable to stringify %u-byte long address of %s transport>",
                     (unsigned int) address->address_length,
                     address->transport_name);
    return unable_to_show;
  }
  return (NULL != (s = api->address_to_string (NULL,
                                               address->address,
                                               address->address_length))
          ? s
          : "<invalid>");
}
/**
 * Client asked to resolve an address.  Process the request.
 *
 * @param cls unused
 * @param client the client
 * @param message the resolution request
 */
static void
clients_handle_address_to_string (void *cls,
                                  struct GNUNET_SERVER_Client *client,
                                  const struct GNUNET_MessageHeader *message)
{
  const struct AddressLookupMessage *alum;
  struct GNUNET_TRANSPORT_PluginFunctions *papi;
  const char *plugin_name;
  const char *address;
  uint32_t address_len;
  uint16_t size;
  struct GNUNET_SERVER_TransmitContext *tc;
  struct AddressToStringContext *actx;
  struct GNUNET_TIME_Relative rtimeout;
  int32_t numeric;

  size = ntohs (message->size);
  if (size < sizeof (struct AddressLookupMessage))
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  alum = (const struct AddressLookupMessage *) message;
  address_len = ntohs (alum->addrlen);
  if (size <= sizeof (struct AddressLookupMessage) + address_len)
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  address = (const char *) &alum[1];
  plugin_name = (const char *) &address[address_len];
  if ('\0' != plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1])
  {
    GNUNET_break (0);
    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
    return;
  }
  rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
  numeric = ntohs (alum->numeric_only);
  tc = GNUNET_SERVER_transmit_context_create (client);
  papi = GST_plugins_printer_find (plugin_name);
  if (NULL == papi)
  {
    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
                                                GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
    GNUNET_SERVER_transmit_context_run (tc, rtimeout);
    return;
  }
  actx = GNUNET_new (struct AddressToStringContext);
  actx->tc = tc;
  GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx);
  GNUNET_SERVER_disable_receive_done_warning (client);
  papi->address_pretty_printer (papi->cls, plugin_name, address, address_len,
                                numeric, rtimeout, &transmit_address_to_client,
                                actx);
}
/**
 * Convert a given address to a human-readable format.  Note that the
 * return value will be overwritten on the next call to this function.
 *
 * @param address the address to convert
 * @return statically allocated (!) human-readable address
 */
const char *
GST_plugins_a2s (const struct GNUNET_HELLO_Address *address)
{
  struct GNUNET_TRANSPORT_PluginFunctions *api;
  static char unable_to_show[1024];

  if (address == NULL)
    return "<inbound>";
  api = GST_plugins_printer_find (address->transport_name);
  if (NULL == api)
    return "<plugin unknown>";
  if (0 == address->address_length)
  {
    GNUNET_snprintf (unable_to_show, sizeof (unable_to_show),
                     "<unable to stringify %u-byte long address of %s transport>",
                     (unsigned int) address->address_length,
                     address->transport_name);
    return unable_to_show;
  }
  return api->address_to_string (NULL, address->address,
                                 address->address_length);
}