gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r16378 - gnunet/src/transport


From: gnunet
Subject: [GNUnet-SVN] r16378 - gnunet/src/transport
Date: Thu, 4 Aug 2011 22:49:35 +0200

Author: grothoff
Date: 2011-08-04 22:49:35 +0200 (Thu, 04 Aug 2011)
New Revision: 16378

Added:
   gnunet/src/transport/gnunet-service-transport_blacklist.c
   gnunet/src/transport/gnunet-service-transport_neighbours.c
Modified:
   gnunet/src/transport/Makefile.am
   gnunet/src/transport/gnunet-service-transport_blacklist.h
   gnunet/src/transport/gnunet-service-transport_neighbours.h
Log:
implementing blacklist

Modified: gnunet/src/transport/Makefile.am
===================================================================
--- gnunet/src/transport/Makefile.am    2011-08-04 19:29:40 UTC (rev 16377)
+++ gnunet/src/transport/Makefile.am    2011-08-04 20:49:35 UTC (rev 16378)
@@ -149,10 +149,10 @@
 
 gnunet_service_transport_new_SOURCES = \
  gnunet-service-transport-new.c gnunet-service-transport.h \
- gnunet-service-transport_blacklist.h \
+ gnunet-service-transport_blacklist.h gnunet-service-transport_blacklist.c \
  gnunet-service-transport_clients.h gnunet-service-transport_clients.c \
  gnunet-service-transport_hello.h gnunet-service-transport_hello.c \
- gnunet-service-transport_neighbours.h \
+ gnunet-service-transport_neighbours.h gnunet-service-transport_neighbours.c \
  gnunet-service-transport_plugins.h gnunet-service-transport_plugins.c \
  gnunet-service-transport_validation.h 
 gnunet_service_transport_new_LDADD = \

Added: gnunet/src/transport/gnunet-service-transport_blacklist.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_blacklist.c                   
        (rev 0)
