123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2009-2014, 2016 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- 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
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @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_MQ_Handle *mq;
- };
- /**
- * Function called with responses from the service.
- *
- * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
- * @param msg message with the human-readable address
- * @return #GNUNET_OK if message is well-formed
- */
- static int
- check_reply (void *cls,
- const struct AddressToStringResultMessage *atsm)
- {
- uint16_t size = ntohs (atsm->header.size) - sizeof(*atsm);
- const char *address;
- int result;
- uint32_t addr_len;
- result = (int) ntohl (atsm->res);
- addr_len = ntohl (atsm->addr_len);
- if (GNUNET_SYSERR == result)
- return GNUNET_OK;
- if (0 == size)
- {
- if (GNUNET_OK != result)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- address = (const char *) &atsm[1];
- if ((addr_len > size) ||
- (address[addr_len - 1] != '\0'))
- {
- /* invalid reply */
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- /**
- * Function called with responses from the service.
- *
- * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
- * @param msg message with the human-readable address
- */
- static void
- handle_reply (void *cls,
- const struct AddressToStringResultMessage *atsm)
- {
- struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
- uint16_t size = ntohs (atsm->header.size) - sizeof(*atsm);
- const char *address;
- int result;
- result = (int) ntohl (atsm->res);
- if (GNUNET_SYSERR == result)
- {
- /* expect more replies; as this is not the last
- call, we must pass the empty string for the address */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Address resolution failed\n");
- alucb->cb (alucb->cb_cls,
- "",
- GNUNET_NO);
- return;
- }
- if (0 == size)
- {
- /* 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];
- /* return normal reply to caller, also expect more replies */
- alucb->cb (alucb->cb_cls,
- address,
- GNUNET_OK);
- }
- /**
- * Generic error handler, called with the appropriate
- * error code and the same closure specified at the creation of
- * the message queue.
- * Not every message queue implementation supports an error handler.
- *
- * @param cls the `struct GNUNET_TRANSPORT_AddressToStringContext *`
- * @param error error code
- */
- static void
- mq_error_handler (void *cls,
- enum GNUNET_MQ_Error error)
- {
- struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Disconnected from transport, address resolution failed\n");
- alucb->cb (alucb->cb_cls,
- NULL,
- GNUNET_SYSERR);
- GNUNET_TRANSPORT_address_to_string_cancel (alucb);
- }
- /**
- * 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)
- {
- struct GNUNET_TRANSPORT_AddressToStringContext *alc
- = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
- struct GNUNET_MQ_MessageHandler handlers[] = {
- GNUNET_MQ_hd_var_size (reply,
- GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY,
- struct AddressToStringResultMessage,
- alc),
- GNUNET_MQ_handler_end ()
- };
- size_t alen;
- size_t slen;
- struct AddressLookupMessage *msg;
- struct GNUNET_MQ_Envelope *env;
- char *addrbuf;
- alen = address->address_length;
- slen = strlen (address->transport_name) + 1;
- if ((alen + slen >= GNUNET_MAX_MESSAGE_SIZE
- - sizeof(struct AddressLookupMessage)) ||
- (alen >= GNUNET_MAX_MESSAGE_SIZE) ||
- (slen >= GNUNET_MAX_MESSAGE_SIZE))
- {
- GNUNET_break (0);
- GNUNET_free (alc);
- return NULL;
- }
- alc->cb = aluc;
- alc->cb_cls = aluc_cls;
- alc->mq = GNUNET_CLIENT_connect (cfg,
- "transport",
- handlers,
- &mq_error_handler,
- alc);
- if (NULL == alc->mq)
- {
- GNUNET_break (0);
- GNUNET_free (alc);
- return NULL;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client tries to resolve for peer `%s' address plugin %s len %u\n",
- GNUNET_i2s (&address->peer),
- address->transport_name,
- (unsigned int) address->address_length);
- env = GNUNET_MQ_msg_extra (msg,
- alen + slen,
- 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];
- GNUNET_memcpy (addrbuf,
- address->address,
- alen);
- GNUNET_memcpy (&addrbuf[alen],
- address->transport_name,
- slen);
- GNUNET_MQ_send (alc->mq,
- env);
- return alc;
- }
- /**
- * Cancel request for address conversion.
- *
- * @param alc the context handle
- */
- void
- GNUNET_TRANSPORT_address_to_string_cancel (struct
- GNUNET_TRANSPORT_AddressToStringContext
- *alc)
- {
- GNUNET_MQ_destroy (alc->mq);
- GNUNET_free (alc);
- }
- /* end of transport_api_address_to_string.c */
|