aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-07-14 23:34:21 +0000
committerChristian Grothoff <christian@grothoff.org>2015-07-14 23:34:21 +0000
commite8671499d403467d09d5d28dc5deb4962e391c1f (patch)
tree27b3a7d12a06b10fb0ccecd56912ae189f4993c7 /src
parent99eb14783e48a602085e0d5197bc01ab68633638 (diff)
downloadgnunet-e8671499d403467d09d5d28dc5deb4962e391c1f.tar.gz
gnunet-e8671499d403467d09d5d28dc5deb4962e391c1f.zip
this should fix #3846
Diffstat (limited to 'src')
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c167
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c28
2 files changed, 128 insertions, 67 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c
index 7970b3c86..8cce9eae4 100644
--- a/src/cadet/gnunet-service-cadet_connection.c
+++ b/src/cadet/gnunet-service-cadet_connection.c
@@ -33,6 +33,12 @@
33#include "gnunet-service-cadet_tunnel.h" 33#include "gnunet-service-cadet_tunnel.h"
34 34
35 35
36/**
37 * Should we run somewhat expensive checks on our invariants?
38 */
39#define CHECK_INVARIANTS 0
40
41
36#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__) 42#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
37#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) 43#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
38 44
@@ -198,12 +204,12 @@ struct CadetConnection
198 struct CadetPeerQueue *maintenance_q; 204 struct CadetPeerQueue *maintenance_q;
199 205
200 /** 206 /**
201 * Should equal #get_next_hop(). 207 * Should equal #get_next_hop(), or NULL if that peer disconnected.
202 */ 208 */
203 struct CadetPeer *next_peer; 209 struct CadetPeer *next_peer;
204 210
205 /** 211 /**
206 * Should equal #get_prev_hop(). 212 * Should equal #get_prev_hop(), or NULL if that peer disconnected.
207 */ 213 */
208 struct CadetPeer *prev_peer; 214 struct CadetPeer *prev_peer;
209 215
@@ -231,6 +237,17 @@ struct CadetConnection
231 int destroy; 237 int destroy;
232 238
233 /** 239 /**
240 * In-connection-map flag. Sometimes, when @e destroy is set but
241 * actual destruction is delayed to enable us to finish processing
242 * queues (i.e. in the direction that is still working), we remove
243 * the connection from the map to prevent it from still being
244 * found (and used) by accident. This flag is set to #GNUNET_YES
245 * for a connection that is not in the #connections map. Should
246 * only be #GNUNET_YES if #destroy is also non-zero.
247 */
248 int was_removed;
249
250 /**
234 * Counter to do exponential backoff when creating a connection (max 64). 251 * Counter to do exponential backoff when creating a connection (max 64).
235 */ 252 */
236 unsigned short create_retry; 253 unsigned short create_retry;
@@ -588,7 +605,6 @@ send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force)
588 * @param fwd Was this a FWD going message? 605 * @param fwd Was this a FWD going message?
589 * @param size Size of the message. 606 * @param size Size of the message.
590 * @param wait Time spent waiting for core (only the time for THIS message) 607 * @param wait Time spent waiting for core (only the time for THIS message)
591 *
592 * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise. 608 * @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise.
593 */ 609 */
594static int 610static int
@@ -842,6 +858,8 @@ check_connection (void *cls,
842void 858void
843GCC_check_connections () 859GCC_check_connections ()
844{ 860{
861 if (0 == CHECK_INVARIANTS)
862 return;
845 if (NULL == connections) 863 if (NULL == connections)
846 return; 864 return;
847 GNUNET_CONTAINER_multihashmap_iterate (connections, 865 GNUNET_CONTAINER_multihashmap_iterate (connections,
@@ -861,9 +879,7 @@ GCC_check_connections ()
861static struct CadetPeer * 879static struct CadetPeer *
862get_hop (struct CadetConnection *c, int fwd) 880get_hop (struct CadetConnection *c, int fwd)
863{ 881{
864 if (fwd) 882 return (fwd) ? get_next_hop (c) : get_prev_hop (c);
865 return get_next_hop (c);
866 return get_prev_hop (c);
867} 883}
868 884
869 885
@@ -987,7 +1003,7 @@ send_broken (struct CadetConnection *c,
987 GNUNET_assert (NULL == 1003 GNUNET_assert (NULL ==
988 GCC_send_prebuilt_message (&msg.header, 0, 0, c, fwd, 1004 GCC_send_prebuilt_message (&msg.header, 0, 0, c, fwd,
989 GNUNET_YES, NULL, NULL)); 1005 GNUNET_YES, NULL, NULL));
990 GCC_check_connections (); 1006 GCC_check_connections ();
991} 1007}
992 1008
993 1009
@@ -1309,7 +1325,8 @@ connection_unlock_queue (struct CadetConnection *c, int fwd)
1309 * @param fwd Cancel fwd traffic? 1325 * @param fwd Cancel fwd traffic?
1310 */ 1326 */
1311static void 1327static void
1312connection_cancel_queues (struct CadetConnection *c, int fwd) 1328connection_cancel_queues (struct CadetConnection *c,
1329 int fwd)
1313{ 1330{
1314 struct CadetFlowControl *fc; 1331 struct CadetFlowControl *fc;
1315 struct CadetPeer *peer; 1332 struct CadetPeer *peer;
@@ -1672,18 +1689,13 @@ register_neighbors (struct CadetConnection *c)
1672static void 1689static void
1673unregister_neighbors (struct CadetConnection *c) 1690unregister_neighbors (struct CadetConnection *c)
1674{ 1691{
1675 struct CadetPeer *peer;
1676
1677 /* Either already unregistered or never got registered, it's ok either way. */ 1692 /* Either already unregistered or never got registered, it's ok either way. */
1678 if (NULL == c->path) 1693 if (NULL == c->path)
1679 return; 1694 return;
1680 1695 if (NULL != c->next_peer)
1681 peer = get_next_hop (c); 1696 GCP_remove_connection (c->next_peer, c);
1682 GNUNET_assert (c->next_peer == peer); 1697 if (NULL != c->prev_peer)
1683 GCP_remove_connection (peer, c); 1698 GCP_remove_connection (c->prev_peer, c);
1684 peer = get_prev_hop (c);
1685 GNUNET_assert (c->prev_peer == peer);
1686 GCP_remove_connection (peer, c);
1687} 1699}
1688 1700
1689 1701
@@ -1844,7 +1856,8 @@ log_message (const struct GNUNET_MessageHeader *message,
1844 * #GNUNET_SYSERR to close it (signal serious error) 1856 * #GNUNET_SYSERR to close it (signal serious error)
1845 */ 1857 */
1846int 1858int
1847GCC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, 1859GCC_handle_create (void *cls,
1860 const struct GNUNET_PeerIdentity *peer,
1848 const struct GNUNET_MessageHeader *message) 1861 const struct GNUNET_MessageHeader *message)
1849{ 1862{
1850 struct GNUNET_CADET_ConnectionCreate *msg; 1863 struct GNUNET_CADET_ConnectionCreate *msg;
@@ -2034,14 +2047,6 @@ GCC_handle_confirm (void *cls,
2034 return GNUNET_OK; 2047 return GNUNET_OK;
2035 } 2048 }
2036 2049
2037 if (GNUNET_NO != c->destroy)
2038 {
2039 LOG (GNUNET_ERROR_TYPE_DEBUG,
2040 " connection being destroyed\n");
2041 GCC_check_connections ();
2042 return GNUNET_OK;
2043 }
2044
2045 oldstate = c->state; 2050 oldstate = c->state;
2046 LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer)); 2051 LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer));
2047 pi = GCP_get (peer); 2052 pi = GCP_get (peer);
@@ -2236,7 +2241,8 @@ GCC_handle_destroy (void *cls,
2236 * destroyed the tunnel and retransmitted to children. 2241 * destroyed the tunnel and retransmitted to children.
2237 * Safe to ignore. 2242 * Safe to ignore.
2238 */ 2243 */
2239 GNUNET_STATISTICS_update (stats, "# control on unknown connection", 2244 GNUNET_STATISTICS_update (stats,
2245 "# control on unknown connection",
2240 1, GNUNET_NO); 2246 1, GNUNET_NO);
2241 LOG (GNUNET_ERROR_TYPE_DEBUG, 2247 LOG (GNUNET_ERROR_TYPE_DEBUG,
2242 " connection unknown: already destroyed?\n"); 2248 " connection unknown: already destroyed?\n");
@@ -2250,11 +2256,15 @@ GCC_handle_destroy (void *cls,
2250 return GNUNET_OK; 2256 return GNUNET_OK;
2251 } 2257 }
2252 if (GNUNET_NO == GCC_is_terminal (c, fwd)) 2258 if (GNUNET_NO == GCC_is_terminal (c, fwd))
2253 GNUNET_assert (NULL == GCC_send_prebuilt_message (message, 0, 0, c, fwd, 2259 {
2254 GNUNET_YES, NULL, NULL)); 2260 GNUNET_assert (NULL ==
2261 GCC_send_prebuilt_message (message, 0, 0, c, fwd,
2262 GNUNET_YES, NULL, NULL));
2263 }
2255 else if (0 == c->pending_messages) 2264 else if (0 == c->pending_messages)
2256 { 2265 {
2257 LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); 2266 LOG (GNUNET_ERROR_TYPE_DEBUG,
2267 " directly destroying connection!\n");
2258 GCC_destroy (c); 2268 GCC_destroy (c);
2259 GCC_check_connections (); 2269 GCC_check_connections ();
2260 return GNUNET_OK; 2270 return GNUNET_OK;
@@ -2267,7 +2277,6 @@ GCC_handle_destroy (void *cls,
2267 c->t = NULL; 2277 c->t = NULL;
2268 } 2278 }
2269 GCC_check_connections (); 2279 GCC_check_connections ();
2270
2271 return GNUNET_OK; 2280 return GNUNET_OK;
2272} 2281}
2273 2282
@@ -2309,10 +2318,17 @@ check_message (const struct GNUNET_MessageHeader *message,
2309 /* Check connection */ 2318 /* Check connection */
2310 if (NULL == c) 2319 if (NULL == c)
2311 { 2320 {
2312 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); 2321 GNUNET_STATISTICS_update (stats,
2313 LOG (GNUNET_ERROR_TYPE_DEBUG, "%s on unknown connection %s\n", 2322 "# unknown connection",
2314 GC_m2s (ntohs (message->type)), GNUNET_h2s (GC_h2hc (cid))); 2323 1, GNUNET_NO);
2315 send_broken_unknown (cid, &my_full_id, NULL, neighbor); 2324 LOG (GNUNET_ERROR_TYPE_DEBUG,
2325 "%s on unknown connection %s\n",
2326 GC_m2s (ntohs (message->type)),
2327 GNUNET_h2s (GC_h2hc (cid)));
2328 send_broken_unknown (cid,
2329 &my_full_id,
2330 NULL,
2331 neighbor);
2316 return GNUNET_SYSERR; 2332 return GNUNET_SYSERR;
2317 } 2333 }
2318 2334
@@ -2436,7 +2452,12 @@ handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer,
2436 2452
2437 minumum_size = sizeof (struct GNUNET_MessageHeader) + overhead; 2453 minumum_size = sizeof (struct GNUNET_MessageHeader) + overhead;
2438 c = connection_get (cid); 2454 c = connection_get (cid);
2439 fwd = check_message (message, minumum_size, cid, c, peer, pid); 2455 fwd = check_message (message,
2456 minumum_size,
2457 cid,
2458 c,
2459 peer,
2460 pid);
2440 2461
2441 /* If something went wrong, discard message. */ 2462 /* If something went wrong, discard message. */
2442 if (GNUNET_SYSERR == fwd) 2463 if (GNUNET_SYSERR == fwd)
@@ -2509,7 +2530,12 @@ handle_cadet_kx (const struct GNUNET_PeerIdentity *peer,
2509 expected_size = sizeof (struct GNUNET_CADET_KX) 2530 expected_size = sizeof (struct GNUNET_CADET_KX)
2510 + sizeof (struct GNUNET_MessageHeader); 2531 + sizeof (struct GNUNET_MessageHeader);
2511 c = connection_get (cid); 2532 c = connection_get (cid);
2512 fwd = check_message (&msg->header, expected_size, cid, c, peer, 0); 2533 fwd = check_message (&msg->header,
2534 expected_size,
2535 cid,
2536 c,
2537 peer,
2538 0);
2513 2539
2514 /* If something went wrong, discard message. */ 2540 /* If something went wrong, discard message. */
2515 if (GNUNET_SYSERR == fwd) 2541 if (GNUNET_SYSERR == fwd)
@@ -2603,9 +2629,14 @@ GCC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
2603 c = connection_get (&msg->cid); 2629 c = connection_get (&msg->cid);
2604 if (NULL == c) 2630 if (NULL == c)
2605 { 2631 {
2606 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, 2632 GNUNET_STATISTICS_update (stats,
2633 "# ack on unknown connection",
2634 1,
2607 GNUNET_NO); 2635 GNUNET_NO);
2608 send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); 2636 send_broken_unknown (&msg->cid,
2637 &my_full_id,
2638 NULL,
2639 peer);
2609 GCC_check_connections (); 2640 GCC_check_connections ();
2610 return GNUNET_OK; 2641 return GNUNET_OK;
2611 } 2642 }
@@ -2679,9 +2710,13 @@ GCC_handle_poll (void *cls,
2679 { 2710 {
2680 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, 2711 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
2681 GNUNET_NO); 2712 GNUNET_NO);
2682 LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n", 2713 LOG (GNUNET_ERROR_TYPE_DEBUG,
2714 "POLL message on unknown connection %s!\n",
2683 GNUNET_h2s (GC_h2hc (&msg->cid))); 2715 GNUNET_h2s (GC_h2hc (&msg->cid)));
2684 send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); 2716 send_broken_unknown (&msg->cid,
2717 &my_full_id,
2718 NULL,
2719 peer);
2685 GCC_check_connections (); 2720 GCC_check_connections ();
2686 return GNUNET_OK; 2721 return GNUNET_OK;
2687 } 2722 }
@@ -2990,11 +3025,13 @@ GCC_destroy (struct CadetConnection *c)
2990 GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task); 3025 GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
2991 LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL task BCK canceled\n"); 3026 LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL task BCK canceled\n");
2992 } 3027 }
2993 3028 if (GNUNET_NO == c->was_removed)
2994 GNUNET_break (GNUNET_YES == 3029 {
2995 GNUNET_CONTAINER_multihashmap_remove (connections, 3030 GNUNET_break (GNUNET_YES ==
2996 GCC_get_h (c), 3031 GNUNET_CONTAINER_multihashmap_remove (connections,
2997 c)); 3032 GCC_get_h (c),
3033 c));
3034 }
2998 GNUNET_STATISTICS_update (stats, 3035 GNUNET_STATISTICS_update (stats,
2999 "# connections", 3036 "# connections",
3000 -1, 3037 -1,
@@ -3205,26 +3242,40 @@ GCC_notify_broken (struct CadetConnection *c,
3205 return; 3242 return;
3206 } 3243 }
3207 fwd = (peer == hop); 3244 fwd = (peer == hop);
3208 if (GNUNET_YES == GCC_is_terminal (c, fwd)) 3245 if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) ||
3246 (GNUNET_YES == c->destroy) )
3209 { 3247 {
3210 /* Local shutdown, no one to notify about this. */ 3248 /* Local shutdown, or other peer already down (hence 'c->destroy');
3249 so there is no one to notify about this, just clean up. */
3211 GCC_destroy (c); 3250 GCC_destroy (c);
3212 GCC_check_connections (); 3251 GCC_check_connections ();
3213 return; 3252 return;
3214 } 3253 }
3215 if (GNUNET_NO == c->destroy) 3254 send_broken (c, &my_full_id, GCP_get_id (peer), fwd);
3216 send_broken (c, &my_full_id, GCP_get_id (peer), fwd);
3217
3218 /* Connection will have at least one pending message 3255 /* Connection will have at least one pending message
3219 * (the one we just scheduled), so no point in checking whether to 3256 * (the one we just scheduled), so delay destruction
3220 * destroy immediately. */ 3257 * and remove from map so we don't use accidentally. */
3221 c->destroy = GNUNET_YES; 3258 c->destroy = GNUNET_YES;
3222 c->state = CADET_CONNECTION_DESTROYED; 3259 c->state = CADET_CONNECTION_DESTROYED;
3223 3260 GNUNET_assert (GNUNET_NO == c->was_removed);
3224 /** 3261 c->was_removed = GNUNET_YES;
3225 * Cancel all queues, if no message is left, connection will be destroyed. 3262 GNUNET_break (GNUNET_YES ==
3226 */ 3263 GNUNET_CONTAINER_multihashmap_remove (connections,
3264 GCC_get_h (c),
3265 c));
3266 /* Cancel queue in the direction that just died. */
3227 connection_cancel_queues (c, ! fwd); 3267 connection_cancel_queues (c, ! fwd);
3268 if (fwd)
3269 {
3270 GCP_remove_connection (c->prev_peer, c);
3271 c->prev_peer = NULL;
3272 }
3273 else
3274 {
3275 GCP_remove_connection (c->next_peer, c);
3276 c->next_peer = NULL;
3277 }
3278 GNUNET_assert (NULL != ( (fwd) ? c->next_peer : c->prev_peer) );
3228 GCC_check_connections (); 3279 GCC_check_connections ();
3229} 3280}
3230 3281
@@ -3260,7 +3311,7 @@ GCC_is_origin (struct CadetConnection *c, int fwd)
3260int 3311int
3261GCC_is_terminal (struct CadetConnection *c, int fwd) 3312GCC_is_terminal (struct CadetConnection *c, int fwd)
3262{ 3313{
3263 return GCC_is_origin (c, !fwd); 3314 return GCC_is_origin (c, ! fwd);
3264} 3315}
3265 3316
3266 3317
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c
index ef816bcb5..88bc9179d 100644
--- a/src/cadet/gnunet-service-cadet_peer.c
+++ b/src/cadet/gnunet-service-cadet_peer.c
@@ -1402,10 +1402,16 @@ GCP_queue_destroy (struct CadetPeerQueue *queue,
1402 * message has been sent and therefore the handle is no longer valid. 1402 * message has been sent and therefore the handle is no longer valid.
1403 */ 1403 */
1404struct CadetPeerQueue * 1404struct CadetPeerQueue *
1405GCP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type, 1405GCP_queue_add (struct CadetPeer *peer,
1406 uint16_t payload_type, uint32_t payload_id, size_t size, 1406 void *cls,
1407 struct CadetConnection *c, int fwd, 1407 uint16_t type,
1408 GCP_sent cont, void *cont_cls) 1408 uint16_t payload_type,
1409 uint32_t payload_id,
1410 size_t size,
1411 struct CadetConnection *c,
1412 int fwd,
1413 GCP_sent cont,
1414 void *cont_cls)
1409{ 1415{
1410 struct CadetPeerQueue *q; 1416 struct CadetPeerQueue *q;
1411 int error_level; 1417 int error_level;
@@ -1511,7 +1517,8 @@ GCP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
1511 * the sent continuation call. 1517 * the sent continuation call.
1512 */ 1518 */
1513void 1519void
1514GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c) 1520GCP_queue_cancel (struct CadetPeer *peer,
1521 struct CadetConnection *c)
1515{ 1522{
1516 struct CadetPeerQueue *q; 1523 struct CadetPeerQueue *q;
1517 struct CadetPeerQueue *next; 1524 struct CadetPeerQueue *next;
@@ -1525,7 +1532,9 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
1525 prev = q->prev; 1532 prev = q->prev;
1526 if (q->c == c) 1533 if (q->c == c)
1527 { 1534 {
1528 LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type)); 1535 LOG (GNUNET_ERROR_TYPE_DEBUG,
1536 "GMP queue cancel %s\n",
1537 GC_m2s (q->type));
1529 GNUNET_break (GNUNET_NO == connection_destroyed); 1538 GNUNET_break (GNUNET_NO == connection_destroyed);
1530 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type) 1539 if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type)
1531 { 1540 {
@@ -1550,7 +1559,8 @@ GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
1550 } 1559 }
1551 } 1560 }
1552 1561
1553 if (NULL == peer->queue_head && NULL != peer->core_transmit) 1562 if ( (NULL == peer->queue_head) &&
1563 (NULL != peer->core_transmit) )
1554 { 1564 {
1555 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); 1565 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
1556 peer->core_transmit = NULL; 1566 peer->core_transmit = NULL;
@@ -2245,8 +2255,8 @@ void
2245GCP_check_connection (const struct CadetPeer *peer, 2255GCP_check_connection (const struct CadetPeer *peer,
2246 const struct CadetConnection *c) 2256 const struct CadetConnection *c)
2247{ 2257{
2248 if ( (NULL == peer) || 2258 GNUNET_assert (NULL != peer);
2249 (NULL == peer->connections) ) 2259 GNUNET_assert (NULL != peer->connections);
2250 return; 2260 return;
2251 GNUNET_assert (GNUNET_YES == 2261 GNUNET_assert (GNUNET_YES ==
2252 GNUNET_CONTAINER_multihashmap_contains_value (peer->connections, 2262 GNUNET_CONTAINER_multihashmap_contains_value (peer->connections,