finishing blacklist implementation
authorChristian Grothoff <christian@grothoff.org>
Fri, 22 Jan 2010 14:47:45 +0000 (14:47 +0000)
committerChristian Grothoff <christian@grothoff.org>
Fri, 22 Jan 2010 14:47:45 +0000 (14:47 +0000)
src/transport/gnunet-service-transport_blacklist.c
src/transport/gnunet-service-transport_blacklist.h

index b51f5144260d3429487e0ace4f7b1e3c7c96a6d1..5ddf9c1bfea56aaae246510ad184614a3a2f03c6 100644 (file)
 struct BlacklistEntry
 {
   /**
-   * How long until this entry times out?
-   */
-  struct GNUNET_TIME_Absolute until;
-
-  /**
-   * Task scheduled to run the moment the time does run out.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-};
-
-
-/**
- * Entry in list of notifications still to transmit to
- * a client.
- */
-struct PendingNotificationList 
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct PendingNotificationList *next;
-
-  /**
-   * Identity of the peer to send notification about.
+   * Identity of the peer being blacklisted by this entry.
+   * (also equivalent to the key)  
    */
   struct GNUNET_PeerIdentity peer;
 
-};
-
-
-/**
- * List of clients to notify whenever the blacklist changes.
- */
-struct BlacklistNotificationList
-{
-
   /**
-   * This is a linked list.
-   */
-  struct BlacklistNotificationList *next;
-
-  /**
-   * Client to notify.
+   * How long until this entry times out?
    */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Pending request for transmission to client, or NULL.
-   */ 
-  struct GNUNET_CONNECTION_TransmitHandle *req;
+  struct GNUNET_TIME_Absolute until;
 
   /**
-   * Blacklist entries that still need to be submitted.
+   * Task scheduled to run the moment the time does run out.
    */
-  struct PendingNotificationList *pending;
-  
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
 };
 
 
@@ -104,9 +61,9 @@ struct BlacklistNotificationList
 static struct GNUNET_CONTAINER_MultiHashMap *blacklist;
 
 /**
- * Linked list of clients to notify whenever the blacklist changes.
+ * Notifications for blacklisting.
  */
-static struct BlacklistNotificationList *blacklist_notifiers;
+static struct GNUNET_SERVER_NotificationContext *blacklist_notifiers;
 
 /**
  * Our scheduler.
@@ -120,9 +77,7 @@ static struct GNUNET_SCHEDULER_Handle *sched;
  * @param cls closure, unused
  * @param key current key code
  * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
+ * @return GNUNET_YES (continue to iterate)
  */
 static int
 free_blacklist_entry (void *cls,
@@ -152,6 +107,38 @@ shutdown_task (void *cls,
                                         &free_blacklist_entry,
                                         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.
+ *
+ * @param cls closure (the 'struct BlacklistEntry*')
+ * @param tc scheduler context (unused)
+ */
+static void
+timeout_task (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  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);
 }
 
 
@@ -167,11 +154,67 @@ GNUNET_TRANSPORT_handle_blacklist (void *cls,
                                   struct GNUNET_SERVER_Client *client,
                                   const struct GNUNET_MessageHeader *message)
 {
-  /* FIXME */
+  struct BlacklistEntry *be;
+  const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
+
+  be = GNUNET_CONTAINER_multihashmap_get (blacklist,
+                                         &be->peer.hashPubKey);
+  if (be != NULL)
+    {
+      GNUNET_SCHEDULER_cancel (sched,
+                              be->timeout_task);
+    }
+  else
+    {
+      be = GNUNET_malloc (sizeof (struct BlacklistEntry));
+      be->peer = msg->peer;
+      GNUNET_CONTAINER_multihashmap_put (blacklist,
+                                        &be->peer.hashPubKey,
+                                        be,
+                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+    }
+  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);
 }
 
 
+/**
+ * Notify the given client about all entries in the blacklist.
+ *
+ * @param cls closure, refers to the 'struct GNUNET_SERVER_Client' to notify
+ * @param key current key code (peer identity, not used)
+ * @param value value in the hash map, the 'struct BlacklistEntry*'
+ * @return GNUNET_YES (continue to iterate)
+ */
+static int
+notify_blacklist_entry (void *cls,
+                       const GNUNET_HashCode *key,
+                       void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct BlacklistEntry *be = value;
+  struct BlacklistMessage msg;
+
+  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 (be->until);
+  GNUNET_SERVER_notification_context_unicast (blacklist_notifiers,
+                                             client,
+                                             &msg.header,
+                                             GNUNET_NO);
+  return GNUNET_YES;
+}
+
+
 /**
  * Handle a request for notification of blacklist changes.
  *
@@ -184,13 +227,10 @@ GNUNET_TRANSPORT_handle_blacklist_notify (void *cls,
                                          struct GNUNET_SERVER_Client *client,
                                          const struct GNUNET_MessageHeader *message)
 {
-  struct BlacklistNotificationList *bnl;
-
-  bnl = GNUNET_malloc (sizeof (struct BlacklistNotificationList));
-  bnl->next = blacklist_notifiers;
-  blacklist_notifiers = bnl;
-  /* FIXME */
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVER_notification_context_add (blacklist_notifiers, client);
+  GNUNET_CONTAINER_multihashmap_iterate (blacklist,
+                                        &notify_blacklist_entry,
+                                        client);
 }
 
 
@@ -213,7 +253,8 @@ GNUNET_TRANSPORT_blacklist_check (const struct GNUNET_PeerIdentity *id)
  * @param s scheduler to use
  */
 void 
-GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SCHEDULER_Handle *s)
+GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SERVER_Handle *server,
+                                struct GNUNET_SCHEDULER_Handle *s)
 {
   sched = s;
   blacklist = GNUNET_CONTAINER_multihashmap_create (4);
@@ -221,6 +262,8 @@ GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SCHEDULER_Handle *s)
                                GNUNET_TIME_UNIT_FOREVER_REL,
                                &shutdown_task,
                                NULL);
+  blacklist_notifiers = GNUNET_SERVER_notification_context_create (server, 0);
 }
 
+
 /* end of gnunet-service-transport_blacklist.c */
index 46a65cb61defc12a6bfb3e2e1b82441775b7ce5d..92f81a2e93f64e647aedbf18f97e77d6384647bb 100644 (file)
@@ -69,10 +69,12 @@ 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_SCHEDULER_Handle *s);
+GNUNET_TRANSPORT_blacklist_init (struct GNUNET_SERVER_Handle *server,
+                                struct GNUNET_SCHEDULER_Handle *s);
 
 
 #endif