/** * Disconnect from the PEERSTORE service. Any pending ITERATE and WATCH requests * will be canceled. * Any pending STORE requests will depend on @e snyc_first flag. * * @param h handle to disconnect * @param sync_first send any pending STORE requests before disconnecting */ void GNUNET_PEERSTORE_disconnect (struct GNUNET_PEERSTORE_Handle *h, int sync_first) { struct GNUNET_PEERSTORE_IterateContext *ic; struct GNUNET_PEERSTORE_StoreContext *sc; LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting.\n"); if (NULL != h->watches) { GNUNET_CONTAINER_multihashmap_iterate (h->watches, &destroy_watch, NULL); GNUNET_CONTAINER_multihashmap_destroy (h->watches); h->watches = NULL; } while (NULL != (ic = h->iterate_head)) { GNUNET_break (0); GNUNET_PEERSTORE_iterate_cancel (ic); } if (NULL != h->store_head) { if (GNUNET_YES == sync_first) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Delaying disconnection due to pending store requests.\n"); h->disconnecting = GNUNET_YES; return; } while (NULL != (sc = h->store_head)) GNUNET_PEERSTORE_store_cancel (sc); } do_disconnect (h); }
/** * When a response for iterate request is received * * @param cls a `struct GNUNET_PEERSTORE_Handle *` * @param msg message received, NULL on timeout or fatal error */ static void handle_iterate_result (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_PEERSTORE_Handle *h = cls; struct GNUNET_PEERSTORE_IterateContext *ic; GNUNET_PEERSTORE_Processor callback; void *callback_cls; uint16_t msg_type; struct GNUNET_PEERSTORE_Record *record; int continue_iter; ic = h->iterate_head; if (NULL == ic) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Unexpected iteration response, this should not happen.\n")); reconnect (h); return; } ic->iterating = GNUNET_YES; callback = ic->callback; callback_cls = ic->callback_cls; if (NULL == msg) /* Connection error */ { if (NULL != callback) callback (callback_cls, NULL, _("Error communicating with `PEERSTORE' service.")); reconnect (h); return; } msg_type = ntohs (msg->type); if (GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE_END == msg_type) { ic->iterating = GNUNET_NO; GNUNET_PEERSTORE_iterate_cancel (ic); if (NULL != callback) callback (callback_cls, NULL, NULL); return; } if (NULL != callback) { record = PEERSTORE_parse_record_message (msg); if (NULL == record) continue_iter = callback (callback_cls, NULL, _("Received a malformed response from service.")); else { continue_iter = callback (callback_cls, record, NULL); PEERSTORE_destroy_record (record); } if (GNUNET_NO == continue_iter) ic->callback = NULL; } }
/** * Called when the iterate request is timedout * * @param cls a `struct GNUNET_PEERSTORE_IterateContext *` * @param tc Scheduler task context (unused) */ static void iterate_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PEERSTORE_IterateContext *ic = cls; GNUNET_PEERSTORE_Processor callback; void *callback_cls; ic->timeout_task = NULL; callback = ic->callback; callback_cls = ic->callback_cls; GNUNET_PEERSTORE_iterate_cancel (ic); if (NULL != callback) callback (callback_cls, NULL, _("timeout")); }
static void iter1_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg) { if (NULL != emsg) { GNUNET_PEERSTORE_iterate_cancel (ic); return; } if (NULL != record) { count++; return; } GNUNET_assert (count == 1); count = 0; ic = GNUNET_PEERSTORE_iterate (h, ss, &p1, NULL, GNUNET_TIME_UNIT_FOREVER_REL, iter2_cb, NULL); }
static void iter3_cb (void *cls, const struct GNUNET_PEERSTORE_Record *record, const char *emsg) { if (NULL != emsg) { GNUNET_PEERSTORE_iterate_cancel (ic); return; } if (NULL != record) { count++; return; } GNUNET_assert (count == 3); ok = 0; GNUNET_PEERSTORE_disconnect (h, GNUNET_NO); GNUNET_SCHEDULER_shutdown (); }
/** * Close the existing connection to PEERSTORE and reconnect. * * @param h handle to the service */ static void reconnect (struct GNUNET_PEERSTORE_Handle *h) { 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; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->client = GNUNET_CLIENT_connect ("peerstore", h->cfg); GNUNET_assert (NULL != h->client); h->mq = GNUNET_MQ_queue_for_connection_client (h->client, mq_handlers, &handle_client_error, h); LOG (GNUNET_ERROR_TYPE_DEBUG, "Resending pending requests after reconnect.\n"); if (NULL != h->watches) GNUNET_CONTAINER_multihashmap_iterate (h->watches, &rewatch_it, h); for (ic = h->iterate_head; NULL != ic; ic = ic->next) { ev = PEERSTORE_create_record_mq_envelope (ic->sub_system, &ic->peer, ic->key, NULL, 0, NULL, 0, GNUNET_MESSAGE_TYPE_PEERSTORE_ITERATE); GNUNET_MQ_send (h->mq, ev); ic->timeout_task = GNUNET_SCHEDULER_add_delayed (ic->timeout, &iterate_timeout, ic); } for (sc = h->store_head; NULL != sc; sc = sc->next) { ev = PEERSTORE_create_record_mq_envelope (sc->sub_system, &sc->peer, sc->key, sc->value, sc->size, &sc->expiry, sc->options, GNUNET_MESSAGE_TYPE_PEERSTORE_STORE); GNUNET_MQ_notify_sent (ev, &store_request_sent, sc); GNUNET_MQ_send (h->mq, ev); } }