/**
* The identity of our peer.
*/
-const struct GNUNET_PeerIdentity *my_identity;
+struct GNUNET_PeerIdentity my_identity;
/**
* The configuration for this service.
};
+/**
+ * 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
*/
*/
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?
unsigned long long max_table_size;
- struct GNUNET_TIME_Relative send_interval;
-
unsigned int neighbor_id_loc;
int closing;
&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! */
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
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
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));
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;
}
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;
}
/**
- * 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
"%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;
+ }
}
/**
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);
}
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);
/* 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,
--- /dev/null
+/*
+ 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