-fix
[oweals/gnunet.git] / src / peerinfo-tool / gnunet-peerinfo_plugins.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010,2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file peerinfo-tool/gnunet-peerinfo_plugins.c
23  * @brief plugin management
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet-peerinfo_plugins.h"
28 #include "gnunet_transport_plugin.h"
29 #include "gnunet_hello_lib.h"
30
31 /**
32  * Entry in doubly-linked list of all of our plugins.
33  */
34 struct TransportPlugin
35 {
36   /**
37    * This is a doubly-linked list.
38    */
39   struct TransportPlugin *next;
40
41   /**
42    * This is a doubly-linked list.
43    */
44   struct TransportPlugin *prev;
45
46   /**
47    * API of the transport as returned by the plugin's
48    * initialization function.
49    */
50   struct GNUNET_TRANSPORT_PluginFunctions *api;
51
52   /**
53    * Short name for the plugin (i.e. "tcp").
54    */
55   char *short_name;
56
57   /**
58    * Name of the library (i.e. "gnunet_plugin_transport_tcp").
59    */
60   char *lib_name;
61
62   /**
63    * Environment this transport service is using
64    * for this plugin.
65    */
66   struct GNUNET_TRANSPORT_PluginEnvironment env;
67
68 };
69
70 /**
71  * Head of DLL of all loaded plugins.
72  */
73 static struct TransportPlugin *plugins_head;
74
75 /**
76  * Head of DLL of all loaded plugins.
77  */
78 static struct TransportPlugin *plugins_tail;
79
80
81
82 /**
83  * Load and initialize all plugins.  The respective functions will be
84  * invoked by the plugins when the respective events happen.  The
85  * closure will be set to a 'const char*' containing the name of the
86  * plugin that caused the call.
87  *
88  * @param cfg configuration to use
89  */
90 void
91 GPI_plugins_load (const struct GNUNET_CONFIGURATION_Handle *cfg)
92 {
93   struct TransportPlugin *plug;
94   struct TransportPlugin *next;
95   char *libname;
96   char *plugs;
97   char *pos;
98
99   if (NULL != plugins_head)
100     return; /* already loaded */
101   if (GNUNET_OK !=
102       GNUNET_CONFIGURATION_get_value_string (cfg, "TRANSPORT", "PLUGINS",
103                                              &plugs))
104     return;
105   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting transport plugins `%s'\n"),
106               plugs);
107   for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " "))
108   {
109     GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' transport plugin\n"),
110                 pos);
111     GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", pos);
112     plug = GNUNET_new (struct TransportPlugin);
113     plug->short_name = GNUNET_strdup (pos);
114     plug->lib_name = libname;
115     plug->env.cfg = cfg;
116     plug->env.cls = plug->short_name;
117     GNUNET_CONTAINER_DLL_insert (plugins_head, plugins_tail, plug);
118   }
119   GNUNET_free (plugs);
120   next = plugins_head;
121   while (next != NULL)
122   {
123     plug = next;
124     next = plug->next;
125     plug->api = GNUNET_PLUGIN_load (plug->lib_name, &plug->env);
126     if (plug->api == NULL)
127     {
128       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
129                   _("Failed to load transport plugin for `%s'\n"),
130                   plug->lib_name);
131       GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug);
132       GNUNET_free (plug->short_name);
133       GNUNET_free (plug->lib_name);
134       GNUNET_free (plug);
135     }
136   }
137 }
138
139
140 /**
141  * Unload all plugins
142  */
143 void
144 GPI_plugins_unload ()
145 {
146   struct TransportPlugin *plug;
147
148   while (NULL != (plug = plugins_head))
149   {
150     GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api));
151     GNUNET_free (plug->lib_name);
152     GNUNET_free (plug->short_name);
153     GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug);
154     GNUNET_free (plug);
155   }
156 }
157
158
159 /**
160  * Obtain the plugin API based on a plugin name.
161  *
162  * @param name name of the plugin
163  * @return the plugin's API, NULL if the plugin is not loaded
164  */
165 struct GNUNET_TRANSPORT_PluginFunctions *
166 GPI_plugins_find (const char *name)
167 {
168   struct TransportPlugin *head = plugins_head;
169
170   char *stripped = GNUNET_strdup (name);
171   char *head_stripped;
172   char *sep = strchr (stripped, '_');
173   if (NULL != sep)
174     sep[0] = '\0';
175
176   while (head != NULL)
177   {
178         head_stripped = GNUNET_strdup(head->short_name);
179     char *head_sep = strchr (head_stripped, '_');
180     if (NULL != head_sep)
181         head_sep[0] = '\0';
182     if (0 == strcmp (head_stripped, stripped))
183     {
184         GNUNET_free (head_stripped);
185       break;
186     }
187     GNUNET_free (head_stripped);
188     head = head->next;
189   }
190   GNUNET_free (stripped);
191   if (NULL == head)
192     return NULL;
193   return head->api;
194 }
195
196
197 /* end of file gnunet-peerinfo_plugins.c */