gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r10560 - gnunet/src/dv


From: gnunet
Subject: [GNUnet-SVN] r10560 - gnunet/src/dv
Date: Fri, 12 Mar 2010 09:38:10 +0100

Author: nevans
Date: 2010-03-12 09:38:10 +0100 (Fri, 12 Mar 2010)
New Revision: 10560

Modified:
   gnunet/src/dv/dv.h
   gnunet/src/dv/dv_api.c
   gnunet/src/dv/gnunet-service-dv.c
   gnunet/src/dv/plugin_transport_dv.c
Log:
non-compiling, but getting there

Modified: gnunet/src/dv/dv.h
===================================================================
--- gnunet/src/dv/dv.h  2010-03-11 20:17:32 UTC (rev 10559)
+++ gnunet/src/dv/dv.h  2010-03-12 08:38:10 UTC (rev 10560)
@@ -54,7 +54,7 @@
   /**
    * The sender of the message
    */
-  struct GNUNET_PeerIdentity *sender;
+  struct GNUNET_PeerIdentity sender;
 
   /**
    * The message that was sent
@@ -156,6 +156,54 @@
 
 };
 
+/**
+ * Message that gets sent between nodes updating dv infos
+ */
+typedef struct
+{
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Cost from received from node to neighbor node, takes distance into account
+   */
+  unsigned int cost GNUNET_PACKED;
+
+  /**
+   * Identity of neighbor we learned information about
+   */
+  struct GNUNET_PeerIdentity neighbor;
+
+  /**
+   * Neighbor ID to use when sending to this peer
+   */
+  unsigned int neighbor_id GNUNET_PACKED;
+
+} p2p_dv_MESSAGE_NeighborInfo;
+
+/**
+ * Message that gets sent between nodes carrying information
+ */
+typedef struct
+{
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Identity of peer that ultimately sent the message.
+   * Should be looked up in the set of 'neighbor_id's of
+   * the referring peer.
+   */
+  unsigned int sender GNUNET_PACKED;
+
+  /**
+   * Identity of neighbor this message is going to.  Should
+   * be looked up in the set of our own identifiers for
+   * neighbors!
+   */
+  unsigned int recipient GNUNET_PACKED;
+
+} p2p_dv_MESSAGE_Data;
+
+
 struct GNUNET_DV_Handle *
 GNUNET_DV_connect (struct GNUNET_SCHEDULER_Handle *sched,
                   const struct GNUNET_CONFIGURATION_Handle *cfg,

Modified: gnunet/src/dv/dv_api.c
===================================================================
--- gnunet/src/dv/dv_api.c      2010-03-11 20:17:32 UTC (rev 10559)
+++ gnunet/src/dv/dv_api.c      2010-03-12 08:38:10 UTC (rev 10560)
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file transport/dv_api.c
+ * @file dv/dv_api.c
  * @brief library to access the DV service
  * @author Christian Grothoff
  * @author Not Nathan Evans
@@ -264,7 +264,7 @@
   sender_address = memcpy(sender_address, &received_msg[1], 
ntohs(received_msg->sender_address_len));
 
   handle->receive_handler(handle->receive_cls,
-                          received_msg->sender,
+                          &received_msg->sender,
                           received_msg->msg,
                           ntohl(received_msg->distance),
                           sender_address,
@@ -281,13 +281,13 @@
  * Send a message from the plugin to the DV service indicating that
  * a message should be sent via DV to some peer.
  *
- * @target the final target of the message
- * @msgbuf the msg(s) to send
- * @msgbuf_size the size of msgbuf
- * @priority priority to pass on to core when sending the message
- * @timeout how long can this message be delayed (pass through to core)
- * @addr the address of this peer (internally known to DV)
- * @addrlen the length of the peer address
+ * @param target the final target of the message
+ * @param msgbuf the msg(s) to send
+ * @param msgbuf_size the size of msgbuf
+ * @param priority priority to pass on to core when sending the message
+ * @param timeout how long can this message be delayed (pass through to core)
+ * @param addr the address of this peer (internally known to DV)
+ * @param addrlen the length of the peer address
  *
  */
 int GNUNET_DV_send (struct GNUNET_DV_Handle *dv_handle,
@@ -324,6 +324,8 @@
  *
  * @param sched the scheduler to use
  * @param cfg the configuration to use
+ * @param receive_handler method call when on receipt from the service
+ * @param receive_handler_cls closure for receive_handler
  *
  * @return handle to the DV service
  */

Modified: gnunet/src/dv/gnunet-service-dv.c
===================================================================
--- gnunet/src/dv/gnunet-service-dv.c   2010-03-11 20:17:32 UTC (rev 10559)
+++ gnunet/src/dv/gnunet-service-dv.c   2010-03-12 08:38:10 UTC (rev 10560)
@@ -36,6 +36,7 @@
 #include "gnunet_service_lib.h"
 #include "gnunet_core_service.h"
 #include "gnunet_signal_lib.h"
+#include "gnunet_util_lib.h"
 #include "dv.h"
 
 /**
@@ -50,7 +51,7 @@
 /**
  * The identity of our peer.
  */
-static struct GNUNET_PeerIdentity *my_identity;
+const struct GNUNET_PeerIdentity *my_identity;
 
 /**
  * The configuration for this service.
@@ -63,6 +64,44 @@
 static struct GNUNET_SCHEDULER_Handle *sched;
 
 /**
+ * How often do we check about sending out more peer information (if
+ * we are connected to no peers previously).
+ */
+#define GNUNET_DV_DEFAULT_SEND_INTERVAL (500 * GNUNET_CRON_MILLISECONDS)
+
+/**
+ * How long do we wait at most between sending out information?
+ */
+#define GNUNET_DV_MAX_SEND_INTERVAL (5000 * GNUNET_CRON_MILLISECONDS)
+
+/**
+ * How long can we have not heard from a peer and
+ * still have it in our tables?
+ */
+#define GNUNET_DV_PEER_EXPIRATION_TIME (3000 * GNUNET_CRON_SECONDS)
+
+/**
+ * Priority for gossip.
+ */
+#define GNUNET_DV_DHT_GOSSIP_PRIORITY (GNUNET_EXTREME_PRIORITY / 10)
+
+/**
+ * How often should we check if expiration time has elapsed for
+ * some peer?
+ */
+#define GNUNET_DV_MAINTAIN_FREQUENCY (5 * GNUNET_CRON_SECONDS)
+
+/**
+ * How long to allow a message to be delayed?
+ */
+#define DV_DELAY (5000 * GNUNET_CRON_MILLISECONDS)
+
+/**
+ * Priority to use for DV data messages.
+ */
+#define DV_PRIORITY 0
+
+/**
  * The client, should be the DV plugin connected to us.  Hopefully
  * this client will never change, although if the plugin dies
  * and returns for some reason it may happen.
@@ -72,21 +111,273 @@
 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
 
 /**
+ * Struct where neighbor information is stored.
+ */
+struct DistantNeighbor *referees;
+
+/**
+ * Struct to hold information for updating existing neighbors
+ */
+struct NeighborUpdateInfo
+{
+  /**
+   * Cost
+   */
+  unsigned int cost;
+
+  /**
+   * The existing neighbor
+   */
+  struct DistantNeighbor *neighbor;
+
+  /**
+   * The referrer of the possibly existing peer
+   */
+  struct DirectNeighbor *referrer;
+
+  /**
+   * The time we heard about this peer
+   */
+  struct GNUNET_TIME_Absolute now;
+};
+
+/**
+ * Struct where actual neighbor information is stored,
+ * referenced by min_heap and max_heap.  Freeing dealt
+ * with when items removed from hashmap.
+ */
+struct DirectNeighbor
+{
+  /**
+   * Identity of neighbor.
+   */
+  struct GNUNET_PeerIdentity identity;
+
+  /**
+   * Head of DLL of nodes that this direct neighbor referred to us.
+   */
+  struct DistantNeighbor *referee_head;
+
+  /**
+   * Tail of DLL of nodes that this direct neighbor referred to us.
+   */
+  struct DistantNeighbor *referee_tail;
+
+  /**
+   * Is this one of the direct neighbors that we are "hiding"
+   * from DV?
+   */
+  int hidden;
+};
+
+
+/**
+ * Struct where actual neighbor information is stored,
+ * referenced by min_heap and max_heap.  Freeing dealt
+ * with when items removed from hashmap.
+ */
+struct DistantNeighbor
+{
+  /**
+   * We keep distant neighbor's of the same referrer in a DLL.
+   */
+  struct DistantNeighbor *next;
+
+  /**
+   * We keep distant neighbor's of the same referrer in a DLL.
+   */
+  struct DistantNeighbor *prev;
+
+  /**
+   * Node in min heap
+   */
+  struct GNUNET_CONTAINER_HeapNode *min_loc;
+
+  /**
+   * Node in max heap
+   */
+  struct GNUNET_CONTAINER_HeapNode *max_loc;
+
+  /**
+   * Identity of referrer (next hop towards 'neighbor').
+   */
+  struct DirectNeighbor *referrer;
+
+  /**
+   * Identity of neighbor.
+   */
+  struct GNUNET_PeerIdentity identity;
+
+  /**
+   * Last time we received routing information from this peer
+   */
+  struct GNUNET_TIME_Absolute last_activity;
+
+  /**
+   * Cost to neighbor, used for actual distance vector computations
+   */
+  unsigned int cost;
+
+  /**
+   * Random identifier *we* use for this peer, to be used as shortcut
+   * instead of sending full peer id for each message
+   */
+  unsigned int our_id;
+
+  /**
+   * Random identifier the *referrer* uses for this peer.
+   */
+  unsigned int referrer_id;
+
+  /**
+   * Is this one of the direct neighbors that we are "hiding"
+   * from DV?
+   */
+  int hidden;
+};
+
+
+/**
+ * Global construct
+ */
+struct GNUNET_DV_Context
+{
+  /**
+   * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for all
+   * directly connected peers.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
+
+  /**
+   * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for
+   * peers connected via DV (extended neighborhood).  Does ALSO
+   * include any peers that are in 'direct_neighbors'; for those
+   * peers, the cost will be zero and the referrer all zeros.
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *extended_neighbors;
+
+  /**
+   * We use the min heap (min refers to cost) to prefer
+   * gossipping about peers with small costs.
+   */
+  struct GNUNET_CONTAINER_Heap *neighbor_min_heap;
+
+  /**
+   * We use the max heap (max refers to cost) for general
+   * iterations over all peers and to remove the most costly
+   * connection if we have too many.
+   */
+  struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
+
+  unsigned long long fisheye_depth;
+
+  unsigned long long max_table_size;
+
+  unsigned int send_interval;
+
+  unsigned int neighbor_id_loc;
+
+  int closing;
+};
+
+static char shortID[5];
+
+static struct GNUNET_DV_Context ctx;
+
+struct FindDestinationContext
+{
+  unsigned int tid;
+  struct DistantNeighbor *dest;
+};
+
+
+/**
+ * We've been given a target ID based on the random numbers that
+ * we assigned to our DV-neighborhood.  Find the entry for the
+ * respective neighbor.
+ */
+static int
+find_destination (void *cls,
+                  struct GNUNET_CONTAINER_HeapNode *node,
+                  void *element, GNUNET_CONTAINER_HeapCostType cost)
+{
+  struct FindDestinationContext *fdc = cls;
+  struct DistantNeighbor *dn = element;
+
+  if (fdc->tid != dn->our_id)
+    return GNUNET_YES;
+  fdc->dest = dn;
+  return GNUNET_NO;
+}
+
+/**
+ * Function called to notify a client about the socket
+ * begin ready to queue more data.  "buf" will be
+ * NULL and "size" zero if the socket was closed for
+ * writing in the meantime.
+ *
+ * @param cls closure
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+size_t transmit_to_plugin (void *cls,
+               size_t size, void *buf)
+{
+  struct GNUNET_DV_MessageReceived *msg = cls;
+
+  if (buf == NULL)
+    return 0;
+
+  GNUNET_assert(size >= ntohs(msg->header.size));
+
+  memcpy(buf, msg, size);
+  GNUNET_free(msg);
+  return size;
+}
+
+
+void send_to_plugin(const struct GNUNET_PeerIdentity * sender, const struct 
GNUNET_MessageHeader *message, size_t message_size, struct DistantNeighbor 
*distant_neighbor)
+{
+  struct GNUNET_DV_MessageReceived *received_msg;
+  int size;
+
+  if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived))
+    return;
+
+  size = sizeof(struct GNUNET_DV_MessageReceived) + message_size + 
sizeof(struct GNUNET_PeerIdentity);
+  received_msg = GNUNET_malloc(size);
+  received_msg->header.size = htons(size);
+  received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
+  received_msg->sender_address_len = sizeof(struct GNUNET_PeerIdentity);
+  received_msg->distance = htonl(distant_neighbor->cost);
+  /* Set the sender in this message to be the original sender! */
+  memcpy(&received_msg->sender, &distant_neighbor->identity, sizeof(struct 
GNUNET_PeerIdentity));
+  /* Copy the intermediate sender to the end of the message, this is how the 
transport identifies this peer */
+  memcpy(&received_msg[1], sender, sizeof(struct GNUNET_PeerIdentity));
+
+  /* FIXME: Send to the client please */
+  GNUNET_SERVER_notify_transmit_ready (client_handle,
+                                       size, CLIENT_TRANSMIT_TIMEOUT,
+                                       &transmit_to_plugin, &received_msg);
+
+}
+
+/**
  * Core handler for dv data messages.  Whatever this message
  * contains all we really have to do is rip it out of its
  * DV layering and give it to our pal the DV plugin to report
  * in with.
  *
  * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * @param peer peer which sent the message (immediate sender)
+ * @param message the message
+ * @param latency the latency of the connection we received the message from
+ * @param distance the distance to the immediate peer
  */
-static void handle_dv_data_message (void *cls,
-                             struct GNUNET_PeerIdentity *
-                             peer,
-                             const struct
-                             GNUNET_MessageHeader *
-                             message,
+static int handle_dv_data_message (void *cls,
+                             const struct GNUNET_PeerIdentity * peer,
+                             const struct GNUNET_MessageHeader * message,
                              struct GNUNET_TIME_Relative latency,
                              uint32_t distance)
 {
@@ -95,6 +386,92 @@
               "%s: Receives %s message!\n", "dv", "DV DATA");
 #endif
 
+  const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
+  const struct GNUNET_MessageHeader *packed_message = (const struct 
GNUNET_MessageHeader *) &incoming[1];
+  struct DirectNeighbor *dn;
+  struct DistantNeighbor *pos;
+  unsigned int sid;             /* Sender id */
+  unsigned int tid;             /* Target id */
+  struct GNUNET_PeerIdentity original_sender;
+  struct GNUNET_PeerIdentity destination;
+  struct FindDestinationContext fdc;
+  int ret;
+
+  if ((ntohs (incoming->header.size) <
+       sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
+      || (ntohs (incoming->header.size) !=
+          (sizeof (p2p_dv_MESSAGE_Data) + ntohs (packed_message->size))))
+    {
+      return GNUNET_SYSERR;
+    }
+
+  dn = GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors,
+                                  &peer->hashPubKey);
+  if (dn == NULL)
+    {
+      return GNUNET_OK;
+    }
+  sid = ntohl (incoming->sender);
+  pos = dn->referee_head;
+  while ((NULL != pos) && (pos->referrer_id != sid))
+    pos = pos->next;
+  if (pos == NULL)
+    {
+      /* unknown sender */
+      return GNUNET_OK;
+    }
+  original_sender = pos->identity;
+  tid = ntohl (incoming->recipient);
+  if (tid == 0)
+    {
+      /* 0 == us */
+
+      /* FIXME: Will we support wrapped messages being these types? Probably 
not, they should
+       * be encrypted messages that need decrypting and junk like that.
+       */
+      GNUNET_break_op (ntohs (packed_message->type) != 
GNUNET_MESSAGE_TYPE_DV_GOSSIP);
+      GNUNET_break_op (ntohs (packed_message->type) != 
GNUNET_MESSAGE_TYPE_DV_DATA);
+      if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
+          (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
+      {
+        /* FIXME: send the message, wrap it up and return it to the DV plugin 
*/
+        /*coreAPI->loopback_send (&original_sender, (const char *) 
packed_message,
+        ntohs (packed_message->size), GNUNET_YES, NULL);*/
+        send_to_plugin(peer, packed_message, ntohs(packed_message->size), pos);
+      }
+
+      return GNUNET_OK;
+    }
+
+  /* FIXME: this is the *only* per-request operation we have in DV
+     that is O(n) in relation to the number of connected peers; a
+     hash-table lookup could easily solve this (minor performance
+     issue) */
+  fdc.tid = tid;
+  fdc.dest = NULL;
+  GNUNET_CONTAINER_heap_iterate (ctx.neighbor_max_heap,
+                                 &find_destination, &fdc);
+  if (fdc.dest == NULL)
+    {
+      return GNUNET_OK;
+    }
+  destination = fdc.dest->identity;
+
+  if (0 == memcmp (&destination, peer, sizeof (struct GNUNET_PeerIdentity)))
+    {
+      /* FIXME: create stat: routing loop-discard! */
+      return GNUNET_OK;
+    }
+
+  /* FIXME: Can't send message on, we have to behave.
+   * We have to tell core we have a message for the next peer, and let
+   * transport do transport selection on how to get this message to 'em */
+  /*ret = send_message (&destination,
+                      &original_sender,
+                      packed_message, DV_PRIORITY, DV_DELAY);*/
+  send_to_core(&destination, &original_sender, packed_message, DV_PRIORITY, 
DV_DELAY);
+
+  return GNUNET_OK;
 }
 
 /**
@@ -105,20 +482,23 @@
  * transport service so that it can be used by all others.
  *
  * @param cls closure
- * @param client identification of the client
- * @param message the actual message
+ * @param peer peer which sent the message (immediate sender)
+ * @param message the message
+ * @param latency the latency of the connection we received the message from
+ * @param distance the distance to the immediate peer
  */
-static void handle_dv_gossip_message (void *cls,
-                               struct GNUNET_PeerIdentity * peer,
-                               const struct GNUNET_MessageHeader * message,
-                               struct GNUNET_TIME_Relative latency,
-                               uint32_t distance)
+static int handle_dv_gossip_message (void *cls,
+                                     const struct GNUNET_PeerIdentity *peer,
+                                     const struct GNUNET_MessageHeader 
*message,
+                                     struct GNUNET_TIME_Relative latency,
+                                     uint32_t distance)
 {
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives %s message!\n", "dv", "DV GOSSIP");
 #endif
 
+  return 0;
 }
 
 
@@ -153,8 +533,11 @@
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "%s: Setting client handle (was a different client!)!\n", 
"dv");
   }
+
+  GNUNET_SERVER_receive_done(client, GNUNET_OK);
 }
 
