X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fnamestore%2Fgnunet-namestore-fcfsd.c;h=6e45f822779e2853b47fd2ef3725e5809325700e;hb=c15e7951180d954ca584a95206543e8997b3a7d4;hp=4feb7fc051f5ec86eb41dacd50d4f08fcbbf4e2b;hpb=dbc823a07a03e1085172038125b0edf15b0dc6fe;p=oweals%2Fgnunet.git diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c index 4feb7fc05..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 @@ -112,7 +112,7 @@ struct Request /** * Associated session. */ - struct Session *session; + // FIXME: struct Session *session; /** * Post processor handling form data (IF this is @@ -151,6 +151,8 @@ struct Request */ char public_key[128]; + struct GNUNET_CRYPTO_EcdsaPublicKey pub; + }; /** @@ -192,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. @@ -224,11 +226,9 @@ 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); /** @@ -237,64 +237,104 @@ 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_GNSRECORD_Data *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_GNSRECORD_TYPE_PKEY != rd->record_type) { - GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); + GNUNET_NAMESTORE_zone_iterator_next (zr->list_it, + 1); return; } @@ -302,11 +342,17 @@ iterate_cb (void *cls, 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; @@ -316,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. * @@ -340,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; } @@ -434,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'; @@ -452,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'; @@ -497,6 +553,21 @@ 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. * @@ -515,10 +586,9 @@ zone_to_name_cb (void *cls, { struct Request *request = cls; struct GNUNET_GNSRECORD_Data r; - struct GNUNET_CRYPTO_EcdsaPublicKey pub; 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"), @@ -527,10 +597,8 @@ 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_GNSRECORD_TYPE_PKEY; r.flags = GNUNET_GNSRECORD_RF_NONE; @@ -543,6 +611,20 @@ zone_to_name_cb (void *cls, } +/** + * We encountered an error in the name lookup. + */ +static void +lookup_block_error (void *cls) +{ + struct Request *request = cls; + + request->qe = NULL; + request->phase = RP_FAIL; + run_httpd_now (); +} + + /** * We got a block back from the namestore. Decrypt it * and continue to process the result. @@ -561,16 +643,14 @@ lookup_block_processor (void *cls, const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; - struct GNUNET_CRYPTO_EcdsaPublicKey pub; request->qe = NULL; - if (NULL == label) + if (0 == rd_count) { - request->zi = NULL; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, strlen (request->public_key), - &pub)) + &request->pub)) { GNUNET_break (0); request->phase = RP_FAIL; @@ -579,19 +659,13 @@ lookup_block_processor (void *cls, } request->qe = GNUNET_NAMESTORE_zone_to_name (ns, &fcfs_zone_pkey, - &pub, + &request->pub, + &zone_to_name_error, + request, &zone_to_name_cb, request); return; } - if (0 != strcmp (label, - request->domain_name)) - { - GNUNET_NAMESTORE_zone_iterator_next (request->zi); - return; - } - GNUNET_NAMESTORE_zone_iteration_stop (request->zi); - request->zi = NULL; GNUNET_break (0 != rd_count); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found %u existing records for domain `%s'\n"), @@ -659,10 +733,12 @@ create_response (void *cls, 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, @@ -705,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) '+')) { @@ -716,11 +793,14 @@ create_response (void *cls, request, connection); } request->phase = RP_LOOKUP; - /* FIXME: would be nice to have a more efficient API for this */ - request->zi = GNUNET_NAMESTORE_zone_iteration_start (ns, - &fcfs_zone_pkey, - &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; @@ -743,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; @@ -767,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) @@ -804,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); @@ -827,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 (); } @@ -843,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) { @@ -904,6 +1000,9 @@ identity_cb (void *cls, { int options; + (void) cls; + (void) ctx; + (void) name; id_op = NULL; if (NULL == ego) { @@ -951,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", @@ -973,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); } @@ -988,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;