/** * Queues a message in send queue of the logger handle * * @param h the logger handle * @param msg the message to queue */ static void queue_message (struct GNUNET_TESTBED_LOGGER_Handle *h, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq; uint16_t type; uint16_t size; type = ntohs (msg->type); size = ntohs (msg->size); mq = GNUNET_new (struct MessageQueue); mq->msg = msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing message of type %u, size %u for sending\n", type, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (h->mq_head, h->mq_tail, mq); if (NULL == h->th) { h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); } }
/** * Close down any existing connection to the ARM service and * try re-establishing it later. * * @param h our handle */ static void reconnect_arm_later (struct GNUNET_ARM_Handle *h) { if (GNUNET_NO != h->currently_down) return; if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->currently_down = GNUNET_YES; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_arm_task, h); /* Don't clear pending messages on disconnection, deliver them later clear_pending_messages (h, GNUNET_ARM_REQUEST_DISCONNECTED); GNUNET_assert (NULL == h->control_pending_head); */ h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); if (NULL != h->conn_status) h->conn_status (h->conn_status_cls, GNUNET_NO); }
/** * Close down any existing connection to the ARM service and * try re-establishing it later. * * @param h our handle */ static void reconnect_arm_monitor_later (struct GNUNET_ARM_MonitorHandle *h) { if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->monitor) { GNUNET_CLIENT_disconnect (h->monitor); h->monitor = NULL; } if (NULL != h->init_timeout_task_id) { GNUNET_SCHEDULER_cancel (h->init_timeout_task_id); h->init_timeout_task_id = NULL; } GNUNET_assert (NULL == h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_arm_monitor_task, h); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); }
/** * Transmit our current typemap message to the other peer. * (Done periodically until the typemap is confirmed). * * @param cls the `struct Session *` * @param tc unused */ static void transmit_typemap_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; struct GNUNET_MessageHeader *hdr; struct GNUNET_TIME_Relative delay; session->typemap_delay = GNUNET_TIME_STD_BACKOFF (session->typemap_delay); delay = session->typemap_delay; /* randomize a bit to avoid spont. sync */ delay.rel_value_us += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000); session->typemap_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type map refreshes sent"), 1, GNUNET_NO); hdr = GSC_TYPEMAP_compute_type_map_message (); GSC_KX_encrypt_and_transmit (session->kxinfo, hdr, ntohs (hdr->size)); GNUNET_free (hdr); }
/** * Route the given request via the DHT. This includes updating * the bloom filter and retransmission times, building the P2P * message and initiating the routing operation. */ static void transmit_request (struct ClientQueryRecord *cqr) { int32_t reply_bf_mutator; struct GNUNET_CONTAINER_BloomFilter *reply_bf; struct GNUNET_CONTAINER_BloomFilter *peer_bf; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests from clients injected"), 1, GNUNET_NO); reply_bf_mutator = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); reply_bf = GNUNET_BLOCK_construct_bloomfilter (reply_bf_mutator, cqr->seen_replies, cqr->seen_replies_count); peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); LOG (GNUNET_ERROR_TYPE_DEBUG, "Initiating GET for %s, replication %u, already have %u replies\n", GNUNET_h2s(&cqr->key), cqr->replication, cqr->seen_replies_count); GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, 0 /* hop count */ , &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, reply_bf_mutator, peer_bf); GNUNET_CONTAINER_bloomfilter_free (reply_bf); GNUNET_CONTAINER_bloomfilter_free (peer_bf); /* exponential back-off for retries. * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); }
/** * Function called to notify a client about the connection begin ready to queue * more data. "buf" will be NULL and "size" zero if the connection was closed * for writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_notify (void *cls, size_t size, void *buf) { struct GNUNET_TESTBED_LOGGER_Handle *h = cls; struct MessageQueue *mq; h->th = NULL; mq = h->mq_head; GNUNET_assert (NULL != mq); if ((0 == size) && (NULL == buf)) /* Timeout */ { LOG_DEBUG ("Message sending timed out -- retrying\n"); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (mq->msg->size), h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); return 0; } h->retry_backoff = GNUNET_TIME_UNIT_ZERO; GNUNET_assert (ntohs (mq->msg->size) <= size); size = ntohs (mq->msg->size); memcpy (buf, mq->msg, size); LOG_DEBUG ("Message of type: %u and size: %u sent\n", ntohs (mq->msg->type), size); GNUNET_free (mq->msg); GNUNET_CONTAINER_DLL_remove (h->mq_head, h->mq_tail, mq); GNUNET_free (mq); h->bwrote += (size - sizeof (struct GNUNET_MessageHeader)); mq = h->mq_head; if (NULL != mq) { h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (mq->msg->size), h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); return size; } if (NULL != h->cb) trigger_flush_notification (h); /* Call the flush completion callback */ return size; }
/** * Cut the existing connection and reconnect. * * @param val_ctx our context */ static void reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx) { GNUNET_assert (GNUNET_NO == val_ctx->one_shot); GNUNET_CLIENT_disconnect (val_ctx->client); val_ctx->client = NULL; val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff); val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff, &do_val_connect, val_ctx); }
/** * Cut the existing connection and reconnect. * * @param pal_ctx our context */ static void reconnect_peer_ctx (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx) { GNUNET_assert (GNUNET_NO == pal_ctx->one_shot); GNUNET_CLIENT_disconnect (pal_ctx->client); pal_ctx->client = NULL; pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff); pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff, &do_peer_connect, pal_ctx); }
/** * Disconnect from service and then reconnect. * * @param handle our handle */ static void force_reconnect (struct GNUNET_GNS_Handle *handle) { GNUNET_MQ_destroy (handle->mq); handle->mq = NULL; handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, &reconnect_task, handle); }
/** * This task is run if we should re-try connection to the * service after a while. * * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request * @param tc unused */ static void client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_TIME_Relative delay; th->reconnect_task = NULL; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* give up, was shutdown */ th->client->th = NULL; th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); return; } th->client->connection = do_connect (th->client->service_name, th->client->cfg, th->client->attempts++); th->client->first_message = GNUNET_YES; if (NULL == th->client->connection) { /* could happen if we're out of sockets */ delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout), th->client->back_off); th->client->back_off = GNUNET_TIME_STD_BACKOFF (th->client->back_off); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); GNUNET_assert (NULL == th->th); GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return; } th->th = GNUNET_CONNECTION_notify_transmit_ready (th->client->connection, th->size, GNUNET_TIME_absolute_get_remaining (th->timeout), &client_notify, th); if (NULL == th->th) { GNUNET_break (0); th->client->th = NULL; th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); return; } }
/** * Checks whether a host can be used to start testbed service * * @param host the host to check * @param config the configuration handle to lookup the path of the testbed * helper * @param cb the callback to call to inform about habitability of the given host * @param cb_cls the closure for the callback * @return NULL upon any error or a handle which can be passed to * GNUNET_TESTBED_is_host_habitable_cancel() */ struct GNUNET_TESTBED_HostHabitableCheckHandle * GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *config, GNUNET_TESTBED_HostHabitableCallback cb, void *cb_cls) { struct GNUNET_TESTBED_HostHabitableCheckHandle *h; char **rsh_args; char **rsh_suffix_args; char *stat_args[3]; const char *hostname; char *port; h = GNUNET_new (struct GNUNET_TESTBED_HostHabitableCheckHandle); h->cb = cb; h->cb_cls = cb_cls; h->host = host; hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (config, "testbed", "HELPER_BINARY_PATH", &stat_args[1])) stat_args[1] = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); GNUNET_asprintf (&port, "%u", host->port); rsh_args = gen_rsh_args (port, hostname, host->username); GNUNET_free (port); port = NULL; stat_args[0] = "stat"; stat_args[2] = NULL; rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args); GNUNET_free (stat_args[1]); h->helper_argv = join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); free_argv (rsh_suffix_args); free_argv (rsh_args); h->auxp = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL, NULL, NULL, h->helper_argv[0], h->helper_argv); if (NULL == h->auxp) { GNUNET_break (0); /* Cannot exec SSH? */ GNUNET_free (h); return NULL; } h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); h->habitability_check_task = GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); return h; }
/** * Cut the existing connection and reconnect. * * @param val_ctx our context */ static void reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx) { GNUNET_assert (GNUNET_NO == val_ctx->one_shot); GNUNET_CLIENT_disconnect (val_ctx->client); val_ctx->client = NULL; /* notify clients about (re)connect */ val_ctx->cb (val_ctx->cb_cls, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT); val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff); val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff, &do_val_connect, val_ctx); }
/** * Handle request message for a listen operation * * @param cls the listen handle * @param mh the message */ static void handle_request (void *cls, const struct GNUNET_MessageHeader *mh) { struct GNUNET_SET_ListenHandle *lh = cls; const struct GNUNET_SET_RequestMessage *msg; struct GNUNET_SET_Request req; const struct GNUNET_MessageHeader *context_msg; uint16_t msize; struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_RejectMessage *rmsg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing incoming operation request\n"); msize = ntohs (mh->size); if (msize < sizeof (struct GNUNET_SET_RequestMessage)) { GNUNET_break (0); GNUNET_CLIENT_disconnect (lh->client); lh->client = NULL; GNUNET_MQ_destroy (lh->mq); lh->mq = NULL; lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff, &listen_connect, lh); lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff); return; } /* we got another valid request => reset the backoff */ lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS; msg = (const struct GNUNET_SET_RequestMessage *) mh; req.accept_id = ntohl (msg->accept_id); req.accepted = GNUNET_NO; context_msg = GNUNET_MQ_extract_nested_mh (msg); /* calling #GNUNET_SET_accept() in the listen cb will set req->accepted */ lh->listen_cb (lh->listen_cls, &msg->peer_id, context_msg, &req); if (GNUNET_YES == req.accepted) return; /* the accept-case is handled in #GNUNET_SET_accept() */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Rejecting request\n"); mqm = GNUNET_MQ_msg (rmsg, GNUNET_MESSAGE_TYPE_SET_REJECT); rmsg->accept_reject_id = msg->accept_id; GNUNET_MQ_send (lh->mq, mqm); }
/** * Disconnect from service and then reconnect. * * @param handle our handle */ static void force_reconnect (struct GNUNET_GNS_Handle *handle) { struct GNUNET_GNS_ShortenRequest *st; struct GNUNET_GNS_LookupRequest *lh; struct GNUNET_GNS_GetAuthRequest *ga; struct PendingMessage *p; GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; handle->in_receive = GNUNET_NO; for (st = handle->shorten_head; NULL != st; st = st->next) { p = (struct PendingMessage *) &st[1]; if (GNUNET_NO == p->transmitted) continue; p->transmitted = GNUNET_NO; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, p); } for (lh = handle->lookup_head; NULL != lh; lh = lh->next) { p = (struct PendingMessage *) &lh[1]; if (GNUNET_NO == p->transmitted) continue; p->transmitted = GNUNET_NO; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, p); } for (ga = handle->get_auth_head; NULL != ga; ga = ga->next) { p = (struct PendingMessage *) &ga[1]; if (GNUNET_NO == p->transmitted) continue; p->transmitted = GNUNET_NO; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, p); } handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, &reconnect_task, handle); }
/** * Our connection with the set service encountered an error, * re-initialize with exponential back-off. * * @param cls the `struct GNUNET_SET_ListenHandle *` * @param error reason for the disconnect */ static void handle_client_listener_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SET_ListenHandle *lh = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Listener broke down (%d), re-connecting\n", (int) error); GNUNET_CLIENT_disconnect (lh->client); lh->client = NULL; GNUNET_MQ_destroy (lh->mq); lh->mq = NULL; lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff, &listen_connect, lh); lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff); }
/** * Try reconnecting to the dht service. * * @param cls a `struct GNUNET_DHT_Handle` * @param tc scheduler context */ static void try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_Handle *handle = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting with DHT %p\n", handle); handle->retry_time = GNUNET_TIME_STD_BACKOFF (handle->retry_time); handle->reconnect_task = NULL; if (GNUNET_YES != try_connect (handle)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "dht reconnect failed(!)\n"); return; } GNUNET_CONTAINER_multihashmap_iterate (handle->active_requests, &add_request_to_pending, handle); process_pending_messages (handle); }
/** * Try reconnecting to the datastore service. * * @param cls the 'struct GNUNET_DATASTORE_Handle' * @param tc scheduler context */ static void try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DATASTORE_Handle *h = cls; h->retry_time = GNUNET_TIME_STD_BACKOFF (h->retry_time); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; h->client = GNUNET_CLIENT_connect ("datastore", h->cfg); if (h->client == NULL) { LOG (GNUNET_ERROR_TYPE_ERROR, "DATASTORE reconnect failed (fatally)\n"); return; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# datastore connections (re)created"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnected to DATASTORE\n"); process_queue (h); }
/** * Task for checking whether a host is habitable or not * * @param cls GNUNET_TESTBED_HostHabitableCheckHandle * @param tc the scheduler task context */ static void habitability_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls; void *cb_cls; GNUNET_TESTBED_HostHabitableCallback cb; const struct GNUNET_TESTBED_Host *host; unsigned long code; enum GNUNET_OS_ProcessStatusType type; int ret; h->habitability_check_task = NULL; ret = GNUNET_OS_process_status (h->auxp, &type, &code); if (GNUNET_SYSERR == ret) { GNUNET_break (0); ret = GNUNET_NO; goto call_cb; } if (GNUNET_NO == ret) { h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); h->habitability_check_task = GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); return; } GNUNET_OS_process_destroy (h->auxp); h->auxp = NULL; ret = (0 != code) ? GNUNET_NO : GNUNET_YES; call_cb: if (NULL != h->auxp) GNUNET_OS_process_destroy (h->auxp); cb = h->cb; cb_cls = h->cb_cls; host = h->host; free_argv (h->helper_argv); GNUNET_free (h); if (NULL != cb) cb (cb_cls, host, ret); }
/** * Disconnect from ATS and then reconnect. * * @param sh our handle */ static void force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh) { if (NULL != sh->mq) { GNUNET_MQ_destroy (sh->mq); sh->mq = NULL; } if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } sh->suggest_cb (sh->suggest_cb_cls, NULL, NULL, NULL, GNUNET_BANDWIDTH_ZERO, GNUNET_BANDWIDTH_ZERO); sh->backoff = GNUNET_TIME_STD_BACKOFF (sh->backoff); sh->task = GNUNET_SCHEDULER_add_delayed (sh->backoff, &reconnect_task, sh); }
/** * Close down any existing connection to the CORE service and * try re-establishing it later. * * @param h our handle */ static void reconnect_later (struct GNUNET_CORE_Handle *h) { struct ControlMessage *cm; struct PeerRecord *pr; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->currently_down = GNUNET_YES; GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_task, h); while (NULL != (cm = h->control_pending_head)) { GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, cm); if (NULL != cm->th) cm->th->cm = NULL; if (NULL != cm->cont) cm->cont (cm->cont_cls, GNUNET_NO); GNUNET_free (cm); } GNUNET_CONTAINER_multipeermap_iterate (h->peers, &disconnect_and_free_peer_entry, h); while (NULL != (pr = h->ready_peer_head)) GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); GNUNET_assert (h->control_pending_head == NULL); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); }
/** * Adjust exponential back-off and reconnect to the service. */ static void reconnect () { struct GNUNET_RESOLVER_RequestHandle *rh; if (NULL != r_task) return; GNUNET_assert (NULL == client); if (NULL != (rh = req_head)) { switch (rh->was_transmitted) { case GNUNET_NO: /* nothing more to do */ break; case GNUNET_YES: /* disconnected, transmit again! */ rh->was_transmitted = GNUNET_NO; break; case GNUNET_SYSERR: /* request was cancelled, remove entirely */ GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); break; default: GNUNET_assert (0); break; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will try to connect to DNS service in %s\n", GNUNET_STRINGS_relative_time_to_string (backoff, GNUNET_YES)); GNUNET_assert (NULL != resolver_cfg); r_task = GNUNET_SCHEDULER_add_delayed (backoff, &reconnect_task, NULL); backoff = GNUNET_TIME_STD_BACKOFF (backoff); }
/** * Reschedule a connect attempt to the service. * * @param h transport service to reconnect */ static void reschedule_connect (struct GNUNET_NSE_Handle *h) { GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to nse service in %llu ms.\n", h->reconnect_delay.rel_value); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); }
/** * Reschedule a connect attempt to the service. * * @param h transport service to reconnect */ static void reschedule_connect (struct GNUNET_PSYCSTORE_Handle *h) { GNUNET_assert (h->reconnect_task == NULL); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->in_receive = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to PSYCstore 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); }
/** * Temporarily block a valid address for use by ATS for address * suggestions. This function should be called if an address was * suggested by ATS but failed to perform (i.e. failure to establish a * session or to exchange the PING/PONG). * * @param address the address to block * @param session the session (can be NULL) */ void GST_ats_block_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session) { struct AddressInfo *ai; if (0 == memcmp (&GST_my_identity, &address->peer, sizeof (struct GNUNET_PeerIdentity))) return; /* our own, ignore! */ ai = find_ai (address, session); if (NULL == ai) { GNUNET_assert (0); return; } if (NULL == ai->ar) { /* already blocked, how did it get used!? */ GNUNET_break (0); return; } ai->back_off = GNUNET_TIME_STD_BACKOFF (ai->back_off); if (GNUNET_YES == GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing address %s of peer %s from use (inbound died)\n", GST_plugins_a2s (address), GNUNET_i2s (&address->peer)); else LOG (GNUNET_ERROR_TYPE_INFO, "Blocking address %s of peer %s from use for %s\n", GST_plugins_a2s (address), GNUNET_i2s (&address->peer), GNUNET_STRINGS_relative_time_to_string (ai->back_off, GNUNET_YES)); /* destroy session and address */ if ( (NULL == session) || (GNUNET_NO == GNUNET_ATS_address_del_session (ai->ar, session)) ) { GNUNET_ATS_address_destroy (ai->ar); } /* "ar" has been freed, regardless how the branch above played out: it was either freed in #GNUNET_ATS_address_del_session() because it was incoming, or explicitly in #GNUNET_ATS_address_del_session(). */ ai->ar = NULL; /* determine when the address should come back to life */ ai->blocked = GNUNET_TIME_relative_to_absolute (ai->back_off); ai->unblock_task = GNUNET_SCHEDULER_add_delayed (ai->back_off, &unblock_address, ai); num_blocked++; publish_p2a_stat_update (); }
/** * Periodically announce self id in the DHT * * @param cls closure */ static void announce_id (void *cls) { struct GNUNET_HashCode phash; const struct GNUNET_HELLO_Message *hello; size_t size; struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Relative next_put; hello = GCH_get_mine (); size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; if (0 == size) { expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), announce_delay); announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); } else { expiration = GNUNET_HELLO_get_last_expiration (hello); announce_delay = GNUNET_TIME_UNIT_SECONDS; } /* Call again in id_announce_time, unless HELLO expires first, * but wait at least 1s. */ next_put = GNUNET_TIME_absolute_get_remaining (expiration); next_put = GNUNET_TIME_relative_min (next_put, id_announce_time); next_put = GNUNET_TIME_relative_max (next_put, GNUNET_TIME_UNIT_SECONDS); announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, &announce_id, cls); GNUNET_STATISTICS_update (stats, "# DHT announce", 1, GNUNET_NO); memset (&phash, 0, sizeof (phash)); GNUNET_memcpy (&phash, &my_full_id, sizeof (my_full_id)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Announcing my HELLO (%u bytes) in the DHT\n", size); GNUNET_DHT_put (dht_handle, /* DHT handle */ &phash, /* Key to use */ dht_replication_level, /* Replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ size, /* Size of the data */ (const char *) hello, /* Data itself */ expiration, /* Data expiration */ NULL, /* Continuation */ NULL); /* Continuation closure */ }