2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
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.
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.
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.
21 * @file gns/gnunet-service-gns_reverser.c
22 * @brief GNUnet GNS service
23 * @author Martin Schanzenbach
28 #include "gnunet_gns_service.h"
29 #include "gnunet-service-gns_resolver.h"
30 #include "gnunet-service-gns_reverser.h"
32 struct ReverseRecordEntry
37 struct ReverseRecordEntry *next;
42 struct ReverseRecordEntry *prev;
47 struct GNUNET_GNSRECORD_ReverseRecord *record;
56 struct ReverseRecordEntry *records_head;
61 struct ReverseRecordEntry *records_tail;
64 * Current delegation to expect
66 struct GNUNET_CRYPTO_EcdsaPublicKey target;
69 * The zone target for reverse record resolution
71 struct GNUNET_CRYPTO_EcdsaPublicKey myzone;
74 * The nick of our zone
80 struct ReverseTreeNode
85 struct ReverseTreeNode *next;
90 struct ReverseTreeNode *prev;
93 * Resolved name until now
98 * Depth of the resolution at this node
103 * The pkey of the namespace
105 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
110 struct GNS_ReverserHandle
113 * GNS resolver handle
115 struct GNS_ResolverHandle *rh;
118 * The authority to look for
120 struct GNUNET_CRYPTO_EcdsaPublicKey authority;
123 * Resolution candidate queue
125 struct ReverseTreeNode *node_queue_head;
128 * Resolution candidate queue
130 struct ReverseTreeNode *node_queue_tail;
133 * Max depth for the resolution
140 GNS_ReverseResultProcessor proc;
149 * Reverse record collection task
151 static struct GNUNET_SCHEDULER_Task *reverse_record_check_task;
156 static struct GNS_ResolverHandle *gns_lookup_reverse;
161 static struct GNUNET_NAMESTORE_Handle *ns;
166 static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
169 cleanup_handle (struct GNS_ReverserHandle *rh)
171 struct ReverseTreeNode *rtn;
173 for (rtn = rh->node_queue_head; NULL != rtn; rtn = rh->node_queue_head)
175 if (NULL != rtn->name)
176 GNUNET_free (rtn->name);
177 GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
185 handle_gns_result (void *cls,
187 const struct GNUNET_GNSRECORD_Data *rd)
189 struct GNS_ReverserHandle *rh = cls;
190 const struct GNUNET_GNSRECORD_ReverseRecord *rr;
191 struct ReverseTreeNode *rtn;
194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
195 "Got result (%d)\n", rd_count);
197 for (int i = 0; i < rd_count; i++)
200 * Check if we are in the delegation set
202 if (GNUNET_GNSRECORD_TYPE_REVERSE != rd[i].record_type)
205 name = (const char*) &rr[1];
206 if (0 == memcmp (&rh->authority,
208 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
211 GNUNET_asprintf (&result,
213 rh->node_queue_head->name,
215 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
216 "Found path from %s\n", result);
218 rh->proc (rh->proc_cls, result);
220 GNUNET_free (result);
223 if (rh->node_queue_head->depth >= rh->max_depth)
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
226 "Found REVERSE from %s\n", name);
228 rtn = GNUNET_new (struct ReverseTreeNode);
229 if (NULL == rh->node_queue_head->name)
230 rtn->name = GNUNET_strdup (name);
232 GNUNET_asprintf (&rtn->name,
234 rh->node_queue_head->name,
236 rtn->depth = rh->node_queue_head->depth + 1;
237 rtn->pkey = rr->pkey;
238 GNUNET_CONTAINER_DLL_insert_tail (rh->node_queue_head,
245 * Done here remove node from queue
247 rtn = rh->node_queue_head;
248 GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
251 if (NULL == rh->node_queue_head)
254 rh->proc (rh->proc_cls, NULL);
258 rh->rh = GNS_resolver_lookup (&rh->node_queue_head->pkey,
259 GNUNET_GNSRECORD_TYPE_REVERSE,
262 GNUNET_GNS_LO_DEFAULT,
267 struct GNS_ReverserHandle *
268 GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
269 const struct GNUNET_CRYPTO_EcdsaPublicKey *authority,
270 GNS_ReverseResultProcessor proc,
273 struct GNS_ReverserHandle *rh;
274 struct ReverseTreeNode *rtn;
276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
277 "Starting reverse resolution\n");
278 rh = GNUNET_new (struct GNS_ReverserHandle);
280 rh->proc_cls = proc_cls;
281 rtn = GNUNET_new (struct ReverseTreeNode);
285 GNUNET_CONTAINER_DLL_insert (rh->node_queue_head,
288 rh->authority = *authority;
289 rh->max_depth = 3; //TODO make argument
290 rh->rh = GNS_resolver_lookup (target,
291 GNUNET_GNSRECORD_TYPE_REVERSE,
294 GNUNET_GNS_LO_DEFAULT,
301 * Cancel active resolution (i.e. client disconnected).
303 * @param rh resolution to abort
306 GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh)
316 handle_gns_result_iter (void *cls,
318 const struct GNUNET_GNSRECORD_Data *rd)
320 struct IteratorHandle *ith = cls;
321 struct ReverseRecordEntry *rr;
322 if ((rd_count != 1) ||
323 (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type))
325 gns_lookup_reverse = NULL;
326 GNUNET_SCHEDULER_add_now (&next_it, NULL);
331 rr = GNUNET_new (struct ReverseRecordEntry);
332 rr->record = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_ReverseRecord)
333 + strlen (ith->mynick) + 1);
334 rr->record->pkey = ith->target;
335 rr->record->expiration.abs_value_us = rd->expiration_time;
336 GNUNET_memcpy ((char*)&rr->record[1],
338 strlen (ith->mynick));
339 GNUNET_CONTAINER_DLL_insert (ith->records_head,
342 GNUNET_SCHEDULER_add_now (&next_it, NULL);
348 GNUNET_assert (NULL != namestore_iter);
349 GNUNET_NAMESTORE_zone_iterator_next (namestore_iter);
353 iterator_cb (void *cls,
354 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
356 unsigned int rd_count,
357 const struct GNUNET_GNSRECORD_Data *rd)
359 struct IteratorHandle *ith = cls;
360 struct GNUNET_CRYPTO_EcdsaPublicKey *target;
361 struct GNUNET_CRYPTO_EcdsaPublicKey zone;
363 if ((rd_count != 1) ||
364 (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type))
366 GNUNET_SCHEDULER_add_now (&next_it, NULL);
369 GNUNET_CRYPTO_ecdsa_key_get_public (key,
371 if (0 != memcmp (&zone, &ith->myzone,
372 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
374 GNUNET_SCHEDULER_add_now (&next_it, NULL);
377 target = (struct GNUNET_CRYPTO_EcdsaPublicKey *) rd->data;
378 gns_lookup_reverse = GNS_resolver_lookup (target,
379 GNUNET_GNSRECORD_TYPE_PKEY,
382 GNUNET_GNS_LO_DEFAULT,
383 &handle_gns_result_iter,
387 void check_reverse_records (void *cls);
390 finished_cb (void *cls)
392 struct IteratorHandle *ith = cls;
393 struct ReverseRecordEntry *rr;
395 //TODO add results to namestore!
396 for (rr = ith->records_head; NULL != rr; rr = ith->records_head)
398 GNUNET_CONTAINER_DLL_remove (ith->records_head,
401 GNUNET_free (rr->record);
404 reverse_record_check_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_DAYS,
405 &check_reverse_records,
417 check_reverse_records (void *cls)
419 struct IteratorHandle *ith = cls;
420 namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (ns,
431 GNS_reverse_init (const struct GNUNET_CONFIGURATION_Handle *c,
432 const struct GNUNET_NAMESTORE_Handle *nh,
433 const struct GNUNET_CRYPTO_EcdsaPublicKey *myzone,
436 struct IteratorHandle *ith;
439 ith = GNUNET_new (struct IteratorHandle);
440 ith->mynick = GNUNET_strdup (mynick);
441 ith->myzone = *myzone;
442 reverse_record_check_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_DAYS,
443 &check_reverse_records,