gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r8566 - in gnunet: . src/core src/topology src/transport


From: gnunet
Subject: [GNUnet-SVN] r8566 - in gnunet: . src/core src/topology src/transport
Date: Sun, 14 Jun 2009 19:28:44 -0600

Author: grothoff
Date: 2009-06-14 19:28:43 -0600 (Sun, 14 Jun 2009)
New Revision: 8566

Modified:
   gnunet/TODO
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/topology/Makefile.am
   gnunet/src/topology/gnunet-daemon-topology.c
   gnunet/src/transport/gnunet-service-transport.c
Log:
implemented advertising

Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2009-06-14 20:21:18 UTC (rev 8565)
+++ gnunet/TODO 2009-06-15 01:28:43 UTC (rev 8566)
@@ -1,10 +1,5 @@
 PHASE #1: (Goal: settle key design questions)
 
-Topology:
-* Forwarding of known HELLOs to neighbours (advertising)
-  [ Inbound HELLOs are processed by transport, right?  
-    But what about inbound encrypted HELLOs? ]
-
 ARM:
 * Make sure ARM supports daemons (non-service background processes, see 
hostlist/topology)
 

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2009-06-14 20:21:18 UTC (rev 
8565)
+++ gnunet/src/core/gnunet-service-core.c       2009-06-15 01:28:43 UTC (rev 
8566)
@@ -23,11 +23,6 @@
  * @brief high-level P2P messaging
  * @author Christian Grothoff
  *
- * POST-TESTING:
- * - topology management:
- *   + bootstrapping (transport offer hello, plugins)
- *   + internal neighbour selection
- *
  * Considerations for later:
  * - check that hostkey used by transport (for HELLOs) is the
  *   same as the hostkey that we are using!

Modified: gnunet/src/topology/Makefile.am
===================================================================
--- gnunet/src/topology/Makefile.am     2009-06-14 20:21:18 UTC (rev 8565)
+++ gnunet/src/topology/Makefile.am     2009-06-15 01:28:43 UTC (rev 8566)
@@ -13,6 +13,7 @@
 gnunet_daemon_topology_LDADD = \
   $(top_builddir)/src/core/libgnunetcore.la \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
 

Modified: gnunet/src/topology/gnunet-daemon-topology.c
===================================================================
--- gnunet/src/topology/gnunet-daemon-topology.c        2009-06-14 20:21:18 UTC 
(rev 8565)
+++ gnunet/src/topology/gnunet-daemon-topology.c        2009-06-15 01:28:43 UTC 
(rev 8566)
@@ -29,6 +29,7 @@
 #include "gnunet_core_service.h"
 #include "gnunet_protocols.h"
 #include "gnunet_peerinfo_service.h"
+#include "gnunet_transport_service.h"
 #include "gnunet_util_lib.h"
 
 
@@ -46,8 +47,21 @@
  */ 
 #define BLACKLIST_AFTER_ATTEMPT_FRIEND GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 15)
 
+/**
+ * How frequently are we allowed to ask PEERINFO for more
+ * HELLO's to advertise (at most)?
+ */ 
+#define MIN_HELLO_GATHER_DELAY GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 27)
 
 /**
+ * How often do we at most advertise the same HELLO to the same peer?
+ * Also used to remove HELLOs of peers that PEERINFO no longer lists
+ * from our cache.
+ */ 
+#define HELLO_ADVERTISEMENT_MIN_FREQUENCY GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_HOURS, 12)
+
+
+/**
  * List of neighbours, friends and blacklisted peers.
  */
 struct PeerList
@@ -75,6 +89,11 @@
   struct GNUNET_TIME_Absolute blacklisted_until;
 
   /**
+   * Last time we transmitted a HELLO to this peer?
+   */
+  struct GNUNET_TIME_Absolute last_hello_sent;
+
+  /**
    * ID of the peer.
    */
   struct GNUNET_PeerIdentity id;
