From d4295e8047e97026135c6a188274f64ae0549100 Mon Sep 17 00:00:00 2001 From: Matthias Wachs Date: Thu, 24 May 2012 11:44:13 +0000 Subject: [PATCH] - fix memory corruption, various mantis bugs: 0002374 0002368 0002367 0002369 --- .../gnunet-service-transport_neighbours.c | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index e0e19ab3d..6f1c4efa5 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -842,6 +842,61 @@ set_address (struct NeighbourAddress *na, } } +/** + * Free a neighbour map entry. + * + * @param n entry to free + */ +static void +free_neighbour_without_terminating_sessions (struct NeighbourMapEntry *n) +{ + struct MessageQueue *mq; + n->is_active = NULL; /* always free'd by its own continuation! */ + + /* fail messages currently in the queue */ + while (NULL != (mq = n->messages_head)) + { + GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); + if (NULL != mq->cont) + mq->cont (mq->cont_cls, GNUNET_SYSERR); + GNUNET_free (mq); + } + /* It is too late to send other peer disconnect notifications, but at + least internally we need to get clean... */ + if (GNUNET_YES == test_connected (n)) + { + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# peers connected"), + --neighbours_connected, + GNUNET_NO); + disconnect_notify_cb (callback_cls, &n->id); + } + + n->state = S_DISCONNECT_FINISHED; + + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (neighbours, + &n->id.hashPubKey, n)); + + /* cut transport-level connection */ + free_address (&n->primary_address); + free_address (&n->alternative_address); + + // FIXME-ATS-API: we might want to be more specific about + // which states we do this from in the future (ATS should + // have given us a 'suggest_address' handle, and if we have + // such a handle, we should cancel the operation here! + GNUNET_ATS_suggest_address_cancel (GST_ats, &n->id); + + if (GNUNET_SCHEDULER_NO_TASK != n->task) + { + GNUNET_SCHEDULER_cancel (n->task); + n->task = GNUNET_SCHEDULER_NO_TASK; + } + /* free rest of memory */ + GNUNET_free (n); +} + /** * Free a neighbour map entry. @@ -2055,13 +2110,12 @@ GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message, check_blacklist (peer, ts, address, session, ats, ats_count); break; case S_DISCONNECT: - /* get rid of remains, ready to re-try */ - free_neighbour (n); + /* get rid of remains without terminating sessions, ready to re-try */ + free_neighbour_without_terminating_sessions (n); n = setup_neighbour (peer); n->state = S_CONNECT_RECV_ATS; GNUNET_ATS_reset_backoff (GST_ats, peer); GNUNET_ATS_suggest_address (GST_ats, peer); - check_blacklist (peer, ts, address, session, ats, ats_count); break; case S_DISCONNECT_FINISHED: /* should not be possible */ -- 2.25.1