first batch of license fixes (boring)
[oweals/gnunet.git] / src / transport / transport_api_address_to_string.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2014, 2016 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14 */
15 /**
16  * @file transport/transport_api_address_to_string.c
17  * @author Christian Grothoff
18  * @brief enable clients to convert addresses to human readable strings
19  */
20 #include "platform.h"
21 #include "gnunet_util_lib.h"
22 #include "gnunet_arm_service.h"
23 #include "gnunet_hello_lib.h"
24 #include "gnunet_protocols.h"
25 #include "gnunet_transport_service.h"
26 #include "transport.h"
27
28 /**
29  * Context for the address lookup.
30  */
31 struct GNUNET_TRANSPORT_AddressToStringContext
32 {
33   /**
34    * Function to call with the human-readable address.
35    */
36   GNUNET_TRANSPORT_AddressToStringCallback cb;
37
38   /**
39    * Closure for @e cb.
40    */
41   void *cb_cls;
42
43   /**
44    * Connection to the service.
45    */
46   struct GNUNET_MQ_Handle *mq;
47
48 };
49
50
51 /**
52  * Function called with responses from the service.
53  *
54  * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
55  * @param msg message with the human-readable address
56  * @return #GNUNET_OK if message is well-formed
57  */
58 static int
59 check_reply (void *cls,
60              const struct AddressToStringResultMessage *atsm)
61 {
62   uint16_t size = ntohs (atsm->header.size) - sizeof (*atsm);
63   const char *address;
64   int result;
65   uint32_t addr_len;
66
67   result = (int) ntohl (atsm->res);
68   addr_len = ntohl (atsm->addr_len);
69   if (GNUNET_SYSERR == result)
70     return GNUNET_OK;
71   if (0 == size)
72   {
73     if (GNUNET_OK != result)
74     {
75       GNUNET_break (0);
76       return GNUNET_SYSERR;
77     }
78     return GNUNET_OK;
79   }
80   address = (const char *) &atsm[1];
81   if ( (addr_len > size) ||
82        (address[addr_len -1] != '\0') )
83   {
84     /* invalid reply */
85     GNUNET_break (0);
86     return GNUNET_SYSERR;
87   }
88   return GNUNET_OK;
89 }
90
91
92 /**
93  * Function called with responses from the service.
94  *
95  * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
96  * @param msg message with the human-readable address
97  */
98 static void
99 handle_reply (void *cls,
100               const struct AddressToStringResultMessage *atsm)
101 {
102   struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
103   uint16_t size = ntohs (atsm->header.size) - sizeof (*atsm);
104   const char *address;
105   int result;
106
107   result = (int) ntohl (atsm->res);
108   if (GNUNET_SYSERR == result)
109   {
110     /* expect more replies; as this is not the last
111        call, we must pass the empty string for the address */
112     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
113                 "Address resolution failed\n");
114     alucb->cb (alucb->cb_cls,
115                "",
116                GNUNET_NO);
117     return;
118   }
119   if (0 == size)
120   {
121     /* we are done (successfully, without communication errors) */
122     alucb->cb (alucb->cb_cls,
123                NULL,
124                GNUNET_OK);
125     GNUNET_TRANSPORT_address_to_string_cancel (alucb);
126     return;
127   }
128   address = (const char *) &atsm[1];
129   /* return normal reply to caller, also expect more replies */
130   alucb->cb (alucb->cb_cls,
131              address,
132              GNUNET_OK);
133 }
134
135
136 /**
137  * Generic error handler, called with the appropriate
138  * error code and the same closure specified at the creation of
139  * the message queue.
140  * Not every message queue implementation supports an error handler.
141  *
142  * @param cls the `struct GNUNET_TRANSPORT_AddressToStringContext *`
143  * @param error error code
144  */
145 static void
146 mq_error_handler (void *cls,
147                   enum GNUNET_MQ_Error error)
148 {
149   struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
150
151   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
152               "Disconnected from transport, address resolution failed\n");
153   alucb->cb (alucb->cb_cls,
154              NULL,
155              GNUNET_SYSERR);
156   GNUNET_TRANSPORT_address_to_string_cancel (alucb);
157 }
158
159
160 /**
161  * Convert a binary address into a human readable address.
162  *
163  * @param cfg configuration to use
164  * @param address address to convert (binary format)
165  * @param numeric should (IP) addresses be displayed in numeric form
166  *                (otherwise do reverse DNS lookup)
167  * @param timeout how long is the lookup allowed to take at most
168  * @param aluc function to call with the results
169  * @param aluc_cls closure for @a aluc
170  * @return handle to cancel the operation, NULL on error
171  */
172 struct GNUNET_TRANSPORT_AddressToStringContext *
173 GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cfg,
174                                     const struct GNUNET_HELLO_Address *address,
175                                     int numeric,
176                                     struct GNUNET_TIME_Relative timeout,
177                                     GNUNET_TRANSPORT_AddressToStringCallback aluc,
178                                     void *aluc_cls)
179 {
180   struct GNUNET_TRANSPORT_AddressToStringContext *alc
181     = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
182   struct GNUNET_MQ_MessageHandler handlers[] = {
183     GNUNET_MQ_hd_var_size (reply,
184                            GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY,
185                            struct AddressToStringResultMessage,
186                            alc),
187     GNUNET_MQ_handler_end ()
188   };
189   size_t alen;
190   size_t slen;
191   struct AddressLookupMessage *msg;
192   struct GNUNET_MQ_Envelope *env;
193   char *addrbuf;
194
195   alen = address->address_length;
196   slen = strlen (address->transport_name) + 1;
197   if ( (alen + slen >= GNUNET_MAX_MESSAGE_SIZE
198         - sizeof (struct AddressLookupMessage)) ||
199        (alen >= GNUNET_MAX_MESSAGE_SIZE) ||
200        (slen >= GNUNET_MAX_MESSAGE_SIZE) )
201   {
202     GNUNET_break (0);
203     GNUNET_free (alc);
204     return NULL;
205   }
206   alc->cb = aluc;
207   alc->cb_cls = aluc_cls;
208   alc->mq = GNUNET_CLIENT_connect (cfg,
209                                    "transport",
210                                    handlers,
211                                    &mq_error_handler,
212                                    alc);
213   if (NULL == alc->mq)
214   {
215     GNUNET_break (0);
216     GNUNET_free (alc);
217     return NULL;
218   }
219   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
220               "Client tries to resolve for peer `%s' address plugin %s len %u\n",
221               GNUNET_i2s (&address->peer),
222               address->transport_name,
223               (unsigned int) address->address_length);
224   env = GNUNET_MQ_msg_extra (msg,
225                              alen + slen,
226                              GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
227   msg->numeric_only = htons ((int16_t) numeric);
228   msg->addrlen = htons ((uint16_t) alen);
229   msg->timeout = GNUNET_TIME_relative_hton (timeout);
230   addrbuf = (char *) &msg[1];
231   GNUNET_memcpy (addrbuf,
232           address->address,
233           alen);
234   GNUNET_memcpy (&addrbuf[alen],
235           address->transport_name,
236           slen);
237   GNUNET_MQ_send (alc->mq,
238                   env);
239   return alc;
240 }
241
242
243 /**
244  * Cancel request for address conversion.
245  *
246  * @param alc the context handle
247  */
248 void
249 GNUNET_TRANSPORT_address_to_string_cancel (struct GNUNET_TRANSPORT_AddressToStringContext *alc)
250 {
251   GNUNET_MQ_destroy (alc->mq);
252   GNUNET_free (alc);
253 }
254
255
256 /* end of transport_api_address_to_string.c */