+
 /**
  * List of handlers for the messages understood by this
  * service.
@@ -171,6 +554,7 @@
   {NULL, 0, 0}
 };
 
+
 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
   {&send_dv_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0},
   {NULL, NULL, 0, 0}
@@ -196,7 +580,7 @@
  */
 void core_init (void *cls,
                 struct GNUNET_CORE_Handle * server,
-                const struct GNUNET_PeerIdentity *my_identity,
+                const struct GNUNET_PeerIdentity *identity,
                 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * 
publicKey)
 {
 
@@ -208,29 +592,201 @@
     }
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%s: Core connection initialized, I am peer: %s\n", "dv", 
GNUNET_i2s(my_identity));
+              "%s: Core connection initialized, I am peer: %s\n", "dv", 
GNUNET_i2s(identity));
 #endif
+  my_identity = identity;
   coreAPI = server;
 }
 
+
 /**
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to
+ *         iterate,
+ *         GNUNET_NO if not.
+ */
+static int update_matching_neighbors (void *cls,
+                                      const GNUNET_HashCode * key,
+                                      void *value)
+{
+  struct NeighborUpdateInfo * update_info = cls;
+  struct DirectNeighbor *direct_neighbor = value;
+
+  if (update_info->referrer == direct_neighbor) /* Direct neighbor matches, 
update it's info and return GNUNET_NO */
+  {
+    /* same referrer, cost change! */
+    GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap,
+                                       update_info->neighbor->max_loc, 
update_info->cost);
+    GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap,
+                                       update_info->neighbor->min_loc, 
update_info->cost);
+    update_info->neighbor->last_activity = update_info->now;
+    update_info->neighbor->cost = update_info->cost;
+    return GNUNET_NO;
+  }
+
+  return GNUNET_YES;
+}
+
+
+/**
+ * Free a DistantNeighbor node, including removing it
+ * from the referer's list.
+ */
+static void
+distant_neighbor_free (struct DistantNeighbor *referee)
+{
+  struct DirectNeighbor *referrer;
+
+  referrer = referee->referrer;
+  if (referrer != NULL)
+    {
+      GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
+                         referrer->referee_tail, referee);
+    }
+  GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_max_heap, referee->max_loc);
+  GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_min_heap, referee->min_loc);
+  GNUNET_CONTAINER_multihashmap_remove_all (ctx.extended_neighbors,
+                                    &referee->identity.hashPubKey);
+  GNUNET_free (referee);
+}
+
+
+/**
+ * Handles when a peer is either added due to being newly connected
+ * or having been gossiped about, also called when a cost for a neighbor
+ * needs to be updated.
+ *
+ * @param peer identity of the peer whose info is being added/updated
+ * @param peer_id id to use when sending to 'peer'
+ * @param referrer if this is a gossiped peer, who did we hear it from?
+ * @param cost the cost of communicating with this peer via 'referrer'
+ */
+static void
+addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer,
+                   unsigned int referrer_peer_id,
+                   struct DirectNeighbor *referrer, unsigned int cost)
+{
+  struct DistantNeighbor *neighbor;
+  struct DistantNeighbor *max;
+  struct GNUNET_TIME_Absolute now;
+  struct NeighborUpdateInfo *neighbor_update;
+  unsigned int our_id;
+
+  now = GNUNET_TIME_absolute_get ();
+  our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, RAND_MAX - 1) 
+ 1;
+
+  neighbor = GNUNET_CONTAINER_multihashmap_get (ctx.extended_neighbors,
+                                                &peer->hashPubKey);
+  neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo));
+  neighbor_update->neighbor = neighbor;
+  neighbor_update->cost = cost;
+  neighbor_update->now = now;
+  neighbor_update->referrer = referrer;
+
+  /* Either we do not know this peer, or we already do but via a different 
immediate peer */
+  if ((neighbor == NULL) ||
+      (GNUNET_CONTAINER_multihashmap_get_multiple(ctx.extended_neighbors,
+                                                  &peer->hashPubKey,
+                                                  &update_matching_neighbors,
+                                                  neighbor_update) != 
GNUNET_SYSERR))
+    {
+      /* new neighbor! */
+      if (cost > ctx.fisheye_depth)
+        {
+          /* too costly */
+          return;
+        }
+      if (ctx.max_table_size <=
+          GNUNET_CONTAINER_multihashmap_size (ctx.extended_neighbors))
+        {
+          /* remove most expensive entry */
+          max = GNUNET_CONTAINER_heap_peek (ctx.neighbor_max_heap);
+          if (cost > max->cost)
+            {
+              /* new entry most expensive, don't create */
+              return;
+            }
+          if (max->cost > 0)
+            {
+              /* only free if this is not a direct connection;
+                 we could theoretically have more direct
+                 connections than DV entries allowed total! */
+              distant_neighbor_free (max);
+            }
+        }
+
+      neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
+      GNUNET_CONTAINER_DLL_insert (referrer->referee_head,
+                         referrer->referee_tail, neighbor);
+      neighbor->max_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_max_heap,
+                                                        neighbor, cost);
+      neighbor->min_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_min_heap,
+                                                        neighbor, cost);
+      neighbor->referrer = referrer;
+      memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
+      neighbor->last_activity = now;
+      neighbor->cost = cost;
+      neighbor->referrer_id = referrer_peer_id;
+      neighbor->our_id = our_id;
+      neighbor->hidden =
+        (cost == 0) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
4) ==
+                       0) : GNUNET_NO;
+      GNUNET_CONTAINER_multihashmap_put (ctx.extended_neighbors, 
&peer->hashPubKey,
+                                 neighbor,
+                                 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+
+      return;
+    }
+
+  /* Old logic to remove entry and replace, not needed now as we only want to 
remove when full
+   * or when the referring peer disconnects from us.
+   */
+  /*
+  GNUNET_DLL_remove (neighbor->referrer->referee_head,
+                     neighbor->referrer->referee_tail, neighbor);
+  neighbor->referrer = referrer;
+  GNUNET_DLL_insert (referrer->referee_head,
+                     referrer->referee_tail, neighbor);
+  GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap,
+                                     neighbor->max_loc, cost);
+  GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap,
+                                     neighbor->min_loc, cost);
+  neighbor->referrer_id = referrer_peer_id;
+  neighbor->last_activity = now;
+  neighbor->cost = cost;
+  */
+}
+
+
+/**
  * Method called whenever a given peer either connects.
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other'
+ * @param latency reported latency of the connection with peer
+ * @param distance reported distance (DV) to peer
  */
 void handle_core_connect (void *cls,
                           const struct GNUNET_PeerIdentity * peer,
                           struct GNUNET_TIME_Relative latency,
                           uint32_t distance)
 {
-
+  struct DirectNeighbor *neighbor;
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "%s: Receives core connect message!\n", "dv");
+              "%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);
 }
 
 /**
@@ -238,16 +794,30 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other'
  */
 void handle_core_disconnect (void *cls,
                              const struct GNUNET_PeerIdentity * peer)
 {
+  struct DirectNeighbor *neighbor;
+  struct DistantNeighbor *referee;
+
 #if DEBUG_DV
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "%s: Receives core peer disconnect message!\n", "dv");
 #endif
