X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fnamestore%2Fgnunet-namestore-fcfsd.c;h=6e45f822779e2853b47fd2ef3725e5809325700e;hb=c15e7951180d954ca584a95206543e8997b3a7d4;hp=08f03a0559ecea72c2502423d562e2c592f64bac;hpb=9351b1e9bdf2b067b6db06562c26ba658cff42b8;p=oweals%2Fgnunet.git diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c index 08f03a055..6e45f8227 100644 --- a/src/namestore/gnunet-namestore-fcfsd.c +++ b/src/namestore/gnunet-namestore-fcfsd.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2012-2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2012-2014 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ 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. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** * @file gnunet-namestore-fcfsd.c @@ -34,6 +34,7 @@ #include #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" +#include "gnunet_gnsrecord_lib.h" #include "gnunet_namestore_service.h" /** @@ -111,7 +112,7 @@ struct Request /** * Associated session. */ - struct Session *session; + // FIXME: struct Session *session; /** * Post processor handling form data (IF this is @@ -130,6 +131,11 @@ struct Request */ struct GNUNET_NAMESTORE_QueueEntry *qe; + /** + * Active iteration with the namestore. + */ + struct GNUNET_NAMESTORE_ZoneIterator *zi; + /** * Current processing phase. */ @@ -145,6 +151,8 @@ struct Request */ char public_key[128]; + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + }; /** @@ -186,7 +194,7 @@ static struct MHD_Daemon *httpd; /** * Main HTTP task. */ -static GNUNET_SCHEDULER_TaskIdentifier httpd_task; +static struct GNUNET_SCHEDULER_Task * httpd_task; /** * Handle to the namestore. @@ -212,17 +220,15 @@ static struct GNUNET_IDENTITY_Operation *id_op; * Port we use for the HTTP server. */ static unsigned long long port; - + /** * Task run whenever HTTP server operations are pending. * * @param cls unused - * @param tc scheduler context */ static void -do_httpd (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +do_httpd (void *cls); /** @@ -231,76 +237,122 @@ do_httpd (void *cls, static void run_httpd_now () { - if (GNUNET_SCHEDULER_NO_TASK != httpd_task) + if (NULL != httpd_task) { GNUNET_SCHEDULER_cancel (httpd_task); - httpd_task = GNUNET_SCHEDULER_NO_TASK; + httpd_task = NULL; } httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); } +/** + * Function called on error in zone iteration. + */ static void -iterate_cb (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *name, - unsigned int rd_len, - const struct GNUNET_NAMESTORE_RecordData *rd) +zone_iteration_error (void *cls) +{ + struct ZoneinfoRequest *zr = cls; + struct MHD_Response *response; + + zr->list_it = NULL; + response = MHD_create_response_from_buffer (strlen ("internal error"), + (void *) "internal error", + MHD_RESPMEM_PERSISTENT); + MHD_queue_response (zr->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + response); + MHD_destroy_response (response); + GNUNET_free (zr->zoneinfo); + GNUNET_free (zr); + run_httpd_now (); +} + + +/** + * Function called once the zone iteration is done. + */ +static void +zone_iteration_end (void *cls) { struct ZoneinfoRequest *zr = cls; struct MHD_Response *response; char* full_page; - size_t bytes_free; - char* pkey; - char* new_buf; + zr->list_it = NULL; - if (NULL == name) - { - zr->list_it = NULL; - - /* return static form */ - GNUNET_asprintf (&full_page, - ZONEINFO_PAGE, - zr->zoneinfo, - zr->zoneinfo); - response = MHD_create_response_from_buffer (strlen (full_page), + /* return static form */ + GNUNET_asprintf (&full_page, + ZONEINFO_PAGE, + zr->zoneinfo, + zr->zoneinfo); + response = MHD_create_response_from_buffer (strlen (full_page), (void *) full_page, MHD_RESPMEM_MUST_FREE); - MHD_add_response_header (response, + MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, MIME_HTML); - MHD_queue_response (zr->connection, - MHD_HTTP_OK, - response); - MHD_destroy_response (response); - GNUNET_free (zr->zoneinfo); - GNUNET_free (zr); - run_httpd_now (); - return; - } + MHD_queue_response (zr->connection, + MHD_HTTP_OK, + response); + MHD_destroy_response (response); + GNUNET_free (zr->zoneinfo); + GNUNET_free (zr); + run_httpd_now (); +} + + +/** + * Process a record that was stored in the namestore, adding + * the information to the HTML. + * + * @param cls closure with the `struct ZoneinfoRequest *` + * @param zone_key private key of the zone; NULL on disconnect + * @param name label of the records; NULL on disconnect + * @param rd_len number of entries in @a rd array, 0 if label was deleted + * @param rd array of records with data to store + */ +static void +iterate_cb (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *name, + unsigned int rd_len, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct ZoneinfoRequest *zr = cls; + size_t bytes_free; + char* pkey; + char* new_buf; if (1 != rd_len) { - GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it, + 1); return; } - if (GNUNET_NAMESTORE_TYPE_PKEY != rd->record_type) + if (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type) { - GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it, + 1); return; } bytes_free = zr->buf_len - zr->write_offset; - pkey = GNUNET_NAMESTORE_value_to_string (rd->record_type, + pkey = GNUNET_GNSRECORD_value_to_string (rd->record_type, rd->data, rd->data_size); - + if (NULL == pkey) + { + GNUNET_break (0); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it, + 1); + return; + } if (bytes_free < (strlen (name) + strlen (pkey) + 40)) { new_buf = GNUNET_malloc (zr->buf_len * 2); - memcpy (new_buf, zr->zoneinfo, zr->write_offset); + GNUNET_memcpy (new_buf, zr->zoneinfo, zr->write_offset); GNUNET_free (zr->zoneinfo); zr->zoneinfo = new_buf; zr->buf_len *= 2; @@ -310,12 +362,12 @@ iterate_cb (void *cls, name, pkey); zr->write_offset = strlen (zr->zoneinfo); - GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it, + 1); GNUNET_free (pkey); } - /** * Handler that returns FCFS zoneinfo page. * @@ -334,8 +386,12 @@ serve_zoneinfo_page (struct MHD_Connection *connection) zr->write_offset = 0; zr->list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, &fcfs_zone_pkey, + &zone_iteration_error, + zr, &iterate_cb, - zr); + zr, + &zone_iteration_end, + zr); return MHD_YES; } @@ -428,15 +484,21 @@ post_iterator (void *cls, const char *filename, const char *content_type, const char *transfer_encoding, - const char *data, uint64_t off, size_t size) + const char *data, + uint64_t off, + size_t size) { struct Request *request = cls; + (void) kind; + (void) filename; + (void) content_type; + (void) transfer_encoding; if (0 == strcmp ("domain", key)) { if (size + off >= sizeof(request->domain_name)) size = sizeof (request->domain_name) - off - 1; - memcpy (&request->domain_name[off], + GNUNET_memcpy (&request->domain_name[off], data, size); request->domain_name[size+off] = '\0'; @@ -446,7 +508,7 @@ post_iterator (void *cls, { if (size + off >= sizeof(request->public_key)) size = sizeof (request->public_key) - off - 1; - memcpy (&request->public_key[off], + GNUNET_memcpy (&request->public_key[off], data, size); request->public_key[size+off] = '\0'; @@ -459,16 +521,14 @@ post_iterator (void *cls, } - - /** * Continuation called to notify client about result of the * operation. * * @param cls closure - * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) - * GNUNET_NO if content was already there - * GNUNET_YES (or other positive value) on success + * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) + * #GNUNET_NO if content was already there + * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void @@ -493,13 +553,28 @@ put_continuation (void *cls, } +/** + * Function called if we had an error in zone-to-name mapping. + */ +static void +zone_to_name_error (void *cls) +{ + struct Request *request = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Error when mapping zone to name\n")); + request->phase = RP_FAIL; + run_httpd_now (); +} + + /** * Test if a name mapping was found, if so, refuse. If not, initiate storing of the record. * * @param cls closure * @param zone_key public key of the zone * @param name name that is being mapped (at most 255 characters long) - * @param rd_count number of entries in 'rd' array + * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ static void @@ -507,14 +582,13 @@ zone_to_name_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) + const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; - struct GNUNET_NAMESTORE_RecordData r; - struct GNUNET_CRYPTO_EcdsaPublicKey pub; + struct GNUNET_GNSRECORD_Data r; request->qe = NULL; - if (NULL != name) + if (0 != rd_count) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found existing name `%s' for the given key\n"), @@ -523,13 +597,11 @@ zone_to_name_cb (void *cls, run_httpd_now (); return; } - GNUNET_CRYPTO_ecdsa_key_get_public (zone_key, - &pub); - r.data = &pub; - r.data_size = sizeof (pub); + r.data = &request->pub; + r.data_size = sizeof (request->pub); r.expiration_time = UINT64_MAX; - r.record_type = GNUNET_NAMESTORE_TYPE_PKEY; - r.flags = GNUNET_NAMESTORE_RF_NONE; + r.record_type = GNUNET_GNSRECORD_TYPE_PKEY; + r.flags = GNUNET_GNSRECORD_RF_NONE; request->qe = GNUNET_NAMESTORE_records_store (ns, &fcfs_zone_pkey, request->domain_name, @@ -540,47 +612,16 @@ zone_to_name_cb (void *cls, /** - * Process a record that was stored in the namestore. Used to check if - * the requested name already exists in the namestore. If not, - * proceed to check if the requested key already exists. - * - * @param cls closure - * @param rd_count number of entries in 'rd' array - * @param rd array of records with data to store + * We encountered an error in the name lookup. */ static void -lookup_result_processor (void *cls, - unsigned int rd_count, - const struct GNUNET_NAMESTORE_RecordData *rd) +lookup_block_error (void *cls) { struct Request *request = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey pub; - if (0 != rd_count) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Found %u existing records for domain `%s'\n"), - rd_count, - request->domain_name); - request->phase = RP_FAIL; - run_httpd_now (); - return; - } - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, - strlen (request->public_key), - &pub)) - { - GNUNET_break (0); - request->phase = RP_FAIL; - run_httpd_now (); - return; - } - request->qe = GNUNET_NAMESTORE_zone_to_name (ns, - &fcfs_zone_pkey, - &pub, - &zone_to_name_cb, - request); + request->qe = NULL; + request->phase = RP_FAIL; + run_httpd_now (); } @@ -589,35 +630,50 @@ lookup_result_processor (void *cls, * and continue to process the result. * * @param cls the 'struct Request' we are processing - * @param block block returned form namestore, NULL on error + * @param zone private key of the zone; NULL on disconnect + * @param label label of the records; NULL on disconnect + * @param rd_count number of entries in @a rd array, 0 if label was deleted + * @param rd array of records with data to store */ static void lookup_block_processor (void *cls, - const struct GNUNET_NAMESTORE_Block *block) + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey pub; request->qe = NULL; - if (NULL == block) + if (0 == rd_count) { - lookup_result_processor (request, 0, NULL); - return; - } - GNUNET_CRYPTO_ecdsa_key_get_public (&fcfs_zone_pkey, - &pub); - if (GNUNET_OK != - GNUNET_NAMESTORE_block_decrypt (block, - &pub, - request->domain_name, - &lookup_result_processor, - request)) - { - GNUNET_break (0); - request->phase = RP_FAIL; - run_httpd_now (); + if (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, + strlen (request->public_key), + &request->pub)) + { + GNUNET_break (0); + request->phase = RP_FAIL; + run_httpd_now (); + return; + } + request->qe = GNUNET_NAMESTORE_zone_to_name (ns, + &fcfs_zone_pkey, + &request->pub, + &zone_to_name_error, + request, + &zone_to_name_cb, + request); return; } + GNUNET_break (0 != rd_count); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Found %u existing records for domain `%s'\n"), + rd_count, + request->domain_name); + request->phase = RP_FAIL; + run_httpd_now (); + return; } @@ -637,7 +693,7 @@ lookup_block_processor (void *cls, * data *will* be made available incrementally in * upload_data) * @param upload_data_size set initially to the size of the - * upload_data provided; the method must update this + * @a upload_data provided; the method must update this * value to the number of bytes NOT processed; * @param ptr pointer to location where we store the 'struct Request' * @return MHD_YES if the connection was handled successfully, @@ -656,9 +712,8 @@ create_response (void *cls, { struct MHD_Response *response; struct Request *request; - int ret; struct GNUNET_CRYPTO_EcdsaPublicKey pub; - struct GNUNET_HashCode query; + int ret; if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) @@ -674,14 +729,16 @@ create_response (void *cls, return ret; } if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) - { + { request = *ptr; if (NULL == request) { - request = GNUNET_malloc (sizeof (struct Request)); + request = GNUNET_new (struct Request); *ptr = request; - request->pp = MHD_create_post_processor (connection, 1024, - &post_iterator, request); + request->pp = MHD_create_post_processor (connection, + 1024, + &post_iterator, + request); if (NULL == request->pp) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -708,8 +765,8 @@ create_response (void *cls, } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, - strlen (request->public_key), - &pub)) + strlen (request->public_key), + &pub)) { /* parse error */ return fill_s_reply ("Failed to parse given public key", @@ -724,7 +781,8 @@ create_response (void *cls, _("Domain name must not contain `.'\n")); request->phase = RP_FAIL; return fill_s_reply ("Domain name must not contain `.', sorry.", - request, connection); + request, + connection); } if (NULL != strchr (request->domain_name, (int) '+')) { @@ -735,15 +793,14 @@ create_response (void *cls, request, connection); } request->phase = RP_LOOKUP; - GNUNET_CRYPTO_ecdsa_key_get_public (&fcfs_zone_pkey, - &pub); - GNUNET_NAMESTORE_query_from_public_key (&pub, - request->domain_name, - &query); - request->qe = GNUNET_NAMESTORE_lookup_block (ns, - &query, - &lookup_block_processor, - request); + request->qe + = GNUNET_NAMESTORE_records_lookup (ns, + &fcfs_zone_pkey, + request->domain_name, + &lookup_block_error, + request, + &lookup_block_processor, + request); break; case RP_LOOKUP: break; @@ -766,7 +823,7 @@ create_response (void *cls, (void *) METHOD_ERROR, MHD_RESPMEM_PERSISTENT); ret = MHD_queue_response (connection, - MHD_HTTP_METHOD_NOT_ACCEPTABLE, + MHD_HTTP_NOT_ACCEPTABLE, response); MHD_destroy_response (response); return ret; @@ -790,6 +847,9 @@ request_completed_callback (void *cls, { struct Request *request = *con_cls; + (void) cls; + (void) connection; + (void) toe; if (NULL == request) return; if (NULL != request->pp) @@ -827,19 +887,34 @@ run_httpd () wes = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; - GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); - haveto = MHD_get_timeout (httpd, &timeout); + GNUNET_assert (MHD_YES == + MHD_get_fdset (httpd, + &rs, + &ws, + &es, + &max)); + haveto = MHD_get_timeout (httpd, + &timeout); if (haveto == MHD_YES) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; - GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); - GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); - GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); + GNUNET_NETWORK_fdset_copy_native (wrs, + &rs, + max + 1); + GNUNET_NETWORK_fdset_copy_native (wws, + &ws, + max + 1); + GNUNET_NETWORK_fdset_copy_native (wes, + &es, + max + 1); httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, - tv, wrs, wws, - &do_httpd, NULL); + tv, + wrs, + wws, + &do_httpd, + NULL); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); GNUNET_NETWORK_fdset_destroy (wes); @@ -850,13 +925,12 @@ run_httpd () * Task run whenever HTTP server operations are pending. * * @param cls unused - * @param tc scheduler context */ static void -do_httpd (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +do_httpd (void *cls) { - httpd_task = GNUNET_SCHEDULER_NO_TASK; + (void) cls; + httpd_task = NULL; MHD_run (httpd); run_httpd (); } @@ -866,16 +940,15 @@ do_httpd (void *cls, * Task run on shutdown. Cleans up everything. * * @param cls unused - * @param tc scheduler context */ static void -do_shutdown (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +do_shutdown (void *cls) { - if (GNUNET_SCHEDULER_NO_TASK != httpd_task) + (void) cls; + if (NULL != httpd_task) { GNUNET_SCHEDULER_cancel (httpd_task); - httpd_task = GNUNET_SCHEDULER_NO_TASK; + httpd_task = NULL; } if (NULL != ns) { @@ -927,6 +1000,9 @@ identity_cb (void *cls, { int options; + (void) cls; + (void) ctx; + (void) name; id_op = NULL; if (NULL == ego) { @@ -974,9 +1050,14 @@ identity_cb (void *cls, * @param cfg configuration */ static void -run (void *cls, char *const *args, const char *cfgfile, +run (void *cls, + char *const *args, + const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { + (void) cls; + (void) args; + (void) cfgfile; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "fcfsd", @@ -996,10 +1077,15 @@ run (void *cls, char *const *args, const char *cfgfile, } identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); + if (NULL == identity) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to identity\n")); + return; + } id_op = GNUNET_IDENTITY_get (identity, "fcfsd", &identity_cb, NULL); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &do_shutdown, NULL); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); } @@ -1011,21 +1097,27 @@ run (void *cls, char *const *args, const char *cfgfile, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - int ret; - if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + if (GNUNET_OK != + GNUNET_STRINGS_get_utf8_args (argc, argv, + &argc, &argv)) return 2; - GNUNET_log_setup ("fcfsd", "WARNING", NULL); + GNUNET_log_setup ("fcfsd", + "WARNING", + NULL); ret = (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "fcfsd", + GNUNET_PROGRAM_run (argc, + argv, + "gnunet-namestore-fcfsd", _("GNU Name System First Come First Serve name registration service"), options, &run, NULL)) ? 0 : 1;