/** * Notification of FS that a search probe has made progress. * This function is used INSTEAD of the client's event handler * for downloads where the #GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. * * @param cls closure, always NULL (!), actual closure * is in the client-context of the info struct * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the `struct GNUNET_FS_ProgressInfo`. */ void * GNUNET_FS_search_probe_progress_ (void *cls, const struct GNUNET_FS_ProgressInfo *info) { struct GNUNET_FS_SearchResult *sr = info->value.download.cctx; struct GNUNET_TIME_Relative dur; switch (info->status) { case GNUNET_FS_STATUS_DOWNLOAD_START: /* ignore */ break; case GNUNET_FS_STATUS_DOWNLOAD_RESUME: /* probes should never be resumed */ GNUNET_assert (0); break; case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: /* probes should never be suspended */ GNUNET_break (0); break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: /* ignore */ break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, &probe_failure_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr->probe_cancel_task = GNUNET_SCHEDULER_add_now (&probe_success_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr = NULL; break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: if (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task) { sr->probe_active_time = GNUNET_TIME_absolute_get (); sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, &probe_failure_handler, sr); } break; case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } dur = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); sr->remaining_probe_time = GNUNET_TIME_relative_subtract (sr->remaining_probe_time, dur); if (0 == sr->remaining_probe_time.rel_value_us) sr->probe_cancel_task = GNUNET_SCHEDULER_add_now (&probe_failure_handler, sr); GNUNET_FS_search_result_sync_ (sr); break; default: GNUNET_break (0); return NULL; } return sr; }
static struct GNUNET_TIME_Relative get_delay (struct TrafficGenerator *tg) { struct GNUNET_TIME_Relative delay; struct GNUNET_TIME_Relative time_delta; long long int cur_rate; long long int delta_rate; delay.rel_value_us = 0; /* Calculate the current transmission rate based on the type of traffic */ switch (tg->type) { case GNUNET_ATS_TEST_TG_CONSTANT: if (UINT32_MAX == tg->base_rate) return GNUNET_TIME_UNIT_ZERO; cur_rate = tg->base_rate; break; case GNUNET_ATS_TEST_TG_LINEAR: time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us; delta_rate = ((double) time_delta.rel_value_us / tg->duration_period.rel_value_us) * (tg->max_rate - tg->base_rate); if ((tg->max_rate < tg->base_rate) && ((tg->max_rate - tg->base_rate) > tg->base_rate)) { /* This will cause an underflow */ GNUNET_break (0); } cur_rate = tg->base_rate + delta_rate; break; case GNUNET_ATS_TEST_TG_RANDOM: cur_rate = tg->base_rate + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tg->max_rate - tg->base_rate); break; case GNUNET_ATS_TEST_TG_SINUS: time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us; if ((tg->max_rate - tg->base_rate) > tg->base_rate) { /* This will cause an underflow for second half of sinus period, * will be detected in general when experiments are loaded */ GNUNET_break (0); } delta_rate = (tg->max_rate - tg->base_rate) * sin ( (2 * M_PI) / ((double) tg->duration_period.rel_value_us) * time_delta.rel_value_us); cur_rate = tg->base_rate + delta_rate; break; default: return delay; break; } if (cur_rate < 0) { cur_rate = 1; } /* Calculate the delay for the next message based on the current delay */ delay.rel_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us * TEST_MESSAGE_SIZE / cur_rate; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Current rate is %u, calculated delay is %u \n", cur_rate, delay.rel_value_us); return delay; }
static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: printf ("Publishing complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); start = GNUNET_TIME_absolute_get (); unindex = GNUNET_FS_unindex_start (fs, fn, "unindex"); GNUNET_assert (unindex != NULL); break; case GNUNET_FS_STATUS_UNINDEX_COMPLETED: printf ("Unindex complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); GNUNET_SCHEDULER_add_now (&abort_unindex_task, NULL); break; case GNUNET_FS_STATUS_UNINDEX_PROGRESS: consider_restart (event->status); GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unindex is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.unindex.completed, (unsigned long long) event->value.unindex.size, event->value.unindex.specifics.progress.depth, (unsigned long long) event->value.unindex.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_SUSPEND: if (event->value.publish.pc == publish) publish = NULL; break; case GNUNET_FS_STATUS_PUBLISH_RESUME: if (NULL == publish) { publish = event->value.publish.pc; return "publish-context"; } break; case GNUNET_FS_STATUS_UNINDEX_SUSPEND: GNUNET_assert (event->value.unindex.uc == unindex); unindex = NULL; break; case GNUNET_FS_STATUS_UNINDEX_RESUME: GNUNET_assert (NULL == unindex); unindex = event->value.unindex.uc; return "unindex"; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL); break; case GNUNET_FS_STATUS_UNINDEX_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error unindexing file: %s\n", event->value.unindex.specifics.error.message); GNUNET_SCHEDULER_add_now (&abort_unindex_task, NULL); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_UNINDEX_START: consider_restart (event->status); GNUNET_assert (unindex == NULL); GNUNET_assert (0 == strcmp ("unindex", event->value.unindex.cctx)); GNUNET_assert (0 == strcmp (fn, event->value.unindex.filename)); GNUNET_assert (FILESIZE == event->value.unindex.size); GNUNET_assert (0 == event->value.unindex.completed); break; case GNUNET_FS_STATUS_UNINDEX_STOPPED: GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL); break; default: printf ("Unexpected event: %d\n", event->status); break; } return NULL; }
/** * Function called when the transport service is ready to receive a * message for the respective peer * * @param cls neighbour to use message from * @param size number of bytes we can transmit * @param buf where to copy the message * @return number of bytes transmitted */ static size_t transmit_ready (void *cls, size_t size, void *buf) { struct Neighbour *n = cls; struct NeighbourMessageEntry *m; size_t ret; char *cbuf; struct GNUNET_TIME_Relative delay; struct GNUNET_TIME_Relative overdue; n->th = NULL; m = n->message_head; if (NULL == m) { GNUNET_break (0); return 0; } GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m); n->queue_size--; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission of message of type %u and size %u failed\n", (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type), (unsigned int) m->size); GNUNET_free (m); process_queue (n); return 0; } delay = GNUNET_TIME_absolute_get_duration (m->submission_time); overdue = GNUNET_TIME_absolute_get_duration (m->deadline); cbuf = buf; GNUNET_assert (size >= m->size); memcpy (cbuf, &m[1], m->size); ret = m->size; if (overdue.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Copied overdue message of type %u and size %u into transport buffer for `%s' with delay of %s\n", (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type), (unsigned int) ret, GNUNET_i2s (&n->peer), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Copied message of type %u and size %u into transport buffer for `%s' with delay of %s\n", (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type), (unsigned int) ret, GNUNET_i2s (&n->peer), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); GNUNET_free (m); n->has_excess_bandwidth = GNUNET_NO; process_queue (n); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# encrypted bytes given to transport"), ret, GNUNET_NO); return ret; }
/** * We've received a PONG. Check if it matches a pending PING and * mark the respective address as confirmed. * * @param sender peer sending the PONG * @param hdr the PONG */ void GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr) { const struct TransportPongMessage *pong; struct ValidationEntry *ve; const char *tname; const char *addr; size_t addrlen; size_t slen; size_t size; struct GNUNET_HELLO_Message *hello; struct GNUNET_HELLO_Address address; if (ntohs (hdr->size) < sizeof (struct TransportPongMessage)) { GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO); pong = (const struct TransportPongMessage *) hdr; tname = (const char *) &pong[1]; size = ntohs (hdr->size) - sizeof (struct TransportPongMessage); addr = memchr (tname, '\0', size); if (NULL == addr) { GNUNET_break_op (0); return; } addr++; slen = strlen (tname) + 1; addrlen = size - slen; address.peer = *sender; address.address = addr; address.address_length = addrlen; address.transport_name = tname; ve = find_validation_entry (NULL, &address); if ((NULL == ve) || (ve->expecting_pong == GNUNET_NO)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs dropped, no matching pending validation"), 1, GNUNET_NO); return; } /* now check that PONG is well-formed */ if (0 != memcmp (&ve->pid, sender, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return; } if (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &pong->purpose, &pong->signature, &ve->public_key)) { GNUNET_break_op (0); return; } if (GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value == 0) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs dropped, signature expired"), 1, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Address validated for peer `%s' with plugin `%s': `%s'\n", GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address)); /* validity achieved, remember it! */ ve->expecting_pong = GNUNET_NO; ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); ve->latency = GNUNET_TIME_absolute_get_duration (ve->send_time); { struct GNUNET_ATS_Information ats; ats.type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); ats.value = htonl ((uint32_t) ve->latency.rel_value); GNUNET_ATS_address_update (GST_ats, ve->address, NULL, &ats, 1); } /* build HELLO to store in PEERINFO */ ve->copied = GNUNET_NO; hello = GNUNET_HELLO_create (&ve->public_key, &add_valid_peer_address, ve); GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL); GNUNET_free (hello); }
static int testDirectory (unsigned int i) { struct GNUNET_FS_DirectoryBuilder *db; char *data; size_t dlen; struct GNUNET_FS_Uri **uris; struct GNUNET_CONTAINER_MetaData **mds; struct GNUNET_CONTAINER_MetaData *meta; struct PCLS cls; char *emsg; int p; int q; char uri[512]; char txt[128]; int ret = 0; struct GNUNET_TIME_Absolute start; const char *s; cls.max = i; uris = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri *) * i); mds = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MetaData *) * i); meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "A title", strlen ("A title") + 1); GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_AUTHOR_NAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "An author", strlen ("An author") + 1); for (p = 0; p < i; p++) { mds[p] = GNUNET_CONTAINER_meta_data_create (); for (q = 0; q <= p; q++) { GNUNET_snprintf (txt, sizeof (txt), "%u -- %u\n", p, q); GNUNET_CONTAINER_meta_data_insert (mds[p], "<test>", #if HAVE_EXTRACTOR_H && HAVE_LIBEXTRACTOR q % EXTRACTOR_metatype_get_max (), #else q % 128, #endif EXTRACTOR_METAFORMAT_UTF8, "text/plain", txt, strlen (txt) + 1); } GNUNET_snprintf (uri, sizeof (uri), "gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.%u", p); emsg = NULL; uris[p] = GNUNET_FS_uri_parse (uri, &emsg); if (uris[p] == NULL) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); while (--p > 0) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); GNUNET_FS_uri_destroy (uris[p]); } GNUNET_free (mds); GNUNET_free (uris); GNUNET_free (emsg); GNUNET_CONTAINER_meta_data_destroy (meta); ABORT (); /* error in testcase */ } GNUNET_assert (emsg == NULL); } start = GNUNET_TIME_absolute_get (); db = GNUNET_FS_directory_builder_create (meta); for (p = 0; p < i; p++) GNUNET_FS_directory_builder_add (db, uris[p], mds[p], NULL); GNUNET_FS_directory_builder_finish (db, &dlen, (void **) &data); s = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES); FPRINTF (stdout, "Creating directory with %u entires and total size %llu took %s\n", i, (unsigned long long) dlen, s); if (i < 100) { cls.pos = 0; cls.uri = uris; cls.md = mds; GNUNET_FS_directory_list_contents (dlen, data, 0, &processor, &cls); GNUNET_assert (cls.pos == i); } GNUNET_free (data); GNUNET_CONTAINER_meta_data_destroy (meta); for (p = 0; p < i; p++) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); GNUNET_FS_uri_destroy (uris[p]); } GNUNET_free (uris); GNUNET_free (mds); return ret; }