* @author Christian Grothoff
*
* TODO:
- * - implement messages ATS -> transport
- * - implement loading / unloading of ATS plugins
- * - expose plugin the API to send messages ATS -> transport
+ * - implement unloading of ATS plugins
*/
#include "platform.h"
#include "gnunet_util_lib.h"
/**
* Handle for statistics.
*/
-static struct GNUNET_STATISTICS_Handle *GSA_stats;
+static struct GNUNET_STATISTICS_Handle *stats;
/**
* Our solver.
*/
static struct GNUNET_ATS_SolverFunctions *plugin;
+/**
+ * Solver plugin name as string
+ */
+static char *plugin_name;
+
/**
* The transport client (there can only be one at a time).
*/
static struct Client *transport_client;
+/**
+ * Function called by the solver to prompt the transport to
+ * try out a new address.
+ *
+ * @param cls closure, NULL
+ * @param pid peer this is about
+ * @param address address the transport should try
+ */
+static void
+suggest_cb (void *cls,
+ const struct GNUNET_PeerIdentity *pid,
+ const char *address)
+{
+ struct GNUNET_MQ_Envelope *env;
+ size_t slen = strlen (address) + 1;
+ struct AddressSuggestionMessage *as;
+
+ if (NULL == transport_client)
+ {
+ // FIXME: stats!
+ return;
+ }
+ env = GNUNET_MQ_msg_extra (as,
+ slen,
+ GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION);
+ as->peer = *pid;
+ memcpy (&as[1],
+ address,
+ slen);
+ GNUNET_MQ_send (transport_client->mq,
+ env);
+}
+
+
+/**
+ * Function called by the solver to tell the transpor to
+ * allocate bandwidth for the specified session.
+ *
+ * @param cls closure, NULL
+ * @param session session this is about
+ * @param peer peer this is about
+ * @param bw_in suggested bandwidth for receiving
+ * @param bw_out suggested bandwidth for transmission
+ */
+static void
+allocate_cb (void *cls,
+ struct GNUNET_ATS_Session *session,
+ const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_BANDWIDTH_Value32NBO bw_in,
+ struct GNUNET_BANDWIDTH_Value32NBO bw_out)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct SessionAllocationMessage *sam;
+
+ (void) cls;
+ if ( (NULL == transport_client) ||
+ (session->client != transport_client) )
+ {
+ /* transport must have just died and solver is addressing the
+ losses of sessions (possibly of previous transport), ignore! */
+ return;
+ }
+ env = GNUNET_MQ_msg (sam,
+ GNUNET_MESSAGE_TYPE_ATS_SESSION_ALLOCATION);
+ sam->session_id = session->session_id;
+ sam->peer = *peer;
+ sam->bandwidth_in = bw_in;
+ sam->bandwidth_out = bw_out;
+ GNUNET_MQ_send (transport_client->mq,
+ env);
+}
+
+
/**
* Convert @a properties to @a prop
*
const struct SessionAddMessage *message)
{
struct Client *c = cls;
- struct GNUNET_ATS_Session *session;
+ const char *address = (const char *) &message[1];
+ struct GNUNET_ATS_Session *session;
int inbound_only = (GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY ==
ntohs (message->header.type));
session,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
session->sh = plugin->session_add (plugin->cls,
- &session->data);
+ &session->data,
+ address);
GNUNET_SERVICE_client_continue (c->client);
}
-
/**
* Handle 'session update' messages from transport clients.
*
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"ATS shutdown initiated\n");
- if (NULL != GSA_stats)
+ if (NULL != stats)
{
- GNUNET_STATISTICS_destroy (GSA_stats,
+ GNUNET_STATISTICS_destroy (stats,
GNUNET_NO);
- GSA_stats = NULL;
+ stats = NULL;
+ }
+ if (NULL != plugin_name)
+ {
+ GNUNET_free (plugin_name);
+ plugin_name = NULL;
}
}
const struct GNUNET_CONFIGURATION_Handle *cfg,
struct GNUNET_SERVICE_Handle *service)
{
- GSA_stats = GNUNET_STATISTICS_create ("ats",
- cfg);
+ static struct GNUNET_ATS_PluginEnvironment env;
+ char *solver;
+
+ stats = GNUNET_STATISTICS_create ("ats",
+ cfg);
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "ats",
+ "SOLVER",
+ &solver))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "No ATS solver configured, using 'simple' approach\n");
+ solver = GNUNET_strdup ("simple");
+ }
GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
NULL);
-#if 0
- if (GNUNET_OK !=
- GAS_plugin_init (cfg))
+ env.cls = NULL;
+ env.cfg = cfg;
+ env.stats = stats;
+ env.suggest_cb = &suggest_cb;
+ env.allocate_cb = &allocate_cb;
+ GNUNET_asprintf (&plugin_name,
+ "libgnunet_plugin_ats2_%s",
+ solver);
+ GNUNET_free (solver);
+ if (NULL == (plugin = GNUNET_PLUGIN_load (plugin_name,
+ &env)))
{
- GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to initialize solver `%s'!\n"),
+ plugin_name);
GNUNET_SCHEDULER_shutdown ();
- return;
+ return;
}
-#endif
}
struct GNUNET_ATS_PreferenceHandle *ph,
const struct GNUNET_ATS_Preference *pref);
-
+ /**
+ * Transport established a new session with performance
+ * characteristics given in @a data.
+ *
+ * @param cls closure
+ * @param data performance characteristics of @a sh
+ * @param address address information (for debugging)
+ * @return handle by which the plugin will identify this session
+ */
struct GNUNET_ATS_SessionHandle *
(*session_add)(void *cls,
- const struct GNUNET_ATS_SessionData *data);
+ const struct GNUNET_ATS_SessionData *data,
+ const char *address);
+ /**
+ * @a data changed for a given @a sh, solver should consider
+ * the updated performance characteristics.
+ *
+ * @param cls closure
+ * @param sh session this is about
+ * @param data performance characteristics of @a sh
+ */
void
(*session_update)(void *cls,
struct GNUNET_ATS_SessionHandle *sh,
const struct GNUNET_ATS_SessionData *data);
+ /**
+ * A session went away. Solver should update accordingly.
+ *
+ * @param cls closure
+ * @param sh session this is about
+ * @param data (last) performance characteristics of @a sh
+ */
void
(*session_del)(void *cls,
struct GNUNET_ATS_SessionHandle *sh,
};
+
+/**
+ * The ATS plugin will pass a pointer to a struct
+ * of this type as to the initialization function
+ * of the ATS plugins.
+ */
+struct GNUNET_ATS_PluginEnvironment
+{
+ /**
+ * Configuration handle to be used by the solver
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Statistics handle to be used by the solver
+ */
+ struct GNUNET_STATISTICS_Handle *stats;
+
+ /**
+ * Closure to pass to all callbacks in this struct.
+ */
+ void *cls;
+
+ /**
+ * Suggest to the transport that it should try establishing
+ * a connection using the given address.
+ *
+ * @param cls closure, NULL
+ * @param pid peer this is about
+ * @param address address the transport should try
+ */
+ void
+ (*suggest_cb) (void *cls,
+ const struct GNUNET_PeerIdentity *pid,
+ const char *address);
+
+ /**
+ * Tell the transport that it should allocate the given
+ * bandwidth to the specified session.
+ *
+ * @param cls closure, NULL
+ * @param session session this is about
+ * @param peer peer this is about
+ * @param bw_in suggested bandwidth for receiving
+ * @param bw_out suggested bandwidth for transmission
+ */
+ void
+ (*allocate_cb) (void *cls,
+ struct GNUNET_ATS_Session *session,
+ const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_BANDWIDTH_Value32NBO bw_in,
+ struct GNUNET_BANDWIDTH_Value32NBO bw_out);
+
+};
+
+
+
#endif
/** @} */ /* end of group */