summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-02-20 12:49:18 +0100
committerChristian Grothoff <christian@grothoff.org>2019-02-20 12:49:18 +0100
commitad10f3bd2c507018c1091849d959b56630bb7386 (patch)
treec2edf5a5669b689e0395d53423c654f11a019ca1 /src
parentb41d189210287550d1c8d5526101be3eb2e0ce23 (diff)
fix #4244
Diffstat (limited to 'src')
-rw-r--r--src/peerstore/peerstore_api.c140
-rw-r--r--src/transport/transport_api2_address.c2
2 files changed, 100 insertions, 42 deletions
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
index 6abdef43a..243e26c8b 100644
--- a/src/peerstore/peerstore_api.c
+++ b/src/peerstore/peerstore_api.c
@@ -11,7 +11,7 @@
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
-
+
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -76,6 +76,16 @@ struct GNUNET_PEERSTORE_Handle
struct GNUNET_CONTAINER_MultiHashMap *watches;
/**
+ * ID of the task trying to reconnect to the service.
+ */
+ struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+ /**
+ * Delay until we try to reconnect.
+ */
+ struct GNUNET_TIME_Relative reconnect_delay;
+
+ /**
* Are we in the process of disconnecting but need to sync first?
*/
int disconnecting;
@@ -245,10 +255,72 @@ struct GNUNET_PEERSTORE_WatchContext
/**
* Close the existing connection to PEERSTORE and reconnect.
*
- * @param h handle to the service
+ * @param cls a `struct GNUNET_PEERSTORE_Handle *h`
+ */
+static void
+reconnect (void *cls);
+
+
+/**
+ * Disconnect from the peerstore service.
+ *
+ * @param h peerstore handle to disconnect
+ */
+static void
+disconnect (struct GNUNET_PEERSTORE_Handle *h)
+{
+ struct GNUNET_PEERSTORE_IterateContext *next;
+
+ for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head;
+ NULL != ic;
+ ic = next)
+ {
+ next = ic->next;
+ if (GNUNET_YES == ic->iterating)
+ {
+ GNUNET_PEERSTORE_Processor icb;
+ void *icb_cls;
+
+ icb = ic->callback;
+ icb_cls = ic->callback_cls;
+ GNUNET_PEERSTORE_iterate_cancel (ic);
+ if (NULL != icb)
+ icb (icb_cls,
+ NULL,
+ "Iteration canceled due to reconnection");
+ }
+ }
+
+ if (NULL != h->mq)
+ {
+ GNUNET_MQ_destroy (h->mq);
+ h->mq = NULL;
+ }
+}
+
+
+/**
+ * Function that will schedule the job that will try
+ * to connect us again to the client.
+ *
+ * @param h peerstore to reconnect
*/
static void
-reconnect (struct GNUNET_PEERSTORE_Handle *h);
+disconnect_and_schedule_reconnect (struct GNUNET_PEERSTORE_Handle *h)
+{
+ GNUNET_assert (NULL == h->reconnect_task);
+ disconnect (h);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling task to reconnect to PEERSTORE service in %s.\n",
+ GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay,
+ GNUNET_YES));
+ h->reconnect_task =
+ GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
+ &reconnect,
+ h);
+ h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
+}
+
/**
@@ -288,7 +360,7 @@ handle_client_error (void *cls,
LOG (GNUNET_ERROR_TYPE_ERROR,
"Received an error notification from MQ of type: %d\n",
error);
- reconnect (h);
+ disconnect_and_schedule_reconnect (h);
}
@@ -345,7 +417,7 @@ destroy_watch (void *cls,
* @param h Handle to the service.
*/
static void
-do_disconnect (struct GNUNET_PEERSTORE_Handle *h)
+final_disconnect (struct GNUNET_PEERSTORE_Handle *h)
{
if (NULL != h->mq)
{
@@ -419,7 +491,7 @@ GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h,
while (NULL != (sc = h->store_head))
GNUNET_PEERSTORE_store_cancel (sc);
}
- do_disconnect (h);
+ final_disconnect (h);
}
@@ -443,8 +515,9 @@ GNUNET_PEERSTORE_store_cancel (struct GNUNET_PEERSTORE_StoreContext *sc)
GNUNET_free (sc->value);
GNUNET_free (sc->key);
GNUNET_free (sc);
- if ((GNUNET_YES == h->disconnecting) && (NULL == h->store_head))
- do_disconnect (h);
+ if ( (GNUNET_YES == h->disconnecting) &&
+ (NULL == h->store_head) )
+ final_disconnect (h);
}
@@ -530,7 +603,7 @@ handle_iterate_end (void *cls,
{
LOG (GNUNET_ERROR_TYPE_ERROR,
_("Unexpected iteration response, this should not happen.\n"));
- reconnect (h);
+ disconnect_and_schedule_reconnect (h);
return;
}
callback = ic->callback;
@@ -538,7 +611,10 @@ handle_iterate_end (void *cls,
ic->iterating = GNUNET_NO;
GNUNET_PEERSTORE_iterate_cancel (ic);
if (NULL != callback)
- callback (callback_cls, NULL, NULL);
+ callback (callback_cls,
+ NULL,
+ NULL);
+ h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
}
@@ -579,7 +655,7 @@ handle_iterate_result (void *cls,
{
LOG (GNUNET_ERROR_TYPE_ERROR,
_("Unexpected iteration response, this should not happen.\n"));
- reconnect (h);
+ disconnect_and_schedule_reconnect (h);
return;
}
ic->iterating = GNUNET_YES;
@@ -715,7 +791,7 @@ handle_watch_record (void *cls,
record = PEERSTORE_parse_record_message (msg);
if (NULL == record)
{
- reconnect (h);
+ disconnect_and_schedule_reconnect (h);
return;
}
PEERSTORE_hash_key (record->sub_system,
@@ -730,13 +806,14 @@ handle_watch_record (void *cls,
LOG (GNUNET_ERROR_TYPE_ERROR,
_("Received a watch result for a non existing watch.\n"));
PEERSTORE_destroy_record (record);
- reconnect (h);
+ disconnect_and_schedule_reconnect (h);
return;
}
if (NULL != wc->callback)
wc->callback (wc->callback_cls,
record,
NULL);
+ h->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
PEERSTORE_destroy_record (record);
}
@@ -744,11 +821,12 @@ handle_watch_record (void *cls,
/**
* Close the existing connection to PEERSTORE and reconnect.
*
- * @param h handle to the service
+ * @param cls a `struct GNUNET_PEERSTORE_Handle *`
*/
static void
-reconnect (struct GNUNET_PEERSTORE_Handle *h)
+reconnect (void *cls)
{
+ struct GNUNET_PEERSTORE_Handle *h = cls;
struct GNUNET_MQ_MessageHandler mq_handlers[] = {
GNUNET_MQ_hd_fixed_size (iterate_end,
GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END,
@@ -764,34 +842,10 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h)
h),
GNUNET_MQ_handler_end ()
};
- struct GNUNET_PEERSTORE_IterateContext *ic;
- struct GNUNET_PEERSTORE_IterateContext *next;
- GNUNET_PEERSTORE_Processor icb;
- void *icb_cls;
- struct GNUNET_PEERSTORE_StoreContext *sc;
struct GNUNET_MQ_Envelope *ev;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Reconnecting...\n");
- for (ic = h->iterate_head; NULL != ic; ic = next)
- {
- next = ic->next;
- if (GNUNET_YES == ic->iterating)
- {
- icb = ic->callback;
- icb_cls = ic->callback_cls;
- GNUNET_PEERSTORE_iterate_cancel (ic);
- if (NULL != icb)
- icb (icb_cls,
- NULL,
- "Iteration canceled due to reconnection");
- }
- }
- if (NULL != h->mq)
- {
- GNUNET_MQ_destroy (h->mq);
- h->mq = NULL;
- }
h->mq = GNUNET_CLIENT_connect (h->cfg,
"peerstore",
mq_handlers,
@@ -805,7 +859,9 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h)
GNUNET_CONTAINER_multihashmap_iterate (h->watches,
&rewatch_it,
h);
- for (ic = h->iterate_head; NULL != ic; ic = ic->next)
+ for (struct GNUNET_PEERSTORE_IterateContext *ic = h->iterate_head;
+ NULL != ic;
+ ic = ic->next)
{
ev = PEERSTORE_create_record_mq_envelope (ic->sub_system,
&ic->peer,
@@ -816,7 +872,9 @@ reconnect (struct GNUNET_PEERSTORE_Handle *h)
GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE);
GNUNET_MQ_send (h->mq, ev);
}
- for (sc = h->store_head; NULL != sc; sc = sc->next)
+ for (struct GNUNET_PEERSTORE_StoreContext *sc = h->store_head;
+ NULL != sc;
+ sc = sc->next)
{
ev = PEERSTORE_create_record_mq_envelope (sc->sub_system,
&sc->peer,
diff --git a/src/transport/transport_api2_address.c b/src/transport/transport_api2_address.c
index 1ae1e5b1e..1ff599efb 100644
--- a/src/transport/transport_api2_address.c
+++ b/src/transport/transport_api2_address.c
@@ -123,7 +123,7 @@ reconnect (void *cls)
/**
* Disconnect from the transport service.
*
- * @param h transport service to reconnect
+ * @param h transport service to disconnect
*/
static void
disconnect (struct GNUNET_TRANSPORT_AddressHandle *h)