gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r10970 - in gnunet: . src/core src/fs src/hostlist src/incl


From: gnunet
Subject: [GNUnet-SVN] r10970 - in gnunet: . src/core src/fs src/hostlist src/include src/testing src/topology src/transport
Date: Sun, 18 Apr 2010 22:23:40 +0200

Author: grothoff
Date: 2010-04-18 22:23:40 +0200 (Sun, 18 Apr 2010)
New Revision: 10970

Modified:
   gnunet/TODO
   gnunet/src/core/core.h
   gnunet/src/core/core_api.c
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/core/test_core_api.c
   gnunet/src/core/test_core_api_start_only.c
   gnunet/src/fs/gnunet-service-fs.c
   gnunet/src/hostlist/gnunet-daemon-hostlist.c
   gnunet/src/include/gnunet_core_service.h
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_transport_service.h
   gnunet/src/testing/test_testing_topology.c
   gnunet/src/testing/testing.c
   gnunet/src/topology/gnunet-daemon-topology.c
   gnunet/src/transport/Makefile.am
   gnunet/src/transport/gnunet-service-transport_blacklist.c
   gnunet/src/transport/gnunet-service-transport_blacklist.h
   gnunet/src/transport/transport.h
   gnunet/src/transport/transport_api_blacklist.c
Log:
towards fixing blacklisting APIs and implementation

Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/TODO 2010-04-18 20:23:40 UTC (rev 10970)
@@ -2,20 +2,10 @@
 * PEERINFO: [CG]
   - trust: need *fast* way to check/update trust in peers
            (async peerinfo would not be right; certainly not with the current 
API)
+* TRANSPORT: [CG]
+  - need to implement and test new blacklisting code (server-side only, client 
API exists)
 * TOPOLOGY: [CG]
-  - If the topology daemon crashes, peers that were put on the
-    blacklist with transport will never be removed from it (until
-    transport service dies); we should use the blacklist notification
-    API to learn about the exact set of blacklisted peers at all times
-    (FIXME: the transport_api implementation of blacklisting
-     also does not work nicely for this since it won't let us know about
-     disconnect-reconnect events and the implicit whitelisting
-     that might happen here; that's not so bad since we will
-     re-blacklist on pre-connect attempts anyway, so this is 
-     a minor issue; OTOH, we might want to be more explicit about
-     allowing/forbidding connects on pre-connect to avoid 
-     entering connect attempts to just be blacklisted shortly afterwards).
-  - needs more testing (especially F2F topology)
+  - needs more testing (especially F2F topology) -- need transport 
blacklisting to be implemented first!
 * FS: [CG]
   - support recursive download even if filename is NULL and we hence
     do not generate files on disk (use temp_filename)

Modified: gnunet/src/core/core.h
===================================================================
--- gnunet/src/core/core.h      2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/core/core.h      2010-04-18 20:23:40 UTC (rev 10970)
@@ -43,13 +43,12 @@
  * transmitted to the client.
  */
 #define GNUNET_CORE_OPTION_NOTHING             0
-#define GNUNET_CORE_OPTION_SEND_PRE_CONNECT    1
-#define GNUNET_CORE_OPTION_SEND_CONNECT        2
-#define GNUNET_CORE_OPTION_SEND_DISCONNECT     4
-#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   8
-#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND   16
-#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
-#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  64
+#define GNUNET_CORE_OPTION_SEND_CONNECT        1
+#define GNUNET_CORE_OPTION_SEND_DISCONNECT     2
+#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   4
+#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND    8
+#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16
+#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  32
 
 
 /**

Modified: gnunet/src/core/core_api.c
===================================================================
--- gnunet/src/core/core_api.c  2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/core/core_api.c  2010-04-18 20:23:40 UTC (rev 10970)
@@ -56,12 +56,6 @@
   GNUNET_CORE_StartupCallback init;
 
   /**
-   * Function to call whenever we're notified about a peer connecting
-   * (pre-connects, no session key exchange yet).
-   */
-  GNUNET_CORE_ConnectEventHandler pre_connects;
-
-  /**
    * Function to call whenever we're notified about a peer connecting.
    */
   GNUNET_CORE_ConnectEventHandler connects;
@@ -406,23 +400,6 @@
 #endif
   switch (ntohs (msg->type))
     {
-    case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT:
-      if (NULL == h->pre_connects)
-        {
-          GNUNET_break (0);
-          break;
-        }
-      if (msize != sizeof (struct ConnectNotifyMessage))
-        {
-          GNUNET_break (0);
-          break;
-        }
-      cnm = (const struct ConnectNotifyMessage *) msg;
-      h->pre_connects (h->cls,
-                      &cnm->peer,
-                      GNUNET_TIME_relative_ntoh (cnm->latency),
-                      ntohl (cnm->distance));
-      break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
       if (NULL == h->connects)
         {
@@ -662,8 +639,6 @@
   init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
   init->header.size = htons (msize);
   opt = GNUNET_CORE_OPTION_NOTHING;
-  if (h->pre_connects != NULL)
-    opt |= GNUNET_CORE_OPTION_SEND_PRE_CONNECT;
   if (h->connects != NULL)
     opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
   if (h->disconnects != NULL)
@@ -705,7 +680,6 @@
  * @param cls closure for the various callbacks that follow (including 
handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
  *        connected to the core service; note that timeout is only meaningful 
if init is not NULL
- * @param pre_connects function to call on peer pre-connect (no session key 
yet), can be NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be 
NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -726,7 +700,6 @@
                      struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
-                     GNUNET_CORE_ConnectEventHandler pre_connects,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
                      GNUNET_CORE_MessageCallback inbound_notify,
@@ -742,7 +715,6 @@
   h->cfg = cfg;
   h->cls = cls;
   h->init = init;
-  h->pre_connects = pre_connects;
   h->connects = connects;
   h->disconnects = disconnects;
   h->inbound_notify = inbound_notify;

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2010-04-17 22:54:36 UTC (rev 
10969)
+++ gnunet/src/core/gnunet-service-core.c       2010-04-18 20:23:40 UTC (rev 
10970)
@@ -3450,13 +3450,6 @@
           (n->status != PEER_STATE_KEY_CONFIRMED))
         {
           GNUNET_break_op (0);
-         /* blacklist briefly (?); might help recover (?) */
-         GNUNET_TRANSPORT_blacklist (sched, cfg,
-                                     &n->peer, 
-                                     GNUNET_TIME_UNIT_SECONDS,
-                                     GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MILLISECONDS,
-                                                                    5),
-                                     NULL, NULL);
           return;
         }
       handle_encrypted_message (n, (const struct EncryptedMessage *) message);
@@ -3626,7 +3619,6 @@
                                 unsigned int distance)
 {
   struct Neighbour *n;
-  struct ConnectNotifyMessage cnm;
 
   if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
     {
@@ -3665,12 +3657,6 @@
               "Received connection from `%4s'.\n",
               GNUNET_i2s (&n->peer));
 #endif
-  cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT);
-  cnm.distance = htonl (n->last_distance);
-  cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
-  cnm.peer = *peer;
-  send_to_all_clients (&cnm.header, GNUNET_YES, 
GNUNET_CORE_OPTION_SEND_PRE_CONNECT);
   GNUNET_TRANSPORT_set_quota (transport,
                              &n->peer,
                              n->bw_in,

Modified: gnunet/src/core/test_core_api.c
===================================================================
--- gnunet/src/core/test_core_api.c     2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/core/test_core_api.c     2010-04-18 20:23:40 UTC (rev 10970)
@@ -229,8 +229,7 @@
                            p2.cfg,
                            TIMEOUT,
                            &p2,
-                           &init_notify,
-                          NULL,
+                           &init_notify,                        
                            &connect_notify,
                            &disconnect_notify,
                            &inbound_notify,
@@ -325,8 +324,7 @@
                        TIMEOUT,
                        &p1,
                        &init_notify,
-                      NULL,
-                       &connect_notify,
+                      &connect_notify,
                        &disconnect_notify,
                        &inbound_notify,
                        GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);