+++ gnunet/src/transport/gnunet-service-transport_blacklist.c   2011-08-04 
20:49:35 UTC (rev 16378)
@@ -0,0 +1,800 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010,2011 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 3, 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 transport/gnunet-service-transport_blacklist.c
+ * @brief blacklisting implementation
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet-service-transport.h"
+#include "gnunet-service-transport_blacklist.h"
+#include "gnunet-service-transport_neighbours.h"
+#include "transport.h"
+
+
+/**
+ * Size of the blacklist hash map.
+ */
+#define TRANSPORT_BLACKLIST_HT_SIZE 64
+
+
+/**
+ * Context we use when performing a blacklist check.
+ */
+struct BlacklistCheck;
+
+
+/**
+ * Information kept for each client registered to perform
+ * blacklisting.
+ */
+struct Blacklisters
+{
+  /**
+   * This is a linked list.
+   */
+  struct Blacklisters *next;
+
+  /**
+   * This is a linked list.
+   */
+  struct Blacklisters *prev;
+
+  /**
+   * Client responsible for this entry.
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Blacklist check that we're currently performing.
+   */
+  struct BlacklistCheck *bc;
+
+};
+
+
+
+/**
+ * Context we use when performing a blacklist check.
+ */
+struct BlacklistCheck
+{
+
+  /**
+   * This is a linked list.
+   */
+  struct BlacklistCheck *next;
+
+  /**
+   * This is a linked list.
+   */
+  struct BlacklistCheck *prev;
+
+  /**
+   * Peer being checked.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * Continuation to call with the result.
+   */
+  GST_BlacklistTestContinuation cont;
+
+  /**
+   * Closure for cont.
+   */
+  void *cont_cls;
+
+  /**
+   * Current transmission request handle for this client, or NULL if no
+   * request is pending.
+   */
+  struct GNUNET_CONNECTION_TransmitHandle *th;
+
+  /**
+   * Our current position in the blacklisters list.
+   */
+  struct Blacklisters *bl_pos;
+
+  /**
+   * Current task performing the check.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier task;
+
+};
+
+
+/**
+ * Head of DLL of active blacklisting queries.
+ */
+static struct BlacklistCheck *bc_head;
+
+/**
+ * Tail of DLL of active blacklisting queries.
+ */
+static struct BlacklistCheck *bc_tail;
+
+/**
+ * Head of DLL of blacklisting clients.
+ */
+static struct Blacklisters *bl_head;
+
+/**
+ * Tail of DLL of blacklisting clients.
+ */
+static struct Blacklisters *bl_tail;
+
+/**
+ * Hashmap of blacklisted peers.  Values are of type 'char *' (transport 
names),
+ * can be NULL if we have no static blacklist.
+ */
+static struct GNUNET_CONTAINER_MultiHashMap *blacklist;
+
+
+/**
+ * Perform next action in the blacklist check.
+ *
+ * @param cls the 'struct BlacklistCheck*'
+ * @param tc unused
+ */
+static void
+do_blacklist_check (void *cls,
+                   const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Called whenever a client is disconnected.  Frees our
+ * resources associated with that client.
+ *
+ * @param cls closure (unused)
+ * @param client identification of the client
+ */
+static void
+client_disconnect_notification (void *cls,
+                                struct GNUNET_SERVER_Client *client)
+{
+  struct Blacklisters *bl;
+  struct BlacklistCheck *bc;
+
+  if (client == NULL)
+    return;
+  for (bl = bl_head; bl != NULL; bl = bl->next)
+    {
+      if (bl->client != client)
+       continue;
+      for (bc = bc_head; bc != NULL; bc = bc->next)
+       {
+         if (bc->bl_pos != bl)
+           continue;
+         bc->bl_pos = bl->next;
+         if (bc->th != NULL)
+           {
+             GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
+             bc->th = NULL;
+           }
+         if (bc->task == GNUNET_SCHEDULER_NO_TASK)
+           bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                                bc);
+         break;
+       }
+      GNUNET_CONTAINER_DLL_remove (bl_head,
+                                  bl_tail,
+                                  bl);
+      GNUNET_SERVER_client_drop (bl->client);
+      GNUNET_free (bl);
+      break;
+    }
+}
+
+
+/**
+ * Read the blacklist file, containing transport:peer entries.
+ * Provided the transport is loaded, set up hashmap with these
+ * entries to blacklist peers by transport.
+ *
+ */
+static void
+read_blacklist_file ()
+{
+  char *fn;
+  char *data;
+  size_t pos;
+  size_t colon_pos;
+  int tsize;
+  struct GNUNET_PeerIdentity pid;
+  struct stat frstat;
+  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
+  unsigned int entries_found;
+  char *transport_name;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (GST_cfg,
+                                               "TRANSPORT",
+                                               "BLACKLIST_FILE",
+                                               &fn))
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Option `%s' in section `%s' not specified!\n",
+                  "BLACKLIST_FILE",
+                  "TRANSPORT");
+#endif
+      return;
+    }
+  if (GNUNET_OK != GNUNET_DISK_file_test (fn))
+    GNUNET_DISK_fn_write (fn, NULL, 0, 
+                         GNUNET_DISK_PERM_USER_READ | 
GNUNET_DISK_PERM_USER_WRITE);
+  if (0 != STAT (fn, &frstat))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Could not read blacklist file `%s'\n"), 
+                 fn);
+      GNUNET_free (fn);
+      return;
+    }
+  if (frstat.st_size == 0)
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Blacklist file `%s' is empty.\n"),
+                  fn);
+#endif
+      GNUNET_free (fn);
+      return;
+    }
+  /* FIXME: use mmap */
+  data = GNUNET_malloc_large (frstat.st_size);
+  GNUNET_assert(data != NULL);
+  if (frstat.st_size !=
+      GNUNET_DISK_fn_read (fn, data, frstat.st_size))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Failed to read blacklist from `%s'\n"), 
+                 fn);
+      GNUNET_free (fn);
+      GNUNET_free (data);
+      return;
+    }
+  entries_found = 0;
+  pos = 0;
+  while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
+    pos++;
+  while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
+         (pos <= frstat.st_size - sizeof (struct 
GNUNET_CRYPTO_HashAsciiEncoded)))
+    {
+      colon_pos = pos;
+      while ( (colon_pos < frstat.st_size) && 
+             (data[colon_pos] != ':') && 
+             (! isspace ( (unsigned char) data[colon_pos])) )
+        colon_pos++;
+      if (colon_pos >= frstat.st_size)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      _("Syntax error in blacklist file at offset %llu, giving 
up!\n"),
+                      (unsigned long long) colon_pos);
+          GNUNET_free (fn);
+          GNUNET_free (data);
+          return;
+        }
+
+      if (isspace( (unsigned char) data[colon_pos]))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    _("Syntax error in blacklist file at offset %llu, skipping 
bytes.\n"),
+                    (unsigned long long) colon_pos);
+        pos = colon_pos;
+        while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
+          pos++;
+        continue;
+      }
+      tsize = colon_pos - pos;
+      if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) || (tsize 
== 0))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      _("Syntax error in blacklist file at offset %llu, giving 
up!\n"),
+                      (unsigned long long) colon_pos);
+          GNUNET_free (fn);
+          GNUNET_free (data);
+          return;
+        }
+
+      if (tsize < 1)
+        continue;
+
+      transport_name = GNUNET_malloc(tsize + 1);
+      memcpy(transport_name, &data[pos], tsize);
+      pos = colon_pos + 1;
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Read transport name `%s' in blacklist file.\n",
+                  transport_name);
+#endif
+      memcpy (&enc, 
+             &data[pos],
+             sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
+      if (! isspace ( (unsigned char) enc.encoding[sizeof (struct 
GNUNET_CRYPTO_HashAsciiEncoded) - 1]))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      _("Syntax error in blacklist file at offset %llu, 
skipping bytes.\n"),
+                      (unsigned long long) pos);
+          pos++;
+          while ((pos < frstat.st_size) && (!isspace ( (unsigned char) 
data[pos])))
+            pos++;
+          GNUNET_free_non_null(transport_name);
+          continue;
+        }
+      enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0';
+      if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, 
&pid.hashPubKey))
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      _("Syntax error in blacklist file at offset %llu, 
skipping bytes `%s'.\n"),
+                      (unsigned long long) pos,
+                      &enc);
+        }
+      else
+        {
+          if (0 != memcmp (&pid,
+                           &GST_my_identity,
+                           sizeof (struct GNUNET_PeerIdentity)))
+            {
+              entries_found++;
+              GST_blacklist_add_peer (&pid,
+                                     transport_name);
+            }
+          else
+            {
+              GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                          _("Found myself `%s' in blacklist (useless, 
ignored)\n"),
+                          GNUNET_i2s (&pid));
+            }
+        }
+      pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
+      GNUNET_free_non_null(transport_name);
+      while ((pos < frstat.st_size) && isspace ( (unsigned char) data[pos]))
+        pos++;
+    }
+  GNUNET_STATISTICS_update (GST_stats, 
+                           "# Transport entries blacklisted",
+                           entries_found,
+                           GNUNET_NO);
+  GNUNET_free (data);
+  GNUNET_free (fn);
+}
+
+
+/**
+ * Start blacklist subsystem.
+ *
+ * @param server server used to accept clients from
+ */
+void
+GST_blacklist_start (struct GNUNET_SERVER_Handle *server)
+{
+  read_blacklist_file ();
+  GNUNET_SERVER_disconnect_notify (server,
+                                  &client_disconnect_notification,
+                                  NULL);
+}
+
+
+/**
+ * Free the given entry in the blacklist.
+ *
+ * @param cls unused
+ * @param key host identity (unused)
+ * @param value the blacklist entry
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+free_blacklist_entry (void *cls,
+                     const GNUNET_HashCode *key,
+                     void *value)
+{
+  char *be = value;
+
+  GNUNET_free (be);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Stop blacklist subsystem.
+ */
+void
+GST_blacklist_stop ()
+{
+  if (NULL != blacklist)
+    {
+      GNUNET_CONTAINER_multihashmap_iterate (blacklist,
+                                            &free_blacklist_entry,
+                                            NULL);
+      GNUNET_CONTAINER_multihashmap_destroy (blacklist);
+      blacklist = NULL;
+    }
+}
+
+
+/**
+ * Transmit blacklist query to the client.
+ *
+ * @param cls the 'struct BlacklistCheck'
+ * @param size number of bytes allowed
+ * @param buf where to copy the message
+ * @return number of bytes copied to buf
+ */
+static size_t
+transmit_blacklist_message (void *cls,
+                           size_t size,
+                           void *buf)
+{
+  struct BlacklistCheck *bc = cls;
+  struct Blacklisters *bl;
+  struct BlacklistMessage bm;
+
+  bc->th = NULL;
+  if (size == 0)
+    {
+      GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK);
+      bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                          bc);
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 "Failed to send blacklist test for peer `%s' to client\n",
+                 GNUNET_i2s (&bc->peer));
+      return 0;
+    }
+#if DEBUG_TRANSPORT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Sending blacklist test for peer `%s' to client\n",
+             GNUNET_i2s (&bc->peer));
+#endif
+  bl = bc->bl_pos;
+  bm.header.size = htons (sizeof (struct BlacklistMessage));
+  bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
+  bm.is_allowed = htonl (0);
+  bm.peer = bc->peer;
+  memcpy (buf, &bm, sizeof (bm));
+  GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
+  return sizeof (bm);
+}
+
+
+/**
+ * Perform next action in the blacklist check.
+ *
+ * @param cls the 'struct BlacklistCheck*'
+ * @param tc unused
+ */
+static void
+do_blacklist_check (void *cls,
+                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct BlacklistCheck *bc = cls;
+  struct Blacklisters *bl;
+
+  bc->task = GNUNET_SCHEDULER_NO_TASK;
+  bl = bc->bl_pos;
+  if (bl == NULL)
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "No other blacklist clients active, will allow neighbour 
`%s'\n",
+                 GNUNET_i2s (&bc->peer));
+#endif
+      bc->cont (bc->cont_cls,
+               &bc->peer, 
+               GNUNET_OK);
+      GNUNET_free (bc);
+      return;
+    }
+  if (bl->bc != NULL)
+    return; /* someone else busy with this client */
+  bl->bc = bc;
+  bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client,
+                                               sizeof (struct 
BlacklistMessage),
+                                               GNUNET_TIME_UNIT_FOREVER_REL,
+                                               &transmit_blacklist_message,
+                                               bc);    
+}
+
+
+/**
+ * Got the result about an existing connection from a new blacklister.
+ * Shutdown the neighbour if necessary.
+ *
+ * @param cls unused
+ * @param peer the neighbour that was investigated
+ * @param allowed GNUNET_OK if we can keep it,
+ *                GNUNET_NO if we must shutdown the connection
+ */
+static void
+confirm_or_drop_neighbour (void *cls,
+                          const struct GNUNET_PeerIdentity *peer,
+                          int allowed)
+{
+  if (GNUNET_OK == allowed)
+    return; /* we're done */
+  GNUNET_STATISTICS_update (GST_stats,
+                           gettext_noop ("# disconnects due to blacklist"),
+                           1,
+                           GNUNET_NO);
+  GST_neighbours_force_disconnect (peer);
+}
+
+
+/**
+ * Closure for 'test_connection_ok'.
+ */
+struct TestConnectionContext
+{
+  /**
+   * Is this the first neighbour we're checking?
+   */ 
+  int first;
+
+  /**
+   * Handle to the blacklisting client we need to ask.
+   */
+  struct Blacklisters *bl;
+};
+
+
+/**
+ * Test if an existing connection is still acceptable given a new
+ * blacklisting client.
+ *
+ * @param cls the 'struct TestConnectionContest'
+ * @param pid neighbour's identity
+ */
+static void
+test_connection_ok (void *cls,
+                   const struct GNUNET_PeerIdentity *neighbour)
+{
+  struct TestConnectionContext *tcc = cls;
+  struct BlacklistCheck *bc;
+
+  bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+  GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
+  bc->peer = *neighbour;
+  bc->cont = &confirm_or_drop_neighbour;
+  bc->cont_cls = NULL;
+  bc->bl_pos = tcc->bl;
+  if (GNUNET_YES == tcc->first)
+    { 
+      /* all would wait for the same client, no need to
+        create more than just the first task right now */
+      bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                          bc);
+      tcc->first = GNUNET_NO;
+    }
+}
+
+
+
+/**
+ * Initialize a blacklisting client.  We got a blacklist-init
+ * message from this client, add him to the list of clients
+ * to query for blacklisting.
+ *
+ * @param cls unused
+ * @param client the client
+ * @param message the blacklist-init message that was sent
+ */
+void
+GST_blacklist_handle_init (void *cls,
+                          struct GNUNET_SERVER_Client *client,
+                          const struct GNUNET_MessageHeader *message)
+{
+  struct Blacklisters *bl;
+  struct TestConnectionContext tcc;
+
+  bl = bl_head;
+  while (bl != NULL)
+    {
+      if (bl->client == client)
+       {
+         GNUNET_break (0);
+         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+         return;
+       }
+      bl = bl->next;
+    }
+  bl = GNUNET_malloc (sizeof (struct Blacklisters));
+  bl->client = client;
+  GNUNET_SERVER_client_keep (client);
+  GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl);
+
+  /* confirm that all existing connections are OK! */
+  tcc.bl = bl;
+  tcc.first = GNUNET_YES;
+  GST_neighbours_iterate (&test_connection_ok,
+                         &tcc);
+}
+
+
+/**
+ * A blacklisting client has sent us reply. Process it.
+ *
+ * @param cls unused
+ * @param client the client
+ * @param message the blacklist-init message that was sent
+ */
+void
+GST_blacklist_handle_reply (void *cls,
+                           struct GNUNET_SERVER_Client *client,
+                           const struct GNUNET_MessageHeader *message)
+{
+  const struct BlacklistMessage *msg = (const struct BlacklistMessage*) 
message;
+  struct Blacklisters *bl;
+  struct BlacklistCheck *bc;
+
+  bl = bl_head;
+  while ( (bl != NULL) &&
+         (bl->client != client) )
+    bl = bl->next;
+  if (bl == NULL)
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Blacklist client disconnected\n");
+#endif
+      /* FIXME: other error handling here!? */
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
+    }
+  bc = bl->bc;
+  bl->bc = NULL;
+  if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Blacklist check failed, peer not allowed\n");
+#endif
+      bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO);
+      GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
+      GNUNET_free (bc);
+    }
+  else
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Blacklist check succeeded, continuing with checks\n");
+#endif
+      bc->bl_pos = bc->bl_pos->next;
+      bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                          bc);
+    }
+  /* check if any other bc's are waiting for this blacklister */
+  bc = bc_head;
+  while (bc != NULL)
+    {
+      if ( (bc->bl_pos == bl) &&
+          (GNUNET_SCHEDULER_NO_TASK == bc->task) )
+       bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                            bc);
+      bc = bc->next;
+    }
+}
+
+
+/**
+ * Add the given peer to the blacklist (for the given transport).
+ * 
+ * @param peer peer to blacklist
+ * @param transport_name transport to blacklist for this peer, NULL for all
+ */
+void
+GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
+                       const char *transport_name)
+{
+#if DEBUG_TRANSPORT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Adding peer `%s' with plugin `%s' to blacklist\n",
+             GNUNET_i2s (peer),
+             transport_name);
+#endif
+  if (blacklist == NULL)
+    blacklist = 
GNUNET_CONTAINER_multihashmap_create(TRANSPORT_BLACKLIST_HT_SIZE);
+  GNUNET_CONTAINER_multihashmap_put (blacklist,
+                                    &peer->hashPubKey,
+                                    GNUNET_strdup (transport_name),
+                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+}
+
+
+/**
+ * Test if the given blacklist entry matches.  If so,
+ * abort the iteration.
+ *
+ * @param cls the transport name to match (const char*)
+ * @param key the key (unused)
+ * @param value the 'char *' (name of a blacklisted transport)
+ * @return GNUNET_OK if the entry does not match, GNUNET_NO if it matches
+ */
+static int
+test_blacklisted (void *cls,
+                 const GNUNET_HashCode *key,
+                 void *value)
+{
+  const char *transport_name = cls;
+  char *be = value;
+
+  if (0 == strcmp (transport_name,
+                  be))
+    return GNUNET_NO; /* abort iteration! */
+  return GNUNET_OK;
+}
+
+
+/**
+ * Test if a peer/transport combination is blacklisted.
+ *
+ * @param peer the identity of the peer to test
+ * @param transport_name name of the transport to test, never NULL
+ * @param cont function to call with result
+ * @param cont_cls closure for 'cont'
+ */
+void
+GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
+                           const char *transport_name,
+                           GST_BlacklistTestContinuation cont,
+                           void *cont_cls)
+{
+  struct BlacklistCheck *bc;
+  
+  if ( (blacklist != NULL) &&
+       (GNUNET_SYSERR ==
+       GNUNET_CONTAINER_multihashmap_get_multiple (blacklist,
+                                                   &peer->hashPubKey,
+                                                   &test_blacklisted,
+                                                   (void*) transport_name)) )
+    {
+      /* disallowed by config, disapprove instantly */
+      GNUNET_STATISTICS_update (GST_stats,
+                                gettext_noop ("# disconnects due to 
blacklist"),
+                                1,
+                                GNUNET_NO);
+      if (cont != NULL)
+       cont (cont_cls, peer, GNUNET_NO);
+      return;
+    }
+
+  if (bl_head == NULL)
+    {
+      /* no blacklist clients, approve instantly */
+      if (cont != NULL)
+        cont (cont_cls, peer, GNUNET_OK);
+      return;
+    }
+
+  /* need to query blacklist clients */
+  bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+  GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
+  bc->peer = *peer;
+  bc->cont = cont;
+  bc->cont_cls = cont_cls;
+  bc->bl_pos = bl_head;
+  bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
+                                      bc);
+}
+                                                
+
+
+/* end of file gnunet-service-transport_blacklist.c */

