aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet-new_connection.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-17 11:54:31 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-17 11:54:31 +0100
commit500842f42c4e51c4c5fc3c1cdfc1c1f7166b2d0d (patch)
tree9a80967af02b49319d0ab406b0ec9fa3d31e13fd /src/cadet/gnunet-service-cadet-new_connection.c
parentd0bb14e2a958f4f816c6c006dd8b7a979e6de289 (diff)
downloadgnunet-500842f42c4e51c4c5fc3c1cdfc1c1f7166b2d0d.tar.gz
gnunet-500842f42c4e51c4c5fc3c1cdfc1c1f7166b2d0d.zip
more work on new CADET
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_connection.c')
-rw-r--r--src/cadet/gnunet-service-cadet-new_connection.c327
1 files changed, 311 insertions, 16 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c
index ea0b2c6e5..1f31331a5 100644
--- a/src/cadet/gnunet-service-cadet-new_connection.c
+++ b/src/cadet/gnunet-service-cadet-new_connection.c
@@ -30,6 +30,45 @@
30#include "gnunet-service-cadet-new_paths.h" 30#include "gnunet-service-cadet-new_paths.h"
31#include "gnunet-service-cadet-new_peer.h" 31#include "gnunet-service-cadet-new_peer.h"
32#include "gnunet-service-cadet-new_connection.h" 32#include "gnunet-service-cadet-new_connection.h"
33#include "gnunet_cadet_service.h"
34#include "cadet_protocol.h"
35
36
37/**
38 * All the states a connection can be in.
39 */
40enum CadetConnectionState
41{
42 /**
43 * Uninitialized status, we have not yet even gotten the message queue.
44 */
45 CADET_CONNECTION_NEW,
46
47 /**
48 * Connection create message in queue, awaiting transmission by CORE.
49 */
50 CADET_CONNECTION_SENDING_CREATE,
51
52 /**
53 * Connection create message sent, waiting for ACK.
54 */
55 CADET_CONNECTION_SENT,
56
57 /**
58 * Connection confirmed, ready to carry traffic.
59 */
60 CADET_CONNECTION_READY,
61
62 /**
63 * Connection to be destroyed, just waiting to empty queues.
64 */
65 CADET_CONNECTION_DESTROYED,
66
67 /**
68 * Connection to be destroyed because of a distant peer, same as DESTROYED.
69 */
70 CADET_CONNECTION_BROKEN
71};
33 72
34 73
35/** 74/**
@@ -37,6 +76,12 @@
37 */ 76 */
38struct CadetConnection 77struct CadetConnection
39{ 78{
79
80 /**
81 * ID of the connection.
82 */
83 struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
84
40 /** 85 /**
41 * To which peer does this connection go? 86 * To which peer does this connection go?
42 */ 87 */
@@ -48,6 +93,26 @@ struct CadetConnection
48 struct CadetPeerPath *path; 93 struct CadetPeerPath *path;
49 94
50 /** 95 /**
96 * Pending message, NULL if we are ready to transmit.
97 */
98 struct GNUNET_MQ_Envelope *env;
99
100 /**
101 * Message queue to the first hop, or NULL if we have no connection yet.
102 */
103 struct GNUNET_MQ_Handle *mq;
104
105 /**
106 * Handle for calling #GCP_request_mq_cancel() once we are finished.
107 */
108 struct GCP_MessageQueueManager *mq_man;
109
110 /**
111 * Task for connection maintenance.
112 */
113 struct GNUNET_SCHEDULER_Task *task;
114
115 /**
51 * Function to call once we are ready to transmit. 116 * Function to call once we are ready to transmit.
52 */ 117 */
53 GNUNET_SCHEDULER_TaskCallback ready_cb; 118 GNUNET_SCHEDULER_TaskCallback ready_cb;
@@ -58,6 +123,16 @@ struct CadetConnection
58 void *ready_cb_cls; 123 void *ready_cb_cls;
59 124
60 /** 125 /**
126 * How long do we wait before we try again with a CREATE message?
127 */
128 struct GNUNET_TIME_Relative retry_delay;
129
130 /**
131 * State of the connection.
132 */
133 enum CadetConnectionState state;
134
135 /**
61 * Offset of our @e destination in @e path. 136 * Offset of our @e destination in @e path.
62 */ 137 */
63 unsigned int off; 138 unsigned int off;
@@ -74,8 +149,9 @@ struct CadetConnection
74int 149int
75GCC_is_ready (struct CadetConnection *cc) 150GCC_is_ready (struct CadetConnection *cc)
76{ 151{
77 GNUNET_break (0); 152 return ( (NULL != cc->mq) &&
78 return GNUNET_NO; 153 (CADET_CONNECTION_READY == cc->state) &&
154 (NULL == cc->env) ) ? GNUNET_YES : GNUNET_NO;
79} 155}
80 156
81 157
@@ -87,15 +163,193 @@ GCC_is_ready (struct CadetConnection *cc)
87void 163void
88GCC_destroy (struct CadetConnection *cc) 164GCC_destroy (struct CadetConnection *cc)
89{ 165{
166 if (NULL != cc->env)
167 {
168 if (NULL != cc->mq)
169 GNUNET_MQ_send_cancel (cc->env);
170 else
171 GNUNET_MQ_discard (cc->env);
172 cc->env = NULL;
173 }
174 if ( (NULL != cc->mq) &&
175 (CADET_CONNECTION_SENDING_CREATE != cc->state) )
176 {
177 /* Need to notify next hop that we are down. */
178 struct GNUNET_MQ_Envelope *env;
179 struct GNUNET_CADET_ConnectionDestroy *destroy_msg;
180
181 env = GNUNET_MQ_msg (destroy_msg,
182 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
183 destroy_msg->cid = cc->cid;
184 GNUNET_MQ_send (cc->mq,
185 env);
186 }
187 cc->mq = NULL;
188 GCP_request_mq_cancel (cc->mq_man);
189 cc->mq_man = NULL;
90 GCPP_del_connection (cc->path, 190 GCPP_del_connection (cc->path,
91 cc->off, 191 cc->off,
92 cc); 192 cc);
93 GNUNET_assert (0); // FIXME: incomplete implementation!
94 GNUNET_free (cc); 193 GNUNET_free (cc);
95} 194}
96 195
97 196
98/** 197/**
198 * Expand the shorter CADET hash to a full GNUnet hash.
199 *
200 * @param id hash to expand
201 * @return expanded hash
202 */
203static const struct GNUNET_HashCode *
204h2hc (const struct GNUNET_CADET_Hash *id)
205{
206 static struct GNUNET_HashCode hc;
207 char *ptr = (char *) &hc;
208
209 GNUNET_assert (sizeof (hc) == 2 * sizeof (*id));
210 GNUNET_memcpy (ptr,
211 id,
212 sizeof (*id));
213 GNUNET_memcpy (&ptr[sizeof (*id)],
214 id,
215 sizeof (*id));
216 return &hc;
217}
218
219
220/**
221 * Get the connection ID as a full hash.
222 *
223 * @param cc Connection to get the ID from.
224 * @return full hash ID of the connection.
225 */
226const struct GNUNET_HashCode *
227GCC_get_h (const struct CadetConnection *cc)
228{
229 return h2hc (&cc->cid.connection_of_tunnel);
230}
231
232
233/**
234 * An ACK was received for this connection, process it.
235 *
236 * @param cc the connection that got the ACK.
237 */
238void
239GCC_handle_ack (struct CadetConnection *cc)
240{
241 GNUNET_SCHEDULER_cancel (cc->task);
242#if FIXME
243 cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period,
244 &send_keepalive,
245 cc);
246#endif
247 cc->state = CADET_CONNECTION_READY;
248 cc->ready_cb (cc->ready_cb_cls);
249}
250
251
252/**
253 * Send a CREATE message to the first hop.
254 *
255 * @param cls the `struct CadetConnection` to initiate
256 */
257static void
258send_create (void *cls);
259
260
261/**
262 * We finished transmission of the create message, now wait for
263 * ACK or retransmit.
264 *
265 * @param cls the `struct CadetConnection` that sent the create message
266 */
267static void
268transmit_create_done_cb (void *cls)
269{
270 struct CadetConnection *cc = cls;
271
272 cc->state = CADET_CONNECTION_SENT;
273 cc->env = NULL;
274 /* FIXME: at some point, we need to reset the delay back to 0! */
275 cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay);
276 cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay,
277 &send_create,
278 cc);
279}
280
281
282/**
283 * Send a CREATE message to the first hop.
284 *
285 * @param cls the `struct CadetConnection` to initiate
286 */
287static void
288send_create (void *cls)
289{
290 struct CadetConnection *cc = cls;
291 struct GNUNET_CADET_ConnectionCreate *create_msg;
292 struct GNUNET_PeerIdentity *pids;
293 struct GNUNET_MQ_Envelope *env;
294 unsigned int path_length;
295
296 cc->task = NULL;
297 GNUNET_assert (NULL != cc->mq);
298 path_length = GCPP_get_length (cc->path);
299 env = GNUNET_MQ_msg_extra (create_msg,
300 path_length * sizeof (struct GNUNET_PeerIdentity),
301 GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
302 create_msg->cid = cc->cid;
303 pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
304 for (unsigned int i=0;i<path_length;i++)
305 pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path,
306 i));
307 cc->env = env;
308 GNUNET_MQ_notify_sent (env,
309 &transmit_create_done_cb,
310 cc);
311 GNUNET_MQ_send (cc->mq,
312 env);
313}
314
315
316/**
317 * There has been a change in the message queue existence for our
318 * peer at the first hop. Adjust accordingly.
319 *
320 * @param cls the `struct CadetConnection`
321 * @param mq NULL if the CORE connection was lost, non-NULL if
322 * it became available
323 */
324static void
325manage_first_hop_mq (void *cls,
326 struct GNUNET_MQ_Handle *mq)
327{
328 struct CadetConnection *cc = cls;
329
330 if (NULL == mq)
331 {
332 /* Connection is down, for now... */
333 cc->mq = NULL;
334 if (NULL != cc->task)
335 {
336 GNUNET_SCHEDULER_cancel (cc->task);
337 cc->task = NULL;
338 }
339 return;
340 }
341
342 cc->mq = mq;
343 cc->state = CADET_CONNECTION_SENDING_CREATE;
344
345 /* Now repeat sending connection creation messages
346 down the path, until we get an ACK! */
347 cc->task = GNUNET_SCHEDULER_add_now (&send_create,
348 cc);
349}
350
351
352/**
99 * Create a connection to @a destination via @a path and 353 * Create a connection to @a destination via @a path and
100 * notify @a cb whenever we are ready for more data. 354 * notify @a cb whenever we are ready for more data.
101 * 355 *
@@ -103,6 +357,7 @@ GCC_destroy (struct CadetConnection *cc)
103 * @param path which path to take (may not be the full path) 357 * @param path which path to take (may not be the full path)
104 * @param ready_cb function to call when ready to transmit 358 * @param ready_cb function to call when ready to transmit
105 * @param ready_cb_cls closure for @a cb 359 * @param ready_cb_cls closure for @a cb
360 * @return handle to the connection
106 */ 361 */
107struct CadetConnection * 362struct CadetConnection *
108GCC_create (struct CadetPeer *destination, 363GCC_create (struct CadetPeer *destination,
@@ -111,44 +366,82 @@ GCC_create (struct CadetPeer *destination,
111 void *ready_cb_cls) 366 void *ready_cb_cls)
112{ 367{
113 struct CadetConnection *cc; 368 struct CadetConnection *cc;
369 struct CadetPeer *first_hop;
114 unsigned int off; 370 unsigned int off;
115 371
116 off = GCPP_find_peer (path, 372 off = GCPP_find_peer (path,
117 destination); 373 destination);
118 GNUNET_assert (UINT_MAX > off); 374 GNUNET_assert (UINT_MAX > off);
119
120 GNUNET_assert (0); // fIXME: unfinished
121
122 cc = GNUNET_new (struct CadetConnection); 375 cc = GNUNET_new (struct CadetConnection);
376 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
377 &cc->cid,
378 sizeof (cc->cid));
379 GNUNET_assert (GNUNET_OK ==
380 GNUNET_CONTAINER_multihashmap_put (connections,
381 GCC_get_h (cc),
382 cc,
383 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
384 cc->ready_cb = ready_cb;
385 cc->ready_cb_cls = ready_cb_cls;
123 cc->path = path; 386 cc->path = path;
124 cc->off = off; 387 cc->off = off;
125 GCPP_add_connection (path, 388 GCPP_add_connection (path,
126 off, 389 off,
127 cc); 390 cc);
128 for (unsigned int i=0;i<off;i++) 391 for (unsigned int i=0;i<off;i++)
129 { 392 GCP_add_connection (GCPP_get_peer_at_offset (path,
130 // FIXME: remember existence of this connection with 393 off),
131 // ALL peers on the path! 394 cc);
132 // (and remove on destruction of connection!) 395
133 } 396 first_hop = GCPP_get_peer_at_offset (path,
397 0);
398 cc->mq_man = GCP_request_mq (first_hop,
399 &manage_first_hop_mq,
400 cc);
134 return cc; 401 return cc;
135} 402}
136 403
137 404
138/** 405/**
406 * We finished transmission of a message, if we are still ready, tell
407 * the tunnel!
408 *
409 * @param cls our `struct CadetConnection`
410 */
411static void
412transmit_done_cb (void *cls)
413{
414 struct CadetConnection *cc = cls;
415
416 cc->env = NULL;
417 if ( (NULL != cc->mq) &&
418 (CADET_CONNECTION_READY == cc->state) )
419 cc->ready_cb (cc->ready_cb_cls);
420}
421
422
423/**
139 * Transmit message @a msg via connection @a cc. Must only be called 424 * Transmit message @a msg via connection @a cc. Must only be called
140 * (once) after the connection has signalled that it is ready via the 425 * (once) after the connection has signalled that it is ready via the
141 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the 426 * `ready_cb`. Clients can also use #GCC_is_ready() to check if the
142 * connection is right now ready for transmission. 427 * connection is right now ready for transmission.
143 * 428 *
144 * @param cc connection identification 429 * @param cc connection identification
145 * @param msg message to transmit 430 * @param env envelope with message to transmit
146 */ 431 */
147void 432void
148GCC_transmit (struct CadetConnection *cc, 433GCC_transmit (struct CadetConnection *cc,
149 const struct GNUNET_MessageHeader *msg) 434 struct GNUNET_MQ_Envelope *env)
150{ 435{
151 GNUNET_assert (0); // FIXME 436 GNUNET_assert (NULL == cc->env);
437 cc->env = env;
438 GNUNET_MQ_notify_sent (env,
439 &transmit_done_cb,
440 cc);
441 if ( (NULL != cc->mq) &&
442 (CADET_CONNECTION_READY == cc->state) )
443 GNUNET_MQ_send (cc->mq,
444 env);
152} 445}
153 446
154 447
@@ -174,8 +467,7 @@ GCC_get_path (struct CadetConnection *cc)
174const struct GNUNET_CADET_ConnectionTunnelIdentifier * 467const struct GNUNET_CADET_ConnectionTunnelIdentifier *
175GCC_get_id (struct CadetConnection *cc) 468GCC_get_id (struct CadetConnection *cc)
176{ 469{
177 GNUNET_assert (0); // FIXME 470 return &cc->cid;
178 return NULL;
179} 471}
180 472
181 473
@@ -189,4 +481,7 @@ void
189GCC_debug (struct CadetConnection *cc, 481GCC_debug (struct CadetConnection *cc,
190 enum GNUNET_ErrorType level) 482 enum GNUNET_ErrorType level)
191{ 483{
484 GNUNET_break (0); // FIXME: implement...
192} 485}
486
487/* end of gnunet-service-cadet-new_connection.c */