libgnunettransporttesting_la_SOURCES = \
transport-testing.c
+libgnunettransporttesting_la_LIBADD = \
+ $(top_builddir)/src/transport/libgnunettransport.la \
+ $(top_builddir)/src/hello/libgnunethello.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+libgnunettransporttesting_la_DEPENDS = \
+ libgnunettransport.la
libgnunettransport_la_SOURCES = \
transport_api.c transport.h \
uint16_t sender_address_len)
{
const char *plugin_name = cls;
-
+
+
if (NULL != message)
GST_clients_broadcast (message, GNUNET_YES);
GNUNET_ATS_address_update (GST_ats,
/**
* Context we use when performing a blacklist check.
*/
-struct BlacklistCheck;
+struct GST_BlacklistCheck;
/**
struct GNUNET_SERVER_Client *client;
/**
- * Blacklist check that we're currently performing.
+ * Blacklist check that we're currently performing (or NULL
+ * if we're performing one that has been cancelled).
*/
- struct BlacklistCheck *bc;
+ struct GST_BlacklistCheck *bc;
+
+ /**
+ * Set to GNUNET_YES if we're currently waiting for a reply.
+ */
+ int waiting_for_reply;
};
/**
* Context we use when performing a blacklist check.
*/
-struct BlacklistCheck
+struct GST_BlacklistCheck
{
/**
* This is a linked list.
*/
- struct BlacklistCheck *next;
+ struct GST_BlacklistCheck *next;
/**
* This is a linked list.
*/
- struct BlacklistCheck *prev;
+ struct GST_BlacklistCheck *prev;
/**
* Peer being checked.
/**
* Head of DLL of active blacklisting queries.
*/
-static struct BlacklistCheck *bc_head;
+static struct GST_BlacklistCheck *bc_head;
/**
* Tail of DLL of active blacklisting queries.
*/
-static struct BlacklistCheck *bc_tail;
+static struct GST_BlacklistCheck *bc_tail;
/**
* Head of DLL of blacklisting clients.
struct GNUNET_SERVER_Client *client)
{
struct Blacklisters *bl;
- struct BlacklistCheck *bc;
+ struct GST_BlacklistCheck *bc;
if (client == NULL)
return;
/**
* Transmit blacklist query to the client.
*
- * @param cls the 'struct BlacklistCheck'
+ * @param cls the 'struct GST_BlacklistCheck'
* @param size number of bytes allowed
* @param buf where to copy the message
* @return number of bytes copied to buf
size_t size,
void *buf)
{
- struct BlacklistCheck *bc = cls;
+ struct GST_BlacklistCheck *bc = cls;
struct Blacklisters *bl;
struct BlacklistMessage bm;
bm.peer = bc->peer;
memcpy (buf, &bm, sizeof (bm));
GNUNET_SERVER_receive_done (bl->client, GNUNET_OK);
+ bl->waiting_for_reply = GNUNET_YES;
return sizeof (bm);
}
/**
* Perform next action in the blacklist check.
*
- * @param cls the 'struct BlacklistCheck*'
+ * @param cls the 'struct GST_BlacklistCheck*'
* @param tc unused
*/
static void
do_blacklist_check (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct BlacklistCheck *bc = cls;
+ struct GST_BlacklistCheck *bc = cls;
struct Blacklisters *bl;
bc->task = GNUNET_SCHEDULER_NO_TASK;
GNUNET_free (bc);
return;
}
- if (bl->bc != NULL)
+ if ( (bl->bc != NULL) ||
+ (bl->waiting_for_reply != GNUNET_NO) )
return; /* someone else busy with this client */
bl->bc = bc;
bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client,
uint32_t ats_count)
{
struct TestConnectionContext *tcc = cls;
- struct BlacklistCheck *bc;
+ struct GST_BlacklistCheck *bc;
- bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+ bc = GNUNET_malloc (sizeof (struct GST_BlacklistCheck));
GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
bc->peer = *neighbour;
bc->cont = &confirm_or_drop_neighbour;
{
const struct BlacklistMessage *msg = (const struct BlacklistMessage*) message;
struct Blacklisters *bl;
- struct BlacklistCheck *bc;
+ struct GST_BlacklistCheck *bc;
bl = bl_head;
while ( (bl != NULL) &&
}
bc = bl->bc;
bl->bc = NULL;
- if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
+ bl->waiting_for_reply = GNUNET_NO;
+ if (NULL != bc)
{
+ /* only run this if the blacklist check has not been
+ cancelled in the meantime... */
+ if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
+ {
#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Blacklist check failed, peer not allowed\n");
+ 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
- {
+ 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");
+ 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);
+ 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) )
+ for (bc = bc_head; bc != NULL; bc = bc->next)
+ if ( (bc->bl_pos == bl) &&
+ (GNUNET_SCHEDULER_NO_TASK == bc->task) )
+ {
bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
bc);
- bc = bc->next;
- }
+ break;
+ }
}
* @param transport_name name of the transport to test, never NULL
* @param cont function to call with result
* @param cont_cls closure for 'cont'
+ * @return handle to the blacklist check
*/
-void
+struct GST_BlacklistCheck *
GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
const char *transport_name,
GST_BlacklistTestContinuation cont,
void *cont_cls)
{
- struct BlacklistCheck *bc;
+ struct GST_BlacklistCheck *bc;
if ( (blacklist != NULL) &&
(GNUNET_SYSERR ==
}
/* need to query blacklist clients */
- bc = GNUNET_malloc (sizeof (struct BlacklistCheck));
+ bc = GNUNET_malloc (sizeof (struct GST_BlacklistCheck));
GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc);
bc->peer = *peer;
bc->cont = cont;
bc->bl_pos = bl_head;
bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check,
bc);
+ return bc;
}
-
+
+
+/**
+ * Cancel a blacklist check.
+ *
+ * @param bc check to cancel
+ */
+void
+GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc)
+{
+ GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
+ if (bc->bl_pos != NULL)
+ {
+ if (bc->bl_pos->bc == bc)
+ {
+ /* we're at the head of the queue, remove us! */
+ bc->bl_pos->bc = NULL;
+ }
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != bc->task)
+ {
+ GNUNET_SCHEDULER_cancel (bc->task);
+ bc->task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != bc->th)
+ {
+ GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
+ bc->th = NULL;
+ }
+ GNUNET_free (bc);
+}
/* end of file gnunet-service-transport_blacklist.c */
void
GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
const char *transport_name);
-
+
+
+/**
+ * Handle to an active blacklist check.
+ */
+struct GST_BlacklistCheck;
+
/**
* Continuation called from a blacklist 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'
+ * @return handle to the blacklist check
*/
-void
+struct GST_BlacklistCheck *
GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer,
const char *transport_name,
GST_BlacklistTestContinuation cont,
void *cont_cls);
+/**
+ * Cancel a blacklist check.
+ *
+ * @param bc check to cancel
+ */
+void
+GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc);
#endif
/* end of file gnunet-service-transport_blacklist.h */
* @author Christian Grothoff
*/
#include "platform.h"
+#include "gnunet-service-transport_blacklist.h"
#include "gnunet-service-transport_clients.h"
#include "gnunet-service-transport_hello.h"
#include "gnunet-service-transport_neighbours.h"
{ &clients_handle_address_lookup, NULL, 0},
{ &clients_handle_peer_address_lookup, NULL, sizeof (struct PeerAddressLookupMessage)},
{ &clients_handle_address_iterate, NULL, sizeof (struct GNUNET_MessageHeader)},
+ { &GST_blacklist_handle_init, NULL, sizeof (struct GNUNET_MessageHeader)},
+ { &GST_blacklist_handle_reply, NULL, sizeof (struct BlacklistMessage)},
{NULL, NULL, 0, 0}
};
GNUNET_SERVER_add_handlers (server, handlers);
*/
const void *addr;
+ /**
+ * Handle to the blacklist check (if we're currently in it).
+ */
+ struct GST_BlacklistCheck *bc;
+
/**
* Public key of the peer.
*/
{
struct ValidationEntry *ve = value;
+ if (NULL != ve->bc)
+ {
+ GST_blacklist_test_cancel (ve->bc);
+ ve->bc = NULL;
+ }
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_remove (validation_map,
+ &va->pid.hashPubKey,
+ va));
GNUNET_free (ve->transport_name);
if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
{
timeout_hello_validation (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct ValidationEntry *va = cls;
+ struct ValidationEntry *ve = cls;
- va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ ve->timeout_task = GNUNET_SCHEDULER_NO_TASK;
GNUNET_STATISTICS_update (GST_stats,
gettext_noop ("# address records discarded"),
1,
GNUNET_NO);
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_remove (validation_map,
- &va->pid.hashPubKey,
- va));
- GNUNET_free (va->transport_name);
- GNUNET_free (va);
+ cleanup_validation_entry (NULL, &ve->pid.hashPubKey, ve);
}
/**
- * Iterator callback to go over all addresses and try to validate them
- * (unless blocked or already validated).
+ * Function called with the result from blacklisting.
+ * Send a PING to the other peer if a communication is allowed.
*
- * @param cls pointer to a 'struct ValidateAddressContext'
- * @param tname name of the transport
- * @param expiration expiration time
- * @param addr the address
- * @param addrlen length of the address
- * @return GNUNET_OK (keep the address)
+ * @param cls ou r'struct ValidationEntry'
+ * @param pid identity of the other peer
+ * @param result GNUNET_OK if the connection is allowed, GNUNET_NO if not
*/
-static int
-validate_address (void *cls,
- const char *tname,
- struct GNUNET_TIME_Absolute expiration,
- const void *addr,
- uint16_t addrlen)
+static void
+transmit_ping_if_allowed (void *cls,
+ const struct GNUNET_PeerIdentity *pid,
+ int result)
{
- const struct ValidateAddressContext *vac = cls;
- const struct GNUNET_PeerIdentity *pid = &vac->pid;
- struct ValidationEntry *ve;
+ struct ValidationEntry *ve = cls;
struct TransportPingMessage ping;
struct GNUNET_TRANSPORT_PluginFunctions *papi;
const struct GNUNET_MessageHeader *hello;
size_t slen;
uint16_t hsize;
- if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0)
- return GNUNET_OK; /* expired */
- ve = find_validation_entry (&vac->public_key, pid, tname, addr, addrlen);
- if (GNUNET_TIME_absolute_get_remaining (ve->validation_block).rel_value > 0)
- return GNUNET_OK; /* blocked */
- if ( (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task) &&
- (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value > 0) )
- return GNUNET_OK; /* revalidation task already scheduled & still valid */
- ve->validation_block = GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME);
- if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
- GNUNET_SCHEDULER_cancel (ve->timeout_task);
- ve->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_REVALIDATION_START_TIME,
- &timeout_hello_validation,
- ve);
+ ve->bc = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transmitting plain PING to `%s'\n",
GNUNET_i2s (pid));
1,
GNUNET_NO);
}
+}
+
+
+/**
+ * Iterator callback to go over all addresses and try to validate them
+ * (unless blocked or already validated).
+ *
+ * @param cls pointer to a 'struct ValidateAddressContext'
+ * @param tname name of the transport
+ * @param expiration expiration time
+ * @param addr the address
+ * @param addrlen length of the address
+ * @return GNUNET_OK (keep the address)
+ */
+static int
+validate_address (void *cls,
+ const char *tname,
+ struct GNUNET_TIME_Absolute expiration,
+ const void *addr,
+ uint16_t addrlen)
+{
+ const struct ValidateAddressContext *vac = cls;
+ const struct GNUNET_PeerIdentity *pid = &vac->pid;
+ struct ValidationEntry *ve;
+
+ if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0)
+ return GNUNET_OK; /* expired */
+ ve = find_validation_entry (&vac->public_key, pid, tname, addr, addrlen);
+ if (GNUNET_TIME_absolute_get_remaining (ve->validation_block).rel_value > 0)
+ return GNUNET_OK; /* blocked */
+ if ( (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task) &&
+ (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value > 0) )
+ return GNUNET_OK; /* revalidation task already scheduled & still valid */
+ ve->validation_block = GNUNET_TIME_relative_to_absolute (HELLO_REVALIDATION_START_TIME);
+ if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task)
+ GNUNET_SCHEDULER_cancel (ve->timeout_task);
+ ve->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_REVALIDATION_START_TIME,
+ &timeout_hello_validation,
+ ve);
+ ve->bc = GST_blacklist_test_allowed (pid,
+ tname,
+ &transmit_ping_if_allowed,
+ ve);
return GNUNET_OK;
}