+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 GST_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);
+}
+