123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- This file is part of GNUnet.
- (C) 2009-2014 Christian Grothoff (and other contributing authors)
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
- /**
- * @file transport/transport_api_address_to_string.c
- * @author Christian Grothoff
- * @brief enable clients to convert addresses to human readable strings
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "gnunet_arm_service.h"
- #include "gnunet_hello_lib.h"
- #include "gnunet_protocols.h"
- #include "gnunet_transport_service.h"
- #include "transport.h"
- /**
- * Context for the address lookup.
- */
- struct GNUNET_TRANSPORT_AddressToStringContext
- {
- /**
- * Function to call with the human-readable address.
- */
- GNUNET_TRANSPORT_AddressToStringCallback cb;
- /**
- * Closure for @e cb.
- */
- void *cb_cls;
- /**
- * Connection to the service.
- */
- struct GNUNET_CLIENT_Connection *client;
- };
- /**
- * Function called with responses from the service.
- *
- * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
- * @param msg NULL on timeout or error, otherwise presumably a
- * message with the human-readable address
- */
- static void
- address_response_processor (void *cls,
- const struct GNUNET_MessageHeader *msg)
- {
- struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
- const struct AddressToStringResultMessage *atsm;
- const char *address;
- uint16_t size;
- int result;
- uint32_t addr_len;
- if (NULL == msg)
- {
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_SYSERR);
- GNUNET_TRANSPORT_address_to_string_cancel (alucb);
- return;
- }
- GNUNET_break (ntohs (msg->type) ==
- GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
- size = ntohs (msg->size);
- if (size < sizeof (struct AddressToStringResultMessage))
- {
- GNUNET_break (0);
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_SYSERR);
- GNUNET_TRANSPORT_address_to_string_cancel (alucb);
- return;
- }
- atsm = (const struct AddressToStringResultMessage *) msg;
- result = (int) ntohl (atsm->res);
- addr_len = ntohl (atsm->addr_len);
- if (GNUNET_SYSERR == result)
- {
- /* expect more replies; as this is not the last
- call, we must pass the empty string for the address */
- alucb->cb (alucb->cb_cls,
- "",
- GNUNET_NO);
- GNUNET_CLIENT_receive (alucb->client,
- &address_response_processor,
- alucb,
- GNUNET_TIME_UNIT_FOREVER_REL);
- return;
- }
- if (size == (sizeof (struct AddressToStringResultMessage)))
- {
- if (GNUNET_OK != result)
- {
- GNUNET_break (0);
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_SYSERR);
- GNUNET_CLIENT_disconnect (alucb->client);
- GNUNET_free (alucb);
- return;
- }
- /* we are done (successfully, without communication errors) */
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_OK);
- GNUNET_TRANSPORT_address_to_string_cancel (alucb);
- return;
- }
- address = (const char *) &atsm[1];
- if ( (addr_len > (size - (sizeof (struct AddressToStringResultMessage)))) ||
- (address[addr_len -1] != '\0') )
- {
- /* invalid reply */
- GNUNET_break (0);
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_SYSERR);
- GNUNET_TRANSPORT_address_to_string_cancel (alucb);
- return;
- }
- /* expect more replies */
- GNUNET_CLIENT_receive (alucb->client,
- &address_response_processor,
- alucb,
- GNUNET_TIME_UNIT_FOREVER_REL);
- /* return normal reply to caller */
- alucb->cb (alucb->cb_cls,
- address,
- GNUNET_OK);
- }
- /**
- * Convert a binary address into a human readable address.
- *
- * @param cfg configuration to use
- * @param address address to convert (binary format)
- * @param numeric should (IP) addresses be displayed in numeric form
- * (otherwise do reverse DNS lookup)
- * @param timeout how long is the lookup allowed to take at most
- * @param aluc function to call with the results
- * @param aluc_cls closure for @a aluc
- * @return handle to cancel the operation, NULL on error
- */
- struct GNUNET_TRANSPORT_AddressToStringContext *
- GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
- const struct GNUNET_HELLO_Address *address,
- int numeric,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_TRANSPORT_AddressToStringCallback aluc,
- void *aluc_cls)
- {
- size_t len;
- size_t alen;
- size_t slen;
- struct AddressLookupMessage *msg;
- struct GNUNET_TRANSPORT_AddressToStringContext *alc;
- struct GNUNET_CLIENT_Connection *client;
- char *addrbuf;
- GNUNET_assert (NULL != address);
- alen = address->address_length;
- slen = strlen (address->transport_name) + 1;
- len = sizeof (struct AddressLookupMessage) + alen + slen;
- if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
- {
- GNUNET_break (0);
- return NULL;
- }
- client = GNUNET_CLIENT_connect ("transport", cfg);
- if (NULL == client)
- return NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client %p tries to resolve for peer `%s'address len %u \n",
- client,
- GNUNET_i2s (&address->peer),
- address->address_length);
- msg = GNUNET_malloc (len);
- msg->header.size = htons (len);
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
- msg->numeric_only = htons ((int16_t) numeric);
- msg->addrlen = htons ((uint16_t) alen);
- msg->timeout = GNUNET_TIME_relative_hton (timeout);
- addrbuf = (char *) &msg[1];
- memcpy (addrbuf,
- address->address,
- alen);
- memcpy (&addrbuf[alen],
- address->transport_name,
- slen);
- alc = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
- alc->cb = aluc;
- alc->cb_cls = aluc_cls;
- alc->client = client;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CLIENT_transmit_and_get_response (client,
- &msg->header,
- GNUNET_TIME_UNIT_FOREVER_REL,
- GNUNET_YES,
- &address_response_processor,
- alc));
- GNUNET_free (msg);
- return alc;
- }
- /**
- * Cancel request for address conversion.
- *
- * @param pic the context handle
- */
- void
- GNUNET_TRANSPORT_address_to_string_cancel (struct GNUNET_TRANSPORT_AddressToStringContext *pic)
- {
- GNUNET_CLIENT_disconnect (pic->client);
- GNUNET_free (pic);
- }
- /* end of transport_api_address_to_string.c */
|