/** * Method called to retrieve information about a specific tunnel the mesh peer * has established, o`r is trying to establish. * * @param cls Closure. * @param peer Peer towards whom the tunnel is directed. * @param n_channels Number of channels. * @param n_connections Number of connections. * @param channels Channels. * @param connections Connections. * @param estate Encryption status. * @param cstate Connectivity status. */ void tunnel_callback (void *cls, const struct GNUNET_PeerIdentity *peer, unsigned int n_channels, unsigned int n_connections, uint32_t *channels, struct GNUNET_HashCode *connections, unsigned int estate, unsigned int cstate) { unsigned int i; if (NULL != peer) { FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer)); FPRINTF (stdout, "- %u channels\n", n_channels); for (i = 0; i < n_channels; i++) FPRINTF (stdout, " %u\n", channels[i]); FPRINTF (stdout, "- %u connections\n", n_connections); for (i = 0; i < n_connections; i++) FPRINTF (stdout, " %s\n", GNUNET_h2s_full (&connections[i])); FPRINTF (stdout, "- enc state: %u\n", estate); FPRINTF (stdout, "- con state: %u\n", cstate); } if (GNUNET_YES != monitor_connections) { GNUNET_SCHEDULER_shutdown(); } return; }
/** * Connect both PUT and GET connection for a session * * @param s the session to connect * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ static int client_connect (struct Session *s) { struct HTTP_Client_Plugin *plugin = s->plugin; int res = GNUNET_OK; /* create url */ if (NULL == http_common_plugin_address_to_string (NULL, s->addr, s->addrlen)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Invalid address peer `%s'\n", GNUNET_i2s (&s->target)); return GNUNET_SYSERR; } GNUNET_asprintf (&s->url, "%s/%s;%u", http_common_plugin_address_to_string (plugin, s->addr, s->addrlen), GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey), plugin->last_tag); plugin->last_tag++; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Initiating outbound session peer `%s' using address `%s'\n", GNUNET_i2s (&s->target), s->url); if ((GNUNET_SYSERR == client_connect_get (s)) || (GNUNET_SYSERR == client_connect_put (s))) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p: connected with connections GET %p and PUT %p\n", s, s->client_get, s->client_put); /* Perform connect */ plugin->cur_connections += 2; GNUNET_STATISTICS_set (plugin->env->stats, "# HTTP client connections", plugin->cur_connections, GNUNET_NO); /* Re-schedule since handles have changed */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin); return res; }
/** * Get the block for a particular zone and label in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param query hash of public key derived from the zone and the label * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namecache_lookup_block (void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls) { struct Plugin *plugin = cls; const struct GNUNET_GNSRECORD_Block *block; block = GNUNET_CONTAINER_multihashmap_get (plugin->hm, query); if (NULL == block) return GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found block under derived key `%s'\n", GNUNET_h2s_full (query)); iter (iter_cls, block); return GNUNET_YES; }
/** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected * @param ats performance data * @param ats_count number of entries in ats (excluding 0-termination) */ static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { if (0 != memcmp (&pid, peer, sizeof (struct GNUNET_PeerIdentity))) return; ret = 0; if (try_connect) { /* all done, terminate instantly */ FPRINTF (stdout, _("Successfully connected to `%s'\n"), GNUNET_h2s_full (&peer->hashPubKey)); ret = 0; if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } if (benchmark_send) { if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (verbosity > 0) FPRINTF (stdout, _("Successfully connected to `%s', starting to send benchmark data in %u Kb blocks\n"), GNUNET_i2s (&pid), BLOCKSIZE); start_time = GNUNET_TIME_absolute_get (); if (NULL == th) th = GNUNET_TRANSPORT_notify_transmit_ready (handle, peer, BLOCKSIZE * 1024, 0, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_data, NULL); else GNUNET_break (0); return; } }
static void operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ResolutionContext *cur; struct ResolutionContext *next; op_timeout = GNUNET_SCHEDULER_NO_TASK; if ((try_connect) || (benchmark_send) || (benchmark_receive)) { FPRINTF (stdout, _("Failed to connect to `%s'\n"), GNUNET_h2s_full (&pid.hashPubKey)); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); ret = 1; return; } if (iterate_connections) { next = rc_head; while (NULL != (cur = next)) { next = cur->next; FPRINTF (stdout, _("Failed to resolve address for peer `%s'\n"), GNUNET_i2s (&cur->addrcp->peer)); GNUNET_CONTAINER_DLL_remove (rc_head, rc_tail, cur); GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); GNUNET_free (cur->addrcp); GNUNET_free (cur); } FPRINTF (stdout, "%s", _("Failed to list connections, timeout occured\n")); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); ret = 1; return; } }
/** * Cache a block in the datastore. * * @param cls closure (internal context for the plugin) * @param block block to cache * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namecache_cache_block (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct Plugin *plugin = cls; struct GNUNET_HashCode query; struct FlatFileEntry *entry; size_t block_size; namecache_expire_blocks (plugin); GNUNET_CRYPTO_hash (&block->derived_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &query); block_size = ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature); if (block_size > 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } entry = GNUNET_malloc (sizeof (struct FlatFileEntry)); entry->block = GNUNET_malloc (block_size); memcpy (entry->block, block, block_size); GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, &query); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (plugin->hm, &query, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_free (entry); GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block under derived key `%s'\n", GNUNET_h2s_full (&query)); return GNUNET_OK; }
DownloadItem* DownloadsModel::addDownload(DownloadItem *pde, struct GNUNET_FS_DownloadContext *dc, const struct GNUNET_FS_Uri *uri, QString filePath, const struct GNUNET_CONTAINER_MetaData *meta, qint64 size, qint64 completed ) { //Convert uri to Key GNUNET_HashCode hashcode; GNUNET_FS_uri_to_key(uri,&hashcode); //Get as QString const char * hash = GNUNET_h2s_full(&hashcode); QString strHash = QString(hash); DownloadItem* download = new DownloadItem(strHash); download->setParent(pde); download->setContext(dc); char* fancyName = GNUNET_CONTAINER_meta_data_get_first_by_types (meta, EXTRACTOR_METATYPE_PACKAGE_NAME, EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METATYPE_BOOK_TITLE, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METATYPE_DESCRIPTION, EXTRACTOR_METATYPE_SUMMARY, EXTRACTOR_METATYPE_ALBUM, EXTRACTOR_METATYPE_COMMENT, EXTRACTOR_METATYPE_SUBJECT, EXTRACTOR_METATYPE_KEYWORDS, -1); char* fileName = GNUNET_CONTAINER_meta_data_get_first_by_types (meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METATYPE_PACKAGE_NAME, EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METATYPE_BOOK_TITLE, EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METATYPE_DESCRIPTION, EXTRACTOR_METATYPE_SUMMARY, EXTRACTOR_METATYPE_ALBUM, EXTRACTOR_METATYPE_COMMENT, EXTRACTOR_METATYPE_SUBJECT, EXTRACTOR_METATYPE_KEYWORDS, -1); download->setPath(filePath); download->setFancyName(QString(fancyName)); download->setFileName(QString(fileName)); download->setMetadata(meta); download->setSize(size); download->setCompleted(completed); emit addDownloadSignal(download); return download; }
/** * Handler for DHT GET messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetMessage *get; struct ClientQueryRecord *cqr; size_t xquery_size; const char *xquery; uint16_t size; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage); get = (const struct GNUNET_DHT_ClientGetMessage *) message; xquery = (const char *) &get[1]; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests received from clients"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received GET request for %s from local client %p, xq: %.*s\n", GNUNET_h2s (&get->key), client, xquery_size, xquery); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-GET %s\n", GNUNET_h2s_full (&get->key)); cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size); cqr->key = get->key; cqr->client = find_active_client (client); cqr->xquery = (void *) &cqr[1]; memcpy (&cqr[1], xquery, xquery_size); cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0); cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS; cqr->retry_time = GNUNET_TIME_absolute_get (); cqr->unique_id = get->unique_id; cqr->xquery_size = xquery_size; cqr->replication = ntohl (get->desired_replication_level); cqr->msg_options = ntohl (get->options); cqr->type = ntohl (get->type); // FIXME use cqr->key, set multihashmap create to GNUNET_YES GNUNET_CONTAINER_multihashmap_put (forward_map, &get->key, cqr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GDS_CLIENTS_process_get (ntohl (get->options), ntohl (get->type), 0, ntohl (get->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), &get->key); /* start remote requests */ if (GNUNET_SCHEDULER_NO_TASK != retry_task) GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_add_now (&transmit_next_request_task, NULL); /* perform local lookup */ GDS_DATACACHE_handle_get (&get->key, cqr->type, cqr->xquery, xquery_size, NULL, 0); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Handler for PUT messages. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientPutMessage *dht_msg; struct GNUNET_CONTAINER_BloomFilter *peer_bf; uint16_t size; struct PendingMessage *pm; struct GNUNET_DHT_ClientPutConfirmationMessage *conf; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests received from clients"), 1, GNUNET_NO); dht_msg = (const struct GNUNET_DHT_ClientPutMessage *) message; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-PUT %s\n", GNUNET_h2s_full (&dht_msg->key)); /* give to local clients */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling local PUT of %u-bytes for query %s\n", size - sizeof (struct GNUNET_DHT_ClientPutMessage), GNUNET_h2s (&dht_msg->key)); GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* store locally */ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* route to other peers */ peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), ntohl (dht_msg->options), ntohl (dht_msg->desired_replication_level), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 0 /* hop count */ , peer_bf, &dht_msg->key, 0, NULL, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GDS_CLIENTS_process_put (ntohl (dht_msg->options), ntohl (dht_msg->type), 0, ntohl (dht_msg->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GNUNET_CONTAINER_bloomfilter_free (peer_bf); pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK); conf->reserved = htonl (0); conf->unique_id = dht_msg->unique_id; pm->msg = &conf->header; add_pending_message (find_active_client (client), pm); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Iterator over hash map entries that send a given reply to * each of the matching clients. With some tricky recycling * of the buffer. * * @param cls the 'struct ForwardReplyContext' * @param key current key * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate), * if the result is mal-formed, GNUNET_NO */ static int forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ForwardReplyContext *frc = cls; struct ClientQueryRecord *record = value; struct PendingMessage *pm; struct GNUNET_DHT_ClientResultMessage *reply; enum GNUNET_BLOCK_EvaluationResult eval; int do_free; struct GNUNET_HashCode ch; unsigned int i; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-RESULT %s\n", GNUNET_h2s_full (key)); if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Record type missmatch, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Key match, type mismatches in REPLY to CLIENT"), 1, GNUNET_NO); return GNUNET_YES; /* type mismatch */ } GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch); for (i = 0; i < record->seen_replies_count; i++) if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (struct GNUNET_HashCode))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Duplicate reply, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate REPLIES to CLIENT request dropped"), 1, GNUNET_NO); return GNUNET_YES; /* duplicate */ } eval = GNUNET_BLOCK_evaluate (GDS_block_context, record->type, key, NULL, 0, record->xquery, record->xquery_size, frc->data, frc->data_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Evaluation result is %d for key %s for local client's query\n", (int) eval, GNUNET_h2s (key)); switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_LAST: do_free = GNUNET_YES; break; case GNUNET_BLOCK_EVALUATION_OK_MORE: GNUNET_array_append (record->seen_replies, record->seen_replies_count, ch); do_free = GNUNET_NO; break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: /* should be impossible to encounter here */ GNUNET_break (0); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_break_op (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in request!\n"), record->type); return GNUNET_NO; default: GNUNET_break (0); return GNUNET_NO; } if (GNUNET_NO == frc->do_copy) { /* first time, we can use the original data */ pm = frc->pm; frc->do_copy = GNUNET_YES; } else { /* two clients waiting for same reply, must copy for queueing */ pm = GNUNET_malloc (sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); memcpy (pm, frc->pm, sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); pm->next = pm->prev = NULL; pm->msg = (struct GNUNET_MessageHeader *) &pm[1]; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# RESULTS queued for clients"), 1, GNUNET_NO); reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; reply->unique_id = record->unique_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing reply to query %s for client %p\n", GNUNET_h2s (key), record->client->client_handle); add_pending_message (record->client, pm); if (GNUNET_YES == do_free) remove_client_records (record->client, key, record); return GNUNET_YES; }
/** * Get the block for a particular zone and label in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param query hash of public key derived from the zone and the label * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namecache_sqlite_lookup_block (void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls) { struct Plugin *plugin = cls; int ret; int sret; size_t block_size; const struct GNUNET_GNSRECORD_Block *block; if (SQLITE_OK != sqlite3_bind_blob (plugin->lookup_block, 1, query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->lookup_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } ret = GNUNET_NO; if (SQLITE_ROW == (sret = sqlite3_step (plugin->lookup_block))) { block = sqlite3_column_blob (plugin->lookup_block, 0); block_size = sqlite3_column_bytes (plugin->lookup_block, 0); if ( (block_size < sizeof (struct GNUNET_GNSRECORD_Block)) || (ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature) != block_size) ) { GNUNET_break (0); ret = GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found block under derived key `%s'\n", GNUNET_h2s_full (query)); iter (iter_cls, block); ret = GNUNET_YES; } } else { if (SQLITE_DONE != sret) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); ret = GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No block found under derived key `%s'\n", GNUNET_h2s_full (query)); } } if (SQLITE_OK != sqlite3_reset (plugin->lookup_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return ret; }
/** * Cache a block in the datastore. * * @param cls closure (internal context for the plugin) * @param block block to cache * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namecache_sqlite_cache_block (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct Plugin *plugin = cls; struct GNUNET_HashCode query; struct GNUNET_TIME_Absolute expiration; int64_t dval; size_t block_size; int n; namecache_sqlite_expire_blocks (plugin); GNUNET_CRYPTO_hash (&block->derived_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &query); expiration = GNUNET_TIME_absolute_ntoh (block->expiration_time); dval = (int64_t) expiration.abs_value_us; if (dval < 0) dval = INT64_MAX; block_size = ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature); if (block_size > 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } /* delete old version of the block */ if ( (SQLITE_OK != sqlite3_bind_blob (plugin->delete_block, 1, &query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->delete_block, 2, dval)) ) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->delete_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (plugin->delete_block); switch (n) { case SQLITE_DONE: GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Old block deleted\n"); break; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); break; } if (SQLITE_OK != sqlite3_reset (plugin->delete_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); /* insert new version of the block */ if ((SQLITE_OK != sqlite3_bind_blob (plugin->cache_block, 1, &query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_blob (plugin->cache_block, 2, block, block_size, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->cache_block, 3, dval))) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->cache_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block under derived key `%s'\n", GNUNET_h2s_full (&query)); n = sqlite3_step (plugin->cache_block); if (SQLITE_OK != sqlite3_reset (plugin->cache_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); switch (n) { case SQLITE_DONE: LOG (GNUNET_ERROR_TYPE_DEBUG, "Record stored\n"); return GNUNET_OK; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_NO; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_SYSERR; } }
int client_connect (struct Session *s) { struct Plugin *plugin = s->plugin; int res = GNUNET_OK; char *url; CURLMcode mret; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Initiating outbound session peer `%s'\n", GNUNET_i2s (&s->target)); s->inbound = GNUNET_NO; plugin->last_tag++; /* create url */ GNUNET_asprintf (&url, "%s%s;%u", http_plugin_address_to_string (plugin, s->addr, s->addrlen), GNUNET_h2s_full (&plugin->env->my_identity->hashPubKey), plugin->last_tag); #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "URL `%s'\n", url); #endif /* create get connection */ s->client_get = curl_easy_init (); #if VERBOSE_CURL curl_easy_setopt (s->client_get, CURLOPT_VERBOSE, 1L); curl_easy_setopt (s->client_get, CURLOPT_DEBUGFUNCTION, &client_log); curl_easy_setopt (s->client_get, CURLOPT_DEBUGDATA, s->client_get); #endif #if BUILD_HTTPS curl_easy_setopt (s->client_get, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYHOST, 0); #endif curl_easy_setopt (s->client_get, CURLOPT_URL, url); //curl_easy_setopt (s->client_get, CURLOPT_HEADERFUNCTION, &curl_get_header_cb); //curl_easy_setopt (s->client_get, CURLOPT_WRITEHEADER, ps); curl_easy_setopt (s->client_get, CURLOPT_READFUNCTION, client_send_cb); curl_easy_setopt (s->client_get, CURLOPT_READDATA, s); curl_easy_setopt (s->client_get, CURLOPT_WRITEFUNCTION, client_receive); curl_easy_setopt (s->client_get, CURLOPT_WRITEDATA, s); curl_easy_setopt (s->client_get, CURLOPT_TIMEOUT_MS, (long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); curl_easy_setopt (s->client_get, CURLOPT_PRIVATE, s); curl_easy_setopt (s->client_get, CURLOPT_CONNECTTIMEOUT_MS, (long) HTTP_NOT_VALIDATED_TIMEOUT.rel_value); curl_easy_setopt (s->client_get, CURLOPT_BUFFERSIZE, 2 * GNUNET_SERVER_MAX_MESSAGE_SIZE); #if CURL_TCP_NODELAY curl_easy_setopt (ps->recv_endpoint, CURLOPT_TCP_NODELAY, 1); #endif /* create put connection */ s->client_put = curl_easy_init (); #if VERBOSE_CURL curl_easy_setopt (s->client_put, CURLOPT_VERBOSE, 1L); curl_easy_setopt (s->client_put, CURLOPT_DEBUGFUNCTION, &client_log); curl_easy_setopt (s->client_put, CURLOPT_DEBUGDATA, s->client_put); #endif #if BUILD_HTTPS curl_easy_setopt (s->client_put, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYHOST, 0); #endif curl_easy_setopt (s->client_put, CURLOPT_URL, url); curl_easy_setopt (s->client_put, CURLOPT_PUT, 1L); //curl_easy_setopt (s->client_put, CURLOPT_HEADERFUNCTION, &curl_put_header_cb); //curl_easy_setopt (s->client_put, CURLOPT_WRITEHEADER, ps); curl_easy_setopt (s->client_put, CURLOPT_READFUNCTION, client_send_cb); curl_easy_setopt (s->client_put, CURLOPT_READDATA, s); curl_easy_setopt (s->client_put, CURLOPT_WRITEFUNCTION, client_receive); curl_easy_setopt (s->client_put, CURLOPT_WRITEDATA, s); curl_easy_setopt (s->client_put, CURLOPT_TIMEOUT_MS, (long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value); curl_easy_setopt (s->client_put, CURLOPT_PRIVATE, s); curl_easy_setopt (s->client_put, CURLOPT_CONNECTTIMEOUT_MS, (long) HTTP_NOT_VALIDATED_TIMEOUT.rel_value); curl_easy_setopt (s->client_put, CURLOPT_BUFFERSIZE, 2 * GNUNET_SERVER_MAX_MESSAGE_SIZE); #if CURL_TCP_NODELAY curl_easy_setopt (s->client_put, CURLOPT_TCP_NODELAY, 1); #endif GNUNET_free (url); mret = curl_multi_add_handle (plugin->client_mh, s->client_get); if (mret != CURLM_OK) { curl_easy_cleanup (s->client_get); res = GNUNET_SYSERR; GNUNET_break (0); } mret = curl_multi_add_handle (plugin->client_mh, s->client_put); if (mret != CURLM_OK) { curl_multi_remove_handle (plugin->client_mh, s->client_get); curl_easy_cleanup (s->client_get); curl_easy_cleanup (s->client_put); res = GNUNET_SYSERR; GNUNET_break (0); } /* Perform connect */ plugin->cur_connections += 2; plugin->outbound_sessions ++; GNUNET_STATISTICS_set (plugin->env->stats, "# HTTP outbound sessions", plugin->outbound_sessions, GNUNET_NO); /* Re-schedule since handles have changed */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin); return res; }