Modified: gnunet/src/transport/gnunet-service-transport_blacklist.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_blacklist.h   2011-08-04 
19:29:40 UTC (rev 16377)
+++ gnunet/src/transport/gnunet-service-transport_blacklist.h   2011-08-04 
20:49:35 UTC (rev 16378)
@@ -30,37 +30,52 @@
 #include "gnunet_util_lib.h"
 
 /**
+ * Start blacklist subsystem.
  *
+ * @param server server used to accept clients from
  */
 void
-GST_blacklist_start (void);
+GST_blacklist_start (struct GNUNET_SERVER_Handle *server);
 
 
 /**
- *
+ * Stop blacklist subsystem.
  */
 void
 GST_blacklist_stop (void);
 
 
 /**
+ * Initialize a blacklisting client.  We got a blacklist-init
+ * message from this client, add him to the list of clients
+ * to query for blacklisting.
  *
+ * @param cls unused
+ * @param client the client
+ * @param message the blacklist-init message that was sent
  */
 void
 GST_blacklist_handle_init (void *cls,
-                          const struct GNUNET_SERVER_Client *client,
+                          struct GNUNET_SERVER_Client *client,
                           const struct GNUNET_MessageHeader *message);
 
 /**
+ * A blacklisting client has sent us reply. Process it.
  *
+ * @param cls unused
+ * @param client the client
+ * @param message the blacklist-init message that was sent
  */
 void
 GST_blacklist_handle_reply (void *cls,
-                           const struct GNUNET_SERVER_Client *client,
+                           struct GNUNET_SERVER_Client *client,
                            const struct GNUNET_MessageHeader *message);
 
 /**
- *
+ * Add the given peer to the blacklist (for the given transport).
+ * 
+ * @param peer peer to blacklist
+ * @param transport_name transport to blacklist for this peer, NULL for all
  */
 void
 GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
