2 This file is part of GNUnet.
3 Copyright (C) 2012-2014 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file gnunet-namestore-fcfsd.c
22 * @brief HTTP daemon that offers first-come-first-serve GNS domain registration
23 * @author Christian Grothoff
26 * - need to track active zone info requests so we can cancel them
27 * during shutdown, right?
28 * - the code currently contains a 'race' between checking that the
29 * domain name is available and allocating it to the new public key
30 * (should this race be solved by namestore or by fcfsd?)
31 * - nicer error reporting to browser
34 #include <microhttpd.h>
35 #include "gnunet_util_lib.h"
36 #include "gnunet_identity_service.h"
37 #include "gnunet_gnsrecord_lib.h"
38 #include "gnunet_namestore_service.h"
41 * Invalid method page.
43 #define METHOD_ERROR \
44 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>Illegal request</title></head><body>Go away.</body></html>"
50 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>GNUnet FCFS Authority Name Registration Service</title></head><body><form action=\"S\" method=\"post\">What is your desired domain name? (at most 63 lowercase characters, no dots allowed.) <input type=\"text\" name=\"domain\" /> <p> What is your public key? (Copy from gnunet-setup.) <input type=\"text\" name=\"pkey\" /> <input type=\"submit\" value=\"Next\" /><br/><a href=./Zoneinfo> List of all registered names </a></body></html>"
56 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>%s</title></head><body>%s</body></html>"
59 * Fcfs zoneinfo page (/Zoneinfo)
61 #define ZONEINFO_PAGE \
62 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\"><html><head><title>FCFS Zoneinfo</title></head><body><h1> FCFS Zoneinfo </h1><table border=\"1\"><th>name</th><th>PKEY</th>%s</table></body></html>"
64 #define FCFS_ZONEINFO_URL "/Zoneinfo"
67 * Mime type for HTML pages.
69 #define MIME_HTML "text/html"
74 #define COOKIE_NAME "namestore-fcfsd"
76 #define DEFAULT_ZONEINFO_BUFSIZE 2048
79 * Phases a request goes through.
84 * Start phase (parsing POST, checking).
89 * Lookup to see if the domain name is taken.
94 * Storing of the record.
99 * We're done with success.
104 * Send failure message.
111 * Data kept per request.
116 * Associated session.
118 // FIXME: struct Session *session;
121 * Post processor handling form data (IF this is
124 struct MHD_PostProcessor *pp;
129 struct MHD_Connection *con;
131 * URL to serve in response to this POST (if this request
134 const char *post_url;
137 * Active request with the namestore.
139 struct GNUNET_NAMESTORE_QueueEntry *qe;
142 * Active lookup iterator
143 * TODO: deprecate or fix lookup by label and use above member
145 struct GNUNET_NAMESTORE_ZoneIterator *lookup_it;
147 * Active iteration with the namestore.
149 struct GNUNET_NAMESTORE_ZoneIterator *zi;
152 * Current processing phase.
157 * Domain name submitted via form.
159 char domain_name[64];
162 * Public key submitted via form.
164 char public_key[128];
166 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
172 struct ZoneinfoRequest
177 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
190 * Buffer write offset
196 * MHD deamon reference.
198 static struct MHD_Daemon *httpd;
203 static struct GNUNET_SCHEDULER_Task *httpd_task;
206 * Handle to the namestore.
208 static struct GNUNET_NAMESTORE_Handle *ns;
211 * Private key for the fcfsd zone.
213 static struct GNUNET_CRYPTO_EcdsaPrivateKey fcfs_zone_pkey;
216 * Connection to identity service.
218 static struct GNUNET_IDENTITY_Handle *identity;
221 * Zoneinfo page we currently use.
223 static struct MHD_Response *info_page;
226 * Task that runs #update_zoneinfo_page peridicially.
228 static struct GNUNET_SCHEDULER_Task *uzp_task;
231 * Request for our ego.
233 static struct GNUNET_IDENTITY_Operation *id_op;
236 * Port we use for the HTTP server.
238 static unsigned long long port;
241 * Name of the zone we manage.
247 * Task run whenever HTTP server operations are pending.
252 do_httpd (void *cls);
256 * Schedule task to run MHD server now.
261 if (NULL != httpd_task)
263 GNUNET_SCHEDULER_cancel (httpd_task);
266 httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
271 * Create fresh version of zone information.
274 update_zoneinfo_page (void *cls);
278 * Function called on error in zone iteration.
281 zone_iteration_error (void *cls)
283 struct ZoneinfoRequest *zr = cls;
286 GNUNET_free (zr->zoneinfo);
287 GNUNET_SCHEDULER_cancel (uzp_task);
288 uzp_task = GNUNET_SCHEDULER_add_now (&update_zoneinfo_page,
294 * Function called once the zone iteration is done.
297 zone_iteration_end (void *cls)
299 struct ZoneinfoRequest *zr = cls;
300 struct MHD_Response *response;
305 /* return static form */
306 GNUNET_asprintf (&full_page,
310 response = MHD_create_response_from_buffer (strlen (full_page),
312 MHD_RESPMEM_MUST_FREE);
313 MHD_add_response_header (response,
314 MHD_HTTP_HEADER_CONTENT_TYPE,
316 MHD_destroy_response (info_page);
317 info_page = response;
318 GNUNET_free (zr->zoneinfo);
323 * Process a record that was stored in the namestore, adding
324 * the information to the HTML.
326 * @param cls closure with the `struct ZoneinfoRequest *`
327 * @param zone_key private key of the zone; NULL on disconnect
328 * @param name label of the records; NULL on disconnect
329 * @param rd_len number of entries in @a rd array, 0 if label was deleted
330 * @param rd array of records with data to store
333 iterate_cb (void *cls,
334 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
337 const struct GNUNET_GNSRECORD_Data *rd)
339 struct ZoneinfoRequest *zr = cls;
347 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it,
352 if (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type)
354 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it,
359 bytes_free = zr->buf_len - zr->write_offset;
360 pkey = GNUNET_GNSRECORD_value_to_string (rd->record_type,
366 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it,
370 if (bytes_free < (strlen (name) + strlen (pkey) + 40))
372 new_buf = GNUNET_malloc (zr->buf_len * 2);
373 GNUNET_memcpy (new_buf, zr->zoneinfo, zr->write_offset);
374 GNUNET_free (zr->zoneinfo);
375 zr->zoneinfo = new_buf;
378 sprintf (zr->zoneinfo + zr->write_offset,
379 "<tr><td>%s</td><td>%s</td></tr>",
382 zr->write_offset = strlen (zr->zoneinfo);
383 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it,
390 * Handler that returns FCFS zoneinfo page.
392 * @param connection connection to use
395 serve_zoneinfo_page (struct MHD_Connection *connection)
397 return MHD_queue_response (connection,
404 * Create fresh version of zone information.
407 update_zoneinfo_page (void *cls)
409 static struct ZoneinfoRequest zr;
412 uzp_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
413 &update_zoneinfo_page,
415 if (NULL != zr.list_it)
417 zr.zoneinfo = GNUNET_malloc (DEFAULT_ZONEINFO_BUFSIZE);
418 zr.buf_len = DEFAULT_ZONEINFO_BUFSIZE;
420 zr.list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
422 &zone_iteration_error,
432 * Handler that returns a simple static HTTP page.
434 * @param connection connection to use
435 * @return #MHD_YES on success
438 serve_main_page (struct MHD_Connection *connection)
441 struct MHD_Response *response;
443 /* return static form */
444 response = MHD_create_response_from_buffer (strlen (MAIN_PAGE),
446 MHD_RESPMEM_PERSISTENT);
447 MHD_add_response_header (response,
448 MHD_HTTP_HEADER_CONTENT_TYPE,
450 ret = MHD_queue_response (connection,
453 MHD_destroy_response (response);
459 * Send the 'SUBMIT_PAGE'.
461 * @param info information string to send to the user
462 * @param request request information
463 * @param connection connection to use
466 fill_s_reply (const char *info,
467 struct Request *request,
468 struct MHD_Connection *connection)
472 struct MHD_Response *response;
475 GNUNET_asprintf (&reply,
479 /* return static form */
480 response = MHD_create_response_from_buffer (strlen (reply),
482 MHD_RESPMEM_MUST_FREE);
483 MHD_add_response_header (response,
484 MHD_HTTP_HEADER_CONTENT_TYPE,
486 ret = MHD_queue_response (connection,
489 MHD_destroy_response (response);
495 * Iterator over key-value pairs where the value
496 * maybe made available in increments and/or may
497 * not be zero-terminated. Used for processing
500 * @param cls user-specified closure
501 * @param kind type of the value
502 * @param key 0-terminated key for the value
503 * @param filename name of the uploaded file, NULL if not known
504 * @param content_type mime-type of the data, NULL if not known
505 * @param transfer_encoding encoding of the data, NULL if not known
506 * @param data pointer to size bytes of data at the
508 * @param off offset of data in the overall value
509 * @param size number of bytes in data available
510 * @return MHD_YES to continue iterating,
511 * MHD_NO to abort the iteration
514 post_iterator (void *cls,
515 enum MHD_ValueKind kind,
517 const char *filename,
518 const char *content_type,
519 const char *transfer_encoding,
524 struct Request *request = cls;
529 (void) transfer_encoding;
530 if (0 == strcmp ("domain", key))
532 if (size + off >= sizeof(request->domain_name))
533 size = sizeof(request->domain_name) - off - 1;
534 GNUNET_memcpy (&request->domain_name[off],
537 request->domain_name[size + off] = '\0';
540 if (0 == strcmp ("pkey", key))
542 if (size + off >= sizeof(request->public_key))
543 size = sizeof(request->public_key) - off - 1;
544 GNUNET_memcpy (&request->public_key[off],
547 request->public_key[size + off] = '\0';
550 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
551 _ ("Unsupported form value `%s'\n"),
558 * Continuation called to notify client about result of the
562 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
563 * #GNUNET_NO if content was already there
564 * #GNUNET_YES (or other positive value) on success
565 * @param emsg NULL on success, otherwise an error message
568 put_continuation (void *cls,
572 struct Request *request = cls;
577 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
578 _ ("Failed to create record for domain `%s': %s\n"),
579 request->domain_name,
581 request->phase = RP_FAIL;
584 request->phase = RP_SUCCESS;
585 MHD_resume_connection (request->con);
591 * Function called if we had an error in zone-to-name mapping.
594 zone_to_name_error (void *cls)
596 struct Request *request = cls;
598 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
599 _ ("Error when mapping zone to name\n"));
600 request->phase = RP_FAIL;
601 MHD_resume_connection (request->con);
607 * Test if a name mapping was found, if so, refuse. If not, initiate storing of the record.
610 * @param zone_key public key of the zone
611 * @param name name that is being mapped (at most 255 characters long)
612 * @param rd_count number of entries in @a rd array
613 * @param rd array of records with data to store
616 zone_to_name_cb (void *cls,
617 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
619 unsigned int rd_count,
620 const struct GNUNET_GNSRECORD_Data *rd)
622 struct Request *request = cls;
623 struct GNUNET_GNSRECORD_Data r;
630 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
631 _ ("Found existing name `%s' for the given key\n"),
633 request->phase = RP_FAIL;
634 MHD_resume_connection (request->con);
638 r.data = &request->pub;
639 r.data_size = sizeof(request->pub);
640 r.expiration_time = UINT64_MAX;
641 r.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
642 r.flags = GNUNET_GNSRECORD_RF_NONE;
643 request->qe = GNUNET_NAMESTORE_records_store (ns,
645 request->domain_name,
653 * We encountered an error in the name lookup.
656 lookup_it_error (void *cls)
658 struct Request *request = cls;
660 MHD_resume_connection (request->con);
662 request->phase = RP_FAIL;
668 * We got a block back from the namestore. Decrypt it
669 * and continue to process the result.
671 * @param cls the 'struct Request' we are processing
672 * @param zonekey private key of the zone; NULL on disconnect
673 * @param label label of the records; NULL on disconnect
674 * @param rd_count number of entries in @a rd array, 0 if label was deleted
675 * @param rd array of records with data to store
678 lookup_it_processor (void *cls,
679 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zonekey,
681 unsigned int rd_count,
682 const struct GNUNET_GNSRECORD_Data *rd)
684 struct Request *request = cls;
689 if (0 == strcmp (label, request->domain_name))
691 GNUNET_break (0 != rd_count);
692 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
693 _ ("Found %u existing records for domain `%s'\n"),
695 request->domain_name);
696 request->phase = RP_FAIL;
698 GNUNET_NAMESTORE_zone_iterator_next (request->lookup_it, 1);
703 lookup_it_finished (void *cls)
705 struct Request *request = cls;
707 if (RP_FAIL == request->phase)
709 MHD_resume_connection (request->con);
714 GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key,
715 strlen (request->public_key),
719 request->phase = RP_FAIL;
720 MHD_resume_connection (request->con);
724 request->qe = GNUNET_NAMESTORE_zone_to_name (ns,
735 * Main MHD callback for handling requests.
738 * @param connection MHD connection handle
739 * @param url the requested url
740 * @param method the HTTP method used ("GET", "PUT", etc.)
741 * @param version the HTTP version string (i.e. "HTTP/1.1")
742 * @param upload_data the data being uploaded (excluding HEADERS,
743 * for a POST that fits into memory and that is encoded
744 * with a supported encoding, the POST data will NOT be
745 * given in upload_data and is instead available as
746 * part of MHD_get_connection_values; very large POST
747 * data *will* be made available incrementally in
749 * @param upload_data_size set initially to the size of the
750 * @a upload_data provided; the method must update this
751 * value to the number of bytes NOT processed;
752 * @param ptr pointer to location where we store the 'struct Request'
753 * @return #MHD_YES if the connection was handled successfully,
754 * #MHD_NO if the socket must be closed due to a serious
755 * error while handling the request
758 create_response (void *cls,
759 struct MHD_Connection *connection,
763 const char *upload_data,
764 size_t *upload_data_size,
767 struct MHD_Response *response;
768 struct Request *request;
769 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
774 if ((0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
775 (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)))
777 if (0 == strcmp (url, FCFS_ZONEINFO_URL))
778 ret = serve_zoneinfo_page (connection);
780 ret = serve_main_page (connection);
782 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
783 _ ("Failed to create page for `%s'\n"),
787 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
792 request = GNUNET_new (struct Request);
793 request->con = connection;
795 request->pp = MHD_create_post_processor (connection,
799 if (NULL == request->pp)
801 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
802 _ ("Failed to setup post processor for `%s'\n"),
804 return MHD_NO; /* internal error */
808 if (NULL != request->pp)
810 /* evaluate POST data */
811 MHD_post_process (request->pp,
814 if (0 != *upload_data_size)
816 *upload_data_size = 0;
819 /* done with POST data, serve response */
820 MHD_destroy_post_processor (request->pp);
824 GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key,
826 request->public_key),
830 return fill_s_reply ("Failed to parse given public key",
831 request, connection);
833 switch (request->phase)
836 if (NULL != strchr (request->domain_name, (int) '.'))
838 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
839 _ ("Domain name must not contain `.'\n"));
840 request->phase = RP_FAIL;
841 return fill_s_reply ("Domain name must not contain `.', sorry.",
845 if (NULL != strchr (request->domain_name, (int) '+'))
847 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
848 _ ("Domain name must not contain `+'\n"));
849 request->phase = RP_FAIL;
850 return fill_s_reply ("Domain name must not contain `+', sorry.",
851 request, connection);
853 request->phase = RP_LOOKUP;
854 MHD_suspend_connection (request->con);
856 = GNUNET_NAMESTORE_zone_iteration_start (ns,
860 &lookup_it_processor,
873 return fill_s_reply ("Request failed, sorry.",
874 request, connection);
877 return fill_s_reply ("Success.",
878 request, connection);
884 return MHD_YES; /* will have a reply later... */
886 /* unsupported HTTP method */
887 response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
888 (void *) METHOD_ERROR,
889 MHD_RESPMEM_PERSISTENT);
890 ret = MHD_queue_response (connection,
891 MHD_HTTP_NOT_ACCEPTABLE,
893 MHD_destroy_response (response);
899 * Callback called upon completion of a request.
900 * Decrements session reference counter.
902 * @param cls not used
903 * @param connection connection that completed
904 * @param con_cls session handle
905 * @param toe status code
908 request_completed_callback (void *cls,
909 struct MHD_Connection *connection,
911 enum MHD_RequestTerminationCode toe)
913 struct Request *request = *con_cls;
920 if (NULL != request->pp)
921 MHD_destroy_post_processor (request->pp);
922 if (NULL != request->qe)
923 GNUNET_NAMESTORE_cancel (request->qe);
924 GNUNET_free (request);
928 #define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG
932 * Schedule tasks to run MHD server.
940 struct GNUNET_NETWORK_FDSet *wrs;
941 struct GNUNET_NETWORK_FDSet *wws;
942 struct GNUNET_NETWORK_FDSet *wes;
945 UNSIGNED_MHD_LONG_LONG timeout;
946 struct GNUNET_TIME_Relative tv;
951 wrs = GNUNET_NETWORK_fdset_create ();
952 wes = GNUNET_NETWORK_fdset_create ();
953 wws = GNUNET_NETWORK_fdset_create ();
955 GNUNET_assert (MHD_YES ==
956 MHD_get_fdset (httpd,
961 haveto = MHD_get_timeout (httpd,
963 if (haveto == MHD_YES)
964 tv.rel_value_us = (uint64_t) timeout * 1000LL;
966 tv = GNUNET_TIME_UNIT_FOREVER_REL;
967 GNUNET_NETWORK_fdset_copy_native (wrs,
970 GNUNET_NETWORK_fdset_copy_native (wws,
973 GNUNET_NETWORK_fdset_copy_native (wes,
977 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
983 GNUNET_NETWORK_fdset_destroy (wrs);
984 GNUNET_NETWORK_fdset_destroy (wws);
985 GNUNET_NETWORK_fdset_destroy (wes);
990 * Task run whenever HTTP server operations are pending.
1005 * Task run on shutdown. Cleans up everything.
1010 do_shutdown (void *cls)
1013 if (NULL != httpd_task)
1015 GNUNET_SCHEDULER_cancel (httpd_task);
1018 if (NULL != uzp_task)
1020 GNUNET_SCHEDULER_cancel (uzp_task);
1025 GNUNET_NAMESTORE_disconnect (ns);
1030 MHD_stop_daemon (httpd);
1035 GNUNET_IDENTITY_cancel (id_op);
1038 if (NULL != identity)
1040 GNUNET_IDENTITY_disconnect (identity);
1047 * Method called to inform about the egos of this peer.
1049 * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get,
1050 * this function is only called ONCE, and 'NULL' being passed in
1051 * @a ego does indicate an error (i.e. name is taken or no default
1052 * value is known). If @a ego is non-NULL and if '*ctx'
1053 * is set in those callbacks, the value WILL be passed to a subsequent
1054 * call to the identity callback of #GNUNET_IDENTITY_connect (if
1055 * that one was not NULL).
1057 * @param cls closure, NULL
1058 * @param ego ego handle
1059 * @param ctx context for application to store data for this ego
1060 * (during the lifetime of this process, initially NULL)
1061 * @param name name assigned by the user for this ego,
1062 * NULL if the user just deleted the ego and it
1063 * must thus no longer be used
1066 identity_cb (void *cls,
1067 struct GNUNET_IDENTITY_Ego *ego,
1077 if (0 != strcmp (name,
1082 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1083 _ ("No ego configured for `fcfsd` subsystem\n"));
1084 GNUNET_SCHEDULER_shutdown ();
1087 fcfs_zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1089 options = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
1092 httpd = MHD_start_daemon (options,
1095 &create_response, NULL,
1096 MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128,
1097 MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned
1099 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
1100 MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (4
1103 MHD_OPTION_NOTIFY_COMPLETED,
1104 &request_completed_callback, NULL,
1106 if (MHD_USE_DEBUG == options)
1108 options = MHD_USE_DEBUG;
1110 while (NULL == httpd);
1113 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1114 _ ("Failed to start HTTP server\n"));
1115 GNUNET_SCHEDULER_shutdown ();
1123 * Main function that will be run.
1125 * @param cls closure
1126 * @param args remaining command-line arguments
1127 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1128 * @param cfg configuration
1133 const char *cfgfile,
1134 const struct GNUNET_CONFIGURATION_Handle *cfg)
1140 GNUNET_CONFIGURATION_get_value_number (cfg,
1145 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1146 "fcfsd", "HTTPPORT");
1149 ns = GNUNET_NAMESTORE_connect (cfg);
1152 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1153 _ ("Failed to connect to namestore\n"));
1156 identity = GNUNET_IDENTITY_connect (cfg,
1159 if (NULL == identity)
1161 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1162 _ ("Failed to connect to identity\n"));
1165 uzp_task = GNUNET_SCHEDULER_add_now (&update_zoneinfo_page,
1167 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
1173 * The main function for the fcfs daemon.
1175 * @param argc number of arguments from the command line
1176 * @param argv command line arguments
1177 * @return 0 ok, 1 on error
1183 struct GNUNET_GETOPT_CommandLineOption options[] = {
1184 GNUNET_GETOPT_option_mandatory
1185 (GNUNET_GETOPT_option_string ('z',
1189 "name of the zone that is to be managed by FCFSD"),
1191 GNUNET_GETOPT_OPTION_END
1196 GNUNET_STRINGS_get_utf8_args (argc, argv,
1200 GNUNET_log_setup ("fcfsd",
1205 GNUNET_PROGRAM_run (argc,
1207 "gnunet-namestore-fcfsd",
1209 "GNU Name System First Come First Serve name registration service"),
1211 &run, NULL)) ? 0 : 1;
1212 GNUNET_free ((void *) argv);
1213 GNUNET_CRYPTO_ecdsa_key_clear (&fcfs_zone_pkey);
1218 /* end of gnunet-namestore-fcfsd.c */