-fixing doxygen, indentation
[oweals/gnunet.git] / src / transport / transport_api_address_to_string.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
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 cb.
40    */
41   void *cb_cls;
42
43   /**
44    * Connection to the service.
45    */
46   struct GNUNET_CLIENT_Connection *client;
47
48   /**
49    * When should this operation time out?
50    */
51   struct GNUNET_TIME_Absolute timeout;
52 };
53
54
55 /**
56  * Function called with responses from the service.
57  *
58  * @param cls our `struct GNUNET_TRANSPORT_AddressToStringContext *`
59  * @param msg NULL on timeout or error, otherwise presumably a
60  *        message with the human-readable address
61  */
62 static void
63 address_response_processor (void *cls,
64                             const struct GNUNET_MessageHeader *msg)
65 {
66   struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls;
67   struct AddressToStringResultMessage *atsm;
68   const char *address;
69   uint16_t size;
70   uint32_t result;
71   uint32_t addr_len;
72   char *empty_str = "";
73
74   if (NULL == msg)
75   {
76     alucb->cb (alucb->cb_cls,
77                NULL,
78                GNUNET_OK);
79     GNUNET_CLIENT_disconnect (alucb->client);
80     GNUNET_free (alucb);
81     return;
82   }
83   GNUNET_break (ntohs (msg->type) ==
84                 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
85
86   size = ntohs (msg->size);
87   if (size < sizeof (struct AddressToStringResultMessage))
88   {
89     alucb->cb (alucb->cb_cls, NULL, GNUNET_OK);
90     GNUNET_CLIENT_disconnect (alucb->client);
91     GNUNET_free (alucb);
92     return;
93   }
94   atsm = (struct AddressToStringResultMessage *) msg;
95
96   result = ntohl (atsm->res);
97   addr_len = ntohl (atsm->addr_len);
98
99   if (size == (sizeof (struct AddressToStringResultMessage)))
100   {
101     /* done, success depends on result */
102     alucb->cb (alucb->cb_cls, NULL, result);
103     GNUNET_CLIENT_disconnect (alucb->client);
104     GNUNET_free (alucb);
105     return;
106   }
107
108   if (GNUNET_NO == result)
109   {
110     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p failed to resolve address \n",
111         alucb->client);
112     GNUNET_break (0);
113     alucb->cb (alucb->cb_cls, empty_str, GNUNET_SYSERR);
114
115     /* expect more replies */
116     GNUNET_CLIENT_receive (alucb->client, &address_response_processor, alucb,
117                            GNUNET_TIME_absolute_get_remaining (alucb->timeout));
118     return;
119   }
120
121   address = (const char *) &atsm[1];
122   if ( (addr_len > (size - (sizeof (struct AddressToStringResultMessage)))) ||
123        (address[addr_len -1] != '\0') )
124   {
125     /* invalid reply */
126     GNUNET_break (0);
127     alucb->cb (alucb->cb_cls, NULL, GNUNET_SYSERR);
128     GNUNET_CLIENT_disconnect (alucb->client);
129     GNUNET_free (alucb);
130     return;
131   }
132
133   /* expect more replies */
134   GNUNET_CLIENT_receive (alucb->client, &address_response_processor, alucb,
135                          GNUNET_TIME_absolute_get_remaining (alucb->timeout));
136   alucb->cb (alucb->cb_cls, address, GNUNET_OK);
137 }
138
139
140 /**
141  * Convert a binary address into a human readable address.
142  *
143  * @param cfg configuration to use
144  * @param address address to convert (binary format)
145  * @param numeric should (IP) addresses be displayed in numeric form
146  *                (otherwise do reverse DNS lookup)
147  * @param timeout how long is the lookup allowed to take at most
148  * @param aluc function to call with the results
149  * @param aluc_cls closure for aluc
150  * @return handle to cancel the operation, NULL on error
151  */
152 struct GNUNET_TRANSPORT_AddressToStringContext *
153 GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle
154                                     *cfg,
155                                     const struct GNUNET_HELLO_Address *address,
156                                     int numeric,
157                                     struct GNUNET_TIME_Relative timeout,
158                                     GNUNET_TRANSPORT_AddressToStringCallback
159                                     aluc, void *aluc_cls)
160 {
161   size_t len;
162   size_t alen;
163   size_t slen;
164   struct AddressLookupMessage *msg;
165   struct GNUNET_TRANSPORT_AddressToStringContext *alc;
166   struct GNUNET_CLIENT_Connection *client;
167   char *addrbuf;
168
169   GNUNET_assert (address != NULL);
170   alen = address->address_length;
171   slen = strlen (address->transport_name) + 1;
172   len = sizeof (struct AddressLookupMessage) + alen + slen;
173   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
174   {
175     GNUNET_break (0);
176     return NULL;
177   }
178   client = GNUNET_CLIENT_connect ("transport", cfg);
179   if (NULL == client)
180     return NULL;
181   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p tries to resolve for peer `%s'address len %u \n",
182       client, GNUNET_i2s (&address->peer), address->address_length);
183
184   msg = GNUNET_malloc (len);
185   msg->header.size = htons (len);
186   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
187   msg->numeric_only = htons ((int16_t) numeric);
188   msg->addrlen = htons ((uint16_t) alen);
189   msg->timeout = GNUNET_TIME_relative_hton (timeout);
190   addrbuf = (char *) &msg[1];
191   memcpy (addrbuf, address->address, alen);
192   memcpy (&addrbuf[alen], address->transport_name, slen);
193
194   alc = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext);
195   alc->cb = aluc;
196   alc->cb_cls = aluc_cls;
197   alc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
198   alc->client = client;
199   GNUNET_assert (GNUNET_OK ==
200                  GNUNET_CLIENT_transmit_and_get_response (client, &msg->header,
201                                                           timeout, GNUNET_YES,
202                                                           &address_response_processor,
203                                                           alc));
204   GNUNET_free (msg);
205   return alc;
206 }
207
208
209 /**
210  * Cancel request for address conversion.
211  *
212  * @param pic the context handle
213  */
214 void
215 GNUNET_TRANSPORT_address_to_string_cancel (struct
216                                            GNUNET_TRANSPORT_AddressToStringContext
217                                            *pic)
218 {
219   GNUNET_CLIENT_disconnect (pic->client);
220   GNUNET_free (pic);
221 }
222
223
224
225 /* end of transport_api_address_to_string.c */