+
+  neighbor =
+    GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors, 
&peer->hashPubKey);
+  if (neighbor == NULL)
+    {
+      return;
+    }
+  while (NULL != (referee = neighbor->referee_head))
+    distant_neighbor_free (referee);
+  GNUNET_assert (neighbor->referee_tail == NULL);
+  GNUNET_CONTAINER_multihashmap_remove (ctx.direct_neighbors,
+                                &peer->hashPubKey, neighbor);
+  GNUNET_free (neighbor);
 }
 
 
@@ -255,7 +825,7 @@
  * Process dv requests.
  *
  * @param cls closure
- * @param sched scheduler to use
+ * @param scheduler scheduler to use
  * @param server the initialized server
  * @param c configuration to use
  */

Modified: gnunet/src/dv/plugin_transport_dv.c
===================================================================
--- gnunet/src/dv/plugin_transport_dv.c 2010-03-11 20:17:32 UTC (rev 10559)
+++ gnunet/src/dv/plugin_transport_dv.c 2010-03-12 08:38:10 UTC (rev 10560)
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file transport/plugin_transport_dv.c
+ * @file dv/plugin_transport_dv.c
  * @brief DV transport service, takes incoming DV requests and deals with
  * the DV service
  * @author Christian Grothoff





reply via email to

[Prev in Thread] Current Thread [Next in Thread]