/*
This file is part of GNUnet.
- Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2010-2015 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* @file transport/gnunet-service-transport.c
/**
* Information we need for an asynchronous session kill.
*/
-struct SessionKiller
+struct GNUNET_ATS_SessionKiller
{
/**
* Kept in a DLL.
*/
- struct SessionKiller *next;
+ struct GNUNET_ATS_SessionKiller *next;
/**
* Kept in a DLL.
*/
- struct SessionKiller *prev;
+ struct GNUNET_ATS_SessionKiller *prev;
/**
* Session to kill.
*/
- struct Session *session;
+ struct GNUNET_ATS_Session *session;
/**
* Plugin for the session.
/**
* The kill task.
*/
- struct GNUNET_SCHEDULER_Task * task;
+ struct GNUNET_SCHEDULER_Task *task;
};
-/**
- * We track active blacklist checks in a DLL so we can cancel them if
- * necessary. We typically check against the blacklist a few times
- * during connection setup, as the check is asynchronous and the
- * blacklist may change its mind before the connection goes fully up.
- * Similarly, the session may die during the asynchronous check, so
- * we use this list to then cancel ongoing checks.
- */
-struct BlacklistCheckContext
-{
- /**
- * We keep these in a DLL.
- */
- struct BlacklistCheckContext *prev;
-
- /**
- * We keep these in a DLL.
- */
- struct BlacklistCheckContext *next;
-
- /**
- * Handle with the blacklist subsystem.
- */
- struct GST_BlacklistCheck *blc;
-
- /**
- * The address we are checking.
- */
- struct GNUNET_HELLO_Address *address;
-
- /**
- * Session associated with the address (or NULL).
- */
- struct Session *session;
-
- /**
- * Message to process in the continuation if the
- * blacklist check is ok, can be NULL.
- */
- struct GNUNET_MessageHeader *msg;
-
-};
-
/* globals */
/**
/**
* Head of DLL of asynchronous tasks to kill sessions.
*/
-static struct SessionKiller *sk_head;
+static struct GNUNET_ATS_SessionKiller *sk_head;
/**
* Tail of DLL of asynchronous tasks to kill sessions.
*/
-static struct SessionKiller *sk_tail;
+static struct GNUNET_ATS_SessionKiller *sk_tail;
/**
* Interface scanner determines our LAN address range(s).
*/
struct GNUNET_ATS_InterfaceScanner *GST_is;
-/**
- * Head of DLL of blacklist checks we have pending for
- * incoming sessions and/or SYN requests. We may
- * want to move this into the blacklist-logic at some
- * point.
- */
-struct BlacklistCheckContext *bc_head;
-
-/**
- * Tail of DLL of blacklist checks we have pending for
- * incoming sessions and/or SYN requests.
- */
-struct BlacklistCheckContext *bc_tail;
-
/**
* Transmit our HELLO message to the given (connected) neighbour.
*/
static struct GNUNET_TIME_Relative
process_payload (const struct GNUNET_HELLO_Address *address,
- struct Session *session,
+ struct GNUNET_ATS_Session *session,
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_TIME_Relative ret;
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Discarded %u bytes type %u payload from peer `%s'\n",
- msg_size,
+ (unsigned int) msg_size,
ntohs (message->type),
GNUNET_i2s (&address->peer));
GNUNET_STATISTICS_update (GST_stats, gettext_noop
/**
* Task to asynchronously terminate a session.
*
- * @param cls the `struct SessionKiller` with the information for the kill
- * @param tc scheduler context
+ * @param cls the `struct GNUNET_ATS_SessionKiller` with the information for the kill
*/
static void
-kill_session_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+kill_session_task (void *cls)
{
- struct SessionKiller *sk = cls;
+ struct GNUNET_ATS_SessionKiller *sk = cls;
sk->task = NULL;
GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk);
}
-/**
- * Cancel all blacklist checks that are pending for the given address and session.
- * NOTE: Consider moving the "bc_*" logic into blacklist.h?
- *
- * @param address address to remove from check
- * @param sesssion session that must match to remove for check
- */
-static void
-cancel_pending_blacklist_checks (const struct GNUNET_HELLO_Address *address,
- struct Session *session)
-{
- struct BlacklistCheckContext *blctx;
- struct BlacklistCheckContext *next;
-
- next = bc_head;
- for (blctx = next; NULL != blctx; blctx = next)
- {
- next = blctx->next;
- if ( (NULL != blctx->address) &&
- (0 == GNUNET_HELLO_address_cmp(blctx->address, address)) &&
- (blctx->session == session))
- {
- GNUNET_CONTAINER_DLL_remove (bc_head,
- bc_tail,
- blctx);
- if (NULL != blctx->blc)
- {
- GST_blacklist_test_cancel (blctx->blc);
- blctx->blc = NULL;
- }
- GNUNET_HELLO_address_free (blctx->address);
- GNUNET_free_non_null (blctx->msg);
- GNUNET_free (blctx);
- }
- }
-}
-
-
/**
* Force plugin to terminate session due to communication
* issue.
*/
static void
kill_session (const char *plugin_name,
- struct Session *session)
+ struct GNUNET_ATS_Session *session)
{
struct GNUNET_TRANSPORT_PluginFunctions *plugin;
- struct SessionKiller *sk;
+ struct GNUNET_ATS_SessionKiller *sk;
for (sk = sk_head; NULL != sk; sk = sk->next)
if (sk->session == session)
return;
}
/* need to issue disconnect asynchronously */
- sk = GNUNET_new (struct SessionKiller);
+ sk = GNUNET_new (struct GNUNET_ATS_SessionKiller);
sk->session = session;
sk->plugin = plugin;
sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, sk);
* Black list check result for try_connect call
* If connection to the peer is allowed request adddress and ???
*
- * @param cls blc_ctx bl context
+ * @param cls the message
* @param peer the peer
+ * @param address the address
+ * @param session the session
* @param result the result
*/
static void
connect_bl_check_cont (void *cls,
const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_ATS_Session *session,
int result)
{
- struct BlacklistCheckContext *blctx = cls;
+ struct GNUNET_MessageHeader *msg = cls;
- GNUNET_CONTAINER_DLL_remove (bc_head,
- bc_tail,
- blctx);
- blctx->blc = NULL;
if (GNUNET_OK == result)
{
/* Blacklist allows to speak to this peer, forward SYN to neighbours */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received SYN message from peer `%s' at `%s'\n",
GNUNET_i2s (peer),
- GST_plugins_a2s (blctx->address));
+ GST_plugins_a2s (address));
if (GNUNET_OK !=
- GST_neighbours_handle_session_syn (blctx->msg,
- &blctx->address->peer))
+ GST_neighbours_handle_session_syn (msg,
+ peer))
{
- cancel_pending_blacklist_checks (blctx->address,
- blctx->session);
- kill_session (blctx->address->transport_name,
- blctx->session);
+ GST_blacklist_abort_matching (address,
+ session);
+ kill_session (address->transport_name,
+ session);
}
+ GNUNET_free (msg);
+ return;
}
- else
- {
- /* Blacklist denies to speak to this peer */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Discarding SYN message from `%s' due to denied blacklist check\n",
- GNUNET_i2s (peer));
- cancel_pending_blacklist_checks (blctx->address,
- blctx->session);
- kill_session (blctx->address->transport_name,
- blctx->session);
- }
-
- if (NULL != blctx->address)
- GNUNET_HELLO_address_free (blctx->address);
- GNUNET_free (blctx->msg);
- GNUNET_free (blctx);
+ GNUNET_free (msg);
+ if (GNUNET_SYSERR == result)
+ return; /* check was aborted, session destroyed */
+ /* Blacklist denies to speak to this peer */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Discarding SYN message from `%s' due to denied blacklist check\n",
+ GNUNET_i2s (peer));
+ kill_session (address->transport_name,
+ session);
}
struct GNUNET_TIME_Relative
GST_receive_callback (void *cls,
const struct GNUNET_HELLO_Address *address,
- struct Session *session,
+ struct GNUNET_ATS_Session *session,
const struct GNUNET_MessageHeader *message)
{
const char *plugin_name = cls;
struct GNUNET_TIME_Relative ret;
- struct BlacklistCheckContext *blctx;
- struct GST_BlacklistCheck *blc;
uint16_t type;
ret = GNUNET_TIME_UNIT_ZERO;
if (GNUNET_OK != GST_validation_handle_hello (message))
{
GNUNET_break_op (0);
- cancel_pending_blacklist_checks (address,
- session);
+ GST_blacklist_abort_matching (address,
+ session);
}
return ret;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Processing `%s' from `%s'\n", "PING",
+ "Processing PING from `%s'\n",
GST_plugins_a2s (address));
if (GNUNET_OK !=
GST_validation_handle_ping (&address->peer,
address,
session))
{
- cancel_pending_blacklist_checks (address,
- session);
+ GST_blacklist_abort_matching (address,
+ session);
kill_session (plugin_name,
session);
}
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "Processing `%s' from `%s'\n", "PONG",
+ "Processing PONG from `%s'\n",
GST_plugins_a2s (address));
if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message))
{
- GNUNET_break_op(0);
- cancel_pending_blacklist_checks (address, session);
+ GNUNET_break_op (0);
+ GST_blacklist_abort_matching (address,
+ session);
kill_session (plugin_name, session);
}
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN:
/* Do blacklist check if communication with this peer is allowed */
- blctx = GNUNET_new (struct BlacklistCheckContext);
- blctx->address = GNUNET_HELLO_address_copy (address);
- blctx->session = session;
- blctx->msg = GNUNET_malloc (ntohs(message->size));
- memcpy (blctx->msg,
- message,
- ntohs (message->size));
- GNUNET_CONTAINER_DLL_insert (bc_head,
- bc_tail,
- blctx);
- if (NULL !=
- (blc = GST_blacklist_test_allowed (&address->peer,
- NULL,
- &connect_bl_check_cont,
- blctx)))
- {
- blctx->blc = blc;
- }
+ (void) GST_blacklist_test_allowed (&address->peer,
+ NULL,
+ &connect_bl_check_cont,
+ GNUNET_copy_message (message),
+ address,
+ session);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK:
if (GNUNET_OK !=
address,
session))
{
- cancel_pending_blacklist_checks (address, session);
+ GST_blacklist_abort_matching (address, session);
kill_session (plugin_name, session);
}
break;
session))
{
GNUNET_break_op(0);
- cancel_pending_blacklist_checks (address, session);
+ GST_blacklist_abort_matching (address, session);
kill_session (plugin_name, session);
}
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT:
- GST_neighbours_handle_disconnect_message (&address->peer, message);
+ GST_neighbours_handle_disconnect_message (&address->peer,
+ message);
+ break;
+ case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA:
+ GST_neighbours_handle_quota_message (&address->peer,
+ message);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE:
- GST_neighbours_keepalive (&address->peer, message);
+ GST_neighbours_keepalive (&address->peer,
+ message);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE:
- GST_neighbours_keepalive_response (&address->peer, message);
+ GST_neighbours_keepalive_response (&address->peer,
+ message);
break;
default:
/* should be payload */
message);
break;
}
- end:
+ end:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Allowing receive from peer %s to continue in %s\n",
GNUNET_i2s (&address->peer),
if (GNUNET_YES == add_remove)
{
addresses ++;
- GNUNET_STATISTICS_update (cfg, "# transport addresses", 1, GNUNET_NO);
+ GNUNET_STATISTICS_update (cfg,
+ "# transport addresses",
+ 1,
+ GNUNET_NO);
}
else if (GNUNET_NO == add_remove)
{
if (0 == addresses)
+ {
GNUNET_break (0);
+ }
else
{
addresses --;
- GNUNET_STATISTICS_update (cfg, "# transport addresses", -1, GNUNET_NO);
+ GNUNET_STATISTICS_update (cfg,
+ "# transport addresses",
+ -1,
+ GNUNET_NO);
}
}
-
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Transport now has %u addresses to communicate\n",
addresses);
- GST_hello_modify_addresses (add_remove, address);
+ GST_hello_modify_addresses (add_remove,
+ address);
}
static void
plugin_env_session_end (void *cls,
const struct GNUNET_HELLO_Address *address,
- struct Session *session)
+ struct GNUNET_ATS_Session *session)
{
- struct SessionKiller *sk;
+ struct GNUNET_ATS_SessionKiller *sk;
if (NULL == address)
{
GST_plugins_a2s (address));
GST_neighbours_session_terminated (&address->peer, session);
- GST_ats_del_session (address, session);
- cancel_pending_blacklist_checks (address, session);
+ GST_ats_del_session (address,
+ session);
+ GST_blacklist_abort_matching (address, session);
for (sk = sk_head; NULL != sk; sk = sk->next)
{
* plugin gave us a new session in #plugin_env_session_start(). If
* connection to the peer is disallowed, kill the session.
*
- * @param cls blc_ctx bl context
+ * @param cls NULL
* @param peer the peer
+ * @param address address associated with the request
+ * @param session session associated with the request
* @param result the result
*/
static void
plugin_env_session_start_bl_check_cont (void *cls,
const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_ATS_Session *session,
int result)
{
- struct BlacklistCheckContext *blctx = cls;
-
- GNUNET_CONTAINER_DLL_remove (bc_head,
- bc_tail,
- blctx);
- blctx->blc = NULL;
if (GNUNET_OK != result)
{
- cancel_pending_blacklist_checks (blctx->address,
- blctx->session);
- kill_session (blctx->address->transport_name,
- blctx->session);
+ kill_session (address->transport_name,
+ session);
+ return;
}
- else if (GNUNET_YES !=
- GNUNET_HELLO_address_check_option (blctx->address,
- GNUNET_HELLO_ADDRESS_INFO_INBOUND))
+ if (GNUNET_YES !=
+ GNUNET_HELLO_address_check_option (address,
+ GNUNET_HELLO_ADDRESS_INFO_INBOUND))
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Informing verifier about inbound session's address `%s'\n",
- GST_plugins_a2s (blctx->address));
- GST_validation_handle_address (blctx->address);
+ GST_plugins_a2s (address));
+ GST_validation_handle_address (address);
}
- GNUNET_HELLO_address_free (blctx->address);
- GNUNET_free (blctx);
}
static void
plugin_env_session_start (void *cls,
const struct GNUNET_HELLO_Address *address,
- struct Session *session,
+ struct GNUNET_ATS_Session *session,
enum GNUNET_ATS_Network_Type scope)
{
- struct BlacklistCheckContext *blctx;
- struct GST_BlacklistCheck *blc;
struct GNUNET_ATS_Properties prop;
if (NULL == address)
may not know the address yet; add if necessary! */
/* FIXME: maybe change API here so we just pass scope? */
memset (&prop, 0, sizeof (prop));
+ GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != scope);
prop.scope = scope;
GST_ats_add_inbound_address (address,
session,
&prop);
}
/* Do blacklist check if communication with this peer is allowed */
- blctx = GNUNET_new (struct BlacklistCheckContext);
- blctx->address = GNUNET_HELLO_address_copy (address);
- blctx->session = session;
- GNUNET_CONTAINER_DLL_insert (bc_head,
- bc_tail,
- blctx);
- if (NULL !=
- (blc = GST_blacklist_test_allowed (&address->peer,
- address->transport_name,
- &plugin_env_session_start_bl_check_cont,
- blctx)))
- {
- blctx->blc = blc;
- }
+ (void) GST_blacklist_test_allowed (&address->peer,
+ address->transport_name,
+ &plugin_env_session_start_bl_check_cont,
+ NULL,
+ address,
+ session);
}
ats_request_address_change (void *cls,
const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_HELLO_Address *address,
- struct Session *session,
+ struct GNUNET_ATS_Session *session,
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
{
* and cancels pending validations.
*
* @param cls closure, unused
- * @param tc task context (unused)
*/
static void
-shutdown_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
{
GST_neighbours_stop ();
GST_plugins_unload ();
"My identity is `%4s'\n",
GNUNET_i2s_full (&GST_my_identity));
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &shutdown_task,
- NULL);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
if (NULL == GST_peerinfo)
{
GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
}
max_fd_rlimit = 0;
- max_fd_cfg = 0;
#if HAVE_GETRLIMIT
struct rlimit r_file;
if (0 == getrlimit (RLIMIT_NOFILE, &r_file))
{
max_fd_rlimit = r_file.rlim_cur;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Maximum number of open files was: %u/%u\n",
- r_file.rlim_cur,
- r_file.rlim_max);
+ "Maximum number of open files was: %u/%u\n",
+ (unsigned int) r_file.rlim_cur,
+ (unsigned int) r_file.rlim_max);
}
max_fd_rlimit = (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */
#endif
- GNUNET_CONFIGURATION_get_value_number (GST_cfg,
- "transport",
- "MAX_FD",
- &max_fd_cfg);
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (GST_cfg,
+ "transport",
+ "MAX_FD",
+ &max_fd_cfg))
+ max_fd_cfg = max_fd_rlimit;
if (max_fd_cfg > max_fd_rlimit)
max_fd = max_fd_cfg;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Limiting number of sockets to %u: validation %u, neighbors: %u\n",
- max_fd, (max_fd / 3), (max_fd / 3) * 2);
+ max_fd,
+ (max_fd / 3),
+ (max_fd / 3) * 2);
friend_only = GNUNET_CONFIGURATION_get_value_yesno (GST_cfg,
"topology",
if (GNUNET_SYSERR == friend_only)
friend_only = GNUNET_NO; /* According to topology defaults */
/* start subsystems */
- GST_hello_start (friend_only,
- &process_hello_update,
- NULL);
GST_blacklist_start (GST_server,
GST_cfg,
&GST_my_identity);
&plugin_env_address_change_notification,
&plugin_env_session_start,
&plugin_env_session_end);
+ GST_hello_start (friend_only,
+ &process_hello_update,
+ NULL);
GST_neighbours_start ((max_fd / 3) * 2);
GST_clients_start (GST_server);
GST_validation_start ((max_fd / 3));