X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport_plugins.c;h=c6c5e04442e4bf2c6360c398bc48ff6910c32b56;hb=5268a6fed72de00832cf075f480c03fe86952bb6;hp=4b3dd455de5dc1ac0b7a8cb9d1a7166ebb636c22;hpb=71ea5bd2d05058008e604ffd42993be9c7250e04;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_plugins.c b/src/transport/gnunet-service-transport_plugins.c index 4b3dd455d..c6c5e0444 100644 --- a/src/transport/gnunet-service-transport_plugins.c +++ b/src/transport/gnunet-service-transport_plugins.c @@ -1,21 +1,21 @@ /* - This file is part of GNUnet. - (C) 2010,2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - 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. + This file is part of GNUnet. + Copyright (C) 2010-2014 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later */ /** @@ -26,6 +26,7 @@ #include "platform.h" #include "gnunet-service-transport.h" #include "gnunet-service-transport_hello.h" +#include "gnunet-service-transport_ats.h" #include "gnunet-service-transport_plugins.h" /** @@ -78,6 +79,48 @@ static struct TransportPlugin *plugins_head; static struct TransportPlugin *plugins_tail; +/** + * Function that will be called to update metrics for an address + * + * @param cls closure + * @param address address to update metrics for + * @param session the session + * @param distance new distance + */ +static void +plugin_env_update_distance (void *cls, + const struct GNUNET_HELLO_Address *address, + uint32_t distance) +{ + GST_ats_update_distance (address, + distance); +} + + +/** + * Function that will be called to figure if an address is an loopback, + * LAN, WAN etc. address + * + * @param cls closure + * @param addr binary address + * @param addrlen length of the @a addr + * @return type of the network @a addr belongs to + */ +static enum GNUNET_NetworkType +plugin_env_address_to_type (void *cls, + const struct sockaddr *addr, + size_t addrlen) +{ + if (NULL == GST_is) + { + GNUNET_break(0); + return GNUNET_NT_UNSPECIFIED; + } + return GNUNET_NT_scanner_get_type (GST_is, + addr, + addrlen); +} + /** * Load and initialize all plugins. The respective functions will be @@ -87,11 +130,14 @@ static struct TransportPlugin *plugins_tail; * * @param recv_cb function to call when data is received * @param address_cb function to call when our public addresses changed + * @param session_start_cb function to call when a session was created * @param session_end_cb function to call when a session was terminated + * @param address_type_cb function to call when a address type is requested */ void GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, GNUNET_TRANSPORT_AddressNotification address_cb, + GNUNET_TRANSPORT_SessionStart session_start_cb, GNUNET_TRANSPORT_SessionEnd session_end_cb) { struct TransportPlugin *plug; @@ -100,27 +146,36 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, char *libname; char *plugs; char *pos; + int fail; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (GST_cfg, "TRANSPORT", - "NEIGHBOUR_LIMIT", &tneigh)) + GNUNET_CONFIGURATION_get_value_number (GST_cfg, + "TRANSPORT", + "NEIGHBOUR_LIMIT", + &tneigh)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Transport service is lacking NEIGHBOUR_LIMIT option.\n")); return; } if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (GST_cfg, "TRANSPORT", "PLUGINS", + GNUNET_CONFIGURATION_get_value_string (GST_cfg, + "TRANSPORT", + "PLUGINS", &plugs)) return; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting transport plugins `%s'\n"), + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Starting transport plugins `%s'\n"), plugs); for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' transport plugin\n"), + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Loading `%s' transport plugin\n"), pos); - GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", pos); - plug = GNUNET_malloc (sizeof (struct TransportPlugin)); + GNUNET_asprintf (&libname, + "libgnunet_plugin_transport_%s", + pos); + plug = GNUNET_new (struct TransportPlugin); plug->short_name = GNUNET_strdup (pos); plug->lib_name = libname; plug->env.cfg = GST_cfg; @@ -129,24 +184,135 @@ GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, plug->env.cls = plug->short_name; plug->env.receive = recv_cb; plug->env.notify_address = address_cb; + plug->env.session_start = session_start_cb; plug->env.session_end = session_end_cb; + plug->env.get_address_type = &plugin_env_address_to_type; + plug->env.update_address_distance = &plugin_env_update_distance; plug->env.max_connections = tneigh; plug->env.stats = GST_stats; - GNUNET_CONTAINER_DLL_insert (plugins_head, plugins_tail, plug); + GNUNET_CONTAINER_DLL_insert (plugins_head, + plugins_tail, + plug); } GNUNET_free (plugs); next = plugins_head; - while (next != NULL) + while (NULL != next) { plug = next; next = plug->next; - plug->api = GNUNET_PLUGIN_load (plug->lib_name, &plug->env); - if (plug->api == NULL) + plug->api = GNUNET_PLUGIN_load (plug->lib_name, + &plug->env); + if (NULL == plug->api) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to load transport plugin for `%s'\n"), plug->lib_name); - GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); + GNUNET_CONTAINER_DLL_remove (plugins_head, + plugins_tail, + plug); + GNUNET_free (plug->short_name); + GNUNET_free (plug->lib_name); + GNUNET_free (plug); + continue; + } + fail = GNUNET_NO; + if (NULL == plug->api->address_pretty_printer) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "address_pretty_printer", + plug->lib_name); + } + if (NULL == plug->api->address_to_string) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "address_to_string", + plug->lib_name); + } + if (NULL == plug->api->string_to_address) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "string_to_address", + plug->lib_name); + } + if (NULL == plug->api->check_address) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "check_address", + plug->lib_name); + } + if (NULL == plug->api->get_session) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "get_session", + plug->lib_name); + } + if (NULL == plug->api->get_network) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "get_network", + plug->lib_name); + } + if (NULL == plug->api->send) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "send", + plug->lib_name); + } + if (NULL == plug->api->disconnect_peer) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "disconnect_peer", + plug->lib_name); + } + if (NULL == plug->api->disconnect_session) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "disconnect_session", + plug->lib_name); + } + if (NULL == plug->api->query_keepalive_factor) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "query_keepalive_factor", + plug->lib_name); + } + if (NULL == plug->api->update_session_timeout) + { + fail = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Missing function `%s' in transport plugin for `%s'\n"), + "update_session_timeout", + plug->lib_name); + } + if (GNUNET_YES == fail) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Did not load plugin `%s' due to missing functions\n"), + plug->lib_name); + GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api)); + GNUNET_CONTAINER_DLL_remove (plugins_head, + plugins_tail, + plug); GNUNET_free (plug->short_name); GNUNET_free (plug->lib_name); GNUNET_free (plug); @@ -183,13 +349,43 @@ GST_plugins_unload () struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find (const char *name) { - struct TransportPlugin *head = plugins_head; + struct TransportPlugin *pos; - while ((head != NULL) && (0 != strcmp (name, head->short_name))) - head = head->next; - if (NULL == head) + for (pos = plugins_head; NULL != pos; pos = pos->next) + if (0 == strcmp (name, pos->short_name)) + break; + if (NULL == pos) return NULL; - return head->api; + return pos->api; +} + + +/** + * Obtain the plugin API based on a the stripped plugin name after the underscore. + * + * Example: GST_plugins_printer_find (http_client) will return all plugins + * starting with the prefix "http": + * http_client or server if loaded + * + * @param name name of the plugin + * @return the plugin's API, NULL if the plugin is not loaded + */ +struct GNUNET_TRANSPORT_PluginFunctions * +GST_plugins_printer_find (const char *name) +{ + struct TransportPlugin *pos; + char *stripped = GNUNET_strdup (name); + char *sep = strchr (stripped, '_'); + + if (NULL != sep) + sep[0] = '\0'; + for (pos = plugins_head; NULL != pos; pos = pos->next) + if (pos->short_name == strstr (pos->short_name, stripped)) + break; + GNUNET_free (stripped); + if (NULL == pos) + return NULL; + return pos->api; } @@ -205,22 +401,56 @@ GST_plugins_a2s (const struct GNUNET_HELLO_Address *address) { struct GNUNET_TRANSPORT_PluginFunctions *api; static char unable_to_show[1024]; + static const char *s; - if (address == NULL) - return ""; - api = GST_plugins_find (address->transport_name); + if (NULL == address) + return ""; + if (0 == address->address_length) + return TRANSPORT_SESSION_INBOUND_STRING; /* Addresse with length 0 are inbound, address->address itself may be NULL */ + api = GST_plugins_printer_find (address->transport_name); if (NULL == api) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Failed to find transport plugin `%s'\n", + address->transport_name); return ""; + } if (0 == address->address_length) { - GNUNET_snprintf (unable_to_show, sizeof (unable_to_show), + GNUNET_snprintf (unable_to_show, + sizeof (unable_to_show), "", (unsigned int) address->address_length, address->transport_name); return unable_to_show; } - return api->address_to_string (NULL, address->address, - address->address_length); + return (NULL != (s = api->address_to_string (NULL, + address->address, + address->address_length)) + ? s + : ""); +} + + +/** + * Register callback with all plugins to monitor their status. + * + * @param cb callback to register, NULL to unsubscribe + * @param cb_cls closure for @a cb + */ +void +GST_plugins_monitor_subscribe (GNUNET_TRANSPORT_SessionInfoCallback cb, + void *cb_cls) +{ + struct TransportPlugin *pos; + + for (pos = plugins_head; NULL != pos; pos = pos->next) + if (NULL == pos->api->setup_monitor) + GNUNET_break (0); + else + pos->api->setup_monitor (pos->api->cls, + cb, + cb_cls); }