/**
* Front page. (/)
*/
-#define MAIN_PAGE "<!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? <input type=\"text\" name=\"domain\" /> <p> What is your public key? <input type=\"text\" name=\"pkey\" /> <input type=\"submit\" value=\"Next\" /></body></html>"
+#define MAIN_PAGE "<!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>"
/**
* Second page (/S)
*/
#define SUBMIT_PAGE "<!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>"
+/**
+ * Fcfs zoneinfo page (/Zoneinfo)
+ */
+#define ZONEINFO_PAGE "<!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>"
+
+#define FCFS_ZONEINFO_URL "/Zoneinfo"
+
/**
* Mime type for HTML pages.
*/
*/
#define COOKIE_NAME "gns-fcfs"
+#define DEFAULT_ZONEINFO_BUFSIZE 2048
/**
* Phases a request goes through.
/**
* Public key submitted via form.
*/
- char public_key[1024];
+ char public_key[64];
};
+/**
+ * Zoneinfo request
+ */
+struct ZoneinfoRequest
+{
+ /**
+ * Connection
+ */
+ struct MHD_Connection *connection;
+
+ /**
+ * List iterator
+ */
+ struct GNUNET_NAMESTORE_ZoneIterator *list_it;
+
+ /**
+ * Buffer
+ */
+ char* zoneinfo;
+
+ /**
+ * Buffer length
+ */
+ size_t buf_len;
+
+ /**
+ * Buffer write offset
+ */
+ size_t write_offset;
+};
/**
* MHD deamon reference.
/**
* Hash of the public key of the fcfsd zone.
*/
-static GNUNET_HashCode fcfsd_zone;
+static struct GNUNET_CRYPTO_ShortHashCode fcfsd_zone;
/**
* Private key for the fcfsd zone.
static struct GNUNET_CRYPTO_RsaPrivateKey *fcfs_zone_pkey;
+/**
+ * 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);
+
+
+/**
+ * Schedule task to run MHD server now.
+ */
+static void
+run_httpd_now ()
+{
+ if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
+ {
+ GNUNET_SCHEDULER_cancel (httpd_task);
+ httpd_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
+}
+
+static void
+iterate_cb (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_len,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct ZoneinfoRequest *zr = cls;
+ struct MHD_Response *response;
+ char* full_page;
+ size_t bytes_free;
+ char* pkey;
+ char* new_buf;
+
+
+ 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),
+ (void *) full_page,
+ MHD_RESPMEM_MUST_FREE);
+ 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;
+ }
+
+ if (1 != rd_len)
+ {
+ GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
+ return;
+ }
+
+ if (GNUNET_NAMESTORE_TYPE_PKEY != rd->record_type)
+ {
+ GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
+ return;
+ }
+
+ bytes_free = zr->buf_len - zr->write_offset;
+ pkey = GNUNET_NAMESTORE_value_to_string (rd->record_type,
+ rd->data,
+ rd->data_size);
+
+ 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_free (zr->zoneinfo);
+ zr->zoneinfo = new_buf;
+ zr->buf_len *= 2;
+ }
+ sprintf (zr->zoneinfo + zr->write_offset,
+ "<tr><td>%s</td><td>%s</td></tr>",
+ name,
+ pkey);
+ zr->write_offset = strlen (zr->zoneinfo);
+ GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
+ GNUNET_free (pkey);
+}
+
+
+
+/**
+ * Handler that returns FCFS zoneinfo page.
+ *
+ * @param connection connection to use
+ * @return MHD_YES on success
+ */
+static int
+serve_zoneinfo_page (struct MHD_Connection *connection)
+{
+ struct ZoneinfoRequest *zr;
+
+ zr = GNUNET_malloc (sizeof (struct ZoneinfoRequest));
+
+ zr->zoneinfo = GNUNET_malloc (DEFAULT_ZONEINFO_BUFSIZE);
+ zr->buf_len = DEFAULT_ZONEINFO_BUFSIZE;
+ zr->connection = connection;
+ zr->write_offset = 0;
+
+ printf ("adsadad1!\n");
+ zr->list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
+ &fcfsd_zone,
+ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION,
+ GNUNET_NAMESTORE_RF_PRIVATE,
+ &iterate_cb,
+ zr);
+
+ return MHD_YES;
+}
+
+
/**
* Handler that returns a simple static HTTP page.
*
(void *) reply,
MHD_RESPMEM_MUST_FREE);
MHD_add_response_header (response,
- MHD_HTTP_HEADER_CONTENT_ENCODING,
+ MHD_HTTP_HEADER_CONTENT_TYPE,
MIME_HTML);
ret = MHD_queue_response (connection,
MHD_HTTP_OK,
}
-/**
- * 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);
-
-
-/**
- * Schedule task to run MHD server now.
- */
-static void
-run_httpd_now ()
-{
- if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
- {
- GNUNET_SCHEDULER_cancel (httpd_task);
- httpd_task = GNUNET_SCHEDULER_NO_TASK;
- }
- httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
-}
/**
/**
- * Process a record that was stored in the namestore.
+ * 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
* because the user queried for a particular record type only)
*/
static void
-lookup_result_processor (void *cls,
- const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
- struct GNUNET_TIME_Absolute expire,
- const char *name,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd,
- const struct GNUNET_CRYPTO_RsaSignature *signature)
+zone_to_name_cb (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
{
struct Request *request = cls;
struct GNUNET_NAMESTORE_RecordData r;
- GNUNET_HashCode pub;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_hash_from_string2 (request->public_key,
- strlen (request->public_key),
- &pub));
request->qe = NULL;
- if (0 != rd_count)
+ if (NULL != name)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Found %u existing records for domain `%s'\n"),
- rd_count,
- request->domain_name);
+ _("Found existing name `%s' for the given key\n"),
+ name);
request->phase = RP_FAIL;
run_httpd_now ();
return;
}
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &pub));
r.data = &pub;
r.data_size = sizeof (pub);
- r.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+ r.expiration_time = UINT64_MAX;
r.record_type = GNUNET_NAMESTORE_TYPE_PKEY;
r.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
request->qe = GNUNET_NAMESTORE_record_create (ns,
}
+/**
+ * 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 zone_key public key of the zone
+ * @param expire when does the corresponding block in the DHT expire (until
+ * when should we never do a DHT lookup for the same name again)?;
+ * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
+ * or the expiration time of the block in the namestore (even if there are zero
+ * records matching the desired record type)
+ * @param name name that is being mapped (at most 255 characters long)
+ * @param rd_count number of entries in 'rd' array
+ * @param rd array of records with data to store
+ * @param signature signature of the record block, NULL if signature is unavailable (i.e.
+ * because the user queried for a particular record type only)
+ */
+static void
+lookup_result_processor (void *cls,
+ const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
+ struct GNUNET_TIME_Absolute expire,
+ const char *name,
+ unsigned int rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd,
+ const struct GNUNET_CRYPTO_RsaSignature *signature)
+{
+ struct Request *request = cls;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
+
+ request->qe = NULL;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &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;
+ }
+ request->qe = GNUNET_NAMESTORE_zone_to_name (ns,
+ &fcfsd_zone,
+ &pub,
+ &zone_to_name_cb,
+ request);
+}
+
+
/**
* Main MHD callback for handling requests.
*
* 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 MHS_YES if the connection was handled successfully,
- * MHS_NO if the socket must be closed due to a serios
+ * @return MHD_YES if the connection was handled successfully,
+ * MHD_NO if the socket must be closed due to a serious
* error while handling the request
*/
static int
struct MHD_Response *response;
struct Request *request;
int ret;
- GNUNET_HashCode pub;
+ struct GNUNET_CRYPTO_ShortHashCode pub;
if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
(0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
{
- ret = serve_main_page (connection);
+ if (0 == strcmp (url, FCFS_ZONEINFO_URL))
+ ret = serve_zoneinfo_page (connection);
+ else
+ ret = serve_main_page (connection);
if (ret != MHD_YES)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Failed to create page for `%s'\n"),
request->pp = NULL;
}
if (GNUNET_OK !=
- GNUNET_CRYPTO_hash_from_string2 (request->public_key,
- strlen (request->public_key),
- &pub))
+ GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
+ strlen (request->public_key),
+ &pub))
{
/* parse error */
return fill_s_reply ("Failed to parse given public key",
switch (request->phase)
{
case RP_START:
+ if (NULL != strchr (request->domain_name, (int) '.'))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Domain name must not contain `.'\n"));
+ request->phase = RP_FAIL;
+ return fill_s_reply ("Domain name must not contain `.', sorry.",
+ request, connection);
+ }
+ if (NULL != strchr (request->domain_name, (int) '+'))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ _("Domain name must not contain `+'\n"));
+ request->phase = RP_FAIL;
+ return fill_s_reply ("Domain name must not contain `+', sorry.",
+ request, connection);
+ }
request->phase = RP_LOOKUP;
request->qe = GNUNET_NAMESTORE_lookup_record (ns,
&fcfsd_zone,
}
+#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG
+
+
/**
* Schedule tasks to run MHD server.
*/
struct GNUNET_NETWORK_FDSet *wes;
int max;
int haveto;
- unsigned MHD_LONG_LONG timeout;
+ UNSIGNED_MHD_LONG_LONG timeout;
struct GNUNET_TIME_Relative tv;
FD_ZERO (&rs);
GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
httpd_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
- GNUNET_SCHEDULER_NO_TASK, tv, wrs, wws,
+ tv, wrs, wws,
&do_httpd, NULL);
GNUNET_NETWORK_fdset_destroy (wrs);
GNUNET_NETWORK_fdset_destroy (wws);
}
if (NULL != ns)
{
- GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO);
+ GNUNET_NAMESTORE_disconnect (ns);
ns = NULL;
}
if (NULL != httpd)
"HTTPPORT",
&port))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Option `%s' not specified in configuration section `%s'\n"),
- "HTTPPORT",
- "fcfsd");
- return;
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "fcfsd", "HTTPPORT");
+ return;
}
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
"ZONEKEY",
&keyfile))
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("Option `%s' not specified in configuration section `%s'\n"),
- "ZONEKEY",
- "fcfsd");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "fcfsd", "ZONEKEY");
return;
}
fcfs_zone_pkey = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
}
GNUNET_CRYPTO_rsa_key_get_public (fcfs_zone_pkey,
&pub);
- GNUNET_CRYPTO_hash (&pub, sizeof (pub), &fcfsd_zone);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Managing `%s' as FCFS zone on port %llu\n"),
- GNUNET_h2s_full (&fcfsd_zone),
- port);
+ GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &fcfsd_zone);
ns = GNUNET_NAMESTORE_connect (cfg);
if (NULL == ns)
{
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Failed to start HTTP server\n"));
- GNUNET_NAMESTORE_disconnect (ns, GNUNET_NO);
+ GNUNET_NAMESTORE_disconnect (ns);
ns = NULL;
return;
}
int ret;
+ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+ return 2;
+
GNUNET_log_setup ("fcfsd", "WARNING", NULL);
ret =
(GNUNET_OK ==
_("GNUnet GNS first come first serve registration service"),
options,
&run, NULL)) ? 0 : 1;
-
+ GNUNET_free ((void*) argv);
return ret;
}