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;
};
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.
* @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,
&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);
}
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.
*
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,
+ ¬ify_blacklist_entry,
+ client);
}
* @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);
GNUNET_TIME_UNIT_FOREVER_REL,
&shutdown_task,
NULL);
+ blacklist_notifiers = GNUNET_SERVER_notification_context_create (server, 0);
}
+
/* end of gnunet-service-transport_blacklist.c */