Modified: gnunet/src/core/test_core_api_start_only.c
===================================================================
--- gnunet/src/core/test_core_api_start_only.c  2010-04-17 22:54:36 UTC (rev 
10969)
+++ gnunet/src/core/test_core_api_start_only.c  2010-04-18 20:23:40 UTC (rev 
10970)
@@ -130,8 +130,7 @@
                            p2.cfg,
                            TIMEOUT,
                            &p2,
-                           &init_notify,
-                          NULL,
+                           &init_notify,                        
                            &connect_notify,
                            &disconnect_notify,
                            &inbound_notify,
@@ -185,8 +184,7 @@
                        TIMEOUT,
                        &p1,
                        &init_notify,
-                      NULL,
-                       &connect_notify,
+                      &connect_notify,
                        &disconnect_notify,
                        &inbound_notify,
                        GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);

Modified: gnunet/src/fs/gnunet-service-fs.c
===================================================================
--- gnunet/src/fs/gnunet-service-fs.c   2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/fs/gnunet-service-fs.c   2010-04-18 20:23:40 UTC (rev 10970)
@@ -3025,7 +3025,6 @@
                              GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              NULL,
-                             NULL,
                              &peer_connect_handler,
                              &peer_disconnect_handler,
                              NULL, GNUNET_NO,

Modified: gnunet/src/hostlist/gnunet-daemon-hostlist.c
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-04-17 22:54:36 UTC 
(rev 10969)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-04-18 20:23:40 UTC 
(rev 10970)
@@ -296,7 +296,7 @@
                              GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              &core_init,
-                             NULL, &connect_handler, &disconnect_handler,
+                             &connect_handler, &disconnect_handler,
                              NULL, GNUNET_NO,
                              NULL, GNUNET_NO,
                              learning? learn_handlers : no_learn_handlers);

Modified: gnunet/src/include/gnunet_core_service.h
===================================================================
--- gnunet/src/include/gnunet_core_service.h    2010-04-17 22:54:36 UTC (rev 
10969)
+++ gnunet/src/include/gnunet_core_service.h    2010-04-18 20:23:40 UTC (rev 
10970)
@@ -51,7 +51,7 @@
 
 
 /**
- * Method called whenever a given peer either connects.
+ * Method called whenever a given peer connects.
  *
  * @param cls closure
  * @param peer peer identity this notification is about
@@ -164,7 +164,6 @@
  * @param cls closure for the various callbacks that follow (including 
handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
  *        connected to the core service; note that timeout is only meaningful 
if init is not NULL
- * @param pre_connects function to call on peer pre-connect (no session key 
yet), can be NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be 
NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -200,7 +199,6 @@
                      struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
-                    GNUNET_CORE_ConnectEventHandler pre_connects,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
                      GNUNET_CORE_MessageCallback inbound_notify,

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2010-04-17 22:54:36 UTC (rev 
10969)
+++ gnunet/src/include/gnunet_protocols.h       2010-04-18 20:23:40 UTC (rev 
10970)
@@ -174,18 +174,21 @@
 #define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY 28
 
 /**
- * Change in blacklisting status of a peer.
+ * Register a client that wants to do blacklisting.
  */
-#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST 29
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT 29
 
 /**
- * Request to transport to notify us about any blacklisting status
- * changes on this connection (and to immediately send all
- * active blacklist entries).
+ * Query to a blacklisting client (is this peer blacklisted)?
  */
-#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY 30
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY 30
 
 /**
+ * Reply from blacklisting client (answer to blacklist query).
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY 31
+
+/**
  * Transport PING message
  */
 #define GNUNET_MESSAGE_TYPE_TRANSPORT_PING 32

Modified: gnunet/src/include/gnunet_transport_service.h
===================================================================
--- gnunet/src/include/gnunet_transport_service.h       2010-04-17 22:54:36 UTC 
(rev 10969)
+++ gnunet/src/include/gnunet_transport_service.h       2010-04-18 20:23:40 UTC 
(rev 10970)
@@ -299,99 +299,52 @@
 
 
 /**
- * Handle for blacklisting requests.
+ * Handle for blacklisting peers.
  */
-struct GNUNET_TRANSPORT_BlacklistRequest;
+struct GNUNET_TRANSPORT_Blacklist;
 
 
 /**
- * Blacklist a peer for a given period of time.  All connections
- * (inbound and outbound) to a peer that is blacklisted will be
- * dropped (as soon as we learn who the connection is for).  A second
- * call to this function for the same peer overrides previous
- * blacklisting requests.
+ * Function that decides if a connection is acceptable or not.
  *
- * @param sched scheduler to use
- * @param cfg configuration to use
- * @param peer identity of peer to blacklist
- * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to
- *        re-enable connections
- * @param timeout when should this operation (trying to establish the
- *        blacklisting time out)
- * @param cont continuation to call once the request has been processed
- * @param cont_cls closure for cont
- * @return NULL on error, otherwise handle for cancellation
- */
-struct GNUNET_TRANSPORT_BlacklistRequest *
-GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
-                           const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           const struct GNUNET_PeerIdentity *peer,
-                           struct GNUNET_TIME_Relative duration,
-                           struct GNUNET_TIME_Relative timeout,
-                           GNUNET_SCHEDULER_Task cont,
-                           void *cont_cls);
-
-
-/**
- * Abort transmitting the blacklist request.  Note that this function
- * is NOT for removing a peer from the blacklist (for that, call 
- * GNUNET_TRANSPORT_blacklist with a duration of zero).  This function
- * is only for aborting the transmission of a blacklist request
- * (i.e. because of shutdown).
- *
- * @param br handle of the request that is to be cancelled
- */
-void
-GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * 
br);
-
-
-/**
- * Handle for blacklist notifications.
- */
-struct GNUNET_TRANSPORT_BlacklistNotification;
-
-
-/**
- * Signature of function called whenever the blacklist status of
- * a peer changes.  This includes changes to the duration of the
- * blacklist status as well as the expiration of an existing
- * blacklist status.
- *
  * @param cls closure
- * @param peer identity of peer with the change
- * @param until GNUNET_TIME_UNIT_ZERO_ABS if the peer is no
- *              longer blacklisted, otherwise the time at
- *              which the current blacklisting will expire
+ * @param pid peer to approve or disapproave
+ * @return GNUNET_OK if the connection is allowed
  */
