static void put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) { struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded zone_key; struct GNUNET_TIME_Absolute expire; char name[64]; unsigned int rd_count = 1 + (id % 1024); struct GNUNET_NAMESTORE_RecordData rd[rd_count]; struct GNUNET_CRYPTO_RsaSignature signature; unsigned int i; GNUNET_snprintf (name, sizeof (name), "a%u", (unsigned int ) id); expire = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); for (i=0;i<rd_count;i++) { rd[i].data = "Hello World"; rd[i].data_size = id % 10; rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES).abs_value; rd[i].record_type = 1 + (id % 13); rd[i].flags = (id % 7); } memset (&zone_key, (id % 241), sizeof (zone_key)); memset (&signature, (id % 243), sizeof (signature)); GNUNET_assert (GNUNET_OK == nsp->put_records (nsp->cls, &zone_key, expire, name, rd_count, rd, &signature)); }
/** * Returns the expiration time of the given block of records. The block * expiration time is the expiration time of the record with smallest * expiration time. * * @param rd_count number of records given in @a rd * @param rd array of records * @return absolute expiration time */ struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { unsigned int c; unsigned int c2; struct GNUNET_TIME_Absolute expire; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Relative rt; struct GNUNET_TIME_Absolute at_shadow; struct GNUNET_TIME_Relative rt_shadow; if (NULL == rd) return GNUNET_TIME_UNIT_ZERO_ABS; expire = GNUNET_TIME_UNIT_FOREVER_ABS; for (c = 0; c < rd_count; c++) { if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { rt.rel_value_us = rd[c].expiration_time; at = GNUNET_TIME_relative_to_absolute (rt); } else { at.abs_value_us = rd[c].expiration_time; } for (c2 = 0; c2 < rd_count; c2++) { /* Check for shadow record */ if ((c == c2) || (rd[c].record_type != rd[c2].record_type) || (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))) continue; /* We have a shadow record */ if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { rt_shadow.rel_value_us = rd[2].expiration_time; at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow); } else { at_shadow.abs_value_us = rd[c2].expiration_time; } at = GNUNET_TIME_absolute_max (at, at_shadow); } expire = GNUNET_TIME_absolute_min (at, expire); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Determined expiration time for block with %u records to be %s\n", rd_count, GNUNET_STRINGS_absolute_time_to_string (expire)); return expire; }
/** * Do address validation again to keep address valid. * * @param cls the 'struct ValidationEntry' * @param tc scheduler context (unused) */ static void revalidate_address (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ValidationEntry *ve = cls; struct GNUNET_TIME_Relative canonical_delay; struct GNUNET_TIME_Relative delay; struct GST_BlacklistCheck *bc; uint32_t rdelay; ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; delay = GNUNET_TIME_absolute_get_remaining (ve->revalidation_block); /* How long until we can possibly permit the next PING? */ canonical_delay = (ve->in_use == GNUNET_YES) ? CONNECTED_PING_FREQUENCY : ((GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value > 0) ? VALIDATED_PING_FREQUENCY : UNVALIDATED_PING_KEEPALIVE); if (delay.rel_value > canonical_delay.rel_value * 2) { /* situation changed, recalculate delay */ delay = canonical_delay; ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay); } if (delay.rel_value > 0) { /* should wait a bit longer */ ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); return; } ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay); /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */ rdelay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, canonical_delay.rel_value); delay = GNUNET_TIME_relative_add (canonical_delay, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rdelay)); ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); /* start PINGing by checking blacklist */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# address revalidations started"), 1, GNUNET_NO); bc = GST_blacklist_test_allowed (&ve->pid, ve->address->transport_name, &transmit_ping_if_allowed, ve); if (NULL != bc) ve->bc = bc; /* only set 'bc' if 'transmit_ping_if_allowed' was not already * called... */ }
/** * Modify the given DNS record by asking VPN to create a tunnel * to the given address. When done, continue with submitting * other records from the request context ('submit_request' is * our continuation). * * @param rc context to process * @param rec record to modify */ static void modify_address (struct ReplyContext *rc, struct GNUNET_DNSPARSER_Record *rec) { int af; switch (rec->type) { case GNUNET_DNSPARSER_TYPE_A: af = AF_INET; GNUNET_assert (rec->data.raw.data_len == sizeof (struct in_addr)); break; case GNUNET_DNSPARSER_TYPE_AAAA: af = AF_INET6; GNUNET_assert (rec->data.raw.data_len == sizeof (struct in6_addr)); break; default: GNUNET_assert (0); return; } rc->rec = rec; rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle, af, af, rec->data.raw.data, GNUNET_NO /* nac */, GNUNET_TIME_relative_to_absolute (TIMEOUT), &vpn_allocation_callback, rc); }
/** * Return information about a specific peer or all peers currently known to * transport service once or in monitoring mode. To obtain information about * a specific peer, a peer identity can be passed. To obtain information about * all peers currently known to transport service, NULL can be passed as peer * identity. * * For each peer, the callback is called with information about the address used * to communicate with this peer, the state this peer is currently in and the * the current timeout for this state. * * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one * more time with 'NULL'. After this, the operation must no longer be * explicitly canceled. * * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the * the peer_callback! * * @param cfg configuration to use * @param peer a specific peer identity to obtain information for, * NULL for all peers * @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL), * GNUNET_NO to monitor peers continuously * @param timeout how long is the lookup allowed to take at most * @param peer_callback function to call with the results * @param peer_callback_cls closure for peer_address_callback */ struct GNUNET_TRANSPORT_PeerMonitoringContext * GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_PeerIterateCallback peer_callback, void *peer_callback_cls) { struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("transport", cfg); if (client == NULL) return NULL; if (GNUNET_YES != one_shot) timeout = GNUNET_TIME_UNIT_FOREVER_REL; pal_ctx = GNUNET_new (struct GNUNET_TRANSPORT_PeerMonitoringContext); pal_ctx->cb = peer_callback; pal_ctx->cb_cls = peer_callback_cls; pal_ctx->cfg = cfg; pal_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL != peer) pal_ctx->peer = *peer; pal_ctx->one_shot = one_shot; pal_ctx->client = client; send_peer_mon_request (pal_ctx); return pal_ctx; }
/** * Return information about pending address validation operations for a specific * or all peers * * @param cfg configuration to use * @param peer a specific peer identity to obtain validation entries for, * NULL for all peers * @param one_shot #GNUNET_YES to return all entries and then end (with NULL+NULL), * #GNUNET_NO to monitor validation entries continuously * @param timeout how long is the lookup allowed to take at most * @param validation_callback function to call with the results * @param validation_callback_cls closure for peer_address_callback */ struct GNUNET_TRANSPORT_ValidationMonitoringContext * GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_ValidationIterateCallback validation_callback, void *validation_callback_cls) { struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("transport", cfg); if (NULL == client) return NULL; if (GNUNET_YES != one_shot) timeout = GNUNET_TIME_UNIT_FOREVER_REL; val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext); val_ctx->cb = validation_callback; val_ctx->cb_cls = validation_callback_cls; val_ctx->cfg = cfg; val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL != peer) val_ctx->peer = *peer; val_ctx->one_shot = one_shot; val_ctx->client = client; send_val_mon_request (val_ctx); return val_ctx; }
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_HashCode hash; char *data; size_t data_size = 42; GNUNET_assert (ok == 1); OKPP; die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly, NULL); memset (&hash, 42, sizeof (struct GNUNET_HashCode)); data = GNUNET_malloc (data_size); memset (data, 43, data_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_put!\n"); dht_handle = GNUNET_DHT_connect (cfg, 100); GNUNET_assert (dht_handle != NULL); GNUNET_DHT_put (dht_handle, &hash, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, data_size, data, GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT), &test_get, NULL); GNUNET_free (data); }
/** * Transmit the given message to the given target. * * @param target peer that should receive the message (must be connected) * @param msg message to transmit * @param timeout by when should the transmission be done? */ void GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative timeout) { struct NeighbourMessageEntry *me; struct Neighbour *n; size_t msize; n = find_neighbour (target); if (NULL == n) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer %s not found\n", GNUNET_i2s (target)); return; } msize = ntohs (msg->size); me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize); me->deadline = GNUNET_TIME_relative_to_absolute (timeout); me->size = msize; memcpy (&me[1], msg, msize); GNUNET_CONTAINER_DLL_insert_tail (n->message_head, n->message_tail, me); n->queue_size++; process_queue (n); }
static void sks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; char *msg; struct GNUNET_FS_BlockOptions bo; if (NULL == uri) { fprintf (stderr, "Error publishing: %s\n", emsg); err = 1; GNUNET_FS_stop (fs); return; } meta = GNUNET_CONTAINER_meta_data_create (); msg = NULL; ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg); GNUNET_assert (NULL == msg); ksk_expect_uri = GNUNET_FS_uri_dup (uri); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); GNUNET_FS_publish_ksk (fs, ksk_uri, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &publish_cont, NULL); GNUNET_FS_uri_destroy (ksk_uri); GNUNET_CONTAINER_meta_data_destroy (meta); }
/** * Convenience API that combines sending a request * to the service and waiting for a response. * If either operation times out, the callback * will be called with a "NULL" response (in which * case the connection should probably be destroyed). * * @param client connection to use * @param hdr message to transmit * @param timeout when to give up (for both transmission * and for waiting for a response) * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param rn function to call with the response * @param rn_cls closure for rn * @return GNUNET_OK on success, GNUNET_SYSERR if a request * is already pending */ int GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *client, const struct GNUNET_MessageHeader *hdr, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CLIENT_MessageHandler rn, void *rn_cls) { struct TransmitGetResponseContext *tc; uint16_t msize; if (NULL != client->th) return GNUNET_SYSERR; GNUNET_assert (NULL == client->tag); msize = ntohs (hdr->size); tc = GNUNET_malloc (sizeof (struct TransmitGetResponseContext) + msize); tc->client = client; tc->hdr = (const struct GNUNET_MessageHeader *) &tc[1]; memcpy (&tc[1], hdr, msize); tc->timeout = GNUNET_TIME_relative_to_absolute (timeout); tc->rn = rn; tc->rn_cls = rn_cls; if (NULL == GNUNET_CLIENT_notify_transmit_ready (client, msize, timeout, auto_retry, &transmit_for_response, tc)) { GNUNET_break (0); GNUNET_free (tc); return GNUNET_SYSERR; } client->tag = tc; return GNUNET_OK; }
static void put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) { struct GNUNET_CRYPTO_EcdsaPrivateKey zone_private_key; char label[64]; unsigned int rd_count = 1 + (id % 1024); struct GNUNET_GNSRECORD_Data rd[rd_count]; struct GNUNET_CRYPTO_EcdsaSignature signature; unsigned int i; GNUNET_snprintf (label, sizeof (label), "a%u", (unsigned int ) id); for (i=0;i<rd_count;i++) { rd[i].data = "Hello World"; rd[i].data_size = id % 10; rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES).abs_value_us; rd[i].record_type = 1 + (id % 13); rd[i].flags = 0; } memset (&zone_private_key, (id % 241), sizeof (zone_private_key)); memset (&signature, (id % 243), sizeof (signature)); GNUNET_assert (GNUNET_OK == nsp->store_records (nsp->cls, &zone_private_key, label, rd_count, rd)); }
/** * 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); }
/** * Receive data from the given connection. Note that this function will * call "receiver" asynchronously using the scheduler. It will * "immediately" return. Note that there MUST only be one active * receive call per connection at any given point in time (so do not * call receive again until the receiver callback has been invoked). * * @param connection connection handle * @param max maximum number of bytes to read * @param timeout maximum amount of time to wait * @param receiver function to call with received data * @param receiver_cls closure for receiver */ void GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t max, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_Receiver receiver, void *receiver_cls) { GNUNET_assert ((GNUNET_SCHEDULER_NO_TASK == connection->read_task) && (NULL == connection->receiver)); GNUNET_assert (NULL != receiver); connection->receiver = receiver; connection->receiver_cls = receiver_cls; connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); connection->max = max; if (NULL != connection->sock) { connection->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (connection->receive_timeout), connection->sock, &receive_ready, connection); return; } if ((NULL == connection->dns_active) && (NULL == connection->ap_head)) { connection->receiver = NULL; receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT); return; } }
/** * Request a list of running services. * * @param h handle to ARM * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or is not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ServiceListCallback cont, void *cont_cls) { struct ARMControlMessage *cm; struct GNUNET_ARM_Message *msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting LIST from ARM service with timeout: %s\n", GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES)); cm = GNUNET_new (struct ARMControlMessage); cm->h = h; cm->list_cont = cont; cm->cont_cls = cont_cls; cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message)); msg->header.size = htons (sizeof (struct GNUNET_ARM_Message)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST); msg->reserved = htonl (0); cm->msg = msg; GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, h->control_pending_tail, cm); cm->timeout_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (cm->timeout), &control_message_timeout, cm); trigger_next_request (h, GNUNET_NO); }
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct CpsRunContext *crc; static struct GNUNET_HashCode zkey; datastore = GNUNET_DATASTORE_connect (cfg); start_time = GNUNET_TIME_absolute_get (); crc = GNUNET_malloc (sizeof (struct CpsRunContext)); crc->cfg = cfg; crc->phase = RP_PUT; if (NULL == GNUNET_DATASTORE_put (datastore, 0, &zkey, 4, "TEST", GNUNET_BLOCK_TYPE_TEST, 0, 0, 0, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS), 0, 1, GNUNET_TIME_UNIT_MINUTES, &run_tests, crc)) { FPRINTF (stderr, "%s", "Test 'put' operation failed.\n"); ok = 1; GNUNET_free (crc); } }
/** * Signature of the main function of a task. * * @param cls closure * @param success result of PUT */ static void test_get (void *cls, int success) { struct GNUNET_HashCode hash; memset (&hash, 42, sizeof (struct GNUNET_HashCode)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_get!\n"); GNUNET_assert (dht_handle != NULL); retry_context.real_timeout = GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT); retry_context.next_timeout = BASE_TIMEOUT; get_handle = GNUNET_DHT_get_start (dht_handle, GNUNET_BLOCK_TYPE_TEST, &hash, 1, GNUNET_DHT_RO_NONE, NULL, 0, &test_get_iterator, NULL); if (get_handle == NULL) { GNUNET_break (0); GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } }
/** * Signature of the main function of a task. * * @param cls closure */ static void test_task (void *cls) { struct GNUNET_TIME_Absolute now; now = GNUNET_TIME_absolute_get (); if (now.abs_value_us > target.abs_value_us) cumDelta += (now.abs_value_us - target.abs_value_us); else cumDelta += (target.abs_value_us - now.abs_value_us); target = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, i)); FPRINTF (stderr, "%s", "."); if (i > MAXV) { FPRINTF (stderr, "%s", "\n"); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, i), &test_task, NULL); i += INCR; }
static void testNamespace () { struct GNUNET_CRYPTO_EcdsaPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; struct GNUNET_FS_Uri *sks_uri; ns = GNUNET_CRYPTO_ecdsa_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); sks_uri = GNUNET_FS_uri_sks_create (&nsid, "root"); GNUNET_FS_publish_ksk (fs, ksk_uri, meta, sks_uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &adv_cont, NULL); GNUNET_FS_uri_destroy (sks_uri); kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &do_timeout, NULL); GNUNET_FS_uri_destroy (ksk_uri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_free (ns); }
static void adv_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_CRYPTO_EcdsaPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; if (NULL != emsg) { FPRINTF (stderr, "Error publishing: %s\n", emsg); err = 1; GNUNET_FS_stop (fs); return; } ns = GNUNET_CRYPTO_ecdsa_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); sks_expect_uri = GNUNET_FS_uri_dup (uri); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); GNUNET_CRYPTO_ecdsa_key_get_public (ns, &nsid); GNUNET_FS_publish_sks (fs, ns, "this", "next", meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &sks_cont, NULL); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_free (ns); }
/** * Read from the service. * * @param client the service * @param handler function to call with the message * @param handler_cls closure for handler * @param timeout how long to wait until timing out */ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, GNUNET_CLIENT_MessageHandler handler, void *handler_cls, struct GNUNET_TIME_Relative timeout) { if (NULL == client->connection) { /* already disconnected, fail instantly! */ GNUNET_break (0); /* this should not happen in well-written code! */ if (NULL != handler) handler (handler_cls, NULL); return; } client->receiver_handler = handler; client->receiver_handler_cls = handler_cls; client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); if (GNUNET_YES == client->msg_complete) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->receive_task); client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "calling GNUNET_CONNECTION_receive\n"); GNUNET_assert (GNUNET_NO == client->in_receive); client->in_receive = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, timeout, &receive_helper, client); } }
/** * Construct our HELLO message from all of the addresses of * all of the transports. * * @param cls unused * @param tc scheduler context */ static void refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GeneratorContext gc; int friend_only; hello_task = GNUNET_SCHEDULER_NO_TASK; gc.addr_pos = oal_head; gc.expiration = GNUNET_TIME_relative_to_absolute (hello_expiration); friend_only = GNUNET_HELLO_is_friend_only (our_hello); GNUNET_free (our_hello); our_hello = GNUNET_HELLO_create (&GST_my_public_key, &address_generator, &gc, friend_only); GNUNET_assert (NULL != our_hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Refreshed my %s `%s', new size is %d\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (our_hello)) ? "friend-only" : "public", "HELLO", GNUNET_HELLO_size (our_hello)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# refreshed my HELLO"), 1, GNUNET_NO); if (NULL != hello_cb) hello_cb (hello_cb_cls, GST_hello_get ()); GNUNET_PEERINFO_add_peer (GST_peerinfo, our_hello, NULL, NULL); hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_REFRESH_PERIOD, &refresh_hello_task, NULL); }
/** * Calculate when we would like to send the next HELLO to this * peer and ask for it. * * @param cls for which peer to schedule the HELLO */ static void schedule_next_hello (void *cls) { struct Peer *pl = cls; struct FindAdvHelloContext fah; struct GNUNET_MQ_Envelope *env; size_t want; struct GNUNET_TIME_Relative delay; struct GNUNET_HashCode hc; pl->hello_delay_task = NULL; GNUNET_assert (NULL != pl->mq); /* find applicable HELLOs */ fah.peer = pl; fah.result = NULL; fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); pl->hello_delay_task = GNUNET_SCHEDULER_add_delayed (fah.next_adv, &schedule_next_hello, pl); if (NULL == fah.result) return; delay = GNUNET_TIME_absolute_get_remaining (pl->next_hello_allowed); if (0 != delay.rel_value_us) return; want = GNUNET_HELLO_size (fah.result->hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending HELLO with %u bytes", (unsigned int) want); env = GNUNET_MQ_msg_copy (&fah.result->hello->header); GNUNET_MQ_send (pl->mq, env); /* avoid sending this one again soon */ GNUNET_CRYPTO_hash (&pl->pid, sizeof (struct GNUNET_PeerIdentity), &hc); GNUNET_CONTAINER_bloomfilter_add (fah.result->filter, &hc); GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages gossipped"), 1, GNUNET_NO); /* prepare to send the next one */ if (NULL != pl->hello_delay_task) GNUNET_SCHEDULER_cancel (pl->hello_delay_task); pl->next_hello_allowed = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY); pl->hello_delay_task = GNUNET_SCHEDULER_add_now (&schedule_next_hello, pl); }
/** * Call a method for each known matching host and change its trust * value. The callback method will be invoked once for each matching * host and then finally once with a NULL pointer. After that final * invocation, the iterator context must no longer be used. * * Instead of calling this function with 'peer == NULL' it is often * better to use 'GNUNET_PEERINFO_notify'. * * @param h handle to the peerinfo service * @param peer restrict iteration to this peer only (can be NULL) * @param timeout how long to wait until timing out * @param callback the method to call for each peer * @param callback_cls closure for callback * @return iterator context */ struct GNUNET_PEERINFO_IteratorContext * GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_PeerIdentity *peer, struct GNUNET_TIME_Relative timeout, GNUNET_PEERINFO_Processor callback, void *callback_cls) { struct GNUNET_MessageHeader *lapm; struct ListPeerMessage *lpm; struct GNUNET_PEERINFO_IteratorContext *ic; struct GNUNET_PEERINFO_AddContext *ac; ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext)); if (NULL == peer) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting list of peers from PEERINFO service\n"); ac = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) + sizeof (struct GNUNET_MessageHeader)); ac->size = sizeof (struct GNUNET_MessageHeader); lapm = (struct GNUNET_MessageHeader *) &ac[1]; lapm->size = htons (sizeof (struct GNUNET_MessageHeader)); lapm->type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting information on peer `%4s' from PEERINFO service\n", GNUNET_i2s (peer)); ac = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) + sizeof (struct ListPeerMessage)); ac->size = sizeof (struct ListPeerMessage); lpm = (struct ListPeerMessage *) &ac[1]; lpm->header.size = htons (sizeof (struct ListPeerMessage)); lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET); memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity)); ic->have_peer = GNUNET_YES; ic->peer = *peer; } ic->h = h; ic->ac = ac; ic->callback = callback; ic->callback_cls = callback_cls; ic->timeout = GNUNET_TIME_relative_to_absolute (timeout); ic->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &signal_timeout, ic); ac->cont = &iterator_start_receive; ac->cont_cls = ic; GNUNET_CONTAINER_DLL_insert_tail (h->ac_head, h->ac_tail, ac); GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic); trigger_transmit (h); return ic; }
/** * Get an IP address as a string. * * @param sa host address * @param salen length of host address in @a sa * @param do_resolve use #GNUNET_NO to return numeric hostname * @param timeout how long to try resolving * @param callback function to call with hostnames * last callback is NULL when finished * @param cls closure for @a callback * @return handle that can be used to cancel the request */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t ip_len; const void *ip; check_config (); switch (sa->sa_family) { case AF_INET: GNUNET_assert (salen == sizeof (struct sockaddr_in)); ip_len = sizeof (struct in_addr); ip = &((const struct sockaddr_in*)sa)->sin_addr; break; case AF_INET6: GNUNET_assert (salen == sizeof (struct sockaddr_in6)); ip_len = sizeof (struct in6_addr); ip = &((const struct sockaddr_in6*)sa)->sin6_addr; break; default: GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen); rh->name_callback = callback; rh->cls = cls; rh->af = sa->sa_family; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); memcpy (&rh[1], ip, ip_len); rh->data_len = ip_len; rh->direction = GNUNET_YES; rh->received_response = GNUNET_NO; if (GNUNET_NO == do_resolve) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (NULL != s_task) { GNUNET_SCHEDULER_cancel (s_task); s_task = NULL; } process_requests (); return rh; }
/** * Ask the core to call @a notify once it is ready to transmit the * given number of bytes to the specified @a target. Must only be * called after a connection to the respective peer has been * established (and the client has been informed about this). You may * have one request of this type pending for each connected peer at * any time. If a peer disconnects, the application MUST call * #GNUNET_CORE_notify_transmit_ready_cancel on the respective * transmission request, if one such request is pending. * * @param handle connection to core service * @param cork is corking allowed for this transmission? * @param priority how important is the message? * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES * @param target who should receive the message, never NULL (can be this peer's identity for loopback) * @param notify_size how many bytes of buffer space does @a notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout; clients MUST cancel * all pending transmission requests DURING the disconnect * handler * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we can not even queue the request (request already pending); * if NULL is returned, @a notify will NOT be called. */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, int cork, enum GNUNET_CORE_Priority priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; if (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } GNUNET_assert (NULL != notify); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asking core for transmission of %u bytes to `%s'\n", (unsigned int) notify_size, GNUNET_i2s (target)); pr = GNUNET_CONTAINER_multipeermap_get (handle->peers, target); if (NULL == pr) { /* attempt to send to peer that is not connected */ GNUNET_break (0); return NULL; } if (NULL != pr->th.peer) { /* attempting to queue a second request for the same destination */ GNUNET_break (0); return NULL; } GNUNET_assert (notify_size + sizeof (struct SendMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); th = &pr->th; memset (th, 0, sizeof (struct GNUNET_CORE_TransmitHandle)); th->peer = pr; th->get_message = notify; th->get_message_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->priority = priority; th->msize = notify_size; th->cork = cork; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_add_now (&run_request_next_transmission, pr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission request added to queue\n"); return th; }
/** * Ask the client to call us once the specified number of bytes * are free in the transmission buffer. Will never call the @a notify * callback in this task, but always first go into the scheduler. * * @param client connection to the service * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param notify function to call * @param notify_cls closure for @a notify * @return NULL if our buffer will never hold size bytes, * a handle if the notify callback was queued (can be used to cancel) */ struct GNUNET_CLIENT_TransmitHandle * GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, size_t size, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct GNUNET_CLIENT_TransmitHandle *th; if (NULL != client->th) { /* If this breaks, you most likley called this function twice without waiting * for completion or canceling the request */ GNUNET_assert (0); return NULL; } th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle); th->client = client; th->size = size; th->timeout = GNUNET_TIME_relative_to_absolute (timeout); /* always auto-retry on first message to service */ th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry; client->first_message = GNUNET_NO; th->notify = notify; th->notify_cls = notify_cls; th->attempts_left = MAX_ATTEMPTS; client->th = th; if (NULL == client->connection) { GNUNET_assert (NULL == th->th); GNUNET_assert (NULL == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (client->back_off, &client_delayed_retry, th); } else { th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size, timeout, &client_notify, th); if (NULL == th->th) { GNUNET_break (0); GNUNET_free (th); client->th = NULL; return NULL; } } return th; }
/** * Convert a string to one or more IP addresses. * * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param callback_cls closure for callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t slen; unsigned int i; struct in_addr v4; struct in6_addr v6; slen = strlen (hostname) + 1; if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); rh->af = af; rh->addr_callback = callback; rh->cls = callback_cls; memcpy (&rh[1], hostname, slen); rh->data_len = slen; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); rh->direction = GNUNET_NO; /* first, check if this is a numeric address */ if (((1 == inet_pton (AF_INET, hostname, &v4)) && ((af == AF_INET) || (af == AF_UNSPEC))) || ((1 == inet_pton (AF_INET6, hostname, &v6)) && ((af == AF_INET6) || (af == AF_UNSPEC)))) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh); return rh; } /* then, check if this is a loopback address */ i = 0; while (loopback[i] != NULL) if (0 == strcasecmp (loopback[i++], hostname)) { rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (s_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s_task); s_task = GNUNET_SCHEDULER_NO_TASK; } process_requests (); return rh; }
/** * Ask the connection to call us once the specified number of bytes * are free in the transmission buffer. May call the notify * method immediately if enough space is available. * * @param connection connection * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param notify function to call * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we are already going to notify someone else (busy) */ struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { if (NULL != connection->nth.notify_ready) { GNUNET_assert (0); return NULL; } GNUNET_assert (NULL != notify); GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (connection->write_buffer_off <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_off); connection->nth.notify_ready = notify; connection->nth.notify_ready_cls = notify_cls; connection->nth.connection = connection; connection->nth.notify_size = size; connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); if ((NULL == connection->sock) && (NULL == connection->ap_head) && (NULL == connection->dns_active)) { if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) GNUNET_SCHEDULER_cancel (connection->write_task); connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error, connection); return &connection->nth; } if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) return &connection->nth; /* previous transmission still in progress */ if (NULL != connection->sock) { /* connected, try to transmit now */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmission (%p).\n", connection); connection->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout), connection->sock, &transmit_ready, connection); return &connection->nth; } /* not yet connected, wait for connection */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Need to wait to schedule transmission for connection, adding timeout task (%p).\n", connection); connection->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, connection); return &connection->nth; }
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar" }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_BlockOptions bo; struct GNUNET_FS_FileInformation *fi; size_t i; size_t j; fs = GNUNET_FS_start (cfg, "test-fs-search", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); processed_files = 0; for(j = 0; j < NUM_FILES; j++){ buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } timeout_task = GNUNET_SCHEDULER_add_delayed (LIFETIME, &abort_error, NULL); }
/** * Execute a transmission context. If there is * an error in the transmission, the #GNUNET_SERVER_receive_done() * method will be called with an error code (#GNUNET_SYSERR), * otherwise with #GNUNET_OK. * * @param tc transmission context to use * @param timeout when to time out and abort the transmission */ void GNUNET_SERVER_transmit_context_run (struct GNUNET_SERVER_TransmitContext *tc, struct GNUNET_TIME_Relative timeout) { tc->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL == GNUNET_SERVER_notify_transmit_ready (tc->client, GNUNET_MIN (MIN_BLOCK_SIZE, tc->total), timeout, &transmit_response, tc)) { GNUNET_break (0); GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR); } }