@@ -68,11 +83,31 @@
                                                        
 
 /**
+ * Continuation called from a blacklist test.
  *
+ * @param cls closure
+ * @param peer identity of peer that was tested
+ * @param result GNUNET_OK if the connection is allowed,
+ *               GNUNET_NO if not
  */
-int
-GST_blacklist_test (const struct GNUNET_PeerIdentity *peer,
-                   const char *transport_name);
+typedef void (*GST_BlacklistTestContinuation)(void *cls,
+                                             const struct GNUNET_PeerIdentity 
*peer,
+                                             int result);
+
+
+/**
+ * Test if a peer/transport combination is blacklisted.
+ *
+ * @param peer the identity of the peer to test
+ * @param transport_name name of the transport to test, never NULL
+ * @param cont function to call with result
+ * @param cont_cls closure for 'cont'
+ */
+void
+GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
+                           const char *transport_name,
+                           GST_BlacklistTestContinuation cont,
+                           void *cont_cls);
                                                 
 
 

Added: gnunet/src/transport/gnunet-service-transport_neighbours.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_neighbours.c                  
        (rev 0)
+++ gnunet/src/transport/gnunet-service-transport_neighbours.c  2011-08-04 
20:49:35 UTC (rev 16378)
@@ -0,0 +1,176 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010,2011 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 3, 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 transport/gnunet-service-transport_neighbours.c
+ * @brief neighbour management
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet-service-transport_neighbours.h"
+#include "gnunet-service-transport.h"
+
+// TODO:
+// - have a way to access the currently 'connected' session
+//   (for sending and to notice disconnect of it!)
+// - have a way to access/update bandwidth/quota information per peer
+//   (for CostReport/TrafficReport callbacks)
+
+
+
+/**
+ * Initialize the neighbours subsystem.
+ *
+ * @param cls closure for callbacks
+ * @param connect_cb function to call if we connect to a peer
+ * @param disconnect_cb function to call if we disconnect from a peer
+ */
+void 
+GST_neighbours_start (void *cls,
+                     GNUNET_TRANSPORT_NotifyConnect connect_cb,
+                     GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb)
+{
+}
+
+
+/**
+ * Cleanup the neighbours subsystem.
+ */
+void
+GST_neighbours_stop ()
+{
+}
+
+
+/**
+ * Try to create a connection to the given target (eventually).
+ *
+ * @param target peer to try to connect to
+ */
+void
+GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
+{
+}
+
+
+/**
+ * Test if we're connected to the given peer.
+ * 
+ * @param target peer to test
+ * @return GNUNET_YES if we are connected, GNUNET_NO if not
+ */
+int
+GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
+{
+  return GNUNET_NO;
+}
+
+
+/**
+ * If we have an active connection to the given target, it must be shutdown.
+ *
+ * @param target peer to disconnect from
+ */
+void
+GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
+{
+}
+
+
+/**
+ * Iterate over all connected neighbours.
+ *
+ * @param cb function to call 
+ * @param cb_cls closure for cb
+ */
+void
+GST_neighbours_iterate (GST_NeighbourIterator cb,
+                       void *cb_cls)
+{
+}
+
+
+/**
+ * We have received a PONG.  Update lifeness of the neighbour.
+ *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
+ */
+int
+GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender,
+                           const struct GNUNET_MessageHeader *hdr,
+                           const char *plugin_name,
+                           const void *sender_address,
+                           size_t sender_address_len)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * We have received a CONNECT.  Set the peer to connected.
+ *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
+ */
+int
+GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender,
+                              const struct GNUNET_MessageHeader *hdr,
+                              const char *plugin_name,
+                              const void *sender_address,
+                              size_t sender_address_len)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/**
+ * We have received a DISCONNECT.  Set the peer to disconnected.
+ *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
+ */
+int
+GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender,
+                                 const struct GNUNET_MessageHeader *hdr,
+                                 const char *plugin_name,
+                                 const void *sender_address,
+                                 size_t sender_address_len)
+{
+  return GNUNET_SYSERR;
+}
+
+
+/* end of file gnunet-service-transport_neighbours.c */

