aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api2_application.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport_api2_application.c')
-rw-r--r--src/transport/transport_api2_application.c397
1 files changed, 0 insertions, 397 deletions
diff --git a/src/transport/transport_api2_application.c b/src/transport/transport_api2_application.c
deleted file mode 100644
index 00f5f62eb..000000000
--- a/src/transport/transport_api2_application.c
+++ /dev/null
@@ -1,397 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010--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 * @file transport/transport_api2_application.c
22 * @brief enable clients to ask TRANSPORT about establishing connections to peers
23 * @author Christian Grothoff
24 * @author Matthias Wachs
25 */
26#include "platform.h"
27#include "gnunet_transport_application_service.h"
28#include "gnunet_transport_core_service.h"
29#include "transport.h"
30
31
32#define LOG(kind, ...) \
33 GNUNET_log_from (kind, "transport-application-api", __VA_ARGS__)
34
35
36/**
37 * Handle for TRANSPORT address suggestion requests.
38 */
39struct GNUNET_TRANSPORT_ApplicationSuggestHandle
40{
41 /**
42 * ID of the peer for which address suggestion was requested.
43 */
44 struct GNUNET_PeerIdentity id;
45
46 /**
47 * Connecitivity handle this suggestion handle belongs to.
48 */
49 struct GNUNET_TRANSPORT_ApplicationHandle *ch;
50
51 /**
52 * What preference is being expressed?
53 */
54 enum GNUNET_MQ_PriorityPreferences pk;
55
56 /**
57 * How much bandwidth does the client expect?
58 */
59 struct GNUNET_BANDWIDTH_Value32NBO bw;
60};
61
62
63/**
64 * Handle to the TRANSPORT subsystem for application management.
65 */
66struct GNUNET_TRANSPORT_ApplicationHandle
67{
68 /**
69 * Our configuration.
70 */
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 /**
74 * Map with the identities of all the peers for which we would
75 * like to have address suggestions. The key is the PID, the
76 * value is currently the `struct GNUNET_TRANSPORT_ApplicationSuggestHandle`
77 */
78 struct GNUNET_CONTAINER_MultiPeerMap *sug_requests;
79
80 /**
81 * Message queue for sending requests to the TRANSPORT service.
82 */
83 struct GNUNET_MQ_Handle *mq;
84
85 /**
86 * Task to trigger reconnect.
87 */
88 struct GNUNET_SCHEDULER_Task *task;
89
90 /**
91 * Reconnect backoff delay.
92 */
93 struct GNUNET_TIME_Relative backoff;
94};
95
96
97/**
98 * Re-establish the connection to the TRANSPORT service.
99 *
100 * @param ch handle to use to re-connect.
101 */
102static void
103reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch);
104
105
106/**
107 * Re-establish the connection to the TRANSPORT service.
108 *
109 * @param cls handle to use to re-connect.
110 */
111static void
112reconnect_task (void *cls)
113{
114 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
115
116 ch->task = NULL;
117 reconnect (ch);
118}
119
120
121/**
122 * Disconnect from TRANSPORT and then reconnect.
123 *
124 * @param ch our handle
125 */
126static void
127force_reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch)
128{
129 if (NULL != ch->mq)
130 {
131 GNUNET_MQ_destroy (ch->mq);
132 ch->mq = NULL;
133 }
134 ch->backoff = GNUNET_TIME_STD_BACKOFF (ch->backoff);
135 ch->task = GNUNET_SCHEDULER_add_delayed (ch->backoff, &reconnect_task, ch);
136}
137
138
139/**
140 * We encountered an error handling the MQ to the
141 * TRANSPORT service. Reconnect.
142 *
143 * @param cls the `struct GNUNET_TRANSPORT_ApplicationHandle`
144 * @param error details about the error
145 */
146static void
147error_handler (void *cls, enum GNUNET_MQ_Error error)
148{
149 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
150
151 LOG (GNUNET_ERROR_TYPE_DEBUG,
152 "TRANSPORT connection died (code %d), reconnecting\n",
153 (int) error);
154 force_reconnect (ch);
155}
156
157
158/**
159 * Transmit request for an address suggestion.
160 *
161 * @param cls the `struct GNUNET_TRANSPORT_ApplicationHandle`
162 * @param peer peer to ask for an address suggestion for
163 * @param value the `struct GNUNET_TRANSPORT_SuggestHandle`
164 * @return #GNUNET_OK (continue to iterate), #GNUNET_SYSERR on
165 * failure (message queue no longer exists)
166 */
167static int
168transmit_suggestion (void *cls,
169 const struct GNUNET_PeerIdentity *peer,
170 void *value)
171{
172 struct GNUNET_TRANSPORT_ApplicationHandle *ch = cls;
173 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *sh = value;
174 struct GNUNET_MQ_Envelope *ev;
175 struct ExpressPreferenceMessage *m;
176
177 if (NULL == ch->mq)
178 return GNUNET_SYSERR;
179 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST);
180 m->pk = htonl ((uint32_t) sh->pk);
181 m->bw = sh->bw;
182 m->peer = *peer;
183 GNUNET_MQ_send (ch->mq, ev);
184 return GNUNET_OK;
185}
186
187
188/**
189 * Re-establish the connection to the TRANSPORT service.
190 *
191 * @param ch handle to use to re-connect.
192 */
193static void
194reconnect (struct GNUNET_TRANSPORT_ApplicationHandle *ch)
195{
196 static const struct GNUNET_MQ_MessageHandler handlers[] = { { NULL, 0, 0 } };
197
198 GNUNET_assert (NULL == ch->mq);
199 ch->mq =
200 GNUNET_CLIENT_connect (ch->cfg, "transport", handlers, &error_handler, ch);
201 if (NULL == ch->mq)
202 {
203 force_reconnect (ch);
204 return;
205 }
206 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
207 &transmit_suggestion,
208 ch);
209}
210
211
212/**
213 * Initialize the TRANSPORT application suggestion client handle.
214 *
215 * @param cfg configuration to use
216 * @return transport application handle, NULL on error
217 */
218struct GNUNET_TRANSPORT_ApplicationHandle *
219GNUNET_TRANSPORT_application_init (
220 const struct GNUNET_CONFIGURATION_Handle *cfg)
221{
222 struct GNUNET_TRANSPORT_ApplicationHandle *ch;
223
224 ch = GNUNET_new (struct GNUNET_TRANSPORT_ApplicationHandle);
225 ch->cfg = cfg;
226 ch->sug_requests = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES);
227 reconnect (ch);
228 return ch;
229}
230
231
232/**
233 * Function called to free all `struct GNUNET_TRANSPORT_ApplicationSuggestHandle`s
234 * in the map.
235 *
236 * @param cls NULL
237 * @param key the key
238 * @param value the value to free
239 * @return #GNUNET_OK (continue to iterate)
240 */
241static int
242free_sug_handle (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
243{
244 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *cur = value;
245
246 GNUNET_free (cur);
247 return GNUNET_OK;
248}
249
250
251/**
252 * Client is done with TRANSPORT application management, release resources.
253 *
254 * @param ch handle to release
255 */
256void
257GNUNET_TRANSPORT_application_done (
258 struct GNUNET_TRANSPORT_ApplicationHandle *ch)
259{
260 if (NULL != ch->mq)
261 {
262 GNUNET_MQ_destroy (ch->mq);
263 ch->mq = NULL;
264 }
265 if (NULL != ch->task)
266 {
267 GNUNET_SCHEDULER_cancel (ch->task);
268 ch->task = NULL;
269 }
270 GNUNET_CONTAINER_multipeermap_iterate (ch->sug_requests,
271 &free_sug_handle,
272 NULL);
273 GNUNET_CONTAINER_multipeermap_destroy (ch->sug_requests);
274 GNUNET_free (ch);
275}
276
277
278/**
279 * An application would like TRANSPORT to connect to a peer.
280 *
281 * @param ch handle
282 * @param peer identity of the peer we need an address for
283 * @param pk what kind of application will the application require (can be
284 * #GNUNET_MQ_PRIO_BACKGROUND, we will still try to connect)
285 * @param bw desired bandwidth, can be zero (we will still try to connect)
286 * @return suggest handle, NULL if a request is already pending
287 */
288struct GNUNET_TRANSPORT_ApplicationSuggestHandle *
289GNUNET_TRANSPORT_application_suggest (
290 struct GNUNET_TRANSPORT_ApplicationHandle *ch,
291 const struct GNUNET_PeerIdentity *peer,
292 enum GNUNET_MQ_PriorityPreferences pk,
293 struct GNUNET_BANDWIDTH_Value32NBO bw)
294{
295 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *s;
296
297 s = GNUNET_new (struct GNUNET_TRANSPORT_ApplicationSuggestHandle);
298 s->ch = ch;
299 s->id = *peer;
300 s->pk = pk;
301 s->bw = bw;
302 (void) GNUNET_CONTAINER_multipeermap_put (
303 ch->sug_requests,
304 &s->id,
305 s,
306 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
307 LOG (GNUNET_ERROR_TYPE_DEBUG,
308 "Requesting TRANSPORT to suggest address for `%s'\n",
309 GNUNET_i2s (peer));
310 if (NULL == ch->mq)
311 return s;
312 GNUNET_assert (GNUNET_OK == transmit_suggestion (ch, &s->id, s));
313 return s;
314}
315
316
317/**
318 * We no longer care about being connected to a peer.
319 *
320 * @param sh handle to stop
321 */
322void
323GNUNET_TRANSPORT_application_suggest_cancel (
324 struct GNUNET_TRANSPORT_ApplicationSuggestHandle *sh)
325{
326 struct GNUNET_TRANSPORT_ApplicationHandle *ch = sh->ch;
327 struct GNUNET_MQ_Envelope *ev;
328 struct ExpressPreferenceMessage *m;
329
330 LOG (GNUNET_ERROR_TYPE_DEBUG,
331 "Telling TRANSPORT we no longer care for an address for `%s'\n",
332 GNUNET_i2s (&sh->id));
333 GNUNET_assert (
334 GNUNET_OK ==
335 GNUNET_CONTAINER_multipeermap_remove (ch->sug_requests, &sh->id, sh));
336 if (NULL == ch->mq)
337 {
338 GNUNET_free (sh);
339 return;
340 }
341 ev = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_TRANSPORT_SUGGEST_CANCEL);
342 m->pk = htonl ((uint32_t) sh->pk);
343 m->bw = sh->bw;
344 m->peer = sh->id;
345 GNUNET_MQ_send (ch->mq, ev);
346 GNUNET_free (sh);
347}
348
349
350/**
351 * An application (or a communicator) has received a HELLO (or other address
352 * data of another peer) and wants TRANSPORT to validate that the address is
353 * correct. The result is NOT returned, in fact TRANSPORT may do nothing
354 * (i.e. if it has too many active validations or recently tried this one
355 * already). If the @a addr validates, TRANSPORT will persist the address
356 * with PEERSTORE.
357 *
358 * @param ch handle
359 * @param peer identity of the peer we have an address for
360 * @param nt network type of @a addr (as claimed by the other peer);
361 * used by TRANSPORT to avoid trying @a addr's that really cannot work
362 * due to network type mismatches
363 * @param addr address to validate
364 */
365void
366GNUNET_TRANSPORT_application_validate (
367 struct GNUNET_TRANSPORT_ApplicationHandle *ch,
368 const struct GNUNET_PeerIdentity *peer,
369 enum GNUNET_NetworkType nt,
370 const char *addr)
371{
372 struct GNUNET_MQ_Envelope *ev;
373 struct RequestHelloValidationMessage *m;
374 size_t alen;
375
376 if (NULL == ch->mq)
377 {
378 GNUNET_log (
379 GNUNET_ERROR_TYPE_WARNING,
380 "Address validation for %s:%s skipped as transport is not connected\n",
381 GNUNET_i2s (peer),
382 addr);
383 return;
384 }
385 alen = strlen (addr) + 1;
386 ev =
387 GNUNET_MQ_msg_extra (m,
388 alen,
389 GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_HELLO_VALIDATION);
390 m->peer = *peer;
391 m->nt = htonl ((uint32_t) nt);
392 memcpy (&m[1], addr, alen);
393 GNUNET_MQ_send (ch->mq, ev);
394}
395
396
397/* end of transport_api2_application.c */