aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-01-27 01:08:10 +0100
committerChristian Grothoff <christian@grothoff.org>2019-01-27 01:08:10 +0100
commitb22c452796ec17a0d596dc2d2a2636ee00e12d68 (patch)
treea494b6182e452ff8ea8afcc044d8634fff8ea691 /src/cadet
parent3db0825fdc964032a7c6ee17ccb7dedbbcfb208b (diff)
downloadgnunet-b22c452796ec17a0d596dc2d2a2636ee00e12d68.tar.gz
gnunet-b22c452796ec17a0d596dc2d2a2636ee00e12d68.zip
more work on #5385
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/cadet_api_get_tunnel.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/src/cadet/cadet_api_get_tunnel.c b/src/cadet/cadet_api_get_tunnel.c
new file mode 100644
index 000000000..3b489dd82
--- /dev/null
+++ b/src/cadet/cadet_api_get_tunnel.c
@@ -0,0 +1,278 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 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 cadet/cadet_api_get_tunnel.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_cadet_service.h"
30#include "cadet.h"
31#include "cadet_protocol.h"
32
33
34/**
35 * Operation handle.
36 */
37struct GNUNET_CADET_GetTunnel
38{
39
40 /**
41 * Monitor callback
42 */
43 GNUNET_CADET_TunnelCB callback;
44
45 /**
46 * Closure for @e callback.
47 */
48 void *callback_cls;
49
50 /**
51 * Message queue to talk to CADET service.
52 */
53 struct GNUNET_MQ_Handle *mq;
54
55 /**
56 * Configuration we use.
57 */
58 const struct GNUNET_CONFIGURATION_Handle *cfg;
59
60 /**
61 * Task to reconnect.
62 */
63 struct GNUNET_SCHEDULER_Task *reconnect_task;
64
65 /**
66 * Backoff for reconnect attempts.
67 */
68 struct GNUNET_TIME_Relative backoff;
69
70 /**
71 * Peer we want information about.
72 */
73 struct GNUNET_PeerIdentity id;
74};
75
76
77
78/**
79 * Check that message received from CADET service is well-formed.
80 *
81 * @param cls the `struct GNUNET_CADET_Handle`
82 * @param msg the message we got
83 * @return #GNUNET_OK if the message is well-formed,
84 * #GNUNET_SYSERR otherwise
85 */
86static int
87check_get_tunnel (void *cls,
88 const struct GNUNET_CADET_LocalInfoTunnel *msg)
89{
90 unsigned int ch_n;
91 unsigned int c_n;
92 size_t esize;
93 size_t msize;
94
95 (void) cls;
96 /* Verify message sanity */
97 msize = ntohs (msg->header.size);
98 esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
99 if (esize > msize)
100 {
101 GNUNET_break (0);
102 return GNUNET_SYSERR;
103 }
104 ch_n = ntohl (msg->channels);
105 c_n = ntohl (msg->connections);
106 esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
107 esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
108 if (msize != esize)
109 {
110 GNUNET_break_op (0);
111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
112 "m:%u, e: %u (%u ch, %u conn)\n",
113 (unsigned int) msize,
114 (unsigned int) esize,
115 ch_n,
116 c_n);
117 return GNUNET_SYSERR;
118 }
119 return GNUNET_OK;
120}
121
122
123/**
124 * Process a local tunnel info reply, pass info to the user.
125 *
126 * @param cls a `struct GNUNET_CADET_GetTunnel *`
127 * @param msg Message itself.
128 */
129static void
130handle_get_tunnel (void *cls,
131 const struct GNUNET_CADET_LocalInfoTunnel *msg)
132{
133 struct GNUNET_CADET_GetTunnel *gt = cls;
134 unsigned int ch_n;
135 unsigned int c_n;
136 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
137 const struct GNUNET_CADET_ChannelTunnelNumber *chns;
138
139 ch_n = ntohl (msg->channels);
140 c_n = ntohl (msg->connections);
141
142 /* Call Callback with tunnel info. */
143 conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
144 chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
145 gt->callback (gt->callback_cls,
146 &msg->destination,
147 ch_n,
148 c_n,
149 chns,
150 conns,
151 ntohs (msg->estate),
152 ntohs (msg->cstate));
153}
154
155
156/**
157 * Reconnect to the service and try again.
158 *
159 * @param cls a `struct GNUNET_CADET_GetTunnel` operation
160 */
161static void
162reconnect (void *cls);
163
164
165/**
166 * Function called on connection trouble. Reconnects.
167 *
168 * @param cls a `struct GNUNET_CADET_GetTunnel`
169 * @param error error code from MQ
170 */
171static void
172error_handler (void *cls,
173 enum GNUNET_MQ_Error error)
174{
175 struct GNUNET_CADET_GetTunnel *gt = cls;
176
177 GNUNET_MQ_destroy (gt->mq);
178 gt->mq = NULL;
179 gt->backoff = GNUNET_TIME_randomized_backoff (gt->backoff,
180 GNUNET_TIME_UNIT_MINUTES);
181 gt->reconnect_task = GNUNET_SCHEDULER_add_delayed (gt->backoff,
182 &reconnect,
183 gt);
184}
185
186
187/**
188 * Reconnect to the service and try again.
189 *
190 * @param cls a `struct GNUNET_CADET_GetTunnel` operation
191 */
192static void
193reconnect (void *cls)
194{
195 struct GNUNET_CADET_GetTunnel *gt = cls;
196 struct GNUNET_MQ_MessageHandler handlers[] = {
197 GNUNET_MQ_hd_var_size (get_tunnel,
198 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
199 struct GNUNET_CADET_LocalInfoTunnel,
200 gt),
201 GNUNET_MQ_handler_end ()
202 };
203 struct GNUNET_MQ_Envelope *env;
204 struct GNUNET_CADET_LocalInfo *msg;
205
206 gt->reconnect_task = NULL;
207 gt->mq = GNUNET_CLIENT_connect (gt->cfg,
208 "cadet",
209 handlers,
210 &error_handler,
211 gt);
212 if (NULL == gt->mq)
213 return;
214 env = GNUNET_MQ_msg (msg,
215 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
216 msg->peer = gt->id;
217 GNUNET_MQ_send (gt->mq,
218 env);
219}
220
221/**
222 * Request information about a tunnel of the running cadet peer.
223 * The callback will be called for the tunnel once.
224 *
225 * @param cfg configuration to use
226 * @param id Peer whose tunnel to examine.
227 * @param callback Function to call with the requested data.
228 * @param callback_cls Closure for @c callback.
229 * @return NULL on error
230 */
231struct GNUNET_CADET_GetTunnel *
232GNUNET_CADET_get_tunnel (const struct GNUNET_CONFIGURATION_Handle *cfg,
233 const struct GNUNET_PeerIdentity *id,
234 GNUNET_CADET_TunnelCB callback,
235 void *callback_cls)
236{
237 struct GNUNET_CADET_GetTunnel *gt;
238
239 if (NULL == callback)
240 {
241 GNUNET_break (0);
242 return NULL;
243 }
244 gt = GNUNET_new (struct GNUNET_CADET_GetTunnel);
245 gt->callback = callback;
246 gt->callback_cls = callback_cls;
247 gt->cfg = cfg;
248 gt->id = *id;
249 reconnect (gt);
250 if (NULL == gt->mq)
251 {
252 GNUNET_free (gt);
253 return NULL;
254 }
255 return gt;
256}
257
258
259/**
260 * Cancel a monitor request. The monitor callback will not be called.
261 *
262 * @param lt operation handle
263 * @return Closure given to #GNUNET_CADET_get_tunnel(), if any.
264 */
265void *
266GNUNET_CADET_get_tunnel_cancel (struct GNUNET_CADET_GetTunnel *gt)
267{
268 void *ret = gt->callback_cls;
269
270 if (NULL != gt->mq)
271 GNUNET_MQ_destroy (gt->mq);
272 if (NULL != gt->reconnect_task)
273 GNUNET_SCHEDULER_cancel (gt->reconnect_task);
274 GNUNET_free (gt);
275 return ret;
276}
277
278/* end of cadet_api_get_tunnel.c */