Modified: gnunet/src/transport/gnunet-service-transport_neighbours.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_neighbours.h  2011-08-04 
19:29:40 UTC (rev 16377)
+++ gnunet/src/transport/gnunet-service-transport_neighbours.h  2011-08-04 
20:49:35 UTC (rev 16378)
@@ -20,7 +20,7 @@
 
 /**
  * @file transport/gnunet-service-transport_neighbours.h
- * @brief plugin management API
+ * @brief neighbour management API
  * @author Christian Grothoff
  */
 #ifndef GNUNET_SERVICE_TRANSPORT_NEIGHBOURS_H
@@ -30,51 +30,93 @@
 #include "gnunet_transport_service.h"
 #include "gnunet_util_lib.h"
 
+// TODO:
+// - have a way to access the currently 'connected' session
+//   (for sending and to notice disconnect of it!)
+// - have a way to access/update bandwidth/quota information per peer
+//   (for CostReport/TrafficReport callbacks)
 
+
+
 /**
+ * Initialize the neighbours subsystem.
  *
+ * @param cls closure for callbacks
+ * @param connect_cb function to call if we connect to a peer
+ * @param disconnect_cb function to call if we disconnect from a peer
  */
 void 
 GST_neighbours_start (void *cls,
                      GNUNET_TRANSPORT_NotifyConnect connect_cb,
                      GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb);
 
