also config files
[oweals/gnunet.git] / src / transport / transport_api_hello_get.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 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 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_api_hello_get.c
23  * @brief library to obtain our HELLO from our transport service
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_arm_service.h"
30 #include "gnunet_hello_lib.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_transport_hello_service.h"
33 #include "transport.h"
34
35
36 /**
37  * Functions to call with this peer's HELLO.
38  */
39 struct GNUNET_TRANSPORT_HelloGetHandle
40 {
41   /**
42    * Our configuration.
43    */
44   const struct GNUNET_CONFIGURATION_Handle *cfg;
45
46   /**
47    * Transport handle.
48    */
49   struct GNUNET_MQ_Handle *mq;
50
51   /**
52    * Callback to call once we got our HELLO.
53    */
54   GNUNET_TRANSPORT_HelloUpdateCallback rec;
55
56   /**
57    * Closure for @e rec.
58    */
59   void *rec_cls;
60
61   /**
62    * Task for calling the HelloUpdateCallback when we already have a HELLO
63    */
64   struct GNUNET_SCHEDULER_Task *notify_task;
65
66   /**
67    * ID of the task trying to reconnect to the service.
68    */
69   struct GNUNET_SCHEDULER_Task *reconnect_task;
70
71   /**
72    * Delay until we try to reconnect.
73    */
74   struct GNUNET_TIME_Relative reconnect_delay;
75
76   /**
77    * Type of HELLOs client cares about.
78    */
79   enum GNUNET_TRANSPORT_AddressClass ac;
80 };
81
82
83 /**
84  * Function we use for checking incoming HELLO messages.
85  *
86  * @param cls closure, a `struct GNUNET_TRANSPORT_Handle *`
87  * @param msg message received
88  * @return #GNUNET_OK if message is well-formed
89  */
90 static int
91 check_hello (void *cls,
92              const struct GNUNET_MessageHeader *msg)
93 {
94   struct GNUNET_PeerIdentity me;
95
96   if (GNUNET_OK !=
97       GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg,
98                            &me))
99   {
100     GNUNET_break (0);
101     return GNUNET_SYSERR;
102   }
103   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
104               "Receiving (my own) HELLO message (%u bytes), I am `%s'.\n",
105               (unsigned int) ntohs (msg->size),
106               GNUNET_i2s (&me));
107   return GNUNET_OK;
108 }
109
110
111 /**
112  * Function we use for handling incoming HELLO messages.
113  *
114  * @param cls closure, a `struct GNUNET_TRANSPORT_HelloGetHandle *`
115  * @param msg message received
116  */
117 static void
118 handle_hello (void *cls,
119               const struct GNUNET_MessageHeader *msg)
120 {
121   struct GNUNET_TRANSPORT_HelloGetHandle *ghh = cls;
122
123   ghh->rec (ghh->rec_cls,
124             msg);
125 }
126
127
128 /**
129  * Function that will schedule the job that will try
130  * to connect us again to the client.
131  *
132  * @param ghh transport service to reconnect
133  */
134 static void
135 schedule_reconnect (struct GNUNET_TRANSPORT_HelloGetHandle *ghh);
136
137
138 /**
139  * Generic error handler, called with the appropriate
140  * error code and the same closure specified at the creation of
141  * the message queue.
142  * Not every message queue implementation supports an error handler.
143  *
144  * @param cls closure with the `struct GNUNET_TRANSPORT_Handle *`
145  * @param error error code
146  */
147 static void
148 mq_error_handler (void *cls,
149                   enum GNUNET_MQ_Error error)
150 {
151   struct GNUNET_TRANSPORT_HelloGetHandle *ghh = cls;
152
153   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154               "Error receiving from transport service, disconnecting temporarily.\n");
155   GNUNET_MQ_destroy (ghh->mq);
156   ghh->mq = NULL;
157   schedule_reconnect (ghh);
158 }
159
160
161 /**
162  * Try again to connect to transport service.
163  *
164  * @param cls the handle to the transport service
165  */
166 static void
167 reconnect (void *cls)
168 {
169   struct GNUNET_TRANSPORT_HelloGetHandle *ghh = cls;
170   struct GNUNET_MQ_MessageHandler handlers[] = {
171     GNUNET_MQ_hd_var_size (hello,
172                            GNUNET_MESSAGE_TYPE_HELLO,
173                            struct GNUNET_MessageHeader,
174                            ghh),
175     GNUNET_MQ_handler_end ()
176   };
177   struct GNUNET_MQ_Envelope *env;
178   struct StartMessage *s;
179
180   ghh->reconnect_task = NULL;
181   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182               "Connecting to transport service.\n");
183   GNUNET_assert (NULL == ghh->mq);
184   ghh->mq = GNUNET_CLIENT_connect (ghh->cfg,
185                                    "transport",
186                                    handlers,
187                                    &mq_error_handler,
188                                    ghh);
189   if (NULL == ghh->mq)
190     return;
191   env = GNUNET_MQ_msg (s,
192                        GNUNET_MESSAGE_TYPE_TRANSPORT_START);
193   s->options = htonl (0);
194   GNUNET_MQ_send (ghh->mq,
195                   env);
196 }
197
198
199 /**
200  * Function that will schedule the job that will try
201  * to connect us again to the client.
202  *
203  * @param ghh transport service to reconnect
204  */
205 static void
206 schedule_reconnect (struct GNUNET_TRANSPORT_HelloGetHandle *ghh)
207 {
208   ghh->reconnect_task =
209     GNUNET_SCHEDULER_add_delayed (ghh->reconnect_delay,
210                                   &reconnect,
211                                   ghh);
212   ghh->reconnect_delay = GNUNET_TIME_STD_BACKOFF (ghh->reconnect_delay);
213 }
214
215
216 /**
217  * Obtain the HELLO message for this peer.  The callback given in this function
218  * is never called synchronously.
219  *
220  * @param cfg configuration
221  * @param ac which network type should the addresses from the HELLO belong to?
222  * @param rec function to call with the HELLO, sender will be our peer
223  *            identity; message and sender will be NULL on timeout
224  *            (handshake with transport service pending/failed).
225  *             cost estimate will be 0.
226  * @param rec_cls closure for @a rec
227  * @return handle to cancel the operation
228  */
229 struct GNUNET_TRANSPORT_HelloGetHandle *
230 GNUNET_TRANSPORT_hello_get (const struct GNUNET_CONFIGURATION_Handle *cfg,
231                             enum GNUNET_TRANSPORT_AddressClass ac,
232                             GNUNET_TRANSPORT_HelloUpdateCallback rec,
233                             void *rec_cls)
234 {
235   struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
236
237   ghh = GNUNET_new (struct GNUNET_TRANSPORT_HelloGetHandle);
238   ghh->rec = rec;
239   ghh->rec_cls = rec_cls;
240   ghh->cfg = cfg;
241   ghh->ac = ac;
242   reconnect (ghh);
243   if (NULL == ghh->mq)
244   {
245     GNUNET_free (ghh);
246     return NULL;
247   }
248   return ghh;
249 }
250
251
252 /**
253  * Stop receiving updates about changes to our HELLO message.
254  *
255  * @param ghh handle to cancel
256  */
257 void
258 GNUNET_TRANSPORT_hello_get_cancel (struct GNUNET_TRANSPORT_HelloGetHandle *ghh)
259 {
260   if (NULL != ghh->reconnect_task)
261   {
262     GNUNET_SCHEDULER_cancel (ghh->reconnect_task);
263     ghh->reconnect_task = NULL;
264   }
265   if (NULL != ghh->mq)
266   {
267     GNUNET_MQ_destroy (ghh->mq);
268     ghh->mq = NULL;
269   }
270   GNUNET_free (ghh);
271 }
272
273
274 /* end of transport_api_hello_get.c */