tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / transport / transport_api2_address.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 2016, 2018, 2019 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero 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      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file transport/transport_api2_address.c
23  * @brief library to inform the transport service about addresses to be validated
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_protocols.h"
30 #include "gnunet_transport_address_service.h"
31 #include "gnunet_ats_transport_service.h"
32 #include "transport.h"
33
34 #define LOG(kind,...) GNUNET_log_from (kind, "transport-api-address",__VA_ARGS__)
35
36
37 /**
38  * Handle for the transport service (includes all of the
39  * state for the transport service).
40  */
41 struct GNUNET_TRANSPORT_AddressHandle
42 {
43
44   /**
45    * My client connection to the transport service.
46    */
47   struct GNUNET_MQ_Handle *mq;
48
49   /**
50    * My configuration.
51    */
52   const struct GNUNET_CONFIGURATION_Handle *cfg;
53
54   /**
55    * ID of the task trying to reconnect to the service.
56    */
57   struct GNUNET_SCHEDULER_Task *reconnect_task;
58
59   /**
60    * Delay until we try to reconnect.
61    */
62   struct GNUNET_TIME_Relative reconnect_delay;
63
64 };
65
66
67 /**
68  * Function that will schedule the job that will try
69  * to connect us again to the client.
70  *
71  * @param h transport service to reconnect
72  */
73 static void
74 disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_AddressHandle *h);
75
76
77 /**
78  * Generic error handler, called with the appropriate
79  * error code and the same closure specified at the creation of
80  * the message queue.
81  * Not every message queue implementation supports an error handler.
82  *
83  * @param cls closure with the `struct GNUNET_TRANSPORT_AddressHandle *`
84  * @param error error code
85  */
86 static void
87 mq_error_handler (void *cls,
88                   enum GNUNET_MQ_Error error)
89 {
90   struct GNUNET_TRANSPORT_AddressHandle *h = cls;
91
92   LOG (GNUNET_ERROR_TYPE_DEBUG,
93        "Error receiving from transport service, disconnecting temporarily.\n");
94   disconnect_and_schedule_reconnect (h);
95 }
96
97
98 /**
99  * Try again to connect to transport service.
100  *
101  * @param cls the handle to the transport service
102  */
103 static void
104 reconnect (void *cls)
105 {
106   struct GNUNET_TRANSPORT_AddressHandle *h = cls;
107   struct GNUNET_MQ_MessageHandler handlers[] = {
108     GNUNET_MQ_handler_end ()
109   };
110
111   h->reconnect_task = NULL;
112   LOG (GNUNET_ERROR_TYPE_DEBUG,
113        "Connecting to transport service.\n");
114   GNUNET_assert (NULL == h->mq);
115   h->mq = GNUNET_CLIENT_connect (h->cfg,
116                                  "transport",
117                                  handlers,
118                                  &mq_error_handler,
119                                  h);
120 }
121
122
123 /**
124  * Disconnect from the transport service.
125  *
126  * @param h transport service to disconnect
127  */
128 static void
129 disconnect (struct GNUNET_TRANSPORT_AddressHandle *h)
130 {
131   if (NULL != h->mq)
132   {
133     GNUNET_MQ_destroy (h->mq);
134     h->mq = NULL;
135   }
136 }
137
138
139 /**
140  * Function that will schedule the job that will try
141  * to connect us again to the client.
142  *
143  * @param h transport service to reconnect
144  */
145 static void
146 disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_AddressHandle *h)
147 {
148   GNUNET_assert (NULL == h->reconnect_task);
149   disconnect (h);
150   LOG (GNUNET_ERROR_TYPE_DEBUG,
151        "Scheduling task to reconnect to transport service in %s.\n",
152        GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay,
153                                                GNUNET_YES));
154   h->reconnect_task =
155       GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
156                                     &reconnect,
157                                     h);
158   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
159 }
160
161
162 /**
163  * Connect to the transport service.
164  *
165  * @param cfg configuration to use
166  * @return NULL on error
167  */
168 struct GNUNET_TRANSPORT_AddressHandle *
169 GNUNET_TRANSPORT_address_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
170 {
171   struct GNUNET_TRANSPORT_AddressHandle *h;
172
173   h = GNUNET_new (struct GNUNET_TRANSPORT_AddressHandle);
174   h->cfg = cfg;
175   h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
176   LOG (GNUNET_ERROR_TYPE_DEBUG,
177        "Connecting to transport service\n");
178   reconnect (h);
179   if (NULL == h->mq)
180   {
181     GNUNET_free (h);
182     return NULL;
183   }
184   return h;
185 }
186
187
188 /**
189  * Disconnect from the transport service.
190  *
191  * @param handle handle to the service as returned from #GNUNET_TRANSPORT_address_connect()
192  */
193 void
194 GNUNET_TRANSPORT_address_disconnect (struct GNUNET_TRANSPORT_AddressHandle *handle)
195 {
196   LOG (GNUNET_ERROR_TYPE_DEBUG,
197        "Transport disconnect called!\n");
198   /* this disconnects all neighbours... */
199   disconnect (handle);
200   /* and now we stop trying to connect again... */
201   if (NULL != handle->reconnect_task)
202   {
203     GNUNET_SCHEDULER_cancel (handle->reconnect_task);
204     handle->reconnect_task = NULL;
205   }
206   GNUNET_free (handle);
207 }
208
209
210 /**
211  * The client has learned about a possible address for peer @a pid
212  * (i.e. via broadcast, multicast, DHT, ...).  The transport service
213  * should consider validating it. Note that the plugin is NOT expected
214  * to have verified the signature, the transport service must decide
215  * whether to check the signature.
216  *
217  * While the notification is sent to @a ch asynchronously, this API
218  * does not return a handle as the delivery of addresses is simply
219  * unreliable, and if @a ch is down, the data provided will simply be
220  * lost.
221  *
222  * @param ch communicator handle
223  * @param pid peer the address is for
224  * @param raw raw address data
225  * @param raw_size number of bytes in @a raw
226  */
227 void
228 GNUNET_TRANSPORT_address_try (struct GNUNET_TRANSPORT_AddressHandle *ch,
229                               const struct GNUNET_PeerIdentity *pid,
230                               const void *raw,
231                               const size_t raw_size)
232 {
233   struct GNUNET_MQ_Envelope *env;
234   struct GNUNET_TRANSPORT_AddressToVerify *hdr;
235
236   env = GNUNET_MQ_msg_extra (hdr,
237                              raw_size,
238                              GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_CONSIDER_VERIFY);
239   hdr->peer = *pid;
240   memcpy (&hdr[1],
241           raw,
242           raw_size);
243   GNUNET_MQ_send (ch->mq,
244                   env);
245 }
246
247
248
249 /* end of transport_api2_address.c */