+
 /**
- *
+ * Cleanup the neighbours subsystem.
  */
 void
 GST_neighbours_stop (void);
 
+
 /**
+ * Try to create a connection to the given target (eventually).
  *
+ * @param target peer to try to connect to
  */
 void
 GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target);
 
+
 /**
- *
+ * Test if we're connected to the given peer.
+ * 
+ * @param target peer to test
+ * @return GNUNET_YES if we are connected, GNUNET_NO if not
  */
 int
 GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target);
 
+
 /**
+ * If we have an active connection to the given target, it must be shutdown.
  *
+ * @param target peer to disconnect from
  */
 void
 GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target);
 
 
+/**
+ * Function called for each connected neighbour.
+ *
+ * @param cls closure
+ * @param neighbour identity of the neighbour
+ */
 typedef void (*GST_NeighbourIterator)(void *cls,
                                      const struct GNUNET_PeerIdentity 
*neighbour);
 
 
+/**
+ * Iterate over all connected neighbours.
+ *
+ * @param cb function to call 
+ * @param cb_cls closure for cb
+ */
 void
 GST_neighbours_iterate (GST_NeighbourIterator cb,
                        void *cb_cls);
 
 
 /**
+ * We have received a PONG.  Update lifeness of the neighbour.
  *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
  */
 int
 GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender,
@@ -83,8 +125,17 @@
                            const void *sender_address,
                            size_t sender_address_len);
 
+
 /**
+ * We have received a CONNECT.  Set the peer to connected.
  *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
  */
 int
 GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender,
@@ -93,8 +144,17 @@
                               const void *sender_address,
                               size_t sender_address_len);
 
+
 /**
+ * We have received a DISCONNECT.  Set the peer to disconnected.
  *
+ * @param sender peer sending the PONG
+ * @param hdr the PONG message (presumably)
+ * @param plugin_name name of transport that delivered the PONG
+ * @param sender_address address of the other peer, NULL if other peer
+ *                       connected to us
+ * @param sender_address_len number of bytes in sender_address
+ * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
  */
 int
 GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender,
@@ -104,7 +164,5 @@
                                  size_t sender_address_len);
 
 
-
-
 #endif
 /* end of file gnunet-service-transport_neighbours.h */




reply via email to

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