-typedef void (*GNUNET_TRANSPORT_BlacklistCallback)(void *cls,
-                                                  const struct 
GNUNET_PeerIdentity *peer,
-                                                  struct GNUNET_TIME_Absolute 
until);
+typedef int (*GNUNET_TRANSPORT_BlacklistCallback)(void *cls,
+                                                 const struct 
GNUNET_PeerIdentity *pid);
 
 
 /**
- * Call a function whenever a peer's blacklisting status changes.
+ * Install a blacklist callback.  The service will be queried for all
+ * existing connections as well as any fresh connections to check if
+ * they are permitted.  If the blacklisting callback is unregistered,
+ * all hosts that were denied in the past will automatically be
+ * whitelisted again.  Cancelling the blacklist handle is also the
+ * only way to re-enable connections from peers that were previously
+ * blacklisted.
  *
  * @param sched scheduler to use
  * @param cfg configuration to use
- * @param bc function to call on status changes
- * @param bc_cls closure for bc
+ * @param cb callback to invoke to check if connections are allowed
+ * @param cb_cls closure for cb
  * @return NULL on error, otherwise handle for cancellation
  */
-struct GNUNET_TRANSPORT_BlacklistNotification *
-GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched,
-                                  const struct GNUNET_CONFIGURATION_Handle 
*cfg,
-                                  GNUNET_TRANSPORT_BlacklistCallback bc,
-                                  void *bc_cls);
+struct GNUNET_TRANSPORT_Blacklist *
+GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           GNUNET_TRANSPORT_BlacklistCallback cb,
+                           void *cb_cls);
 
 
 /**
- * Stop calling the notification callback associated with
- * the given blacklist notification.
+ * Abort the blacklist.  Note that this function is the only way for
+ * removing a peer from the blacklist.
  *
- * @param bn handle of the request that is to be cancelled
+ * @param br handle of the request that is to be cancelled
  */
 void
-GNUNET_TRANSPORT_blacklist_notify_cancel (struct 
GNUNET_TRANSPORT_BlacklistNotification * bn);
+GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br);
 
 
 

Modified: gnunet/src/testing/test_testing_topology.c
===================================================================
--- gnunet/src/testing/test_testing_topology.c  2010-04-17 22:54:36 UTC (rev 
10969)
+++ gnunet/src/testing/test_testing_topology.c  2010-04-18 20:23:40 UTC (rev 
10970)
@@ -392,11 +392,10 @@
                            temp_daemon->cfg,
                            TIMEOUT,
                            new_connection,
-                           &init_notify,
+                           &init_notify,                         
                            NULL,
                            NULL,
                            NULL,
-                           NULL,
                            GNUNET_YES, NULL, GNUNET_YES, handlers);
     }
 }

Modified: gnunet/src/testing/testing.c
===================================================================
--- gnunet/src/testing/testing.c        2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/testing/testing.c        2010-04-18 20:23:40 UTC (rev 10970)
@@ -265,7 +265,7 @@
                                        ARM_START_WAIT,
                                        d,
                                        &testing_init,
-                                       NULL, NULL, NULL,
+                                       NULL, NULL,
                                        NULL, GNUNET_NO,
                                        NULL, GNUNET_NO, no_handlers);
       break;
@@ -904,7 +904,7 @@
                                      timeout,
                                      ctx,
                                      NULL,
-                                     NULL, &connect_notify, NULL,
+                                     &connect_notify, NULL,
                                      NULL, GNUNET_NO,
                                      NULL, GNUNET_NO, no_handlers);
   if (ctx->d1core == NULL)

Modified: gnunet/src/topology/gnunet-daemon-topology.c
===================================================================
--- gnunet/src/topology/gnunet-daemon-topology.c        2010-04-17 22:54:36 UTC 
(rev 10969)
+++ gnunet/src/topology/gnunet-daemon-topology.c        2010-04-18 20:23:40 UTC 
(rev 10970)
@@ -106,12 +106,6 @@
   struct GNUNET_CONTAINER_BloomFilter *filter;
 
   /**
-   * Our request handle for *whitelisting* this peer (NULL if
-   * no whitelisting request is pending).
-   */
-  struct GNUNET_TRANSPORT_BlacklistRequest *wh;
-
-  /**
    * Until what time should we not try to connect again
    * to this peer?
    */
@@ -153,43 +147,10 @@
    */
   int is_connected;
 
