From 3e812a14846665f56f4d5e94a7285c02810581b0 Mon Sep 17 00:00:00 2001 From: "Nathan S. Evans" Date: Sun, 14 Mar 2010 17:02:29 +0000 Subject: [PATCH] fondly remembering ciphertext_send... all the pieces are there, but still doesn't work. Needs debugging, as usual. --- src/dv/dv_api.c | 22 +++++- src/dv/gnunet-service-dv.c | 117 ++++++++++++++++++++++++++------ src/dv/plugin_transport_dv.c | 9 +-- src/include/gnunet_dv_service.h | 73 ++++++++++++++++++++ 4 files changed, 196 insertions(+), 25 deletions(-) create mode 100644 src/include/gnunet_dv_service.h diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c index 9e99790fb..ace020c3e 100644 --- a/src/dv/dv_api.c +++ b/src/dv/dv_api.c @@ -151,6 +151,7 @@ transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_DV_Handle *handle = cls; size_t ret; + size_t tsize; if (buf == NULL) { @@ -159,6 +160,21 @@ transmit_pending (void *cls, size_t size, void *buf) } handle->th = NULL; + ret = 0; + + if (handle->current != NULL) + { + tsize = ntohs(handle->current->msg->header.size); + if (size >= tsize) + { + memcpy(buf, handle->current->msg, tsize); + } + else + { + return ret; + } + } + return ret; } @@ -255,6 +271,11 @@ void handle_message_receipt (void *cls, char *sender_address; char *packed_msg; + if (msg == NULL) + { + return; /* Connection closed? */ + } + GNUNET_assert(ntohs(msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE); if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived)) @@ -323,7 +344,6 @@ int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, memcpy(&msg[1], addr, addrlen); add_pending(dv_handle, msg); - process_pending_message(dv_handle); return GNUNET_OK; } diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 0e182fca8..683fe46b9 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c @@ -51,7 +51,7 @@ static struct GNUNET_CORE_Handle *coreAPI; /** * The identity of our peer. */ -const struct GNUNET_PeerIdentity *my_identity; +struct GNUNET_PeerIdentity my_identity; /** * The configuration for this service. @@ -154,6 +154,30 @@ struct PendingMessage }; +/** + * Context created whenever a direct peer connects to us, + * used to gossip other peers to it. + */ +struct NeighborSendContext +{ + /** + * The peer we will gossip to. + */ + struct DirectNeighbor *toNeighbor; + + /** + * The timeout for this task. + */ + struct GNUNET_TIME_Relative timeout; + + /** + * The task associated with this context. + */ + GNUNET_SCHEDULER_TaskIdentifier task; + +}; + + /** * Struct to hold information for updating existing neighbors */ @@ -202,6 +226,11 @@ struct DirectNeighbor */ struct DistantNeighbor *referee_tail; + /** + * The sending context for gossiping peers to this neighbor. + */ + struct NeighborSendContext *send_context; + /** * Is this one of the direct neighbors that we are "hiding" * from DV? @@ -312,8 +341,6 @@ struct GNUNET_DV_Context unsigned long long max_table_size; - struct GNUNET_TIME_Relative send_interval; - unsigned int neighbor_id_loc; int closing; @@ -470,7 +497,7 @@ send_message (const struct GNUNET_PeerIdentity * recipient, &sender->hashPubKey); if (source == NULL) { - if (0 != (memcmp (my_identity, + if (0 != (memcmp (&my_identity, sender, sizeof (struct GNUNET_PeerIdentity)))) { /* sender unknown to us, drop! */ @@ -634,10 +661,11 @@ static void neighbor_send_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct NeighborSendContext *send_context = cls; #if DEBUG_DV GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%s: Entering neighbor_send_thread...\n", - GNUNET_i2s(my_identity)); + "%s: Entering neighbor_send_task...\n", + GNUNET_i2s(&my_identity)); char * encPeerAbout; char * encPeerTo; #endif @@ -648,10 +676,30 @@ neighbor_send_task (void *cls, struct PendingMessage *pending_message; if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) + { +#if DEBUG_DV + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s: Called with reason shutdown, shutting down!\n", + GNUNET_i2s(&my_identity)); +#endif + send_context->toNeighbor->send_context = NULL; + GNUNET_free(send_context); return; + } + + /* FIXME: this may become a problem, because the heap walk has only one internal "walker". This means + * that if two neighbor_send_tasks are operating in lockstep (which is quite possible, given default + * values for all connected peers) there may be a serious bias as to which peers get gossiped about! + * Probably the *best* way to fix would be to have an opaque pointer to the walk position passed as + * part of the walk_get_next call. Then the heap would have to keep a list of walks, or reset the walk + * whenever a modification has been detected. Yuck either way. Perhaps we could iterate over the heap + * once to get a list of peers to gossip about and gossip them over time... But then if one goes away + * in the mean time that becomes nasty. For now we'll just assume that the walking is done + * asynchronously enough to avoid major problems (-; + */ about = GNUNET_CONTAINER_heap_walk_get_next (ctx.neighbor_min_heap); - to = GNUNET_CONTAINER_heap_get_random (ctx.neighbor_min_heap, GNUNET_CONTAINER_multihashmap_size(ctx.direct_neighbors)); + to = send_context->toNeighbor; if ((about != NULL) && (to != about->referrer /* split horizon */ ) && #if SUPPORT_HIDING @@ -666,7 +714,7 @@ neighbor_send_task (void *cls, encPeerTo = GNUNET_strdup(GNUNET_i2s(&to->identity)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: Sending info about peer %s to directly connected peer %s\n", - GNUNET_i2s(my_identity), + GNUNET_i2s(&my_identity), encPeerAbout, encPeerTo); #endif pending_message = GNUNET_malloc(sizeof(struct PendingMessage)); @@ -692,7 +740,7 @@ neighbor_send_task (void *cls, ctx.send_interval);*/ } - gossip_task = GNUNET_SCHEDULER_add_delayed(sched, ctx.send_interval, &neighbor_send_task, NULL); + GNUNET_SCHEDULER_add_delayed(sched, send_context->timeout, &neighbor_send_task, send_context); return; } @@ -816,7 +864,7 @@ void core_init (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(identity)); #endif - my_identity = identity; + memcpy(&my_identity, identity, sizeof(struct GNUNET_PeerIdentity)); coreAPI = server; } @@ -985,7 +1033,7 @@ addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, /** - * Method called whenever a given peer either connects. + * Method called whenever a peer connects. * * @param cls closure * @param peer peer identity this notification is about @@ -1003,12 +1051,27 @@ void handle_core_connect (void *cls, "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance); #endif - neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor)); - memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity)); - GNUNET_CONTAINER_multihashmap_put (ctx.direct_neighbors, - &peer->hashPubKey, - neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); - addUpdateNeighbor (peer, 0, neighbor, 0); + if ((distance == 0) && (GNUNET_CONTAINER_multihashmap_get(ctx.direct_neighbors, &peer->hashPubKey) == NULL)) + { + neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor)); + neighbor->send_context = GNUNET_malloc(sizeof(struct NeighborSendContext)); + neighbor->send_context->toNeighbor = neighbor; + neighbor->send_context->timeout = default_dv_delay; /* FIXME: base this on total gossip tasks, or bandwidth */ + memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity)); + GNUNET_CONTAINER_multihashmap_put (ctx.direct_neighbors, + &peer->hashPubKey, + neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + addUpdateNeighbor (peer, 0, neighbor, 0); + neighbor->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, neighbor->send_context); + } + else + { +#if DEBUG_DV + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s: Distance (%d) greater than 0 or already know about peer (%s), not re-adding!\n", "dv", distance, GNUNET_i2s(peer)); +#endif + return; + } } /** @@ -1039,6 +1102,8 @@ void handle_core_disconnect (void *cls, GNUNET_assert (neighbor->referee_tail == NULL); GNUNET_CONTAINER_multihashmap_remove (ctx.direct_neighbors, &peer->hashPubKey, neighbor); + if ((neighbor->send_context != NULL) && (neighbor->send_context->task != GNUNET_SCHEDULER_NO_TASK)) + GNUNET_SCHEDULER_cancel(sched, neighbor->send_context->task); GNUNET_free (neighbor); } @@ -1058,11 +1123,25 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_TIME_Relative timeout; - + unsigned long long max_hosts; timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); sched = scheduler; cfg = c; + /* FIXME: Read from config, or calculate, or something other than this! */ + max_hosts = 50; + ctx.max_table_size = 100; + ctx.fisheye_depth = 3; + + ctx.neighbor_min_heap = + GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); + ctx.neighbor_max_heap = + GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); + + ctx.direct_neighbors = GNUNET_CONTAINER_multihashmap_create (max_hosts); + ctx.extended_neighbors = + GNUNET_CONTAINER_multihashmap_create (ctx.max_table_size * 3); + client_transmit_timeout = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); default_dv_delay = GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5); GNUNET_SERVER_add_handlers (server, plugin_handlers); @@ -1086,8 +1165,6 @@ run (void *cls, /* load (server); Huh? */ /* Scheduled the task to clean up when shutdown is called */ - - gossip_task = GNUNET_SCHEDULER_add_delayed(sched, ctx.send_interval, &neighbor_send_task, NULL); cleanup_task = GNUNET_SCHEDULER_add_delayed (sched, GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, diff --git a/src/dv/plugin_transport_dv.c b/src/dv/plugin_transport_dv.c index 7d0b1521f..fa35fa5a8 100644 --- a/src/dv/plugin_transport_dv.c +++ b/src/dv/plugin_transport_dv.c @@ -166,19 +166,20 @@ struct Plugin }; - void handle_dv_message_received (void *cls, struct GNUNET_PeerIdentity *sender, - struct GNUNET_MessageHeader *msg, + char *msg, + size_t msg_len, unsigned int distance, char *sender_address, size_t sender_address_len) { struct Plugin *plugin = cls; + /* TODO: Add in demultiplexing if we think we'll be receiving multiple messages at once */ plugin->env->receive(plugin, sender, - msg, + (struct GNUNET_MessageHeader *)msg, distance, sender_address, sender_address_len); @@ -336,7 +337,7 @@ libgnunet_plugin_transport_dv_init (void *cls) struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; - struct GNUNET_SERVICE_Context *service; + /*struct GNUNET_SERVICE_Context *service;*/ /** * Do we not even need a service for this thing? That's peculiar. diff --git a/src/include/gnunet_dv_service.h b/src/include/gnunet_dv_service.h new file mode 100644 index 000000000..f7367cd80 --- /dev/null +++ b/src/include/gnunet_dv_service.h @@ -0,0 +1,73 @@ +/* + This file is part of GNUnet + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +/** + * @file include/gnunet_dv_service.h + * @brief API to deal with dv service + * + * @author Christian Grothoff + * @author Nathan Evans + */ + +#ifndef GNUNET_DV_SERVICE_H +#define GNUNET_DV_SERVICE_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "gnunet_common.h" +#include "gnunet_configuration_lib.h" +#include "gnunet_scheduler_lib.h" + +/** + * Version of the dv API. + */ +#define GNUNET_DV_VERSION 0x00000000 + +/** + * Opaque handle for the dv service. + */ +struct GNUNET_DV_Handle; + + +int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle, + const struct GNUNET_PeerIdentity *target, + const char *msgbuf, + size_t msgbuf_size, + unsigned int priority, + struct GNUNET_TIME_Relative timeout, + const void *addr, + size_t addrlen); + + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif -- 2.25.1