aboutsummaryrefslogtreecommitdiff
path: root/src/service/namecache/gnunet-service-namecache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/namecache/gnunet-service-namecache.c')
-rw-r--r--src/service/namecache/gnunet-service-namecache.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/service/namecache/gnunet-service-namecache.c b/src/service/namecache/gnunet-service-namecache.c
new file mode 100644
index 000000000..dce843801
--- /dev/null
+++ b/src/service/namecache/gnunet-service-namecache.c
@@ -0,0 +1,390 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file namecache/gnunet-service-namecache.c
23 * @brief namecache for the GNUnet naming system
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_statistics_service.h"
30#include "gnunet_namecache_service.h"
31#include "gnunet_namecache_plugin.h"
32#include "gnunet_signatures.h"
33#include "namecache.h"
34
35#define LOG_STRERROR_FILE(kind, syscall, \
36 filename) GNUNET_log_from_strerror_file (kind, "util", \
37 syscall, \
38 filename)
39
40
41/**
42 * A namecache client
43 */
44struct NamecacheClient
45{
46 /**
47 * The client
48 */
49 struct GNUNET_SERVICE_Client *client;
50
51 /**
52 * The message queue to talk to @e client.
53 */
54 struct GNUNET_MQ_Handle *mq;
55};
56
57
58/**
59 * Configuration handle.
60 */
61static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
62
63/**
64 * Handle to the statistics service
65 */
66static struct GNUNET_STATISTICS_Handle *statistics;
67
68/**
69 * Database handle
70 */
71static struct GNUNET_NAMECACHE_PluginFunctions *GSN_database;
72
73/**
74 * Name of the database plugin
75 */
76static char *db_lib_name;
77
78
79/**
80 * Task run during shutdown.
81 *
82 * @param cls unused
83 */
84static void
85cleanup_task (void *cls)
86{
87 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
88 "Stopping namecache service\n");
89 GNUNET_break (NULL ==
90 GNUNET_PLUGIN_unload (db_lib_name,
91 GSN_database));
92 GNUNET_free (db_lib_name);
93 db_lib_name = NULL;
94 if (NULL != statistics)
95 {
96 GNUNET_STATISTICS_destroy (statistics,
97 GNUNET_NO);
98 statistics = NULL;
99 }
100}
101
102
103/**
104 * Called whenever a client is disconnected.
105 * Frees our resources associated with that client.
106 *
107 * @param cls closure
108 * @param client identification of the client
109 * @param app_ctx the `struct NamecacheClient` for this @a client
110 */
111static void
112client_disconnect_cb (void *cls,
113 struct GNUNET_SERVICE_Client *client,
114 void *app_ctx)
115{
116 struct NamecacheClient *nc = app_ctx;
117
118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
119 "Client %p disconnected\n",
120 client);
121 GNUNET_free (nc);
122}
123
124
125/**
126 * Add a client to our list of active clients.
127 *
128 * @param cls NULL
129 * @param client client to add
130 * @param mq queue to talk to @a client
131 * @return internal namecache client structure for this client
132 */
133static void *
134client_connect_cb (void *cls,
135 struct GNUNET_SERVICE_Client *client,
136 struct GNUNET_MQ_Handle *mq)
137{
138 struct NamecacheClient *nc;
139
140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141 "Client %p connected\n",
142 client);
143 nc = GNUNET_new (struct NamecacheClient);
144 nc->client = client;
145 nc->mq = mq;
146 return nc;
147}
148
149
150/**
151 * Context for name lookups passed from #handle_lookup_block to
152 * #handle_lookup_block_it as closure
153 */
154struct LookupBlockContext
155{
156 /**
157 * The client to send the response to
158 */
159 struct NamecacheClient *nc;
160
161 /**
162 * Operation id for the name lookup
163 */
164 uint32_t request_id;
165
166 /**
167 * Lookup status
168 */
169 int status;
170};
171
172
173/**
174 * A #GNUNET_NAMECACHE_BlockCallback for name lookups in #handle_lookup_block
175 *
176 * @param cls a `struct LookupNameContext *` with information about the request
177 * @param block the block
178 */
179static void
180handle_lookup_block_it (void *cls,
181 const struct GNUNET_GNSRECORD_Block *block)
182{
183 struct LookupBlockContext *lnc = cls;
184 struct GNUNET_MQ_Envelope *env;
185 struct LookupBlockResponseMessage *r;
186 size_t bsize;
187
188 bsize = GNUNET_GNSRECORD_block_get_size (block);
189 env = GNUNET_MQ_msg_extra (r,
190 bsize,
191 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE);
192 r->gns_header.r_id = htonl (lnc->request_id);
193 GNUNET_memcpy (&r[1],
194 block,
195 bsize);
196 GNUNET_STATISTICS_update (statistics,
197 "blocks found in cache",
198 1,
199 GNUNET_NO);
200 r->expire = GNUNET_TIME_absolute_hton (
201 GNUNET_GNSRECORD_block_get_expiration (block));
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203 "Sending NAMECACHE_LOOKUP_BLOCK_RESPONSE message\n");
204 GNUNET_MQ_send (lnc->nc->mq,
205 env);
206}
207
208
209/**
210 * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK message
211 *
212 * @param cls a `struct NamecacheClient *`
213 * @param ln_msg the inbound message
214 */
215static void
216handle_lookup_block (void *cls,
217 const struct LookupBlockMessage *ln_msg)
218{
219 struct NamecacheClient *nc = cls;
220 struct GNUNET_MQ_Envelope *env;
221 struct LookupBlockContext lnc;
222 struct LookupBlockResponseMessage *zir_end;
223 int ret;
224
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
226 "Received NAMECACHE_LOOKUP_BLOCK message\n");
227 GNUNET_STATISTICS_update (statistics,
228 "blocks looked up",
229 1,
230 GNUNET_NO);
231 lnc.request_id = ntohl (ln_msg->gns_header.r_id);
232 lnc.nc = nc;
233 lnc.status = GNUNET_OK;
234 if (GNUNET_SYSERR ==
235 (ret = GSN_database->lookup_block (GSN_database->cls,
236 &ln_msg->query,
237 &handle_lookup_block_it,
238 &lnc)))
239 {
240 /* internal error (in database plugin); might be best to just hang up on
241 plugin rather than to signal that there are 'no' results, which
242 might also be false... */
243 GNUNET_break (0);
244 GNUNET_SERVICE_client_drop (nc->client);
245 return;
246 }
247 if ((0 == ret) || (GNUNET_SYSERR == lnc.status))
248 {
249 /* no records match at all, generate empty response */
250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251 "Sending empty NAMECACHE_LOOKUP_BLOCK_RESPONSE message\n");
252 env = GNUNET_MQ_msg (zir_end,
253 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE);
254 zir_end->gns_header.r_id = ln_msg->gns_header.r_id;
255 GNUNET_MQ_send (nc->mq,
256 env);
257 }
258 GNUNET_SERVICE_client_continue (nc->client);
259}
260
261
262/**
263 * Check a #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message
264 *
265 * @param cls our `struct NamecacheClient`
266 * @param rp_msg message to process
267 * @return #GNUNET_OK (always fine)
268 */
269static int
270check_block_cache (void *cls,
271 const struct BlockCacheMessage *rp_msg)
272{
273 return GNUNET_OK;
274}
275
276
277/**
278 * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message
279 *
280 * @param cls our `struct NamecacheClient`
281 * @param rp_msg message to process
282 */
283static void
284handle_block_cache (void *cls,
285 const struct BlockCacheMessage *rp_msg)
286{
287 struct NamecacheClient *nc = cls;
288 struct GNUNET_MQ_Envelope *env;
289 struct BlockCacheResponseMessage *rpr_msg;
290 struct GNUNET_GNSRECORD_Block *block;
291 size_t esize;
292 int res;
293
294 GNUNET_STATISTICS_update (statistics,
295 "blocks cached",
296 1,
297 GNUNET_NO);
298 esize = ntohs (rp_msg->gns_header.header.size) - sizeof(struct
299 BlockCacheMessage);
300 block = GNUNET_malloc (esize);
301 memcpy (block, &rp_msg[1], esize);
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
303 "Received NAMECACHE_BLOCK_CACHE message with type %u\n",
304 htonl (block->type));
305 res = GSN_database->cache_block (GSN_database->cls,
306 block);
307 GNUNET_free (block);
308 env = GNUNET_MQ_msg (rpr_msg,
309 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE);
310 rpr_msg->gns_header.r_id = rp_msg->gns_header.r_id;
311 rpr_msg->op_result = htonl (res);
312 GNUNET_MQ_send (nc->mq,
313 env);
314 GNUNET_SERVICE_client_continue (nc->client);
315}
316
317
318/**
319 * Process namecache requests.
320 *
321 * @param cls closure
322 * @param cfg configuration to use
323 * @param service the initialized service
324 */
325static void
326run (void *cls,
327 const struct GNUNET_CONFIGURATION_Handle *cfg,
328 struct GNUNET_SERVICE_Handle *service)
329{
330 char *database;
331
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Starting namecache service\n");
334 GSN_cfg = cfg;
335
336 /* Loading database plugin */
337 if (GNUNET_OK !=
338 GNUNET_CONFIGURATION_get_value_string (cfg,
339 "namecache",
340 "database",
341 &database))
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 "No database backend configured\n");
344
345 GNUNET_asprintf (&db_lib_name,
346 "libgnunet_plugin_namecache_%s",
347 database);
348 GSN_database = GNUNET_PLUGIN_load (db_lib_name,
349 (void *) GSN_cfg);
350 GNUNET_free (database);
351 if (NULL == GSN_database)
352 {
353 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354 "Could not load database backend `%s'\n",
355 db_lib_name);
356 GNUNET_SCHEDULER_add_now (&cleanup_task,
357 NULL);
358 return;
359 }
360 statistics = GNUNET_STATISTICS_create ("namecache",
361 cfg);
362
363 /* Configuring server handles */
364 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
365 NULL);
366}
367
368
369/**
370 * Define "main" method using service macro.
371 */
372GNUNET_SERVICE_MAIN
373 ("namecache",
374 GNUNET_SERVICE_OPTION_NONE,
375 &run,
376 &client_connect_cb,
377 &client_disconnect_cb,
378 NULL,
379 GNUNET_MQ_hd_fixed_size (lookup_block,
380 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK,
381 struct LookupBlockMessage,
382 NULL),
383 GNUNET_MQ_hd_var_size (block_cache,
384 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE,
385 struct BlockCacheMessage,
386 NULL),
387 GNUNET_MQ_handler_end ());
388
389
390/* end of gnunet-service-namecache.c */