-  /**
-   * Are we currently blocking this peer (via blacklist)?
-   */
-  int is_blocked;
-
 };
 
 
 /**
- * Entry in linked list of active 'disconnect' requests that we have issued.
- */
-struct DisconnectList
-{
-  /**
-   * This is a doubly-linked list.
-   */
-  struct DisconnectList *next;
-
-  /**
-   * This is a doubly-linked list.
-   */
-  struct DisconnectList *prev;
-  
-  /**
-   * Our request handle.
-   */
-  struct GNUNET_TRANSPORT_BlacklistRequest *rh;
-  
-  /**
-   * Peer we tried to disconnect.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-};
-
-
-/**
  * Our peerinfo notification context.  We use notification
  * to instantly learn about new peers as they are discovered.
  */
@@ -233,6 +194,11 @@
 static struct GNUNET_STATISTICS_Handle *stats;
 
 /**
+ * Blacklist (NULL if we have none).
+ */
+static struct GNUNET_TRANSPORT_Blacklist *blacklist;
+
+/**
  * Flag to disallow non-friend connections (pure F2F mode).
  */
 static int friends_only;
@@ -263,145 +229,46 @@
  */
 static int autoconnect;
 
-/**
- * Head of doubly-linked list of active 'disconnect' requests that we have 
issued.
- */
-static struct DisconnectList *disconnect_head;
 
 /**
- * Head of doubly-linked list of active 'disconnect' requests that we have 
issued.
- */
-static struct DisconnectList *disconnect_tail;
-
-
-/**
- * Function called once our request to 'disconnect' a peer
- * has completed.
+ * Function that decides if a connection is acceptable or not.  
+ * If we have a blacklist, only friends are allowed, so the check
+ * is rather simple.
  *
- * @param cls our 'struct DisconnectList'
- * @param tc unused
+ * @param cls closure
+ * @param pid peer to approve or disapproave
+ * @return GNUNET_OK if the connection is allowed
  */
-static void
-disconnect_done (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+static int
+blacklist_check (void *cls,
+                const struct GNUNET_PeerIdentity *pid)
 {
-  struct DisconnectList *dl = cls;
+  struct Peer *pos;
 
+  pos = GNUNET_CONTAINER_multihashmap_get (peers, &pid->hashPubKey);
+  if ( (pos != NULL) &&
+       (pos->is_friend == GNUNET_YES) )
+    return GNUNET_OK;
   GNUNET_STATISTICS_update (stats,
                            gettext_noop ("# peers blacklisted"),
                            1,
                            GNUNET_NO);
-  GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                              disconnect_tail,
-                              dl);
-  GNUNET_free (dl);
+  return GNUNET_SYSERR;
 }
 
 
 /**
- * Force a disconnect from the specified peer. 
- *
- * @param pl peer to disconnect
- */
-static void
-force_disconnect (struct Peer *pl)
-{
-  const struct GNUNET_PeerIdentity *peer = &pl->pid;
-  struct DisconnectList *dl;
-
-  if (NULL != pl->wh)
-    {
-      GNUNET_TRANSPORT_blacklist_cancel (pl->wh);
-      pl->wh = NULL;
-    }
-  pl->is_blocked = GNUNET_YES;
-  dl = GNUNET_malloc (sizeof (struct DisconnectList));
-  dl->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert (disconnect_head,
-                              disconnect_tail,
-                              dl);
-  dl->rh = GNUNET_TRANSPORT_blacklist (sched, cfg,                             
                
-                                      peer,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      &disconnect_done,
-                                      dl);
-}
-
-
-
-/**
- * Function called once our request to 'whitelist' a peer
- * has completed.
- *
- * @param cls our 'struct Peer'
- * @param tc unused
- */
-static void
-whitelist_done (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct Peer *pl = cls;
-
-  pl->wh = NULL;
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# peers blacklisted"),
-                           -1,
-                           GNUNET_NO);
-}
-
-
-/**
- * Whitelist the given peer (if it was blacklisted before).
- *
- * @param cls closure (not used)
- * @param pid identity of the peer
- * @param value peer to free
- * @return GNUNET_YES (always: continue to iterate)
- */
-static int
-whitelist_peer (void *cls,
-               const GNUNET_HashCode *pid,
-               void *value)
-{
-  struct Peer *pl = value;
-
-  if (! pl->is_blocked)
-    return GNUNET_YES;
-  pl->wh = GNUNET_TRANSPORT_blacklist (sched, cfg,                             
                
-                                      &pl->pid,
-                                      GNUNET_TIME_UNIT_ZERO,
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      &whitelist_done,
-                                      pl);
-  pl->is_blocked = GNUNET_NO;
-  return GNUNET_YES;
-}
-
-
-/**
  * Whitelist all peers that we blacklisted; we've passed
  * the minimum number of friends.
  */
 static void
 whitelist_peers ()
 {
-  struct DisconnectList *dl;
-
-  /* first, cancel all blacklisting requests */
-  while (NULL != (dl = disconnect_head))
+  if (blacklist != NULL)
     {
-      GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                                  disconnect_tail,
-                                  dl);
-      GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
-      GNUNET_free (dl);
+      GNUNET_TRANSPORT_blacklist_cancel (blacklist);
+      blacklist = NULL;
     }
-  /* then, specifically whitelist all peers that we
-     know to have blacklisted */
-  GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                        &whitelist_peer,
-                                        NULL);
 }
 
 
@@ -477,8 +344,6 @@
                                                      pos));
   if (pos->hello_req != NULL)
     GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req);
-  if (pos->wh != NULL)
-    GNUNET_TRANSPORT_blacklist_cancel (pos->wh);
   if (pos->connect_req != NULL)
     GNUNET_CORE_peer_request_connect_cancel (pos->connect_req);              
   if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK)
@@ -521,8 +386,6 @@
     return;
   if (GNUNET_OK != is_connection_allowed (pos))
     return;
-  if (GNUNET_YES == pos->is_blocked)
-    return;
   if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).value > 0)
     return;
   if (GNUNET_YES == pos->is_friend)
