diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-19 15:52:22 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-19 15:52:22 +0100 |
commit | bc43d8978d8695ff97cc67b65c29769e9c7f8f0e (patch) | |
tree | 94d1428dc2b4e70d87d6521b487a92c6fc139827 /src/cadet/gnunet-service-cadet-new_connection.c | |
parent | bd3147503e27ddefcb6ba0dcb99c2b32947622a4 (diff) | |
download | gnunet-bc43d8978d8695ff97cc67b65c29769e9c7f8f0e.tar.gz gnunet-bc43d8978d8695ff97cc67b65c29769e9c7f8f0e.zip |
much work on connection/route/peer-level queue management
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.c | 361 |
1 files changed, 221 insertions, 140 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c index 5123f9d45..bf88d78e1 100644 --- a/src/cadet/gnunet-service-cadet-new_connection.c +++ b/src/cadet/gnunet-service-cadet-new_connection.c | |||
@@ -27,11 +27,8 @@ | |||
27 | * @author Christian Grothoff | 27 | * @author Christian Grothoff |
28 | * | 28 | * |
29 | * TODO: | 29 | * TODO: |
30 | * - congestion control | ||
31 | * - GCC_debug() | ||
32 | * - keepalive messages | 30 | * - keepalive messages |
33 | * - performance metrics | 31 | * - keep performance metrics (?) |
34 | * - back-off reset | ||
35 | */ | 32 | */ |
36 | #include "platform.h" | 33 | #include "platform.h" |
37 | #include "gnunet-service-cadet-new_channel.h" | 34 | #include "gnunet-service-cadet-new_channel.h" |
@@ -64,19 +61,16 @@ enum CadetConnectionState | |||
64 | CADET_CONNECTION_SENT, | 61 | CADET_CONNECTION_SENT, |
65 | 62 | ||
66 | /** | 63 | /** |
67 | * Connection confirmed, ready to carry traffic. | 64 | * We are an inbound connection, and received a CREATE. Need to |
65 | * send an CREATE_ACK back. | ||
68 | */ | 66 | */ |
69 | CADET_CONNECTION_READY, | 67 | CADET_CONNECTION_CREATE_RECEIVED, |
70 | 68 | ||
71 | /** | 69 | /** |
72 | * Connection to be destroyed, just waiting to empty queues. | 70 | * Connection confirmed, ready to carry traffic. |
73 | */ | 71 | */ |
74 | CADET_CONNECTION_DESTROYED, | 72 | CADET_CONNECTION_READY |
75 | 73 | ||
76 | /** | ||
77 | * Connection to be destroyed because of a distant peer, same as DESTROYED. | ||
78 | */ | ||
79 | CADET_CONNECTION_BROKEN | ||
80 | }; | 74 | }; |
81 | 75 | ||
82 | 76 | ||
@@ -112,11 +106,6 @@ struct CadetConnection | |||
112 | struct GNUNET_MQ_Envelope *env; | 106 | struct GNUNET_MQ_Envelope *env; |
113 | 107 | ||
114 | /** | 108 | /** |
115 | * Message queue to the first hop, or NULL if we have no connection yet. | ||
116 | */ | ||
117 | struct GNUNET_MQ_Handle *mq; | ||
118 | |||
119 | /** | ||
120 | * Handle for calling #GCP_request_mq_cancel() once we are finished. | 109 | * Handle for calling #GCP_request_mq_cancel() once we are finished. |
121 | */ | 110 | */ |
122 | struct GCP_MessageQueueManager *mq_man; | 111 | struct GCP_MessageQueueManager *mq_man; |
@@ -129,7 +118,7 @@ struct CadetConnection | |||
129 | /** | 118 | /** |
130 | * Function to call once we are ready to transmit. | 119 | * Function to call once we are ready to transmit. |
131 | */ | 120 | */ |
132 | GNUNET_SCHEDULER_TaskCallback ready_cb; | 121 | GCC_ReadyCallback ready_cb; |
133 | 122 | ||
134 | /** | 123 | /** |
135 | * Closure for @e ready_cb. | 124 | * Closure for @e ready_cb. |
@@ -151,22 +140,12 @@ struct CadetConnection | |||
151 | */ | 140 | */ |
152 | unsigned int off; | 141 | unsigned int off; |
153 | 142 | ||
154 | }; | 143 | /** |
155 | 144 | * Are we ready to transmit via @e mq_man right now? | |
145 | */ | ||
146 | int mqm_ready; | ||
156 | 147 | ||
157 | /** | 148 | }; |
158 | * Is the given connection currently ready for transmission? | ||
159 | * | ||
160 | * @param cc connection to transmit on | ||
161 | * @return #GNUNET_YES if we could transmit | ||
162 | */ | ||
163 | int | ||
164 | GCC_is_ready (struct CadetConnection *cc) | ||
165 | { | ||
166 | return ( (NULL != cc->mq) && | ||
167 | (CADET_CONNECTION_READY == cc->state) && | ||
168 | (NULL == cc->env) ) ? GNUNET_YES : GNUNET_NO; | ||
169 | } | ||
170 | 149 | ||
171 | 150 | ||
172 | /** | 151 | /** |
@@ -177,29 +156,19 @@ GCC_is_ready (struct CadetConnection *cc) | |||
177 | void | 156 | void |
178 | GCC_destroy (struct CadetConnection *cc) | 157 | GCC_destroy (struct CadetConnection *cc) |
179 | { | 158 | { |
180 | if (NULL != cc->env) | 159 | struct GNUNET_MQ_Envelope *env = NULL; |
181 | { | 160 | |
182 | if (NULL != cc->mq) | 161 | if (CADET_CONNECTION_SENDING_CREATE != cc->state) |
183 | GNUNET_MQ_send_cancel (cc->env); | ||
184 | else | ||
185 | GNUNET_MQ_discard (cc->env); | ||
186 | cc->env = NULL; | ||
187 | } | ||
188 | if ( (NULL != cc->mq) && | ||
189 | (CADET_CONNECTION_SENDING_CREATE != cc->state) ) | ||
190 | { | 162 | { |
191 | /* Need to notify next hop that we are down. */ | ||
192 | struct GNUNET_MQ_Envelope *env; | ||
193 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | 163 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; |
194 | 164 | ||
165 | /* Need to notify next hop that we are down. */ | ||
195 | env = GNUNET_MQ_msg (destroy_msg, | 166 | env = GNUNET_MQ_msg (destroy_msg, |
196 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | 167 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); |
197 | destroy_msg->cid = cc->cid; | 168 | destroy_msg->cid = cc->cid; |
198 | GNUNET_MQ_send (cc->mq, | ||
199 | env); | ||
200 | } | 169 | } |
201 | cc->mq = NULL; | 170 | GCP_request_mq_cancel (cc->mq_man, |
202 | GCP_request_mq_cancel (cc->mq_man); | 171 | env); |
203 | cc->mq_man = NULL; | 172 | cc->mq_man = NULL; |
204 | GCPP_del_connection (cc->path, | 173 | GCPP_del_connection (cc->path, |
205 | cc->off, | 174 | cc->off, |
@@ -234,14 +203,20 @@ GCC_get_ct (struct CadetConnection *cc) | |||
234 | void | 203 | void |
235 | GCC_handle_connection_ack (struct CadetConnection *cc) | 204 | GCC_handle_connection_ack (struct CadetConnection *cc) |
236 | { | 205 | { |
237 | GNUNET_SCHEDULER_cancel (cc->task); | 206 | if (NULL != cc->task) |
238 | #if FIXME | 207 | { |
208 | GNUNET_SCHEDULER_cancel (cc->task); | ||
209 | cc->task = NULL; | ||
210 | } | ||
211 | #if FIXME_KEEPALIVE | ||
239 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period, | 212 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period, |
240 | &send_keepalive, | 213 | &send_keepalive, |
241 | cc); | 214 | cc); |
242 | #endif | 215 | #endif |
243 | cc->state = CADET_CONNECTION_READY; | 216 | cc->state = CADET_CONNECTION_READY; |
244 | cc->ready_cb (cc->ready_cb_cls); | 217 | if (GNUNET_YES == cc->mqm_ready) |
218 | cc->ready_cb (cc->ready_cb_cls, | ||
219 | GNUNET_YES); | ||
245 | } | 220 | } |
246 | 221 | ||
247 | 222 | ||
@@ -255,6 +230,12 @@ void | |||
255 | GCC_handle_kx (struct CadetConnection *cc, | 230 | GCC_handle_kx (struct CadetConnection *cc, |
256 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 231 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
257 | { | 232 | { |
233 | if (CADET_CONNECTION_SENT == cc->state) | ||
234 | { | ||
235 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
236 | clearly something is working, so pretend we got an ACK. */ | ||
237 | GCC_handle_connection_ack (cc); | ||
238 | } | ||
258 | GCT_handle_kx (cc->ct, | 239 | GCT_handle_kx (cc->ct, |
259 | msg); | 240 | msg); |
260 | } | 241 | } |
@@ -270,6 +251,12 @@ void | |||
270 | GCC_handle_encrypted (struct CadetConnection *cc, | 251 | GCC_handle_encrypted (struct CadetConnection *cc, |
271 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | 252 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) |
272 | { | 253 | { |
254 | if (CADET_CONNECTION_SENT == cc->state) | ||
255 | { | ||
256 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
257 | clearly something is working, so pretend we got an ACK. */ | ||
258 | GCC_handle_connection_ack (cc); | ||
259 | } | ||
273 | GCT_handle_encrypted (cc->ct, | 260 | GCT_handle_encrypted (cc->ct, |
274 | msg); | 261 | msg); |
275 | } | 262 | } |
@@ -281,37 +268,40 @@ GCC_handle_encrypted (struct CadetConnection *cc, | |||
281 | * @param cls the `struct CadetConnection` to initiate | 268 | * @param cls the `struct CadetConnection` to initiate |
282 | */ | 269 | */ |
283 | static void | 270 | static void |
284 | send_create (void *cls); | 271 | send_create (void *cls) |
285 | |||
286 | |||
287 | /** | ||
288 | * We finished transmission of the create message, now wait for | ||
289 | * ACK or retransmit. | ||
290 | * | ||
291 | * @param cls the `struct CadetConnection` that sent the create message | ||
292 | */ | ||
293 | static void | ||
294 | transmit_create_done_cb (void *cls) | ||
295 | { | 272 | { |
296 | struct CadetConnection *cc = cls; | 273 | struct CadetConnection *cc = cls; |
274 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
275 | struct GNUNET_PeerIdentity *pids; | ||
276 | struct GNUNET_MQ_Envelope *env; | ||
277 | unsigned int path_length; | ||
297 | 278 | ||
279 | cc->task = NULL; | ||
280 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
281 | path_length = GCPP_get_length (cc->path); | ||
282 | env = GNUNET_MQ_msg_extra (create_msg, | ||
283 | path_length * sizeof (struct GNUNET_PeerIdentity), | ||
284 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
285 | create_msg->cid = cc->cid; | ||
286 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
287 | for (unsigned int i=0;i<path_length;i++) | ||
288 | pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | ||
289 | i)); | ||
290 | cc->env = env; | ||
291 | cc->mqm_ready = GNUNET_NO; | ||
298 | cc->state = CADET_CONNECTION_SENT; | 292 | cc->state = CADET_CONNECTION_SENT; |
299 | cc->env = NULL; | 293 | GCP_send (cc->mq_man, |
300 | /* FIXME: at some point, we need to reset the delay back to 0! */ | 294 | env); |
301 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
302 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
303 | &send_create, | ||
304 | cc); | ||
305 | } | 295 | } |
306 | 296 | ||
307 | 297 | ||
308 | /** | 298 | /** |
309 | * Send a CREATE message to the first hop. | 299 | * Send a CREATE_ACK message towards the origin. |
310 | * | 300 | * |
311 | * @param cls the `struct CadetConnection` to initiate | 301 | * @param cls the `struct CadetConnection` to initiate |
312 | */ | 302 | */ |
313 | static void | 303 | static void |
314 | send_create (void *cls) | 304 | send_create_ack (void *cls) |
315 | { | 305 | { |
316 | struct CadetConnection *cc = cls; | 306 | struct CadetConnection *cc = cls; |
317 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | 307 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; |
@@ -320,7 +310,7 @@ send_create (void *cls) | |||
320 | unsigned int path_length; | 310 | unsigned int path_length; |
321 | 311 | ||
322 | cc->task = NULL; | 312 | cc->task = NULL; |
323 | GNUNET_assert (NULL != cc->mq); | 313 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
324 | path_length = GCPP_get_length (cc->path); | 314 | path_length = GCPP_get_length (cc->path); |
325 | env = GNUNET_MQ_msg_extra (create_msg, | 315 | env = GNUNET_MQ_msg_extra (create_msg, |
326 | path_length * sizeof (struct GNUNET_PeerIdentity), | 316 | path_length * sizeof (struct GNUNET_PeerIdentity), |
@@ -331,11 +321,42 @@ send_create (void *cls) | |||
331 | pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | 321 | pids[i] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, |
332 | i)); | 322 | i)); |
333 | cc->env = env; | 323 | cc->env = env; |
334 | GNUNET_MQ_notify_sent (env, | 324 | cc->mqm_ready = GNUNET_NO; |
335 | &transmit_create_done_cb, | 325 | cc->state = CADET_CONNECTION_READY; |
336 | cc); | 326 | GCP_send (cc->mq_man, |
337 | GNUNET_MQ_send (cc->mq, | 327 | env); |
338 | env); | 328 | } |
329 | |||
330 | |||
331 | /** | ||
332 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
333 | * connection that we already have. Either our ACK got lost | ||
334 | * or something is fishy. Consider retransmitting the ACK. | ||
335 | * | ||
336 | * @param cc connection that got the duplicate CREATE | ||
337 | */ | ||
338 | void | ||
339 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
340 | { | ||
341 | if (GNUNET_YES == cc->mqm_ready) | ||
342 | { | ||
343 | /* Tell tunnel that we are not ready for transmission anymore | ||
344 | (until CREATE_ACK is done) */ | ||
345 | cc->ready_cb (cc->ready_cb_cls, | ||
346 | GNUNET_NO); | ||
347 | |||
348 | /* Revert back to the state of having only received the 'CREATE', | ||
349 | and immediately proceed to send the CREATE_ACK. */ | ||
350 | cc->state = CADET_CONNECTION_CREATE_RECEIVED; | ||
351 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
352 | cc); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | /* We are currently sending something else back, which | ||
357 | can only be an ACK or payload, either of which would | ||
358 | do. So actually no need to do anything. */ | ||
359 | } | ||
339 | } | 360 | } |
340 | 361 | ||
341 | 362 | ||
@@ -344,34 +365,62 @@ send_create (void *cls) | |||
344 | * peer at the first hop. Adjust accordingly. | 365 | * peer at the first hop. Adjust accordingly. |
345 | * | 366 | * |
346 | * @param cls the `struct CadetConnection` | 367 | * @param cls the `struct CadetConnection` |
347 | * @param mq NULL if the CORE connection was lost, non-NULL if | 368 | * @param available #GNUNET_YES if sending is now possible, |
348 | * it became available | 369 | * #GNUNET_NO if sending is no longer possible |
370 | * #GNUNET_SYSERR if sending is no longer possible | ||
371 | * and the last envelope was discarded | ||
349 | */ | 372 | */ |
350 | static void | 373 | static void |
351 | manage_first_hop_mq (void *cls, | 374 | manage_first_hop_mq (void *cls, |
352 | struct GNUNET_MQ_Handle *mq) | 375 | int available) |
353 | { | 376 | { |
354 | struct CadetConnection *cc = cls; | 377 | struct CadetConnection *cc = cls; |
355 | 378 | ||
356 | if (NULL == mq) | 379 | if (GNUNET_YES != available) |
357 | { | 380 | { |
358 | /* Connection is down, for now... */ | 381 | /* Connection is down, for now... */ |
359 | cc->mq = NULL; | 382 | cc->mqm_ready = GNUNET_NO; |
383 | cc->state = CADET_CONNECTION_NEW; | ||
384 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
360 | if (NULL != cc->task) | 385 | if (NULL != cc->task) |
361 | { | 386 | { |
362 | GNUNET_SCHEDULER_cancel (cc->task); | 387 | GNUNET_SCHEDULER_cancel (cc->task); |
363 | cc->task = NULL; | 388 | cc->task = NULL; |
364 | } | 389 | } |
390 | cc->ready_cb (cc->ready_cb_cls, | ||
391 | GNUNET_NO); | ||
365 | return; | 392 | return; |
366 | } | 393 | } |
367 | 394 | ||
368 | cc->mq = mq; | 395 | cc->mqm_ready = GNUNET_YES; |
369 | cc->state = CADET_CONNECTION_SENDING_CREATE; | 396 | switch (cc->state) |
370 | 397 | { | |
371 | /* Now repeat sending connection creation messages | 398 | case CADET_CONNECTION_NEW: |
372 | down the path, until we get an ACK! */ | 399 | /* Transmit immediately */ |
373 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | 400 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, |
374 | cc); | 401 | cc); |
402 | break; | ||
403 | case CADET_CONNECTION_SENDING_CREATE: | ||
404 | /* Should not be possible to be called in this state. */ | ||
405 | GNUNET_assert (0); | ||
406 | break; | ||
407 | case CADET_CONNECTION_SENT: | ||
408 | /* Retry a bit later... */ | ||
409 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
410 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
411 | &send_create, | ||
412 | cc); | ||
413 | break; | ||
414 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
415 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
416 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
417 | cc); | ||
418 | break; | ||
419 | case CADET_CONNECTION_READY: | ||
420 | cc->ready_cb (cc->ready_cb_cls, | ||
421 | GNUNET_YES); | ||
422 | break; | ||
423 | } | ||
375 | } | 424 | } |
376 | 425 | ||
377 | 426 | ||
@@ -383,6 +432,7 @@ manage_first_hop_mq (void *cls, | |||
383 | * @param destination where to go | 432 | * @param destination where to go |
384 | * @param path which path to take (may not be the full path) | 433 | * @param path which path to take (may not be the full path) |
385 | * @param ct which tunnel uses this connection | 434 | * @param ct which tunnel uses this connection |
435 | * @param init_state initial state for the connection | ||
386 | * @param ready_cb function to call when ready to transmit | 436 | * @param ready_cb function to call when ready to transmit |
387 | * @param ready_cb_cls closure for @a cb | 437 | * @param ready_cb_cls closure for @a cb |
388 | * @return handle to the connection | 438 | * @return handle to the connection |
@@ -392,7 +442,8 @@ connection_create (struct CadetPeer *destination, | |||
392 | struct CadetPeerPath *path, | 442 | struct CadetPeerPath *path, |
393 | struct CadetTConnection *ct, | 443 | struct CadetTConnection *ct, |
394 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | 444 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
395 | GNUNET_SCHEDULER_TaskCallback ready_cb, | 445 | enum CadetConnectionState init_state, |
446 | GCC_ReadyCallback ready_cb, | ||
396 | void *ready_cb_cls) | 447 | void *ready_cb_cls) |
397 | { | 448 | { |
398 | struct CadetConnection *cc; | 449 | struct CadetConnection *cc; |
@@ -403,6 +454,7 @@ connection_create (struct CadetPeer *destination, | |||
403 | destination); | 454 | destination); |
404 | GNUNET_assert (UINT_MAX > off); | 455 | GNUNET_assert (UINT_MAX > off); |
405 | cc = GNUNET_new (struct CadetConnection); | 456 | cc = GNUNET_new (struct CadetConnection); |
457 | cc->state = init_state; | ||
406 | cc->ct = ct; | 458 | cc->ct = ct; |
407 | cc->cid = *cid; | 459 | cc->cid = *cid; |
408 | GNUNET_assert (GNUNET_OK == | 460 | GNUNET_assert (GNUNET_OK == |
@@ -448,19 +500,16 @@ GCC_create_inbound (struct CadetPeer *destination, | |||
448 | struct CadetPeerPath *path, | 500 | struct CadetPeerPath *path, |
449 | struct CadetTConnection *ct, | 501 | struct CadetTConnection *ct, |
450 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | 502 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
451 | GNUNET_SCHEDULER_TaskCallback ready_cb, | 503 | GCC_ReadyCallback ready_cb, |
452 | void *ready_cb_cls) | 504 | void *ready_cb_cls) |
453 | { | 505 | { |
454 | struct CadetConnection *cc; | 506 | return connection_create (destination, |
455 | 507 | path, | |
456 | cc = connection_create (destination, | 508 | ct, |
457 | path, | 509 | cid, |
458 | ct, | 510 | CADET_CONNECTION_CREATE_RECEIVED, |
459 | cid, | 511 | ready_cb, |
460 | ready_cb, | 512 | ready_cb_cls); |
461 | ready_cb_cls); | ||
462 | /* FIXME: send CREATE_ACK? */ | ||
463 | return cc; | ||
464 | } | 513 | } |
465 | 514 | ||
466 | 515 | ||
@@ -479,41 +528,21 @@ struct CadetConnection * | |||
479 | GCC_create (struct CadetPeer *destination, | 528 | GCC_create (struct CadetPeer *destination, |
480 | struct CadetPeerPath *path, | 529 | struct CadetPeerPath *path, |
481 | struct CadetTConnection *ct, | 530 | struct CadetTConnection *ct, |
482 | GNUNET_SCHEDULER_TaskCallback ready_cb, | 531 | GCC_ReadyCallback ready_cb, |
483 | void *ready_cb_cls) | 532 | void *ready_cb_cls) |
484 | { | 533 | { |
485 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | 534 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
486 | struct CadetConnection *cc; | ||
487 | 535 | ||
488 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | 536 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, |
489 | &cid, | 537 | &cid, |
490 | sizeof (cid)); | 538 | sizeof (cid)); |
491 | cc = connection_create (destination, | 539 | return connection_create (destination, |
492 | path, | 540 | path, |
493 | ct, | 541 | ct, |
494 | &cid, | 542 | &cid, |
495 | ready_cb, | 543 | CADET_CONNECTION_NEW, |
496 | ready_cb_cls); | 544 | ready_cb, |
497 | /* FIXME: send CREATE? */ | 545 | ready_cb_cls); |
498 | return cc; | ||
499 | } | ||
500 | |||
501 | |||
502 | /** | ||
503 | * We finished transmission of a message, if we are still ready, tell | ||
504 | * the tunnel! | ||
505 | * | ||
506 | * @param cls our `struct CadetConnection` | ||
507 | */ | ||
508 | static void | ||
509 | transmit_done_cb (void *cls) | ||
510 | { | ||
511 | struct CadetConnection *cc = cls; | ||
512 | |||
513 | cc->env = NULL; | ||
514 | if ( (NULL != cc->mq) && | ||
515 | (CADET_CONNECTION_READY == cc->state) ) | ||
516 | cc->ready_cb (cc->ready_cb_cls); | ||
517 | } | 546 | } |
518 | 547 | ||
519 | 548 | ||
@@ -524,21 +553,18 @@ transmit_done_cb (void *cls) | |||
524 | * connection is right now ready for transmission. | 553 | * connection is right now ready for transmission. |
525 | * | 554 | * |
526 | * @param cc connection identification | 555 | * @param cc connection identification |
527 | * @param env envelope with message to transmit | 556 | * @param env envelope with message to transmit; must NOT |
557 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
528 | */ | 558 | */ |
529 | void | 559 | void |
530 | GCC_transmit (struct CadetConnection *cc, | 560 | GCC_transmit (struct CadetConnection *cc, |
531 | struct GNUNET_MQ_Envelope *env) | 561 | struct GNUNET_MQ_Envelope *env) |
532 | { | 562 | { |
533 | GNUNET_assert (NULL == cc->env); | 563 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
534 | cc->env = env; | 564 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); |
535 | GNUNET_MQ_notify_sent (env, | 565 | cc->mqm_ready = GNUNET_NO; |
536 | &transmit_done_cb, | 566 | GCP_send (cc->mq_man, |
537 | cc); | 567 | env); |
538 | if ( (NULL != cc->mq) && | ||
539 | (CADET_CONNECTION_READY == cc->state) ) | ||
540 | GNUNET_MQ_send (cc->mq, | ||
541 | env); | ||
542 | } | 568 | } |
543 | 569 | ||
544 | 570 | ||
@@ -569,6 +595,39 @@ GCC_get_id (struct CadetConnection *cc) | |||
569 | 595 | ||
570 | 596 | ||
571 | /** | 597 | /** |
598 | * Get a (static) string for a connection. | ||
599 | * | ||
600 | * @param cc Connection. | ||
601 | */ | ||
602 | const char * | ||
603 | GCC_2s (const struct CadetConnection *cc) | ||
604 | { | ||
605 | static char buf[128]; | ||
606 | |||
607 | if (NULL == cc) | ||
608 | return "Connection(NULL)"; | ||
609 | |||
610 | if (NULL != cc->ct) | ||
611 | { | ||
612 | GNUNET_snprintf (buf, | ||
613 | sizeof (buf), | ||
614 | "Connection(%s(Tunnel(%s)))", | ||
615 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
616 | GCT_2s (cc->ct->t)); | ||
617 | return buf; | ||
618 | } | ||
619 | GNUNET_snprintf (buf, | ||
620 | sizeof (buf), | ||
621 | "Connection(%s(Tunnel(NULL)))", | ||
622 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
623 | return buf; | ||
624 | } | ||
625 | |||
626 | |||
627 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
628 | |||
629 | |||
630 | /** | ||
572 | * Log connection info. | 631 | * Log connection info. |
573 | * | 632 | * |
574 | * @param cc connection | 633 | * @param cc connection |
@@ -578,7 +637,29 @@ void | |||
578 | GCC_debug (struct CadetConnection *cc, | 637 | GCC_debug (struct CadetConnection *cc, |
579 | enum GNUNET_ErrorType level) | 638 | enum GNUNET_ErrorType level) |
580 | { | 639 | { |
581 | GNUNET_break (0); // FIXME: implement... | 640 | int do_log; |
641 | char *s; | ||
642 | |||
643 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
644 | "cadet-con", | ||
645 | __FILE__, __FUNCTION__, __LINE__); | ||
646 | if (0 == do_log) | ||
647 | return; | ||
648 | if (NULL == cc) | ||
649 | { | ||
650 | LOG2 (level, | ||
651 | "Connection (NULL)\n"); | ||
652 | return; | ||
653 | } | ||
654 | s = GCPP_2s (cc->path); | ||
655 | LOG2 (level, | ||
656 | "Connection %s to %s via path %s in state %d is %s\n", | ||
657 | GCC_2s (cc), | ||
658 | GCP_2s (cc->destination), | ||
659 | s, | ||
660 | cc->state, | ||
661 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
662 | GNUNET_free (s); | ||
582 | } | 663 | } |
583 | 664 | ||
584 | /* end of gnunet-service-cadet-new_connection.c */ | 665 | /* end of gnunet-service-cadet-new_connection.c */ |