aboutsummaryrefslogtreecommitdiff
path: root/src/gns
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns')
-rw-r--r--src/gns/Makefile.am10
-rw-r--r--src/gns/gnunet-gns-fcfsd.c980
-rw-r--r--src/gns/gnunet-service-gns_resolver.c55
3 files changed, 31 insertions, 1014 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 16bd6ca1c..e91014021 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -154,16 +154,6 @@ gnunet_service_gns_DEPENDENCIES = \
154 154
155 155
156 156
157gnunet_gns_fcfsd_SOURCES = \
158 gnunet-gns-fcfsd.c
159gnunet_gns_fcfsd_LDADD = -lmicrohttpd \
160 $(top_builddir)/src/util/libgnunetutil.la \
161 $(top_builddir)/src/namestore/libgnunetnamestore.la \
162 $(GN_LIBINTL)
163gnunet_gns_fcfsd_DEPENDENCIES = \
164 $(top_builddir)/src/util/libgnunetutil.la \
165 $(top_builddir)/src/namestore/libgnunetnamestore.la
166
167libw32nsp_la_SOURCES = \ 157libw32nsp_la_SOURCES = \
168 w32nsp.c 158 w32nsp.c
169libw32nsp_la_LIBADD = \ 159libw32nsp_la_LIBADD = \
diff --git a/src/gns/gnunet-gns-fcfsd.c b/src/gns/gnunet-gns-fcfsd.c
deleted file mode 100644
index dd4572cb1..000000000
--- a/src/gns/gnunet-gns-fcfsd.c
+++ /dev/null
@@ -1,980 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file gnunet-gns-fcfsd.c
22 * @brief HTTP daemon that offers first-come-first-serve GNS domain registration
23 * @author Christian Grothoff
24 *
25 * TODO:
26 * - the code currently contains a 'race' between checking that the
27 * domain name is available and allocating it to the new public key
28 * (should this race be solved by namestore or by fcfsd?)
29 * - nicer error reporting to browser
30 * - figure out where this binary should go (is gns the right directory!?)
31 */
32#include "platform.h"
33#include <gnunet_util_lib.h>
34#include <microhttpd.h>
35#include <gnunet_namestore_service.h>
36
37/**
38 * Invalid method page.
39 */
40#define METHOD_ERROR "<!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>"
41
42/**
43 * Front page. (/)
44 */
45#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>"
46
47/**
48 * Second page (/S)
49 */
50#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>"
51
52/**
53 * Fcfs zoneinfo page (/Zoneinfo)
54 */
55#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>"
56
57#define FCFS_ZONEINFO_URL "/Zoneinfo"
58
59/**
60 * Mime type for HTML pages.
61 */
62#define MIME_HTML "text/html"
63
64/**
65 * Name of our cookie.
66 */
67#define COOKIE_NAME "gns-fcfs"
68
69#define DEFAULT_ZONEINFO_BUFSIZE 2048
70
71/**
72 * Phases a request goes through.
73 */
74enum Phase
75 {
76 /**
77 * Start phase (parsing POST, checking).
78 */
79 RP_START = 0,
80
81 /**
82 * Lookup to see if the domain name is taken.
83 */
84 RP_LOOKUP,
85
86 /**
87 * Storing of the record.
88 */
89 RP_PUT,
90
91 /**
92 * We're done with success.
93 */
94 RP_SUCCESS,
95
96 /**
97 * Send failure message.
98 */
99 RP_FAIL
100 };
101
102
103/**
104 * Data kept per request.
105 */
106struct Request
107{
108
109 /**
110 * Associated session.
111 */
112 struct Session *session;
113
114 /**
115 * Post processor handling form data (IF this is
116 * a POST request).
117 */
118 struct MHD_PostProcessor *pp;
119
120 /**
121 * URL to serve in response to this POST (if this request
122 * was a 'POST')
123 */
124 const char *post_url;
125
126 /**
127 * Active request with the namestore.
128 */
129 struct GNUNET_NAMESTORE_QueueEntry *qe;
130
131 /**
132 * Current processing phase.
133 */
134 enum Phase phase;
135
136 /**
137 * Domain name submitted via form.
138 */
139 char domain_name[64];
140
141 /**
142 * Public key submitted via form.
143 */
144 char public_key[64];
145
146};
147
148/**
149 * Zoneinfo request
150 */
151struct ZoneinfoRequest
152{
153 /**
154 * Connection
155 */
156 struct MHD_Connection *connection;
157
158 /**
159 * List iterator
160 */
161 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
162
163 /**
164 * Buffer
165 */
166 char* zoneinfo;
167
168 /**
169 * Buffer length
170 */
171 size_t buf_len;
172
173 /**
174 * Buffer write offset
175 */
176 size_t write_offset;
177};
178
179/**
180 * MHD deamon reference.
181 */
182static struct MHD_Daemon *httpd;
183
184/**
185 * Main HTTP task.
186 */
187static GNUNET_SCHEDULER_TaskIdentifier httpd_task;
188
189/**
190 * Handle to the namestore.
191 */
192static struct GNUNET_NAMESTORE_Handle *ns;
193
194/**
195 * Hash of the public key of the fcfsd zone.
196 */
197static struct GNUNET_CRYPTO_ShortHashCode fcfsd_zone;
198
199/**
200 * Private key for the fcfsd zone.
201 */
202static struct GNUNET_CRYPTO_EccPrivateKey *fcfs_zone_pkey;
203
204
205/**
206 * Task run whenever HTTP server operations are pending.
207 *
208 * @param cls unused
209 * @param tc scheduler context
210 */
211static void
212do_httpd (void *cls,
213 const struct GNUNET_SCHEDULER_TaskContext *tc);
214
215
216/**
217 * Schedule task to run MHD server now.
218 */
219static void
220run_httpd_now ()
221{
222 if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
223 {
224 GNUNET_SCHEDULER_cancel (httpd_task);
225 httpd_task = GNUNET_SCHEDULER_NO_TASK;
226 }
227 httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
228}
229
230static void
231iterate_cb (void *cls,
232 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
233 struct GNUNET_TIME_Absolute expire,
234 const char *name,
235 unsigned int rd_len,
236 const struct GNUNET_NAMESTORE_RecordData *rd,
237 const struct GNUNET_CRYPTO_EccSignature *signature)
238{
239 struct ZoneinfoRequest *zr = cls;
240 struct MHD_Response *response;
241 char* full_page;
242 size_t bytes_free;
243 char* pkey;
244 char* new_buf;
245
246
247 if (NULL == name)
248 {
249 zr->list_it = NULL;
250
251 /* return static form */
252 GNUNET_asprintf (&full_page,
253 ZONEINFO_PAGE,
254 zr->zoneinfo,
255 zr->zoneinfo);
256 response = MHD_create_response_from_buffer (strlen (full_page),
257 (void *) full_page,
258 MHD_RESPMEM_MUST_FREE);
259 MHD_add_response_header (response,
260 MHD_HTTP_HEADER_CONTENT_TYPE,
261 MIME_HTML);
262 MHD_queue_response (zr->connection,
263 MHD_HTTP_OK,
264 response);
265 MHD_destroy_response (response);
266 GNUNET_free (zr->zoneinfo);
267 GNUNET_free (zr);
268 run_httpd_now ();
269 return;
270 }
271
272 if (1 != rd_len)
273 {
274 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
275 return;
276 }
277
278 if (GNUNET_NAMESTORE_TYPE_PKEY != rd->record_type)
279 {
280 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
281 return;
282 }
283
284 bytes_free = zr->buf_len - zr->write_offset;
285 pkey = GNUNET_NAMESTORE_value_to_string (rd->record_type,
286 rd->data,
287 rd->data_size);
288
289 if (bytes_free < (strlen (name) + strlen (pkey) + 40))
290 {
291 new_buf = GNUNET_malloc (zr->buf_len * 2);
292 memcpy (new_buf, zr->zoneinfo, zr->write_offset);
293 GNUNET_free (zr->zoneinfo);
294 zr->zoneinfo = new_buf;
295 zr->buf_len *= 2;
296 }
297 sprintf (zr->zoneinfo + zr->write_offset,
298 "<tr><td>%s</td><td>%s</td></tr>",
299 name,
300 pkey);
301 zr->write_offset = strlen (zr->zoneinfo);
302 GNUNET_NAMESTORE_zone_iterator_next (zr->list_it);
303 GNUNET_free (pkey);
304}
305
306
307
308/**
309 * Handler that returns FCFS zoneinfo page.
310 *
311 * @param connection connection to use
312 * @return MHD_YES on success
313 */
314static int
315serve_zoneinfo_page (struct MHD_Connection *connection)
316{
317 struct ZoneinfoRequest *zr;
318
319 zr = GNUNET_malloc (sizeof (struct ZoneinfoRequest));
320
321 zr->zoneinfo = GNUNET_malloc (DEFAULT_ZONEINFO_BUFSIZE);
322 zr->buf_len = DEFAULT_ZONEINFO_BUFSIZE;
323 zr->connection = connection;
324 zr->write_offset = 0;
325
326 printf ("adsadad1!\n");
327 zr->list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
328 &fcfsd_zone,
329 GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION,
330 GNUNET_NAMESTORE_RF_PRIVATE,
331 &iterate_cb,
332 zr);
333
334 return MHD_YES;
335}
336
337
338/**
339 * Handler that returns a simple static HTTP page.
340 *
341 * @param connection connection to use
342 * @return MHD_YES on success
343 */
344static int
345serve_main_page (struct MHD_Connection *connection)
346{
347 int ret;
348 struct MHD_Response *response;
349
350 /* return static form */
351 response = MHD_create_response_from_buffer (strlen (MAIN_PAGE),
352 (void *) MAIN_PAGE,
353 MHD_RESPMEM_PERSISTENT);
354 MHD_add_response_header (response,
355 MHD_HTTP_HEADER_CONTENT_TYPE,
356 MIME_HTML);
357 ret = MHD_queue_response (connection,
358 MHD_HTTP_OK,
359 response);
360 MHD_destroy_response (response);
361 return ret;
362}
363
364
365/**
366 * Send the 'SUBMIT_PAGE'.
367 *
368 * @param info information string to send to the user
369 * @param request request information
370 * @param connection connection to use
371 */
372static int
373fill_s_reply (const char *info,
374 struct Request *request,
375 struct MHD_Connection *connection)
376{
377 int ret;
378 char *reply;
379 struct MHD_Response *response;
380
381 GNUNET_asprintf (&reply,
382 SUBMIT_PAGE,
383 info,
384 info);
385 /* return static form */
386 response = MHD_create_response_from_buffer (strlen (reply),
387 (void *) reply,
388 MHD_RESPMEM_MUST_FREE);
389 MHD_add_response_header (response,
390 MHD_HTTP_HEADER_CONTENT_TYPE,
391 MIME_HTML);
392 ret = MHD_queue_response (connection,
393 MHD_HTTP_OK,
394 response);
395 MHD_destroy_response (response);
396 return ret;
397}
398
399
400/**
401 * Iterator over key-value pairs where the value
402 * maybe made available in increments and/or may
403 * not be zero-terminated. Used for processing
404 * POST data.
405 *
406 * @param cls user-specified closure
407 * @param kind type of the value
408 * @param key 0-terminated key for the value
409 * @param filename name of the uploaded file, NULL if not known
410 * @param content_type mime-type of the data, NULL if not known
411 * @param transfer_encoding encoding of the data, NULL if not known
412 * @param data pointer to size bytes of data at the
413 * specified offset
414 * @param off offset of data in the overall value
415 * @param size number of bytes in data available
416 * @return MHD_YES to continue iterating,
417 * MHD_NO to abort the iteration
418 */
419static int
420post_iterator (void *cls,
421 enum MHD_ValueKind kind,
422 const char *key,
423 const char *filename,
424 const char *content_type,
425 const char *transfer_encoding,
426 const char *data, uint64_t off, size_t size)
427{
428 struct Request *request = cls;
429
430 if (0 == strcmp ("domain", key))
431 {
432 if (size + off >= sizeof(request->domain_name))
433 size = sizeof (request->domain_name) - off - 1;
434 memcpy (&request->domain_name[off],
435 data,
436 size);
437 request->domain_name[size+off] = '\0';
438 return MHD_YES;
439 }
440 if (0 == strcmp ("pkey", key))
441 {
442 if (size + off >= sizeof(request->public_key))
443 size = sizeof (request->public_key) - off - 1;
444 memcpy (&request->public_key[off],
445 data,
446 size);
447 request->public_key[size+off] = '\0';
448 return MHD_YES;
449 }
450 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
451 _("Unsupported form value `%s'\n"),
452 key);
453 return MHD_YES;
454}
455
456
457
458
459/**
460 * Continuation called to notify client about result of the
461 * operation.
462 *
463 * @param cls closure
464 * @param success GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
465 * GNUNET_NO if content was already there
466 * GNUNET_YES (or other positive value) on success
467 * @param emsg NULL on success, otherwise an error message
468 */
469static void
470put_continuation (void *cls,
471 int32_t success,
472 const char *emsg)
473{
474 struct Request *request = cls;
475
476 request->qe = NULL;
477 if (0 >= success)
478 {
479 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
480 _("Failed to create record for domain `%s': %s\n"),
481 request->domain_name,
482 emsg);
483 request->phase = RP_FAIL;
484 }
485 else
486 request->phase = RP_SUCCESS;
487 run_httpd_now ();
488}
489
490
491/**
492 * Test if a name mapping was found, if so, refuse. If not, initiate storing of the record.
493 *
494 * @param cls closure
495 * @param zone_key public key of the zone
496 * @param expire when does the corresponding block in the DHT expire (until
497 * when should we never do a DHT lookup for the same name again)?;
498 * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
499 * or the expiration time of the block in the namestore (even if there are zero
500 * records matching the desired record type)
501 * @param name name that is being mapped (at most 255 characters long)
502 * @param rd_count number of entries in 'rd' array
503 * @param rd array of records with data to store
504 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
505 * because the user queried for a particular record type only)
506 */
507static void
508zone_to_name_cb (void *cls,
509 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
510 struct GNUNET_TIME_Absolute expire,
511 const char *name,
512 unsigned int rd_count,
513 const struct GNUNET_NAMESTORE_RecordData *rd,
514 const struct GNUNET_CRYPTO_EccSignature *signature)
515{
516 struct Request *request = cls;
517 struct GNUNET_NAMESTORE_RecordData r;
518 struct GNUNET_CRYPTO_ShortHashCode pub;
519
520 request->qe = NULL;
521 if (NULL != name)
522 {
523 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
524 _("Found existing name `%s' for the given key\n"),
525 name);
526 request->phase = RP_FAIL;
527 run_httpd_now ();
528 return;
529 }
530 GNUNET_assert (GNUNET_OK ==
531 GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
532 strlen (request->public_key),
533 &pub));
534 r.data = &pub;
535 r.data_size = sizeof (pub);
536 r.expiration_time = UINT64_MAX;
537 r.record_type = GNUNET_NAMESTORE_TYPE_PKEY;
538 r.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
539 request->qe = GNUNET_NAMESTORE_record_put_by_authority (ns,
540 fcfs_zone_pkey,
541 request->domain_name,
542 1,
543 &r,
544 &put_continuation,
545 request);
546}
547
548
549/**
550 * Process a record that was stored in the namestore. Used to check if
551 * the requested name already exists in the namestore. If not,
552 * proceed to check if the requested key already exists.
553 *
554 * @param cls closure
555 * @param zone_key public key of the zone
556 * @param expire when does the corresponding block in the DHT expire (until
557 * when should we never do a DHT lookup for the same name again)?;
558 * GNUNET_TIME_UNIT_ZERO_ABS if there are no records of any type in the namestore,
559 * or the expiration time of the block in the namestore (even if there are zero
560 * records matching the desired record type)
561 * @param name name that is being mapped (at most 255 characters long)
562 * @param rd_count number of entries in 'rd' array
563 * @param rd array of records with data to store
564 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
565 * because the user queried for a particular record type only)
566 */
567static void
568lookup_result_processor (void *cls,
569 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
570 struct GNUNET_TIME_Absolute expire,
571 const char *name,
572 unsigned int rd_count,
573 const struct GNUNET_NAMESTORE_RecordData *rd,
574 const struct GNUNET_CRYPTO_EccSignature *signature)
575{
576 struct Request *request = cls;
577 struct GNUNET_CRYPTO_ShortHashCode pub;
578
579 request->qe = NULL;
580 GNUNET_assert (GNUNET_OK ==
581 GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
582 strlen (request->public_key),
583 &pub));
584 if (0 != rd_count)
585 {
586 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
587 _("Found %u existing records for domain `%s'\n"),
588 rd_count,
589 request->domain_name);
590 request->phase = RP_FAIL;
591 run_httpd_now ();
592 return;
593 }
594 request->qe = GNUNET_NAMESTORE_zone_to_name (ns,
595 &fcfsd_zone,
596 &pub,
597 &zone_to_name_cb,
598 request);
599}
600
601
602/**
603 * Main MHD callback for handling requests.
604 *
605 * @param cls unused
606 * @param connection MHD connection handle
607 * @param url the requested url
608 * @param method the HTTP method used ("GET", "PUT", etc.)
609 * @param version the HTTP version string (i.e. "HTTP/1.1")
610 * @param upload_data the data being uploaded (excluding HEADERS,
611 * for a POST that fits into memory and that is encoded
612 * with a supported encoding, the POST data will NOT be
613 * given in upload_data and is instead available as
614 * part of MHD_get_connection_values; very large POST
615 * data *will* be made available incrementally in
616 * upload_data)
617 * @param upload_data_size set initially to the size of the
618 * upload_data provided; the method must update this
619 * value to the number of bytes NOT processed;
620 * @param ptr pointer to location where we store the 'struct Request'
621 * @return MHD_YES if the connection was handled successfully,
622 * MHD_NO if the socket must be closed due to a serious
623 * error while handling the request
624 */
625static int
626create_response (void *cls,
627 struct MHD_Connection *connection,
628 const char *url,
629 const char *method,
630 const char *version,
631 const char *upload_data,
632 size_t *upload_data_size,
633 void **ptr)
634{
635 struct MHD_Response *response;
636 struct Request *request;
637 int ret;
638 struct GNUNET_CRYPTO_ShortHashCode pub;
639
640 if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
641 (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
642 {
643 if (0 == strcmp (url, FCFS_ZONEINFO_URL))
644 ret = serve_zoneinfo_page (connection);
645 else
646 ret = serve_main_page (connection);
647 if (ret != MHD_YES)
648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
649 _("Failed to create page for `%s'\n"),
650 url);
651 return ret;
652 }
653 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
654 {
655 request = *ptr;
656 if (NULL == request)
657 {
658 request = GNUNET_malloc (sizeof (struct Request));
659 *ptr = request;
660 request->pp = MHD_create_post_processor (connection, 1024,
661 &post_iterator, request);
662 if (NULL == request->pp)
663 {
664 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
665 _("Failed to setup post processor for `%s'\n"),
666 url);
667 return MHD_NO; /* internal error */
668 }
669 return MHD_YES;
670 }
671 if (NULL != request->pp)
672 {
673 /* evaluate POST data */
674 MHD_post_process (request->pp,
675 upload_data,
676 *upload_data_size);
677 if (0 != *upload_data_size)
678 {
679 *upload_data_size = 0;
680 return MHD_YES;
681 }
682 /* done with POST data, serve response */
683 MHD_destroy_post_processor (request->pp);
684 request->pp = NULL;
685 }
686 if (GNUNET_OK !=
687 GNUNET_CRYPTO_short_hash_from_string2 (request->public_key,
688 strlen (request->public_key),
689 &pub))
690 {
691 /* parse error */
692 return fill_s_reply ("Failed to parse given public key",
693 request, connection);
694 }
695 switch (request->phase)
696 {
697 case RP_START:
698 if (NULL != strchr (request->domain_name, (int) '.'))
699 {
700 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
701 _("Domain name must not contain `.'\n"));
702 request->phase = RP_FAIL;
703 return fill_s_reply ("Domain name must not contain `.', sorry.",
704 request, connection);
705 }
706 if (NULL != strchr (request->domain_name, (int) '+'))
707 {
708 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
709 _("Domain name must not contain `+'\n"));
710 request->phase = RP_FAIL;
711 return fill_s_reply ("Domain name must not contain `+', sorry.",
712 request, connection);
713 }
714 request->phase = RP_LOOKUP;
715 request->qe = GNUNET_NAMESTORE_lookup_record (ns,
716 &fcfsd_zone,
717 request->domain_name,
718 GNUNET_NAMESTORE_TYPE_PKEY,
719 &lookup_result_processor,
720 request);
721 break;
722 case RP_LOOKUP:
723 break;
724 case RP_PUT:
725 break;
726 case RP_FAIL:
727 return fill_s_reply ("Request failed, sorry.",
728 request, connection);
729 case RP_SUCCESS:
730 return fill_s_reply ("Success.",
731 request, connection);
732 default:
733 GNUNET_break (0);
734 return MHD_NO;
735 }
736 return MHD_YES; /* will have a reply later... */
737 }
738 /* unsupported HTTP method */
739 response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
740 (void *) METHOD_ERROR,
741 MHD_RESPMEM_PERSISTENT);
742 ret = MHD_queue_response (connection,
743 MHD_HTTP_METHOD_NOT_ACCEPTABLE,
744 response);
745 MHD_destroy_response (response);
746 return ret;
747}
748
749
750/**
751 * Callback called upon completion of a request.
752 * Decrements session reference counter.
753 *
754 * @param cls not used
755 * @param connection connection that completed
756 * @param con_cls session handle
757 * @param toe status code
758 */
759static void
760request_completed_callback (void *cls,
761 struct MHD_Connection *connection,
762 void **con_cls,
763 enum MHD_RequestTerminationCode toe)
764{
765 struct Request *request = *con_cls;
766
767 if (NULL == request)
768 return;
769 if (NULL != request->pp)
770 MHD_destroy_post_processor (request->pp);
771 if (NULL != request->qe)
772 GNUNET_NAMESTORE_cancel (request->qe);
773 GNUNET_free (request);
774}
775
776
777#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG
778
779
780/**
781 * Schedule tasks to run MHD server.
782 */
783static void
784run_httpd ()
785{
786 fd_set rs;
787 fd_set ws;
788 fd_set es;
789 struct GNUNET_NETWORK_FDSet *wrs;
790 struct GNUNET_NETWORK_FDSet *wws;
791 struct GNUNET_NETWORK_FDSet *wes;
792 int max;
793 int haveto;
794 UNSIGNED_MHD_LONG_LONG timeout;
795 struct GNUNET_TIME_Relative tv;
796
797 FD_ZERO (&rs);
798 FD_ZERO (&ws);
799 FD_ZERO (&es);
800 wrs = GNUNET_NETWORK_fdset_create ();
801 wes = GNUNET_NETWORK_fdset_create ();
802 wws = GNUNET_NETWORK_fdset_create ();
803 max = -1;
804 GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
805 haveto = MHD_get_timeout (httpd, &timeout);
806 if (haveto == MHD_YES)
807 tv.rel_value_us = (uint64_t) timeout * 1000LL;
808 else
809 tv = GNUNET_TIME_UNIT_FOREVER_REL;
810 GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
811 GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
812 GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
813 httpd_task =
814 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
815 tv, wrs, wws,
816 &do_httpd, NULL);
817 GNUNET_NETWORK_fdset_destroy (wrs);
818 GNUNET_NETWORK_fdset_destroy (wws);
819 GNUNET_NETWORK_fdset_destroy (wes);
820}
821
822
823/**
824 * Task run whenever HTTP server operations are pending.
825 *
826 * @param cls unused
827 * @param tc scheduler context
828 */
829static void
830do_httpd (void *cls,
831 const struct GNUNET_SCHEDULER_TaskContext *tc)
832{
833 httpd_task = GNUNET_SCHEDULER_NO_TASK;
834 MHD_run (httpd);
835 run_httpd ();
836}
837
838
839/**
840 * Task run on shutdown. Cleans up everything.
841 *
842 * @param cls unused
843 * @param tc scheduler context
844 */
845static void
846do_shutdown (void *cls,
847 const struct GNUNET_SCHEDULER_TaskContext *tc)
848{
849 if (GNUNET_SCHEDULER_NO_TASK != httpd_task)
850 {
851 GNUNET_SCHEDULER_cancel (httpd_task);
852 httpd_task = GNUNET_SCHEDULER_NO_TASK;
853 }
854 if (NULL != ns)
855 {
856 GNUNET_NAMESTORE_disconnect (ns);
857 ns = NULL;
858 }
859 if (NULL != httpd)
860 {
861 MHD_stop_daemon (httpd);
862 httpd = NULL;
863 }
864 if (NULL != fcfs_zone_pkey)
865 {
866 GNUNET_CRYPTO_ecc_key_free (fcfs_zone_pkey);
867 fcfs_zone_pkey = NULL;
868 }
869}
870
871
872/**
873 * Main function that will be run.
874 *
875 * @param cls closure
876 * @param args remaining command-line arguments
877 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
878 * @param cfg configuration
879 */
880static void
881run (void *cls, char *const *args, const char *cfgfile,
882 const struct GNUNET_CONFIGURATION_Handle *cfg)
883{
884 char *keyfile;
885 unsigned long long port;
886 struct GNUNET_CRYPTO_EccPublicKey pub;
887
888 if (GNUNET_OK !=
889 GNUNET_CONFIGURATION_get_value_number (cfg,
890 "fcfsd",
891 "HTTPPORT",
892 &port))
893 {
894 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
895 "fcfsd", "HTTPPORT");
896 return;
897 }
898 if (GNUNET_OK !=
899 GNUNET_CONFIGURATION_get_value_filename (cfg,
900 "fcfsd",
901 "ZONEKEY",
902 &keyfile))
903 {
904 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
905 "fcfsd", "ZONEKEY");
906 return;
907 }
908 fcfs_zone_pkey = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
909 GNUNET_free (keyfile);
910 if (NULL == fcfs_zone_pkey)
911 {
912 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
913 _("Failed to read or create private zone key\n"));
914 return;
915 }
916 GNUNET_CRYPTO_ecc_key_get_public (fcfs_zone_pkey,
917 &pub);
918 GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &fcfsd_zone);
919 ns = GNUNET_NAMESTORE_connect (cfg);
920 if (NULL == ns)
921 {
922 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
923 _("Failed to connect to namestore\n"));
924 return;
925 }
926 httpd = MHD_start_daemon (MHD_USE_DEBUG,
927 (uint16_t) port,
928 NULL, NULL,
929 &create_response, NULL,
930 MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128,
931 MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
932 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
933 MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (4 * 1024),
934 MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL,
935 MHD_OPTION_END);
936 if (NULL == httpd)
937 {
938 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
939 _("Failed to start HTTP server\n"));
940 GNUNET_NAMESTORE_disconnect (ns);
941 ns = NULL;
942 return;
943 }
944 run_httpd ();
945 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
946 &do_shutdown, NULL);
947}
948
949
950/**
951 * The main function for the fcfs daemon.
952 *
953 * @param argc number of arguments from the command line
954 * @param argv command line arguments
955 * @return 0 ok, 1 on error
956 */
957int
958main (int argc, char *const *argv)
959{
960 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
961 GNUNET_GETOPT_OPTION_END
962 };
963
964 int ret;
965
966 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
967 return 2;
968
969 GNUNET_log_setup ("fcfsd", "WARNING", NULL);
970 ret =
971 (GNUNET_OK ==
972 GNUNET_PROGRAM_run (argc, argv, "fcfsd",
973 _("GNUnet GNS first come first serve registration service"),
974 options,
975 &run, NULL)) ? 0 : 1;
976 GNUNET_free ((void*) argv);
977 return ret;
978}
979
980/* end of gnunet-gns-fcfsd.c */
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index 8aa9e8188..de9e7e014 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -491,6 +491,7 @@ process_pseu_lookup_ns (void *cls,
491{ 491{
492 struct GetPseuAuthorityHandle *gph = cls; 492 struct GetPseuAuthorityHandle *gph = cls;
493 struct GNUNET_NAMESTORE_RecordData new_pkey; 493 struct GNUNET_NAMESTORE_RecordData new_pkey;
494 struct GNUNET_CRYPTO_EccPublicKey pub;
494 495
495 gph->namestore_task = NULL; 496 gph->namestore_task = NULL;
496 if (rd_count > 0) 497 if (rd_count > 0)
@@ -502,14 +503,19 @@ process_pseu_lookup_ns (void *cls,
502 time, this time not using PSEU but the original label */ 503 time, this time not using PSEU but the original label */
503 if (0 == strcmp (name, 504 if (0 == strcmp (name,
504 gph->label)) 505 gph->label))
506 {
505 free_get_pseu_authority_handle (gph); 507 free_get_pseu_authority_handle (gph);
508 }
506 else 509 else
510 {
511 GNUNET_CRYPTO_ecc_key_get_public (&gph->shorten_zone_key,
512 &pub);
507 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle, 513 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
508 &gph->shorten_zone_key, 514 &pub,
509 gph->label, 515 gph->label,
510 GNUNET_NAMESTORE_TYPE_ANY,
511 &process_pseu_lookup_ns, 516 &process_pseu_lookup_ns,
512 gph); 517 gph);
518 }
513 return; 519 return;
514 } 520 }
515 /* name is available */ 521 /* name is available */
@@ -543,6 +549,10 @@ static void
543process_pseu_result (struct GetPseuAuthorityHandle* gph, 549process_pseu_result (struct GetPseuAuthorityHandle* gph,
544 const char *pseu) 550 const char *pseu)
545{ 551{
552 struct GNUNET_CRYPTO_EccPublicKey pub;
553
554 GNUNET_CRYPTO_ecc_key_get_public (&gph->shorten_zone_key,
555 &pub);
546 if (NULL == pseu) 556 if (NULL == pseu)
547 { 557 {
548 /* no PSEU found, try original label */ 558 /* no PSEU found, try original label */
@@ -550,9 +560,8 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph,
550 "No PSEU found, trying original label `%s' instead.\n", 560 "No PSEU found, trying original label `%s' instead.\n",
551 gph->label); 561 gph->label);
552 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle, 562 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
553 &gph->shorten_zone_key, 563 &pub,
554 gph->label, 564 gph->label,
555 GNUNET_NAMESTORE_TYPE_ANY,
556 &process_pseu_lookup_ns, 565 &process_pseu_lookup_ns,
557 gph); 566 gph);
558 return; 567 return;
@@ -560,9 +569,8 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph,
560 569
561 /* check if 'pseu' is taken */ 570 /* check if 'pseu' is taken */
562 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle, 571 gph->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
563 &gph->shorten_zone_key, 572 &pub,
564 pseu, 573 pseu,
565 GNUNET_NAMESTORE_TYPE_ANY,
566 &process_pseu_lookup_ns, 574 &process_pseu_lookup_ns,
567 gph); 575 gph);
568} 576}
@@ -1927,12 +1935,12 @@ process_delegation_result_dht (void* cls,
1927 1935
1928 1936
1929 /* Check for key revocation and delegate */ 1937 /* Check for key revocation and delegate */
1930 rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, 1938 rh->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
1931 &rh->authority, 1939 &rh->authority,
1932 GNUNET_GNS_MASTERZONE_STR, 1940 GNUNET_GNS_MASTERZONE_STR,
1933 GNUNET_NAMESTORE_TYPE_REV, 1941 GNUNET_NAMESTORE_TYPE_REV,
1934 &process_pkey_revocation_result_ns, 1942 &process_pkey_revocation_result_ns,
1935 rh); 1943 rh);
1936 1944
1937 return; 1945 return;
1938 } 1946 }
@@ -2801,12 +2809,12 @@ process_delegation_result_ns (void* cls,
2801 memcpy ((void*)rh->rd.data, rd[i].data, rd[i].data_size); 2809 memcpy ((void*)rh->rd.data, rd[i].data, rd[i].data_size);
2802 rh->rd_count = 1; 2810 rh->rd_count = 1;
2803 /* Check for key revocation and delegate */ 2811 /* Check for key revocation and delegate */
2804 rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, 2812 rh->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
2805 &rh->authority, 2813 &rh->authority,
2806 GNUNET_GNS_MASTERZONE_STR, 2814 GNUNET_GNS_MASTERZONE_STR,
2807 GNUNET_NAMESTORE_TYPE_REV, 2815 GNUNET_NAMESTORE_TYPE_REV,
2808 &process_pkey_revocation_result_ns, 2816 &process_pkey_revocation_result_ns,
2809 rh); 2817 rh);
2810 return; 2818 return;
2811 default: 2819 default:
2812 /* ignore, move to next result */ 2820 /* ignore, move to next result */
@@ -2867,12 +2875,11 @@ resolve_delegation_ns (struct ResolverHandle *rh)
2867 rh->name, 2875 rh->name,
2868 rh->authority_name, 2876 rh->authority_name,
2869 GNUNET_short_h2s (&rh->authority)); 2877 GNUNET_short_h2s (&rh->authority));
2870 rh->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle, 2878 rh->namestore_task = GNUNET_NAMESTORE_lookup (namestore_handle,
2871 &rh->authority, 2879 &rh->authority,
2872 rh->authority_name, 2880 rh->authority_name,
2873 GNUNET_DNSPARSER_TYPE_ANY, 2881 &process_delegation_result_ns,
2874 &process_delegation_result_ns, 2882 rh);
2875 rh);
2876} 2883}
2877 2884
2878#endif 2885#endif