@@ -83,6 +102,48 @@
 
 
 /**
+ * List of HELLOs we may consider for advertising.
+ */
+struct HelloList
+{
+  /**
+   * This is a linked list.
+   */
+  struct HelloList *next;
+
+  /**
+   * Pointer to the HELLO message.  Memory allocated as part
+   * of the "struct HelloList" --- do not free!
+   */
+  struct GNUNET_HELLO_Message *msg;
+
+  /**
+   * Bloom filter used to mark which peers already got
+   * this HELLO.
+   */
+  struct GNUNET_CONTAINER_BloomFilter *filter;
+  
+  /**
+   * What peer is this HELLO for?
+   */
+  struct GNUNET_PeerIdentity id;
+ 
+  /**
+   * When should we remove this entry from the linked list (either
+   * resetting the filter or possibly eliminating it for good because
+   * we no longer consider the peer to be participating in the
+   * network)?
+   */
+  struct GNUNET_TIME_Absolute expiration;
+};
+
+
+/**
+ * Linked list of HELLOs for advertising.
+ */
+static struct HelloList *hellos;
+
+/**
  * Our scheduler.
  */
 static struct GNUNET_SCHEDULER_Handle * sched;
@@ -96,6 +157,11 @@
  * Handle to the core API.
  */
 static struct GNUNET_CORE_Handle *handle;
+   
+/**
+ * Handle to the transport API.
+ */
+static struct GNUNET_TRANSPORT_Handle *transport;
 
 /**
  * Identity of this peer.
@@ -109,6 +175,11 @@
 static struct PeerList *friends;
 
 /**
+ * Timestamp from the last time we tried to gather HELLOs.
+ */
+static struct GNUNET_TIME_Absolute last_hello_gather_time;
+
+/**
  * Flag to disallow non-friend connections (pure F2F mode).
  */
 static int friends_only;
@@ -139,8 +210,14 @@
  */
 static int autoconnect;
 
+/**
+ * Are we currently having a request pending with
+ * PEERINFO asking for HELLOs for advertising?
+ */
+static int hello_gathering_active;
 
 
+
 /**
  * Force a disconnect from the specified peer.
  */
@@ -393,14 +470,85 @@
 }
 
 
+
+
 /**
+ * Iterator called on each address. 
+ * 
+ * @param cls flag that we will set if we see any addresses.
+ */
+static int
+address_iterator (void *cls,
+                 const char *tname,
+                 struct GNUNET_TIME_Absolute expiration,
+                 const void *addr, size_t addrlen)
+{
+  int *flag = cls;
+  *flag = GNUNET_YES;
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * We've gotten a HELLO from another peer.
+ * Consider it for advertising.
+ */
+static void
+consider_for_advertising (const struct GNUNET_HELLO_Message *hello)
+{
+  int have_address;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+  struct GNUNET_PeerIdentity pid;
+  struct HelloList *pos;
+  uint16_t size;
+
+  have_address = GNUNET_NO;
+  GNUNET_HELLO_iterate_addresses (hello,
+                                 GNUNET_NO,
+                                 &address_iterator,
+                                 &have_address);
+  if (GNUNET_NO == have_address)
+    return; /* no point in advertising this one... */
+  GNUNET_HELLO_get_key (hello, &pkey);
+  GNUNET_CRYPTO_hash (&pkey, sizeof (pkey), &pid.hashPubKey);
+  pos = hellos;
+  while (pos != NULL)
+    {
+      if (0 == memcmp (&pos->id,
+                      &pid,
+                      sizeof(struct GNUNET_PeerIdentity)))
+       return; /* duplicate, at least "mostly" */
+      pos = pos->next;
+    }
+  size = GNUNET_HELLO_size (hello);
+  pos = GNUNET_malloc (sizeof(struct HelloList) + size);
+  pos->msg = (struct GNUNET_HELLO_Message*) &pos[1];
+  memcpy (&pos->msg, hello, size);
+  pos->id = pid;
+  pos->expiration = GNUNET_TIME_relative_to_absolute 
(HELLO_ADVERTISEMENT_MIN_FREQUENCY);
+  /* 2^{-5} chance of not sending a HELLO to a peer is 
+     acceptably small (if the filter is 50% full); 
+     64 bytes of memory are small compared to the rest
+     of the data structure and would only really become
+     "useless" once a HELLO has been passed on to ~100
+     other peers, which is likely more than enough in 
+     any case; hence 64, 5 as bloomfilter parameters. */
+  pos->filter = GNUNET_CONTAINER_bloomfilter_load (NULL, 64, 5);
+  /* never send a peer its own HELLO */
+  GNUNET_CONTAINER_bloomfilter_add (pos->filter, &pos->id.hashPubKey);
+  pos->next = hellos;
+  hellos = pos;  
+}
+
+
+/**
  * Peerinfo calls this function to let us know about a
  * possible peer that we might want to connect to.
  */
 static void
 process_peer (void *cls,
-             const struct GNUNET_PeerIdentity * peer,
-             const struct GNUNET_HELLO_Message * hello,
+             const struct GNUNET_PeerIdentity *peer,
+             const struct GNUNET_HELLO_Message *hello,
              uint32_t trust)
 {
   struct PeerList *pos;
@@ -420,6 +568,7 @@
                    peer, sizeof (struct GNUNET_PeerIdentity)))
     return;  /* that's me! */
 
