[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r36070 - gnunet/src/cadet
From: |
gnunet |
Subject: |
[GNUnet-SVN] r36070 - gnunet/src/cadet |
Date: |
Wed, 15 Jul 2015 01:34:21 +0200 |
Author: grothoff
Date: 2015-07-15 01:34:21 +0200 (Wed, 15 Jul 2015)
New Revision: 36070
Modified:
gnunet/src/cadet/gnunet-service-cadet_connection.c
gnunet/src/cadet/gnunet-service-cadet_peer.c
Log:
this should fix #3846
Modified: gnunet/src/cadet/gnunet-service-cadet_connection.c
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_connection.c 2015-07-14 21:56:33 UTC
(rev 36069)
+++ gnunet/src/cadet/gnunet-service-cadet_connection.c 2015-07-14 23:34:21 UTC
(rev 36070)
@@ -33,6 +33,12 @@
#include "gnunet-service-cadet_tunnel.h"
+/**
+ * Should we run somewhat expensive checks on our invariants?
+ */
+#define CHECK_INVARIANTS 0
+
+
#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
@@ -198,12 +204,12 @@
struct CadetPeerQueue *maintenance_q;
/**
- * Should equal #get_next_hop().
+ * Should equal #get_next_hop(), or NULL if that peer disconnected.
*/
struct CadetPeer *next_peer;
/**
- * Should equal #get_prev_hop().
+ * Should equal #get_prev_hop(), or NULL if that peer disconnected.
*/
struct CadetPeer *prev_peer;
@@ -231,6 +237,17 @@
int destroy;
/**
+ * In-connection-map flag. Sometimes, when @e destroy is set but
+ * actual destruction is delayed to enable us to finish processing
+ * queues (i.e. in the direction that is still working), we remove
+ * the connection from the map to prevent it from still being
+ * found (and used) by accident. This flag is set to #GNUNET_YES
+ * for a connection that is not in the #connections map. Should
+ * only be #GNUNET_YES if #destroy is also non-zero.
+ */
+ int was_removed;
+
+ /**
* Counter to do exponential backoff when creating a connection (max 64).
*/
unsigned short create_retry;
@@ -588,7 +605,6 @@
* @param fwd Was this a FWD going message?
* @param size Size of the message.
* @param wait Time spent waiting for core (only the time for THIS message)
- *
* @return #GNUNET_YES if connection was destroyed, #GNUNET_NO otherwise.
*/
static int
@@ -842,6 +858,8 @@
void
GCC_check_connections ()
{
+ if (0 == CHECK_INVARIANTS)
+ return;
if (NULL == connections)
return;
GNUNET_CONTAINER_multihashmap_iterate (connections,
@@ -861,9 +879,7 @@
static struct CadetPeer *
get_hop (struct CadetConnection *c, int fwd)
{
- if (fwd)
- return get_next_hop (c);
- return get_prev_hop (c);
+ return (fwd) ? get_next_hop (c) : get_prev_hop (c);
}
@@ -987,7 +1003,7 @@
GNUNET_assert (NULL ==
GCC_send_prebuilt_message (&msg.header, 0, 0, c, fwd,
GNUNET_YES, NULL, NULL));
- GCC_check_connections ();
+ GCC_check_connections ();
}
@@ -1309,7 +1325,8 @@
* @param fwd Cancel fwd traffic?
*/
static void
-connection_cancel_queues (struct CadetConnection *c, int fwd)
+connection_cancel_queues (struct CadetConnection *c,
+ int fwd)
{
struct CadetFlowControl *fc;
struct CadetPeer *peer;
@@ -1672,18 +1689,13 @@
static void
unregister_neighbors (struct CadetConnection *c)
{
- struct CadetPeer *peer;
-
/* Either already unregistered or never got registered, it's ok either way.
*/
if (NULL == c->path)
return;
-
- peer = get_next_hop (c);
- GNUNET_assert (c->next_peer == peer);
- GCP_remove_connection (peer, c);
- peer = get_prev_hop (c);
- GNUNET_assert (c->prev_peer == peer);
- GCP_remove_connection (peer, c);
+ if (NULL != c->next_peer)
+ GCP_remove_connection (c->next_peer, c);
+ if (NULL != c->prev_peer)
+ GCP_remove_connection (c->prev_peer, c);
}
@@ -1844,7 +1856,8 @@
* #GNUNET_SYSERR to close it (signal serious error)
*/
int
-GCC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
+GCC_handle_create (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_CADET_ConnectionCreate *msg;
@@ -2034,14 +2047,6 @@
return GNUNET_OK;
}
- if (GNUNET_NO != c->destroy)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " connection being destroyed\n");
- GCC_check_connections ();
- return GNUNET_OK;
- }
-
oldstate = c->state;
LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer));
pi = GCP_get (peer);
@@ -2236,7 +2241,8 @@
* destroyed the tunnel and retransmitted to children.
* Safe to ignore.
*/
- GNUNET_STATISTICS_update (stats, "# control on unknown connection",
+ GNUNET_STATISTICS_update (stats,
+ "# control on unknown connection",
1, GNUNET_NO);
LOG (GNUNET_ERROR_TYPE_DEBUG,
" connection unknown: already destroyed?\n");
@@ -2250,11 +2256,15 @@
return GNUNET_OK;
}
if (GNUNET_NO == GCC_is_terminal (c, fwd))
- GNUNET_assert (NULL == GCC_send_prebuilt_message (message, 0, 0, c, fwd,
- GNUNET_YES, NULL, NULL));
+ {
+ GNUNET_assert (NULL ==
+ GCC_send_prebuilt_message (message, 0, 0, c, fwd,
+ GNUNET_YES, NULL, NULL));
+ }
else if (0 == c->pending_messages)
{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ " directly destroying connection!\n");
GCC_destroy (c);
GCC_check_connections ();
return GNUNET_OK;
@@ -2267,7 +2277,6 @@
c->t = NULL;
}
GCC_check_connections ();
-
return GNUNET_OK;
}
@@ -2309,10 +2318,17 @@
/* Check connection */
if (NULL == c)
{
- GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "%s on unknown connection %s\n",
- GC_m2s (ntohs (message->type)), GNUNET_h2s (GC_h2hc (cid)));
- send_broken_unknown (cid, &my_full_id, NULL, neighbor);
+ GNUNET_STATISTICS_update (stats,
+ "# unknown connection",
+ 1, GNUNET_NO);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "%s on unknown connection %s\n",
+ GC_m2s (ntohs (message->type)),
+ GNUNET_h2s (GC_h2hc (cid)));
+ send_broken_unknown (cid,
+ &my_full_id,
+ NULL,
+ neighbor);
return GNUNET_SYSERR;
}
@@ -2436,7 +2452,12 @@
minumum_size = sizeof (struct GNUNET_MessageHeader) + overhead;
c = connection_get (cid);
- fwd = check_message (message, minumum_size, cid, c, peer, pid);
+ fwd = check_message (message,
+ minumum_size,
+ cid,
+ c,
+ peer,
+ pid);
/* If something went wrong, discard message. */
if (GNUNET_SYSERR == fwd)
@@ -2509,7 +2530,12 @@
expected_size = sizeof (struct GNUNET_CADET_KX)
+ sizeof (struct GNUNET_MessageHeader);
c = connection_get (cid);
- fwd = check_message (&msg->header, expected_size, cid, c, peer, 0);
+ fwd = check_message (&msg->header,
+ expected_size,
+ cid,
+ c,
+ peer,
+ 0);
/* If something went wrong, discard message. */
if (GNUNET_SYSERR == fwd)
@@ -2603,9 +2629,14 @@
c = connection_get (&msg->cid);
if (NULL == c)
{
- GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
+ GNUNET_STATISTICS_update (stats,
+ "# ack on unknown connection",
+ 1,
GNUNET_NO);
- send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+ send_broken_unknown (&msg->cid,
+ &my_full_id,
+ NULL,
+ peer);
GCC_check_connections ();
return GNUNET_OK;
}
@@ -2679,9 +2710,13 @@
{
GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n",
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "POLL message on unknown connection %s!\n",
GNUNET_h2s (GC_h2hc (&msg->cid)));
- send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
+ send_broken_unknown (&msg->cid,
+ &my_full_id,
+ NULL,
+ peer);
GCC_check_connections ();
return GNUNET_OK;
}
@@ -2990,11 +3025,13 @@
GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL task BCK canceled\n");
}
-
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (connections,
- GCC_get_h (c),
- c));
+ if (GNUNET_NO == c->was_removed)
+ {
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (connections,
+ GCC_get_h (c),
+ c));
+ }
GNUNET_STATISTICS_update (stats,
"# connections",
-1,
@@ -3205,26 +3242,40 @@
return;
}
fwd = (peer == hop);
- if (GNUNET_YES == GCC_is_terminal (c, fwd))
+ if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) ||
+ (GNUNET_YES == c->destroy) )
{
- /* Local shutdown, no one to notify about this. */
+ /* Local shutdown, or other peer already down (hence 'c->destroy');
+ so there is no one to notify about this, just clean up. */
GCC_destroy (c);
GCC_check_connections ();
return;
}
- if (GNUNET_NO == c->destroy)
- send_broken (c, &my_full_id, GCP_get_id (peer), fwd);
-
+ send_broken (c, &my_full_id, GCP_get_id (peer), fwd);
/* Connection will have at least one pending message
- * (the one we just scheduled), so no point in checking whether to
- * destroy immediately. */
+ * (the one we just scheduled), so delay destruction
+ * and remove from map so we don't use accidentally. */
c->destroy = GNUNET_YES;
c->state = CADET_CONNECTION_DESTROYED;
-
- /**
- * Cancel all queues, if no message is left, connection will be destroyed.
- */
+ GNUNET_assert (GNUNET_NO == c->was_removed);
+ c->was_removed = GNUNET_YES;
+ GNUNET_break (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (connections,
+ GCC_get_h (c),
+ c));
+ /* Cancel queue in the direction that just died. */
connection_cancel_queues (c, ! fwd);
+ if (fwd)
+ {
+ GCP_remove_connection (c->prev_peer, c);
+ c->prev_peer = NULL;
+ }
+ else
+ {
+ GCP_remove_connection (c->next_peer, c);
+ c->next_peer = NULL;
+ }
+ GNUNET_assert (NULL != ( (fwd) ? c->next_peer : c->prev_peer) );
GCC_check_connections ();
}
@@ -3260,7 +3311,7 @@
int
GCC_is_terminal (struct CadetConnection *c, int fwd)
{
- return GCC_is_origin (c, !fwd);
+ return GCC_is_origin (c, ! fwd);
}
Modified: gnunet/src/cadet/gnunet-service-cadet_peer.c
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_peer.c 2015-07-14 21:56:33 UTC
(rev 36069)
+++ gnunet/src/cadet/gnunet-service-cadet_peer.c 2015-07-14 23:34:21 UTC
(rev 36070)
@@ -1402,10 +1402,16 @@
* message has been sent and therefore the handle is no longer valid.
*/
struct CadetPeerQueue *
-GCP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
- uint16_t payload_type, uint32_t payload_id, size_t size,
- struct CadetConnection *c, int fwd,
- GCP_sent cont, void *cont_cls)
+GCP_queue_add (struct CadetPeer *peer,
+ void *cls,
+ uint16_t type,
+ uint16_t payload_type,
+ uint32_t payload_id,
+ size_t size,
+ struct CadetConnection *c,
+ int fwd,
+ GCP_sent cont,
+ void *cont_cls)
{
struct CadetPeerQueue *q;
int error_level;
@@ -1511,7 +1517,8 @@
* the sent continuation call.
*/
void
-GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
+GCP_queue_cancel (struct CadetPeer *peer,
+ struct CadetConnection *c)
{
struct CadetPeerQueue *q;
struct CadetPeerQueue *next;
@@ -1525,7 +1532,9 @@
prev = q->prev;
if (q->c == c)
{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "GMP queue cancel %s\n",
+ GC_m2s (q->type));
GNUNET_break (GNUNET_NO == connection_destroyed);
if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type)
{
@@ -1550,7 +1559,8 @@
}
}
- if (NULL == peer->queue_head && NULL != peer->core_transmit)
+ if ( (NULL == peer->queue_head) &&
+ (NULL != peer->core_transmit) )
{
GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
peer->core_transmit = NULL;
@@ -2245,8 +2255,8 @@
GCP_check_connection (const struct CadetPeer *peer,
const struct CadetConnection *c)
{
- if ( (NULL == peer) ||
- (NULL == peer->connections) )
+ GNUNET_assert (NULL != peer);
+ GNUNET_assert (NULL != peer->connections);
return;
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_contains_value
(peer->connections,
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r36070 - gnunet/src/cadet,
gnunet <=