diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-17 11:54:31 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-17 11:54:31 +0100 |
commit | 500842f42c4e51c4c5fc3c1cdfc1c1f7166b2d0d (patch) | |
tree | 9a80967af02b49319d0ab406b0ec9fa3d31e13fd /src/cadet/gnunet-service-cadet-new_connection.c | |
parent | d0bb14e2a958f4f816c6c006dd8b7a979e6de289 (diff) | |
download | gnunet-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.c | 327 |
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 | */ | ||
40 | enum 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 | */ |
38 | struct CadetConnection | 77 | struct 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 | |||
74 | int | 149 | int |
75 | GCC_is_ready (struct CadetConnection *cc) | 150 | GCC_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) | |||
87 | void | 163 | void |
88 | GCC_destroy (struct CadetConnection *cc) | 164 | GCC_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 | */ | ||
203 | static const struct GNUNET_HashCode * | ||
204 | h2hc (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 | */ | ||
226 | const struct GNUNET_HashCode * | ||
227 | GCC_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 | */ | ||
238 | void | ||
239 | GCC_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 | */ | ||
257 | static void | ||
258 | send_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 | */ | ||
267 | static void | ||
268 | transmit_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 | */ | ||
287 | static void | ||
288 | send_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 | */ | ||
324 | static void | ||
325 | manage_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 | */ |
107 | struct CadetConnection * | 362 | struct CadetConnection * |
108 | GCC_create (struct CadetPeer *destination, | 363 | GCC_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 | */ | ||
411 | static void | ||
412 | transmit_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 | */ |
147 | void | 432 | void |
148 | GCC_transmit (struct CadetConnection *cc, | 433 | GCC_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) | |||
174 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | 467 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
175 | GCC_get_id (struct CadetConnection *cc) | 468 | GCC_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 | |||
189 | GCC_debug (struct CadetConnection *cc, | 481 | GCC_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 */ | ||