+  consider_for_advertising (hello);
   pos = friends;
   while (pos != NULL)
     {
@@ -436,7 +585,7 @@
            }
        }
       pos = pos->next;
-    }
+    }  
   if (GNUNET_YES == friends_only)
     return;
   if (friend_count < minimum_friend_count)
@@ -681,6 +830,162 @@
 
 
 /**
+ * This function is called whenever an encrypted HELLO message is
+ * received.
+ *
+ * @param cls closure
+ * @param peer the other peer involved (sender or receiver, NULL
+ *        for loopback messages where we are both sender and receiver)
+ * @param message the actual HELLO message
+ * @return GNUNET_OK to keep the connection open,
+ *         GNUNET_SYSERR to close it (signal serious error)
+ */
+static int
+handle_encrypted_hello (void *cls,
+                       const struct GNUNET_PeerIdentity * other,
+                       const struct GNUNET_MessageHeader *
+                       message)
+{
+  if (transport != NULL)
+    GNUNET_TRANSPORT_offer_hello (transport,
+                                 message);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Peerinfo calls this function to let us know about a
+ * possible peer that we might want to connect to.
+ */
+static void
+gather_hello_callback (void *cls,
+                      const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_HELLO_Message *hello,
+                      uint32_t trust)
+{
+  if (peer == NULL)
+    {
+      hello_gathering_active = GNUNET_NO;
+      return;
+    }
+  if (hello != NULL)
+    consider_for_advertising (hello);
+}
+
+
+/**
+ * Function to fill send buffer with HELLO.
+ *
+ * @param receiver the receiver of the message
+ * @param position is the reference to the
+ *        first unused position in the buffer where GNUnet is building
+ *        the message
+ * @param padding is the number of bytes left in that buffer.
+ * @return the number of bytes written to
+ *   that buffer (must be a positive number).
+ */
+static unsigned int
+hello_advertising (void *cls,
+                  const struct GNUNET_PeerIdentity *
+                  receiver,
+                  void *position, unsigned int padding)
+{
+  struct PeerList *pl;
+  struct HelloList *pos;
+  struct HelloList *prev;
+  struct HelloList *next;
+  uint16_t size;
+
+  pl = friends;
+  while (pl != NULL)
+    {
+      if (0 == memcmp (&pl->id, receiver, sizeof (struct GNUNET_PeerIdentity)))
+       break;
+      pl = pl->next;
+    }
+  if (pl == NULL)
+    {
+      GNUNET_break (0);
+      return 0;
+    }
+  /* find applicable HELLOs */
+  prev = NULL;
+  next = hellos;
+  while (NULL != (pos = next))
+    {
+      next = pos->next;
+      if (GNUNET_NO == 
+         GNUNET_CONTAINER_bloomfilter_test (pos->filter,
+                                            &receiver->hashPubKey))
+       break;  
+      if (0 == GNUNET_TIME_absolute_get_remaining (pos->expiration).value)
+       {
+         /* time to discard... */
+         if (prev == NULL)
+           prev->next = next;
+         else
+           hellos = next;
+         GNUNET_CONTAINER_bloomfilter_free (pos->filter);
+         GNUNET_free (pos);
+       }
+      else
+       {
+         prev = pos;
+       }
+    }
+  if (pos != NULL)
+    {
+      size = GNUNET_HELLO_size (pos->msg);
+      if (size < padding)
+       {
+         memcpy (position, pos->msg, size);
+         GNUNET_CONTAINER_bloomfilter_add (pos->filter,
+                                           &receiver->hashPubKey);
+       }
+      else
+       {
+         size = 0;
+       }
+      return size;
+    }  
+  if ( (GNUNET_NO == hello_gathering_active) &&
+       (GNUNET_TIME_absolute_get_duration (last_hello_gather_time).value >
+       MIN_HELLO_GATHER_DELAY.value) )
+    {     
+      hello_gathering_active = GNUNET_YES;
+      last_hello_gather_time = GNUNET_TIME_absolute_get();
+      GNUNET_PEERINFO_for_all (cfg,
+                              sched,
+                              NULL,
+                              0, GNUNET_TIME_UNIT_FOREVER_REL,
+                              &gather_hello_callback, NULL);
+    }
+  return 0;
+}
+
+
+/**
+ * Last task run during shutdown.  Disconnects us from
+ * the transport and core.
+ */
+static void
+cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerList *pl;
+
+  GNUNET_TRANSPORT_disconnect (transport);
+  transport = NULL;
+  GNUNET_CORE_disconnect (handle);
+  handle = NULL;
+  while (NULL != (pl = friends))
+    {
+      friends = pl->next;
+      GNUNET_free (pl);
+    }
+}
+
+
+/**
  * Main function that will be run.
  *
  * @param cls closure
@@ -698,6 +1003,7 @@
 {
   struct GNUNET_CORE_MessageHandler handlers[] = 
     {
+      { &handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0},
       { NULL, 0, 0 }
     };
   unsigned long long opt;
@@ -726,6 +1032,13 @@
   if ( (friends_only == GNUNET_YES) ||
        (minimum_friend_count > 0) )
     read_friends_file (cfg);
+
+  transport = GNUNET_TRANSPORT_connect (sched,
+                                       cfg,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL);
   GNUNET_CORE_connect (sched,
                       cfg,
                       GNUNET_TIME_UNIT_FOREVER_REL,
@@ -733,10 +1046,17 @@
                       &core_init,
                       &connect_notify,
                       &disconnect_notify,
-                      NULL,
+                      &hello_advertising,
                       NULL, GNUNET_NO,
                       NULL, GNUNET_NO,
                       handlers);
+  
+  GNUNET_SCHEDULER_add_delayed (sched,
+                                GNUNET_YES,
+                                GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+                                GNUNET_TIME_UNIT_FOREVER_REL,
+                                &cleaning_task, NULL);
 }
 
 

Modified: gnunet/src/transport/gnunet-service-transport.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c     2009-06-14 20:21:18 UTC 
(rev 8565)
+++ gnunet/src/transport/gnunet-service-transport.c     2009-06-15 01:28:43 UTC 
(rev 8566)
@@ -361,12 +361,6 @@
   uint32_t quota_in;
 
   /**
-   * What is the latest version of our HELLO that we have
-   * sent to this neighbour?
-   */
-  unsigned int hello_version_sent;
-
-  /**
    * How often has the other peer (recently) violated the
    * inbound traffic limit?  Incremented by 10 per violation,
    * decremented by 1 per non-violation (for each
@@ -2195,7 +2189,6 @@
     GNUNET_TIME_relative_to_absolute 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
   n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
   add_plugins (n);
-  n->hello_version_sent = our_hello_version;
   n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
                                                   GNUNET_NO,
                                                   
GNUNET_SCHEDULER_PRIORITY_IDLE,





reply via email to

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