@@ -593,7 +456,6 @@
                                        pos);
     }
   if ( (GNUNET_NO == pos->is_friend) &&
-       (GNUNET_NO == pos->is_blocked) &&
        (GNUNET_NO == pos->is_connected) )
     {
       free_peer (NULL, &pos->pid.hashPubKey, pos);
@@ -863,18 +725,7 @@
   if (pos == NULL)    
     {
       pos = make_peer (peer, NULL, GNUNET_NO);
-      if (GNUNET_OK != is_connection_allowed (pos))
-       {
-         GNUNET_assert (pos->is_friend == GNUNET_NO);
-         pos->is_connected = GNUNET_YES;
-#if DEBUG_TOPOLOGY
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     "Connection to `%s' is forbidden, forcing disconnect!\n",
-                     GNUNET_i2s (peer));
-#endif       
-         force_disconnect (pos);
-         return;
-       }
+      GNUNET_break (GNUNET_OK == is_connection_allowed (pos));
     }
   else
     {
@@ -899,35 +750,6 @@
 
 
 /**
- * Disconnect from all non-friends (we're below quota).
- *
- * @param cls closure, not used
- * @param pid identity of a peer
- * @param value 'struct Peer*' for the peer
- * @return GNUNET_YES (continue to iterate)
- */
-static int
-drop_non_friends (void *cls,
-                 const GNUNET_HashCode *pid,
-                 void *value)
-{
-  struct Peer *pos = value;
-
-  if ( (GNUNET_NO == pos->is_friend) &&
-       (GNUNET_YES == pos->is_connected) )
-    {
-#if DEBUG_TOPOLOGY
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Connection to `%s' is not from a friend, forcing 
disconnect!\n",
-                 GNUNET_i2s (&pos->pid));
-#endif       
-      force_disconnect (pos);
-    }
-  return GNUNET_YES;
-}
-
-
-/**
  * Try to add more peers to our connection set.
  *
  * @param cls closure, not used
@@ -995,17 +817,10 @@
     GNUNET_CONTAINER_multihashmap_iterate (peers,
                                           &try_add_peers,
                                           NULL);
-  if (friend_count < minimum_friend_count)
-    {
-      /* disconnect from all non-friends */
-#if DEBUG_TOPOLOGY
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Not enough friendly connections, dropping all non-friend 
connections\n");
-#endif       
-      GNUNET_CONTAINER_multihashmap_iterate (peers,
-                                            &drop_non_friends,
-                                            NULL);
-    }
+  if ( (friend_count < minimum_friend_count) &&
+       (blacklist == NULL) )
+    blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
+                                           &blacklist_check, NULL);
 }
 
 
@@ -1389,13 +1204,21 @@
                            GNUNET_NO);
   peer = GNUNET_CONTAINER_multihashmap_get (peers,
                                            &pid.hashPubKey);
-  if ( (peer != NULL) &&
-       (peer->is_blocked) )
-    return GNUNET_OK; /* ignore: currently blocked */
-  if ( (GNUNET_YES == friends_only) &&
-       ( (peer == NULL) ||
-        (GNUNET_YES != peer->is_friend) ) )
-    return GNUNET_OK; /* ignore: not a friend */
+  if (peer == NULL)
+    {
+      if ( (GNUNET_YES == friends_only) ||
+          (friend_count < minimum_friend_count) )
+       return GNUNET_OK;      
+    }
+  else
+    {
+      if ( (GNUNET_YES != peer->is_friend) &&
+          (GNUNET_YES == friends_only) )
+       return GNUNET_OK;
+      if ( (GNUNET_YES != peer->is_friend) &&
+          (friend_count < minimum_friend_count) )
+       return GNUNET_OK;      
+    }
   if (transport != NULL)
     GNUNET_TRANSPORT_offer_hello (transport,
                                  message);
@@ -1468,8 +1291,6 @@
 cleaning_task (void *cls, 
               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct DisconnectList *dl;
-
   if (NULL != peerinfo_notify)
     {
       GNUNET_PEERINFO_notify_cancel (peerinfo_notify);
@@ -1486,14 +1307,7 @@
       GNUNET_CORE_disconnect (handle);
       handle = NULL;
     }
-  while (NULL != (dl = disconnect_head))
-    {
-      GNUNET_CONTAINER_DLL_remove (disconnect_head,
-                                  disconnect_tail,
-                                  dl);
-      GNUNET_TRANSPORT_blacklist_cancel (dl->rh);
-      GNUNET_free (dl);
-    }
+  whitelist_peers ();
   if (stats != NULL)
     {
       GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
@@ -1560,6 +1374,9 @@
              minimum_friend_count,
              autoconnect ? "autoconnect enabled" : "autoconnect disabled");
 #endif       
+  if (friend_count < minimum_friend_count) 
+    blacklist = GNUNET_TRANSPORT_blacklist (sched, cfg,
+                                           &blacklist_check, NULL);
   transport = GNUNET_TRANSPORT_connect (sched,
                                        cfg,
                                        NULL,
@@ -1571,7 +1388,6 @@
                                GNUNET_TIME_UNIT_FOREVER_REL,
                                NULL,
                                &core_init,
-                               NULL,
                                &connect_notify,
                                &disconnect_notify,
                                NULL, GNUNET_NO,

Modified: gnunet/src/transport/Makefile.am
===================================================================
--- gnunet/src/transport/Makefile.am    2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/transport/Makefile.am    2010-04-18 20:23:40 UTC (rev 10970)
@@ -57,8 +57,7 @@
   $(GN_LIBINTL)
 
 gnunet_service_transport_SOURCES = \
- gnunet-service-transport.c plugin_transport.h \
- gnunet-service-transport_blacklist.c gnunet-service-transport_blacklist.h
+ gnunet-service-transport.c plugin_transport.h 
 gnunet_service_transport_LDADD = \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \

Modified: gnunet/src/transport/gnunet-service-transport_blacklist.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport_blacklist.c   2010-04-17 
22:54:36 UTC (rev 10969)
+++ gnunet/src/transport/gnunet-service-transport_blacklist.c   2010-04-18 
20:23:40 UTC (rev 10970)
@@ -43,32 +43,75 @@
   struct GNUNET_PeerIdentity peer;
 
   /**
-   * How long until this entry times out?
+   * Client responsible for this entry.
    */
-  struct GNUNET_TIME_Absolute until;
+  struct GNUNET_SERVER_Client *client;
 
+};
+
+
+/**
+ * Information kept for each client registered to perform
+ * blacklisting.
+ */
+struct Blacklisters
+{
   /**
-   * Task scheduled to run the moment the time does run out.
+   * This is a linked list.
    */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+  struct Blacklisters *next;
+
+  /**
+   * This is a linked list.
+   */
+  struct Blacklisters *prev;
+
+  /**
+   * Client responsible for this entry.
+   */
+  struct GNUNET_SERVER_Client *client;
+
 };
 
 
 /**
+ * State of blacklist check to be performed for each
+ * connecting peer.
+ */
+struct BlacklistCheck
+{
+
+  
+
+  /**
+   * Identity of the peer being checked.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * Clients we still need to ask.
+   */
+  struct GNUNET_SERVER_Client *pending;
+
+};
+
+
+
+/**
  * Map of blacklisted peers (maps from peer identities
  * to 'struct BlacklistEntry*' values).
  */
 static struct GNUNET_CONTAINER_MultiHashMap *blacklist;
 
 /**
- * Notifications for blacklisting.
+ * Head of DLL of blacklisting clients.
  */
-static struct GNUNET_SERVER_NotificationContext *blacklist_notifiers;
+static struct Blacklisters *bl_head;
 
 /**
- * Our scheduler.
+ * Tail of DLL of blacklisting clients.
  */
-static struct GNUNET_SCHEDULER_Handle *sched;
+static struct Blacklisters *bl_tail;
 
 
 /**
@@ -86,8 +129,6 @@
 {
   struct BlacklistEntry *be = value;
 
-  GNUNET_SCHEDULER_cancel (sched,
-                          be->timeout_task);
   GNUNET_free (be);
   return GNUNET_YES;
 }
@@ -108,37 +149,28 @@
                                         NULL);
   GNUNET_CONTAINER_multihashmap_destroy (blacklist);
   blacklist = NULL;
-  GNUNET_SERVER_notification_context_destroy (blacklist_notifiers);
-  blacklist_notifiers = NULL;
 }
 
 
 /**
- * Task run when a blacklist entry times out.
+ * Handle a request to start a blacklist.
  *
- * @param cls closure (the 'struct BlacklistEntry*')
- * @param tc scheduler context (unused)
+ * @param cls closure (always NULL)
+ * @param client identification of the client
+ * @param message the actual message
  */
-static void
-timeout_task (void *cls,
-             const struct GNUNET_SCHEDULER_TaskContext *tc)
+void
+GNUNET_TRANSPORT_handle_blacklist_init (void *cls,
+                                       struct GNUNET_SERVER_Client *client,
+                                       const struct GNUNET_MessageHeader 
*message)
 {
-  struct BlacklistEntry *be = cls;
-  struct BlacklistMessage msg;
-  
-  be->timeout_task = GNUNET_SCHEDULER_NO_TASK; 
-  msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST);
-  msg.header.size = htons (sizeof (struct BlacklistMessage));
-  msg.reserved = htonl (0);
-  msg.peer = be->peer;
-  msg.until = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_ZERO_ABS);
-  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (blacklist,
-                                                                    
&be->peer.hashPubKey,
-                                                                    be));
-  GNUNET_free (be);
-  GNUNET_SERVER_notification_context_broadcast (blacklist_notifiers,
-                                               &msg.header,
-                                               GNUNET_NO);
+  struct Blacklisters *bl;
+
+  bl = GNUNET_malloc (sizeof (struct Blacklisters));
+  bl->client = client;
+  GNUNET_SERVER_client_keep (client);
+  GNUNET_CONTAINER_DLL_insert (bl_head, bl_tail, bl);
+  /* FIXME: confirm that all existing connections are OK! */
 }
 
 
@@ -150,38 +182,33 @@
  * @param message the actual message
  */
 void
-GNUNET_TRANSPORT_handle_blacklist (void *cls,
-                                  struct GNUNET_SERVER_Client *client,
-                                  const struct GNUNET_MessageHeader *message)
+GNUNET_TRANSPORT_handle_blacklist_reply (void *cls,
+                                        struct GNUNET_SERVER_Client *client,
+                                        const struct GNUNET_MessageHeader 
*message)
 {
-  struct BlacklistEntry *be;
+  struct Blacklisters *bl;
   const struct BlacklistMessage *msg = (const struct BlacklistMessage*) 
message;
 
-  be = GNUNET_CONTAINER_multihashmap_get (blacklist,
-                                         &msg->peer.hashPubKey);
-  if (be != NULL)
+  bl = bl_head;
+  while ( (bl != NULL) &&
+         (bl->client != client) )
+    bl = bl->next;
+  if (bl == NULL)
     {
-      GNUNET_SCHEDULER_cancel (sched,
-                              be->timeout_task);
+      GNUNET_SERVER_client_done (client, GNUNET_SYSERR);
+      return;
     }
-  else
-    {
+  if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
+    {    
       be = GNUNET_malloc (sizeof (struct BlacklistEntry));
       be->peer = msg->peer;
+      be->client = client;
       GNUNET_CONTAINER_multihashmap_put (blacklist,
                                         &msg->peer.hashPubKey,
                                         be,
-                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
     }
-  be->until = GNUNET_TIME_absolute_ntoh (msg->until);
-  be->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                                  
GNUNET_TIME_absolute_get_remaining (be->until),
-                                                  &timeout_task,
-                                                  be);
-  GNUNET_SERVER_notification_context_broadcast (blacklist_notifiers,
-                                               &msg->header,
-                                               GNUNET_NO);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  /* FIXME: trigger continuation... */
 }
 
 
@@ -243,7 +270,9 @@
 int
 GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id)
 {
-  return GNUNET_CONTAINER_multihashmap_contains (blacklist, &id->hashPubKey);
+  if (GNUNET_CONTAINER_multihashmap_contains (blacklist, &id->hashPubKey))    
+    return GNUNET_YES;
+  
 }
 
 
@@ -263,7 +292,6 @@
                                GNUNET_TIME_UNIT_FOREVER_REL,
                                &shutdown_task,
                                NULL);
-  blacklist_notifiers = GNUNET_SERVER_notification_context_create (server, 0);
 }
 
 

Modified: gnunet/src/transport/gnunet-service-transport_blacklist.h
===================================================================
--- gnunet/src/transport/gnunet-service-transport_blacklist.h   2010-04-17 
22:54:36 UTC (rev 10969)
+++ gnunet/src/transport/gnunet-service-transport_blacklist.h   2010-04-18 
20:23:40 UTC (rev 10970)
@@ -31,16 +31,16 @@
 #include "transport.h"
 
 /**
- * Handle a request to blacklist a peer.
+ * Handle a request to start a blacklist.
  *
  * @param cls closure (always NULL)
  * @param client identification of the client
  * @param message the actual message
  */
 void
-GNUNET_TRANSPORT_handle_blacklist (void *cls,
-                                  struct GNUNET_SERVER_Client *client,
-                                  const struct GNUNET_MessageHeader *message);
+GNUNET_TRANSPORT_handle_blacklist_init (void *cls,
+                                       struct GNUNET_SERVER_Client *client,
+                                       const struct GNUNET_MessageHeader 
*message);
 
 
 /**
@@ -51,31 +51,10 @@
  * @param message the actual message
  */
 void
-GNUNET_TRANSPORT_handle_blacklist_notify (void *cls,
-                                         struct GNUNET_SERVER_Client *client,
-                                         const struct GNUNET_MessageHeader 
*message);
+GNUNET_TRANSPORT_handle_blacklist_reply (void *cls,
+                                        struct GNUNET_SERVER_Client *client,
+                                        const struct GNUNET_MessageHeader 
*message);
 
 
-/**
- * Is the given peer currently blacklisted?
- *
- * @param id identity of the peer
- * @return GNUNET_YES if the peer is blacklisted, GNUNET_NO if not
- */
-int
-GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id);
-
-
-/**
- * Initialize the blacklisting subsystem.
- *
- * @param server server we handle requests from (transport service server)
- * @param s scheduler to use
- */
-void 
-GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SERVER_Handle *server,
-                                struct GNUNET_SCHEDULER_Handle *s);
-
-
 #endif
 /* end of gnunet-service-transport_blacklist.h */

Modified: gnunet/src/transport/transport.h
===================================================================
--- gnunet/src/transport/transport.h    2010-04-17 22:54:36 UTC (rev 10969)
+++ gnunet/src/transport/transport.h    2010-04-18 20:23:40 UTC (rev 10970)
@@ -268,27 +268,22 @@
 {
 
   /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST
+   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY or
+   * GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY.
    */
   struct GNUNET_MessageHeader header;
 
   /**
-   * Reserved (for alignment).
+   * 0 for the query, GNUNET_OK (allowed) or GNUNET_SYSERR (disallowed)
+   * for the response.
    */
-  uint32_t reserved GNUNET_PACKED;
+  uint32_t is_allowed GNUNET_PACKED;
 
   /**
-   * Which peer is being blacklisted (or has seen its
-   * blacklisting expire)?
+   * Which peer is being blacklisted or queried?
    */
   struct GNUNET_PeerIdentity peer;
 
-  /**
-   * Until what time is this peer blacklisted (zero for
-   * no longer blacklisted).
-   */
-  struct GNUNET_TIME_AbsoluteNBO until;
-
 };
 
 

Modified: gnunet/src/transport/transport_api_blacklist.c
===================================================================
--- gnunet/src/transport/transport_api_blacklist.c      2010-04-17 22:54:36 UTC 
(rev 10969)
+++ gnunet/src/transport/transport_api_blacklist.c      2010-04-18 20:23:40 UTC 
(rev 10970)
@@ -36,7 +36,7 @@
 /**
  * Handle for blacklisting requests.
  */
-struct GNUNET_TRANSPORT_BlacklistRequest
+struct GNUNET_TRANSPORT_Blacklist
 {
 
   /**
@@ -45,342 +45,255 @@
   struct GNUNET_CLIENT_Connection * client;
 
   /**
-   * Function to call when done.
+   * Scheduler to use.
    */
-  GNUNET_SCHEDULER_Task cont;
+  struct GNUNET_SCHEDULER_Handle *sched;
 
   /**
-   * Clsoure for 'cont'.
+   * Configuration to use.
    */
-  void *cont_cls;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
 
   /**
-   * Scheduler to use.
-   */
-  struct GNUNET_SCHEDULER_Handle *sched;
-
-  /**
-   * Pending handle for the blacklisting request.
+   * Pending handle for the current request.
    */ 
   struct GNUNET_CLIENT_TransmitHandle *th;
-  
+
   /**
-   * How long should 'peer' be blacklisted?
+   * Function to call for determining if a peer is allowed
+   * to communicate with us.
    */
-  struct GNUNET_TIME_Absolute duration;
-  
+  GNUNET_TRANSPORT_BlacklistCallback cb;
+
   /**
-   * Which peer is being blacklisted?
+   * Closure for 'cb'.
    */
+  void *cb_cls;  
+
+  /**
+   * Peer currently under consideration.
+   */
   struct GNUNET_PeerIdentity peer;
-  
+
 };
 
 
 /**
- * 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.
+ * Establish blacklist connection to transport service.
  *
- * @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
+ * @param br overall handle
  */
-static size_t
-transmit_blacklist_request (void *cls,
-                           size_t size, void *buf)
-{
-  struct GNUNET_TRANSPORT_BlacklistRequest *br = cls;
-  struct BlacklistMessage req;
+static void
+reconnect (struct GNUNET_TRANSPORT_Blacklist *br);
 
-  if (buf == NULL)
-    {
-      GNUNET_SCHEDULER_add_continuation (br->sched,
-                                        br->cont,
-                                        br->cont_cls,
-                                        GNUNET_SCHEDULER_REASON_TIMEOUT);
-      GNUNET_free (br);
-      return 0;
-    }
-  req.header.size = htons (sizeof (req));
-  req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST);
-  req.reserved = htonl (0);
-  req.peer = br->peer;
-  req.until = GNUNET_TIME_absolute_hton (br->duration);
-  memcpy (buf, &req, sizeof (req));
-  GNUNET_SCHEDULER_add_continuation (br->sched,
-                                    br->cont,
-                                    br->cont_cls,
-                                    GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-  GNUNET_free (br);
-  return sizeof (req);
-}
 
-
 /**
- * Blacklist a peer for a given period of time.  All connections
- * (inbound and outbound) to a peer that is blacklisted will be
- * dropped (as soon as we learn who the connection is for).  A second
- * call to this function for the same peer overrides previous
- * blacklisting requests.
+ * Send our reply to a blacklisting request.
  *
- * @param sched scheduler to use
- * @param cfg configuration to use
- * @param peer identity of peer to blacklist
- * @param duration how long to blacklist, use GNUNET_TIME_UNIT_ZERO to
- *        re-enable connections
- * @param timeout when should this operation (trying to establish the
- *        blacklisting time out)
- * @param cont continuation to call once the request has been processed
- * @param cont_cls closure for cont
- * @return NULL on error, otherwise handle for cancellation
+ * @param br our overall context
  */
-struct GNUNET_TRANSPORT_BlacklistRequest *
-GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
-                           const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           const struct GNUNET_PeerIdentity *peer,
-                           struct GNUNET_TIME_Relative duration,
-                           struct GNUNET_TIME_Relative timeout,
-                           GNUNET_SCHEDULER_Task cont,
-                           void *cont_cls)
-{
-  struct GNUNET_CLIENT_Connection * client;
-  struct GNUNET_TRANSPORT_BlacklistRequest *ret;
+static void
+reply (struct GNUNET_TRANSPORT_Blacklist *br);
 
-  client = GNUNET_CLIENT_connect (sched, "transport", cfg);
-  if (NULL == client)
-    return NULL;
-  ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistRequest));
-  ret->client = client;
-  ret->peer = *peer;
-  ret->duration = GNUNET_TIME_relative_to_absolute (duration);
-  ret->sched = sched;
-  ret->cont = cont;
-  ret->cont_cls = cont_cls;
-  ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
-                                                sizeof (struct 
BlacklistMessage),
-                                                timeout,
-                                                GNUNET_YES,
-                                                &transmit_blacklist_request,
-                                                ret);
-  GNUNET_assert (NULL != ret->th);
-  return ret;
-}
 
-
 /**
- * Abort transmitting the blacklist request.  Note that this function
- * is NOT for removing a peer from the blacklist (for that, call 
- * GNUNET_TRANSPORT_blacklist with a duration of zero).  This function
- * is only for aborting the transmission of a blacklist request
- * (i.e. because of shutdown).
+ * Handle blacklist queries.
  *
- * @param br handle of the request that is to be cancelled
+ * @param cls our overall handle
+ * @param msg query
  */
-void
-GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_BlacklistRequest * 
br)
+static void
+query_handler (void *cls,
+              const struct GNUNET_MessageHeader *msg)
 {
-  GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
-  GNUNET_free (br);
+  struct GNUNET_TRANSPORT_Blacklist *br = cls;
+  const struct BlacklistMessage *bm;
+  
+  if ( (ntohs(msg->size) != sizeof (struct BlacklistMessage)) ||
+       (ntohs(msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY) )
+    {
+      reconnect (br);
+      return;
+    }
+  bm = (const struct BlacklistMessage *)msg;
+  GNUNET_break (0 == ntohl (bm->is_allowed));
+  br->peer = bm->peer;
+  reply (br);  
 }
 
 
 /**
- * Handle for blacklist notifications.
+ * Receive blacklist queries from transport service.
+ *
+ * @param br overall handle
  */
-struct GNUNET_TRANSPORT_BlacklistNotification
+static void
+receive (struct GNUNET_TRANSPORT_Blacklist *br)
 {
+  GNUNET_CLIENT_receive (br->client,
+                        &query_handler,
+                        br,
+                        GNUNET_TIME_UNIT_FOREVER_REL);
+}
 
-  /**
-   * Function to call whenever there is a change.
-   */
-  GNUNET_TRANSPORT_BlacklistCallback notify;
 
-  /**
-   * Closure for notify.
-   */
-  void *notify_cls;
-
-  /**
-   * Scheduler to use.
-   */
-  struct GNUNET_SCHEDULER_Handle *sched;
-
-  /**
-   * Configuration to use.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  
-  /**
-   * Connection to transport service.
-   */
-  struct GNUNET_CLIENT_Connection * client;
-
-  /**
-   * Pending handle for the notification request.
-   */ 
-  struct GNUNET_CLIENT_TransmitHandle *th;
-};
-
-
 /**
- * Send a request to receive blacklisting notifications
+ * Transmit the blacklist initialization request to the service.
  *
- * @param bn context to initialize
+ * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
  */
-static void
-request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn);
-
-
-/**
- * Destroy the existing connection to the transport service and
- * setup a new one (the existing one had serious problems).
- * 
- * @param bn context to re-initialize
- */
-static void
-retry_get_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn)
+static size_t
+transmit_blacklist_init (void *cls,
+                        size_t size, void *buf)
 {
-  GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO);
-  bn->client = GNUNET_CLIENT_connect (bn->sched, "transport", bn->cfg);
-  request_notifications (bn);
+  struct GNUNET_TRANSPORT_Blacklist *br = cls;
+  struct GNUNET_MessageHeader req;
+
+  if (buf == NULL)
+    {
+      reconnect (br);
+      return 0;
+    }
+  req.size = htons (sizeof (struct GNUNET_MessageHeader));
+  req.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT);
+  memcpy (buf, &req, sizeof (req));
+  receive (br);
+  return sizeof (req);
 }
 
 
 /**
- * Function called whenever we get a blacklisting notification.
- * Pass it on to the callback and wait for more.
+ * Establish blacklist connection to transport service.
  *
- * @param cls our 'struct GNUNET_TRANSPORT_BlacklistNotification *'
- * @param msg the blacklisting notification, NULL on error
+ * @param br overall handle
  */
 static void
-recv_blacklist_info (void *cls,
-                    const struct GNUNET_MessageHeader *msg)
+reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
 {
-  struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls;
-  const struct BlacklistMessage *req;
-
-  if ( (msg == NULL) ||
-       (sizeof(struct BlacklistMessage) != ntohs(msg->size)) ||
-       (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST != ntohs(msg->type)) )
-    {
-      retry_get_notifications (bn);
-      return;
-    }
-  req = (const struct BlacklistMessage*) msg;
-  bn->notify (bn->notify_cls,
-             &req->peer,
-             GNUNET_TIME_absolute_ntoh (req->until));
-  GNUNET_CLIENT_receive (bn->client,
-                        &recv_blacklist_info,
-                        bn,
-                        GNUNET_TIME_UNIT_FOREVER_REL);  
+  if (br->client != NULL)
+    GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
+  br->client = GNUNET_CLIENT_connect (br->sched,
+                                     "transport",
+                                     br->cfg);
+  br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
+                                               sizeof (struct 
GNUNET_MessageHeader),
+                                               GNUNET_TIME_UNIT_FOREVER_REL,
+                                               GNUNET_YES,
+                                               &transmit_blacklist_init,
+                                               br);
 }
 
 
 /**
- * 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.
+ * Transmit the blacklist response to the service.
  *
- * @param cls closure
+ * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*)
  * @param size number of bytes available in buf
  * @param buf where the callee should write the message
  * @return number of bytes written to buf
  */
-static size_t 
-transmit_notify_request (void *cls,
-                        size_t size, void *buf)
+static size_t
+transmit_blacklist_reply (void *cls,
+                         size_t size, void *buf)
 {
-  struct GNUNET_TRANSPORT_BlacklistNotification *bn = cls;
-  struct GNUNET_MessageHeader hdr;
+  struct GNUNET_TRANSPORT_Blacklist *br = cls;
+  struct BlacklistMessage req;
 
-  bn->th = NULL;
   if (buf == NULL)
     {
-      retry_get_notifications (bn);
+      reconnect (br);
       return 0;
     }
-  GNUNET_assert (size >= sizeof(hdr));
-  hdr.size = htons (sizeof (hdr));
-  hdr.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_NOTIFY);
-  memcpy (buf, &hdr, sizeof(hdr));
-  return sizeof(hdr);  
+  req.header.size = htons (sizeof (req));
+  req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY);
+  req.is_allowed = htonl (br->cb (br->cb_cls, &br->peer));
+  req.peer = br->peer;
+  memcpy (buf, &req, sizeof (req));
+  receive (br);
+  return sizeof (req);
 }
 
 
 /**
- * Send a request to receive blacklisting notifications
+ * Send our reply to a blacklisting request.
  *
- * @param bn context to initialize
+ * @param br our overall context
  */
 static void
-request_notifications (struct GNUNET_TRANSPORT_BlacklistNotification *bn)
+reply (struct GNUNET_TRANSPORT_Blacklist *br)
 {
-  GNUNET_assert (bn->client != NULL);
-  bn->th = GNUNET_CLIENT_notify_transmit_ready (bn->client,
-                                               sizeof (struct 
GNUNET_MessageHeader),
+  br->th = GNUNET_CLIENT_notify_transmit_ready (br->client,
+                                               sizeof (struct 
BlacklistMessage),
                                                GNUNET_TIME_UNIT_FOREVER_REL,
-                                               GNUNET_YES,
-                                               &transmit_notify_request,
-                                               bn);
-  GNUNET_assert (bn->th != NULL);
-  GNUNET_CLIENT_receive (bn->client,
-                        &recv_blacklist_info,
-                        bn,
-                        GNUNET_TIME_UNIT_FOREVER_REL);
+                                               GNUNET_NO,
+                                               &transmit_blacklist_reply,
+                                               br);
+  if (br->th == NULL)
+    {
+      reconnect (br);
+      return;
+    }
 }
 
 
 /**
- * Call a function whenever a peer's blacklisting status changes.
+ * Install a blacklist callback.  The service will be queried for all
+ * existing connections as well as any fresh connections to check if
+ * they are permitted.  If the blacklisting callback is unregistered,
+ * all hosts that were denied in the past will automatically be
+ * whitelisted again.  Cancelling the blacklist handle is also the
+ * only way to re-enable connections from peers that were previously
+ * blacklisted.
  *
  * @param sched scheduler to use
  * @param cfg configuration to use
- * @param bc function to call on status changes
- * @param bc_cls closure for bc
+ * @param cb callback to invoke to check if connections are allowed
+ * @param cb_cls closure for cb
  * @return NULL on error, otherwise handle for cancellation
  */
-struct GNUNET_TRANSPORT_BlacklistNotification *
-GNUNET_TRANSPORT_blacklist_notify (struct GNUNET_SCHEDULER_Handle *sched,
-                                  const struct GNUNET_CONFIGURATION_Handle 
*cfg,
-                                  GNUNET_TRANSPORT_BlacklistCallback bc,
-                                  void *bc_cls)
+struct GNUNET_TRANSPORT_Blacklist *
+GNUNET_TRANSPORT_blacklist (struct GNUNET_SCHEDULER_Handle *sched,
+                           const struct GNUNET_CONFIGURATION_Handle *cfg,
+                           GNUNET_TRANSPORT_BlacklistCallback cb,
+                           void *cb_cls)
 {
-  struct GNUNET_TRANSPORT_BlacklistNotification *ret;
   struct GNUNET_CLIENT_Connection * client;
+  struct GNUNET_TRANSPORT_Blacklist *ret;
 
   client = GNUNET_CLIENT_connect (sched, "transport", cfg);
   if (NULL == client)
     return NULL;
-  ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_BlacklistNotification));
+  ret = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_Blacklist));
   ret->client = client;
   ret->sched = sched;
   ret->cfg = cfg;
-  ret->notify = bc;
-  ret->notify_cls = bc_cls;
-  request_notifications (ret);
+  ret->th = GNUNET_CLIENT_notify_transmit_ready (client,
+                                                sizeof (struct 
GNUNET_MessageHeader),
+                                                GNUNET_TIME_UNIT_FOREVER_REL,
+                                                GNUNET_YES,
+                                                &transmit_blacklist_init,
+                                                ret);  
   return ret;
 }
 
 
 /**
- * Stop calling the notification callback associated with
- * the given blacklist notification.
+ * Abort the blacklist.  Note that this function is the only way for
+ * removing a peer from the blacklist.
  *
- * @param bn handle of the request that is to be cancelled
+ * @param br handle of the request that is to be cancelled
  */
 void
-GNUNET_TRANSPORT_blacklist_notify_cancel (struct 
GNUNET_TRANSPORT_BlacklistNotification * bn)
+GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br)
 {
-  if (bn->th != NULL)
-    GNUNET_CLIENT_notify_transmit_ready_cancel (bn->th);
-  GNUNET_CLIENT_disconnect (bn->client, GNUNET_NO);
-  GNUNET_free (bn);
+  if (br->th != NULL)
+    GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
+  GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
+  GNUNET_free (br);
 }
 
+
 /* end of transport_api_blacklist.c */





reply via email to

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