gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 97f8a1ba8d1d43025ae43ab33bca12efbd49f355
parent be479981b97e8eeeb4ac251bb413a08b425a0fdd
Author: Matthias Wachs <wachs@net.in.tum.de>
Date:   Wed, 13 Nov 2013 15:04:21 +0000

adding pseudonym NICK automatically to records sets


Diffstat:
Msrc/namestore/Makefile.am | 20++++++++++++++++++++
Msrc/namestore/gnunet-namestore.c | 16+++-------------
Msrc/namestore/gnunet-service-namestore.c | 183+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/namestore/namestore_api.c | 29+++++++++++++++++++++++++++++
Asrc/namestore/test_namestore_api_lookup_nick.c | 308+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/namestore/test_namestore_api_zone_iteration_nick.c | 466+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 996 insertions(+), 26 deletions(-)

diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am @@ -41,11 +41,13 @@ TESTING_TESTS = \ test_namestore_api_store_update \ test_namestore_api_lookup_public \ test_namestore_api_lookup_private \ + test_namestore_api_lookup_nick \ test_namestore_api_lookup_shadow \ test_namestore_api_lookup_shadow_filter \ test_namestore_api_remove \ test_namestore_api_remove_not_existing_record \ test_namestore_api_zone_iteration \ + test_namestore_api_zone_iteration_nick \ test_namestore_api_zone_iteration_specific_zone \ test_namestore_api_zone_iteration_stop \ test_namestore_api_monitoring \ @@ -199,6 +201,15 @@ test_namestore_api_lookup_public_LDADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +test_namestore_api_lookup_nick_SOURCES = \ + test_namestore_api_lookup_nick.c +test_namestore_api_lookup_nick_LDADD = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ + $(top_builddir)/src/namecache/libgnunetnamecache.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + test_namestore_api_lookup_private_SOURCES = \ test_namestore_api_lookup_private.c test_namestore_api_lookup_private_LDADD = \ @@ -281,6 +292,15 @@ test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la +test_namestore_api_zone_iteration_nick_SOURCES = \ + test_namestore_api_zone_iteration_nick.c +test_namestore_api_zone_iteration_nick_LDADD = \ + $(top_builddir)/src/testing/libgnunettesting.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ + $(top_builddir)/src/namestore/libgnunetnamestore.la + + test_namestore_api_zone_iteration_specific_zone_SOURCES = \ test_namestore_api_zone_iteration_specific_zone.c test_namestore_api_zone_iteration_specific_zone_LDADD = \ diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c @@ -31,6 +31,7 @@ #include <gnunet_dnsparser_lib.h> #include <gnunet_identity_service.h> #include <gnunet_gnsrecord_lib.h> +#include <gnunet_gns_service.h> #include <gnunet_namestore_service.h> @@ -732,19 +733,8 @@ testservice_task (void *cls, ret = 1; return; } - memset (&rd, 0, sizeof (rd)); - rd.data = nickstring; - rd.data_size = strlen(nickstring); - rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; - rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; - add_qe_uri = GNUNET_NAMESTORE_records_store (ns, - &zone_pkey, - "+", - 1, - &rd, - &add_continuation, - &add_qe_uri); + add_qe_uri = GNUNET_NAMESTORE_set_nick(ns, &zone_pkey, nickstring, + &add_continuation, &add_qe_uri); } if (monitor) { diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c @@ -27,6 +27,7 @@ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" +#include "gnunet_gns_service.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_namestore_plugin.h" @@ -63,6 +64,11 @@ struct ZoneIteration struct NamestoreClient *client; /** + * The nick to add to the records + */ + struct GNUNET_GNSRECORD_Data *nick; + + /** * Key of the zone we are iterating over. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; @@ -391,6 +397,109 @@ client_lookup (struct GNUNET_SERVER_Client *client) } +static void lookup_nick_it (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct GNUNET_GNSRECORD_Data **res = (cls); + + int c; + if (0 != strcmp (label, GNUNET_GNS_MASTERZONE_STR)) + { + GNUNET_break (0); + return; + } + for (c = 0; c < rd_count; c++) + { + if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) + { + (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data)); + (*res)->data = &(*res)[1]; + memcpy ((char *)(*res)->data, rd[c].data, rd[c].data_size); + (*res)->data_size = rd[c].data_size; + (*res)->expiration_time = rd[c].expiration_time; + (*res)->flags = rd[c].flags; + (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK; + return; + } + } + (*res) = NULL; +} + + +static struct GNUNET_GNSRECORD_Data * +get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone) +{ + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + struct GNUNET_GNSRECORD_Data *nick; + int res; + + res = GSN_database->lookup_records (GSN_database->cls, zone, + GNUNET_GNS_MASTERZONE_STR, &lookup_nick_it, &nick); + + if ((NULL == nick) || (GNUNET_OK != res)) + { + GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No nick name set for zone `%s'\n", + GNUNET_CRYPTO_ecdsa_public_key_to_string (&pub)); + return NULL; + } + + return nick; +} + + +static void merge_records (unsigned int rdc1, + const struct GNUNET_GNSRECORD_Data *rd1, + unsigned int rdc2, + const struct GNUNET_GNSRECORD_Data *rd2, + unsigned int *rdc_res, + struct GNUNET_GNSRECORD_Data **rd_res) +{ + int c; + size_t req; + char *data; + int record_offset; + size_t data_offset; + (*rdc_res) = rdc1 + rdc2; + + if (0 == rdc1 + rdc2) + { + (*rd_res) = NULL; + return; + } + + req = 0; + for (c=0; c< rdc1; c++) + req += sizeof (struct GNUNET_GNSRECORD_Data) + rd1[c].data_size; + for (c=0; c< rdc2; c++) + req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size; + (*rd_res) = GNUNET_malloc (req); + data = (char *) &(*rd_res)[rdc1 + rdc2]; + data_offset = 0; + + for (c=0; c< rdc1; c++) + { + (*rd_res)[c] = rd1[c]; + (*rd_res)[c].data = (void *) &data[data_offset]; + memcpy ((void *) (*rd_res)[c].data, rd1[c].data, rd1[c].data_size); + data_offset += (*rd_res)[c].data_size; + } + record_offset = rdc1; + for (c=0; c< rdc2; c++) + { + (*rd_res)[c+record_offset] = rd2[c]; + (*rd_res)[c+record_offset].data = (void *) &data[data_offset]; + memcpy ((void *) (*rd_res)[c+record_offset].data, rd2[c].data, rd2[c].data_size); + data_offset += (*rd_res)[c+record_offset].data_size; + } + GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset); +} + + + /** * Generate a 'struct LookupNameResponseMessage' and send it to the * given client using the given notification context. @@ -413,14 +522,29 @@ send_lookup_response (struct GNUNET_SERVER_NotificationContext *nc, const struct GNUNET_GNSRECORD_Data *rd) { struct RecordResultMessage *zir_msg; + struct GNUNET_GNSRECORD_Data *nick; + struct GNUNET_GNSRECORD_Data *res; + unsigned int res_count; size_t name_len; size_t rd_ser_len; size_t msg_size; char *name_tmp; char *rd_ser; + nick = get_nick_record (zone_key); + if ((NULL != nick) && (0 != strcmp(name, GNUNET_GNS_MASTERZONE_STR))) + { + merge_records (rd_count,rd, 1, nick, &res_count, &res); + GNUNET_free (nick); + } + else + { + res_count = rd_count; + res = (struct GNUNET_GNSRECORD_Data *) rd; + } + name_len = strlen (name) + 1; - rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); + rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); msg_size = sizeof (struct RecordResultMessage) + name_len + rd_ser_len; (void) client_lookup (client); zir_msg = GNUNET_malloc (msg_size); @@ -428,13 +552,13 @@ send_lookup_response (struct GNUNET_SERVER_NotificationContext *nc, zir_msg->gns_header.header.size = htons (msg_size); zir_msg->gns_header.r_id = htonl (request_id); zir_msg->name_len = htons (name_len); - zir_msg->rd_count = htons (rd_count); + zir_msg->rd_count = htons (res_count); zir_msg->rd_len = htons (rd_ser_len); zir_msg->private_key = *zone_key; name_tmp = (char *) &zir_msg[1]; memcpy (name_tmp, name, name_len); rd_ser = &name_tmp[name_len]; - GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser); + GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %u records and size %u\n", "RECORD_RESULT", @@ -444,6 +568,8 @@ send_lookup_response (struct GNUNET_SERVER_NotificationContext *nc, client, &zir_msg->gns_header.header, GNUNET_NO); + if (rd != res) + GNUNET_free (res); GNUNET_free (zir_msg); } @@ -573,25 +699,51 @@ struct RecordLookupContext size_t rd_ser_len; char *res_rd; + + struct GNUNET_GNSRECORD_Data *nick; }; -static void lookup_it (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) + + +static void +lookup_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, + const char *label, unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) { struct RecordLookupContext *rlc = cls; + struct GNUNET_GNSRECORD_Data *rd_res; + unsigned int rdc_res; if (0 == strcmp (label, rlc->label)) { rlc->found = GNUNET_YES; if (0 != rd_count) { - rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); - rlc->res_rd_count = rd_count; - rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); - GNUNET_GNSRECORD_records_serialize (rd_count, rd, rlc->rd_ser_len , rlc->res_rd); + if ((NULL != rlc->nick) && (0 != strcmp(label, GNUNET_GNS_MASTERZONE_STR))) + { + /* Merge */ + rd_res = NULL; + rdc_res = 0; + merge_records (rd_count, rd, + 1, rlc->nick, + &rdc_res, &rd_res); + + rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res); + rlc->res_rd_count = rdc_res; + rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); + GNUNET_GNSRECORD_records_serialize (rdc_res, rd_res, rlc->rd_ser_len , rlc->res_rd); + + GNUNET_free (rd_res); + GNUNET_free (rlc->nick); + rlc->nick = NULL; + } + else + { + rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); + rlc->res_rd_count = rd_count; + rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); + GNUNET_GNSRECORD_records_serialize (rd_count, rd, rlc->rd_ser_len , rlc->res_rd); + } } else { @@ -603,6 +755,9 @@ static void lookup_it (void *cls, } + + + /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message * @@ -666,8 +821,8 @@ handle_record_lookup (void *cls, rlc.label = name_tmp; rlc.found = GNUNET_NO; rlc.res_rd_count = 0; - rlc.rd_ser_len = 0; rlc.res_rd = NULL; + rlc.nick = get_nick_record (&ll_msg->zone); res = GSN_database->lookup_records (GSN_database->cls, &ll_msg->zone, name_tmp, &lookup_it, &rlc); @@ -1188,6 +1343,8 @@ handle_iteration_start (void *cls, zi->offset = 0; zi->client = nc; zi->zone = zis_msg->zone; + + GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); run_zone_iteration_round (zi); GNUNET_SERVER_receive_done (client, GNUNET_OK); diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c @@ -33,6 +33,7 @@ #include "gnunet_dnsparser_lib.h" #include "gnunet_arm_service.h" #include "gnunet_signatures.h" +#include "gnunet_gns_service.h" #include "gnunet_namestore_service.h" #include "namestore.h" @@ -1065,6 +1066,34 @@ GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h, return qe; } +/** + * Set the desired nick name for a zone + * + * @param h handle to the namestore + * @param pkey private key of the zone + * @param nick the nick name to set + * @param cont continuation to call when done + * @param cont_cls closure for 'cont' + * @return handle to abort the request + */ +struct GNUNET_NAMESTORE_QueueEntry * +GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, + const char *nick, + GNUNET_NAMESTORE_ContinuationWithStatus cont, + void *cont_cls) +{ + struct GNUNET_GNSRECORD_Data rd; + + memset (&rd, 0, sizeof (rd)); + rd.data = nick; + rd.data_size = strlen (nick) +1; + rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; + rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; + return GNUNET_NAMESTORE_records_store(h, pkey, GNUNET_GNS_MASTERZONE_STR, 1, &rd, cont, cont_cls); +} + /** * Lookup an item in the namestore. diff --git a/src/namestore/test_namestore_api_lookup_nick.c b/src/namestore/test_namestore_api_lookup_nick.c @@ -0,0 +1,308 @@ +/* + This file is part of GNUnet. + (C) 2012 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. +*/ +/** + * @file namestore/test_namestore_api_store.c + * @brief testcase for namestore_api.c: store a record + */ +#include "platform.h" +#include "gnunet_namestore_service.h" +#include "gnunet_testing_lib.h" + +#define TEST_RECORD_TYPE 1234 + +#define TEST_RECORD_DATALEN 123 + +#define TEST_NICK "gnunettestnick" + +#define TEST_RECORD_DATA 'a' + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) + +static struct GNUNET_NAMESTORE_Handle *nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; + +static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; + +static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; + +static int res; + +static struct GNUNET_GNSRECORD_Data rd_orig; + +static struct GNUNET_NAMESTORE_QueueEntry *nsqe; + +//static const char * name = "dummy.dummy.gnunet"; +static const char * name = "d"; + +static void +cleanup () +{ + GNUNET_free_non_null ((void *)rd_orig.data); + if (NULL != nsh) + { + GNUNET_NAMESTORE_disconnect (nsh); + nsh = NULL; + } + if (NULL != privkey) + { + GNUNET_free (privkey); + privkey = NULL; + } + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (NULL != nsqe) + { + GNUNET_NAMESTORE_cancel (nsqe); + nsqe = NULL; + } + cleanup (); + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + cleanup (); + res = 0; +} + +void lookup_it (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + nsqe = NULL; + int c; + int found_record = GNUNET_NO; + int found_nick = GNUNET_NO; + + if (0 != memcmp(privkey, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + + if (NULL == label) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + + if (0 != strcmp (label, name)) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + + if (2 != rd_count) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + + for (c = 0; c < rd_count; c++) + { + if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) + { + if (rd[c].data_size != strlen(TEST_NICK)+1) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + if (rd[c].flags != GNUNET_GNSRECORD_RF_PRIVATE) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + if (0 != strcmp(rd[c].data, TEST_NICK)) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + found_nick = GNUNET_YES; + } + else + { + if (rd[c].record_type != TEST_RECORD_TYPE) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + if (rd[c].data_size != TEST_RECORD_DATALEN) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + if (0 != memcmp (rd[c].data, rd_orig.data, TEST_RECORD_DATALEN)) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + if (rd[c].flags != rd->flags) + { + GNUNET_break(0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + return; + } + found_record = GNUNET_YES; + } + + } + + /* Done */ + if ((GNUNET_YES == found_nick) && (GNUNET_YES == found_record)) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SCHEDULER_add_now (&end, NULL ); + } + else + { + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SCHEDULER_add_now (&endbadly, NULL ); + } +} + + +static void +put_cont (void *cls, int32_t success, const char *emsg) +{ + const char *name = cls; + + nsqe = NULL; + GNUNET_assert (NULL != cls); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Name store added record for `%s': %s\n", + name, + (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + + if (GNUNET_OK != success) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + return; + } + /* Lookup */ + nsqe = GNUNET_NAMESTORE_records_lookup (nsh, privkey, name, lookup_it, NULL); +} + +static void +nick_cont (void *cls, int32_t success, const char *emsg) +{ + const char *name = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Nick added : %s\n", + (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + + rd_orig.expiration_time = GNUNET_TIME_absolute_get().abs_value_us; + rd_orig.record_type = TEST_RECORD_TYPE; + rd_orig.data_size = TEST_RECORD_DATALEN; + rd_orig.data = GNUNET_malloc (TEST_RECORD_DATALEN); + rd_orig.flags = 0; + memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN); + + nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, + 1, &rd_orig, &put_cont, (void *) name); +} + + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + char *hostkey_file; + + endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, + &endbadly, NULL); + GNUNET_asprintf (&hostkey_file, + "zonefiles%s%s", + DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); + + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey, TEST_NICK, &nick_cont, (void *) name); + if (NULL == nsqe) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Namestore cannot store no block\n")); + } +} + + +int +main (int argc, char *argv[]) +{ + res = 1; + if (0 != + GNUNET_TESTING_peer_run ("test-namestore-api", + "test_namestore_api.conf", + &run, + NULL)) + return 1; + return res; +} + + +/* end of test_namestore_api_store.c */ diff --git a/src/namestore/test_namestore_api_zone_iteration_nick.c b/src/namestore/test_namestore_api_zone_iteration_nick.c @@ -0,0 +1,466 @@ +/* + This file is part of GNUnet. + (C) 2013 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. +*/ +/** + * @file namestore/test_namestore_api_zone_iteration.c + * @brief testcase for zone iteration functionality: iterate all zones + */ +#include "platform.h" +#include "gnunet_namestore_service.h" +#include "gnunet_testing_lib.h" +#include "namestore.h" + +#define ZONE_NICK_1 "nick1" +#define ZONE_NICK_2 "nick2" + +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) + + +static struct GNUNET_NAMESTORE_Handle * nsh; + +static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; + +static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; + +static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; + +static struct GNUNET_NAMESTORE_ZoneIterator *zi; + +static int res; + +static int returned_records; + +static char * s_name_1; + +static struct GNUNET_GNSRECORD_Data *s_rd_1; + +static char * s_name_2; + +static struct GNUNET_GNSRECORD_Data *s_rd_2; + +static char * s_name_3; + +static struct GNUNET_GNSRECORD_Data *s_rd_3; + +static struct GNUNET_NAMESTORE_QueueEntry *nsqe; + +/** + * Re-establish the connection to the service. + * + * @param cls handle to use to re-connect. + * @param tc scheduler context + */ +static void +endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (NULL != zi) + { + GNUNET_NAMESTORE_zone_iteration_stop (zi); + zi = NULL; + } + if (nsh != NULL) + { + GNUNET_NAMESTORE_disconnect (nsh); + nsh = NULL; + } + GNUNET_free_non_null(s_name_1); + GNUNET_free_non_null(s_name_2); + GNUNET_free_non_null(s_name_3); + + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + + if (privkey != NULL) + GNUNET_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_free (privkey2); + privkey2 = NULL; + res = 1; +} + + +static void +end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if (NULL != zi) + { + GNUNET_NAMESTORE_zone_iteration_stop (zi); + zi = NULL; + } + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_NO_TASK; + } + + if (privkey != NULL) + GNUNET_free (privkey); + privkey = NULL; + + if (privkey2 != NULL) + GNUNET_free (privkey2); + privkey2 = NULL; + + GNUNET_free (s_name_1); + GNUNET_free (s_name_2); + GNUNET_free (s_name_3); + if (s_rd_1 != NULL) + { + GNUNET_free ((void *)s_rd_1->data); + GNUNET_free (s_rd_1); + } + if (s_rd_2 != NULL) + { + GNUNET_free ((void *)s_rd_2->data); + GNUNET_free (s_rd_2); + } + if (s_rd_3 != NULL) + { + GNUNET_free ((void *)s_rd_3->data); + GNUNET_free (s_rd_3); + } + if (nsh != NULL) + GNUNET_NAMESTORE_disconnect (nsh); + nsh = NULL; +} + +static int +check_zone_1 (const char *label, unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + int failed = GNUNET_NO; + int c; + for (c = 0; c< rd_count ; c++) + { + if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) + if (0 != strcmp (rd[c].data, ZONE_NICK_1)) + { + GNUNET_break (0); + return GNUNET_YES; + } + } + return failed; +} + +static int +check_zone_2 (const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + int failed = GNUNET_NO; + int c; + + for (c = 0; c< rd_count ; c++) + { + if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) + if (0 != strcmp (rd[c].data, ZONE_NICK_2)) + { + GNUNET_break (0); + return GNUNET_YES; + } + } + + return failed; +} + + +static void +zone_proc (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + int failed = GNUNET_NO; + if ((zone == NULL) && (label == NULL)) + { + zi = NULL; + res = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received last result, iteration done after receing %u results\n", + returned_records); + GNUNET_SCHEDULER_add_now (&end, NULL); + return; + } + + if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) + { + failed = check_zone_1 (label, rd_count, rd); + if (GNUNET_YES == failed) + GNUNET_break (0); + } + else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) + { + failed = check_zone_2 (label, rd_count, rd); + if (GNUNET_YES == failed) + GNUNET_break (0); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Received invalid zone\n"); + failed = GNUNET_YES; + GNUNET_break (0); + } + + if (failed == GNUNET_NO) + { + returned_records ++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Telling namestore to send the next result\n"); + GNUNET_NAMESTORE_zone_iterator_next (zi); + } + else + { + GNUNET_break (0); + res = 1; + GNUNET_SCHEDULER_add_now (&end, NULL); + } +} + + +static void +put_cont (void *cls, int32_t success, const char *emsg) +{ + static int c = 0; + + if (success == GNUNET_OK) + { + c++; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", + emsg); + GNUNET_break (0); + if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + return; + } + + if (c == 3) + { + res = 1; + returned_records = 0; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); + zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, + NULL, + &zone_proc, + NULL); + if (zi == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); + GNUNET_break (0); + if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + return; + } + } +} + + +static struct GNUNET_GNSRECORD_Data * +create_record (unsigned int count) +{ + unsigned int c; + struct GNUNET_GNSRECORD_Data * rd; + + rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); + for (c = 0; c < count; c++) + { + rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; + rd[c].record_type = 1111; + rd[c].data_size = 50; + rd[c].data = GNUNET_malloc(50); + rd[c].flags = 0; + memset ((char *) rd[c].data, 'a', 50); + } + return rd; +} + +static void +nick_2_cont (void *cls, int32_t success, const char *emsg) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Nick added : %s\n", + (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); + + GNUNET_asprintf(&s_name_1, "dummy1"); + s_rd_1 = create_record(1); + GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_1, + 1, s_rd_1, + &put_cont, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Created record 2 \n"); + GNUNET_asprintf(&s_name_2, "dummy2"); + s_rd_2 = create_record(1); + GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_2, + 1, s_rd_2, &put_cont, NULL); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Created record 3\n"); + + /* name in different zone */ + GNUNET_asprintf(&s_name_3, "dummy3"); + s_rd_3 = create_record(1); + GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, + 1, s_rd_3, + &put_cont, NULL); +} + + +static void +nick_1_cont (void *cls, int32_t success, const char *emsg) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Nick 1 added : %s\n", + (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); + + nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey2, ZONE_NICK_2, &nick_2_cont, &privkey2); + if (NULL == nsqe) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Namestore cannot store no block\n")); + } + + + +} + + + +/** + * Callback called from the zone iterator when we iterate over + * the empty zone. Check that we got no records and then + * start the actual tests by filling the zone. + */ +static void +empty_zone_proc (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + char *hostkey_file; + GNUNET_assert (nsh == cls); + if (NULL != zone) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Expected empty zone but received zone private key\n")); + GNUNET_break (0); + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + return; + } + if ((NULL != label) || (NULL != rd) || (0 != rd_count)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Expected no zone content but received data\n")); + GNUNET_break (0); + if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + return; + } + + zi = NULL; + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey != NULL); + + GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, + "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); + privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); + GNUNET_free (hostkey_file); + GNUNET_assert (privkey2 != NULL); + + nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey, ZONE_NICK_1, &nick_1_cont, &privkey); + if (NULL == nsqe) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Namestore cannot store no block\n")); + } + +} + + +static void +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_TESTING_Peer *peer) +{ + endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); + nsh = GNUNET_NAMESTORE_connect (cfg); + GNUNET_break (NULL != nsh); + + /* first, iterate over empty namestore */ + zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, + NULL, &empty_zone_proc, nsh); + if (NULL == zi) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); + GNUNET_break (0); + GNUNET_SCHEDULER_cancel (endbadly_task); + endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); + } +} + + +int +main (int argc, char *argv[]) +{ + res = 1; + GNUNET_DISK_directory_remove ("/tmp/test-gnunet-namestore"); + if (0 != + GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", + "test_namestore_api.conf", + &run, + NULL)) + return 1; + return res; +} + + +/* end of test_namestore_api_zone_iteration.c */