- changes
[oweals/gnunet.git] / src / namestore / gnunet-service-namestore.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file namestore/gnunet-service-namestore.c
23  * @brief namestore for the GNUnet naming system
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "namestore.h"
32
33
34
35 /**
36  * A namestore operation.
37  */
38 struct GNUNET_NAMESTORE_Operation
39 {
40   struct GNUNET_NAMESTORE_Operation *next;
41   struct GNUNET_NAMESTORE_Operation *prev;
42
43   uint64_t op_id;
44
45   char *data; /*stub data pointer*/
46 };
47
48
49 /**
50  * A namestore client
51  */
52 struct GNUNET_NAMESTORE_Client
53 {
54   struct GNUNET_NAMESTORE_Client *next;
55   struct GNUNET_NAMESTORE_Client *prev;
56
57   struct GNUNET_SERVER_Client * client;
58
59   struct GNUNET_NAMESTORE_Operation *op_head;
60   struct GNUNET_NAMESTORE_Operation *op_tail;
61 };
62
63
64
65 /**
66  * Configuration handle.
67  */
68 const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
69
70 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
71
72 static char *db_lib_name;
73
74 static struct GNUNET_NAMESTORE_Client *client_head;
75 static struct GNUNET_NAMESTORE_Client *client_tail;
76
77
78 /**
79  * Task run during shutdown.
80  *
81  * @param cls unused
82  * @param tc unused
83  */
84 static void
85 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
86 {
87   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
88
89   struct GNUNET_NAMESTORE_Operation * no;
90   struct GNUNET_NAMESTORE_Client * nc;
91
92   for (nc = client_head; nc != NULL; nc = nc->next)
93   {
94     for (no = nc->op_head; no != NULL; no = no->next)
95     {
96       GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
97       GNUNET_free (no);
98     }
99   }
100
101   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
102   GNUNET_free (nc);
103
104   GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
105   GNUNET_free (db_lib_name);
106 }
107
108 /**
109  * Called whenever a client is disconnected.  Frees our
110  * resources associated with that client.
111  *
112  * @param cls closure
113  * @param client identification of the client
114  */
115 static void
116 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
117 {
118   struct GNUNET_NAMESTORE_Operation * no;
119   struct GNUNET_NAMESTORE_Client * nc;
120   if (NULL == client)
121     return;
122
123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected \n", client);
124
125   for (nc = client_head; nc != NULL; nc = nc->next)
126   {
127     if (client == nc->client)
128       break;
129   }
130   if (NULL == client)
131     return;
132
133   for (no = nc->op_head; no != NULL; no = no->next)
134   {
135     GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
136     GNUNET_free (no);
137   }
138
139   GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
140   GNUNET_free (nc);
141 }
142
143 static void handle_start (void *cls,
144                           struct GNUNET_SERVER_Client * client,
145                           const struct GNUNET_MessageHeader * message)
146 {
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n");
148
149   struct GNUNET_NAMESTORE_Client * nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
150   nc->client = client;
151
152   GNUNET_CONTAINER_DLL_insert(client_head, client_tail, nc);
153
154   GNUNET_SERVER_receive_done (client, GNUNET_OK);
155 }
156
157 static void handle_lookup_name (void *cls,
158                           struct GNUNET_SERVER_Client * client,
159                           const struct GNUNET_MessageHeader * message)
160 {
161   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_LOOKUP_NAME");
162   GNUNET_SERVER_receive_done (client, GNUNET_OK);
163 }
164
165
166 /**
167  * Process template requests.
168  *
169  * @param cls closure
170  * @param server the initialized server
171  * @param cfg configuration to use
172  */
173 static void
174 run (void *cls, struct GNUNET_SERVER_Handle *server,
175      const struct GNUNET_CONFIGURATION_Handle *cfg)
176 {
177   char * database;
178
179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
180
181   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
182     {&handle_start, NULL,
183      GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
184     {&handle_lookup_name, NULL,
185      GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
186     {NULL, NULL, 0, 0}
187   };
188
189   GSN_cfg = cfg;
190
191   /* Loading database plugin */
192   if (GNUNET_OK !=
193       GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
194                                              &database))
195     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
196
197   GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
198   GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
199   if (GSN_database == NULL)
200     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n",
201         db_lib_name);
202   GNUNET_free (database);
203
204   /* Configuring server handles */
205   GNUNET_SERVER_add_handlers (server, handlers);
206   GNUNET_SERVER_disconnect_notify (server,
207                                    &client_disconnect_notification,
208                                    NULL);
209
210   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
211                                 NULL);
212
213 }
214
215
216 /**
217  * The main function for the template service.
218  *
219  * @param argc number of arguments from the command line
220  * @param argv command line arguments
221  * @return 0 ok, 1 on error
222  */
223 int
224 main (int argc, char *const *argv)
225 {
226   return (GNUNET_OK ==
227           GNUNET_SERVICE_run (argc, argv, "namestore",
228                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
229 }
230
231 /* end of gnunet-service-namestore.c */