aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo-tool
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-12 12:51:41 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-12 12:51:41 +0000
commitc870112e1fe50c58fdfde2dfd5775a1d331f0995 (patch)
tree11d84ebffa0b49b00861c962b987034c473a9eee /src/peerinfo-tool
parent9e5c8d198154d018d7ad97efb579749c1625b2b4 (diff)
downloadgnunet-c870112e1fe50c58fdfde2dfd5775a1d331f0995.tar.gz
gnunet-c870112e1fe50c58fdfde2dfd5775a1d331f0995.zip
-fixing #2206/2212
Diffstat (limited to 'src/peerinfo-tool')
-rw-r--r--src/peerinfo-tool/Makefile.am2
-rw-r--r--src/peerinfo-tool/gnunet-peerinfo.c311
2 files changed, 132 insertions, 181 deletions
diff --git a/src/peerinfo-tool/Makefile.am b/src/peerinfo-tool/Makefile.am
index 77604d55f..2182e8a7e 100644
--- a/src/peerinfo-tool/Makefile.am
+++ b/src/peerinfo-tool/Makefile.am
@@ -14,7 +14,7 @@ bin_PROGRAMS = \
14 14
15gnunet_peerinfo_SOURCES = \ 15gnunet_peerinfo_SOURCES = \
16 gnunet-peerinfo.c \ 16 gnunet-peerinfo.c \
17 gnunet-peerinfo_plugins.c 17 gnunet-peerinfo_plugins.c gnunet-peerinfo_plugins.h
18 18
19gnunet_peerinfo_LDADD = \ 19gnunet_peerinfo_LDADD = \
20 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ 20 $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
diff --git a/src/peerinfo-tool/gnunet-peerinfo.c b/src/peerinfo-tool/gnunet-peerinfo.c
index 2ffea8bcd..3ca8b0862 100644
--- a/src/peerinfo-tool/gnunet-peerinfo.c
+++ b/src/peerinfo-tool/gnunet-peerinfo.c
@@ -33,6 +33,10 @@
33#include "gnunet_transport_plugin.h" 33#include "gnunet_transport_plugin.h"
34#include "gnunet-peerinfo_plugins.h" 34#include "gnunet-peerinfo_plugins.h"
35 35
36/**
37 * Prefix that every HELLO URI must start with.
38 */
39#define HELLO_URI_PREFIX "gnunet://hello/"
36 40
37/** 41/**
38 * Structure we use to collect printable address information. 42 * Structure we use to collect printable address information.
@@ -119,24 +123,20 @@ struct GetUriContext
119 123
120 124
121/** 125/**
122 * FIXME. 126 * Context for 'add_address_to_hello'.
123 */ 127 */
124struct GNUNET_PEERINFO_HelloAddressParsingContext 128struct GNUNET_PEERINFO_HelloAddressParsingContext
125{ 129{
126 /** 130 /**
127 * FIXME. 131 * Position in the URI with the next address to parse.
128 */
129 char *tmp;
130
131 /**
132 * FIXME.
133 */ 132 */
134 char *pos; 133 const char *pos;
135 134
136 /** 135 /**
137 * FIXME. 136 * Set to GNUNET_SYSERR to indicate parse errors.
138 */ 137 */
139 size_t tmp_len; 138 int ret;
139
140}; 140};
141 141
142 142
@@ -408,6 +408,7 @@ compose_uri (void *cls, const struct GNUNET_HELLO_Address *address,
408 struct GNUNET_TRANSPORT_PluginFunctions *papi; 408 struct GNUNET_TRANSPORT_PluginFunctions *papi;
409 const char *addr; 409 const char *addr;
410 char *ret; 410 char *ret;
411 char tbuf[16];
411 struct tm *t; 412 struct tm *t;
412 time_t seconds; 413 time_t seconds;
413 414
@@ -429,15 +430,13 @@ compose_uri (void *cls, const struct GNUNET_HELLO_Address *address,
429 return GNUNET_OK; 430 return GNUNET_OK;
430 seconds = expiration.abs_value / 1000; 431 seconds = expiration.abs_value / 1000;
431 t = gmtime (&seconds); 432 t = gmtime (&seconds);
433 GNUNET_assert (0 != strftime (tbuf, sizeof (tbuf),
434 "%Y%m%d%H%M%S",
435 t));
432 GNUNET_asprintf (&ret, 436 GNUNET_asprintf (&ret,
433 "%s!%04u%02u%02u%02u%02u%02u!%s!%s", 437 "%s!%s!%s!%s",
434 guc->uri, 438 guc->uri,
435 t->tm_year, 439 tbuf,
436 t->tm_mon,
437 t->tm_mday,
438 t->tm_hour,
439 t->tm_min,
440 t->tm_sec,
441 address->transport_name, 440 address->transport_name,
442 addr); 441 addr);
443 GNUNET_free (guc->uri); 442 GNUNET_free (guc->uri);
@@ -463,230 +462,180 @@ print_my_uri (void *cls, const struct GNUNET_PeerIdentity *peer,
463 462
464 if (peer == NULL) 463 if (peer == NULL)
465 { 464 {
465 pic = NULL;
466 if (err_msg != NULL) 466 if (err_msg != NULL)
467 FPRINTF (stderr, 467 FPRINTF (stderr,
468 _("Error in communication with PEERINFO service: %s\n"), 468 _("Error in communication with PEERINFO service: %s\n"),
469 err_msg); 469 err_msg);
470 GNUNET_free_non_null (guc->uri);
471 GNUNET_free (guc);
472 tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL);
473 return;
470 } 474 }
471 else 475 if (NULL != hello)
472 { 476 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &compose_uri, guc);
473 if (NULL != hello) 477 printf ("%s\n", (const char *) guc->uri);
474 GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &compose_uri, guc);
475 printf ("%s\n", (const char *) guc->uri);
476 }
477 GNUNET_free (guc->uri);
478 GNUNET_free (guc);
479 tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL);
480} 478}
481 479
482 480
483/* ************************* import HELLO by URI ********************* */ 481/* ************************* import HELLO by URI ********************* */
484 482
485 483
484/**
485 * We're building a HELLO. Parse the next address from the
486 * parsing context and append it.
487 *
488 * @param cls the 'struct GNUNET_PEERINFO_HelloAddressParsingContext'
489 * @param max number of bytes available for HELLO construction
490 * @param buffer where to copy the next address (in binary format)
491 * @return number of bytes added to buffer
492 */
486static size_t 493static size_t
487add_addr_to_hello (void *cls, size_t max, void *buffer) 494add_address_to_hello (void *cls, size_t max, void *buffer)
488{ 495{
496 struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls;
497 const char *tname;
498 const char *address;
499 const char *end;
500 char *plugin_name;
489 struct tm expiration_time; 501 struct tm expiration_time;
490 char buf[5];
491 long l;
492 time_t expiration_seconds; 502 time_t expiration_seconds;
493 struct GNUNET_TIME_Absolute expire; 503 struct GNUNET_TIME_Absolute expire;
494
495 struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls;
496 char *exp1, *exp2;
497 struct GNUNET_TRANSPORT_PluginFunctions *papi; 504 struct GNUNET_TRANSPORT_PluginFunctions *papi;
498 void *addr; 505 void *addr;
499 size_t addr_len; 506 size_t addr_len;
507 struct GNUNET_HELLO_Address haddr;
508 size_t ret;
500 509
501 /* End of string */ 510 if (NULL == ctx->pos)
502 if (ctx->pos - ctx->tmp == ctx->tmp_len)
503 return 0;
504
505 /* Parsed past the end of string, OR wrong format */
506 if ((ctx->pos - ctx->tmp > ctx->tmp_len) || ctx->pos[0] != '!')
507 {
508 GNUNET_break (0);
509 return 0; 511 return 0;
510 } 512 if ('!' != ctx->pos[0])
511
512 /* Not enough bytes (3 for three '!', 14 for expiration date, and
513 * at least 1 for type and 1 for address (1-byte long address is a joke,
514 * but it is not completely unrealistic. Zero-length address is.
515 */
516 if (ctx->tmp_len - (ctx->pos - ctx->tmp) < 1 /*!*/ * 3 + 14 + /* at least */ 2)
517 { 513 {
518 GNUNET_break (0); 514 ctx->ret = GNUNET_SYSERR;
519 return 0; 515 return 0;
520 } 516 }
521 /* Go past the first '!', now we're on expiration date */ 517 tname = strptime (ctx->pos,
522 ctx->pos += 1; 518 "%Y%m%d%H%M%S",
523 /* Its length is known, so check for the next '!' right away */ 519 &expiration_time);
524 if (ctx->pos[14] != '!') 520 if (NULL == tname)
525 { 521 {
526 GNUNET_break (0); 522 ctx->ret = GNUNET_SYSERR;
527 return 0; 523 return 0;
528 } 524 }
529
530 memset (&expiration_time, 0, sizeof (struct tm));
531
532 /* This is FAR more strict than strptime(ctx->pos, "%Y%m%d%H%M%S", ...); */
533 /* FIXME: make it a separate function, since expiration is specified to every address */
534#define GETNDIGITS(n,cond) \
535 strncpy (buf, &ctx->pos[0], n); \
536 buf[n] = '\0'; \
537 errno = 0; \
538 l = strtol (buf, NULL, 10); \
539 if (errno != 0 || cond) \
540 { \
541 GNUNET_break (0); \
542 return 0; \
543 } \
544 ctx->pos += n;
545
546 GETNDIGITS (4, l < 1900)
547 expiration_time.tm_year = l - 1900;
548
549 GETNDIGITS (2, l < 1 || l > 12)
550 expiration_time.tm_mon = l;
551
552 GETNDIGITS (2, l < 1 || l > 31)
553 expiration_time.tm_mday = l;
554
555 GETNDIGITS (2, l < 0 || l > 23)
556 expiration_time.tm_hour = l;
557
558 GETNDIGITS (2, l < 0 || l > 59)
559 expiration_time.tm_min = l;
560
561 /* 60 - with a leap second */
562 GETNDIGITS (2, l < 0 || l > 60)
563 expiration_time.tm_sec = l;
564
565 expiration_time.tm_isdst = -1;
566
567#undef GETNDIGITS
568
569 expiration_seconds = mktime (&expiration_time); 525 expiration_seconds = mktime (&expiration_time);
570 if (expiration_seconds == (time_t) -1) 526 if (expiration_seconds == (time_t) -1)
571 { 527 {
572 GNUNET_break (0); 528 ctx->ret = GNUNET_SYSERR;
573 return 0; 529 return 0;
574 } 530 }
575 expire.abs_value = expiration_seconds * 1000; 531 expire.abs_value = expiration_seconds * 1000;
576 532 if ('!' != tname[0])
577 /* Now we're at '!', advance to the transport type */
578 ctx->pos += 1;
579
580 /* Find the next '!' that separates transport type from
581 * the address
582 */
583 exp1 = strstr (ctx->pos, "!");
584 if (exp1 == NULL)
585 { 533 {
586 GNUNET_break (0); 534 ctx->ret = GNUNET_SYSERR;
587 return 0; 535 return 0;
588 } 536 }
589 /* We need it 0-terminated */ 537 tname++;
590 exp1[0] = '\0'; 538 address = strchr (tname, (int) '!');
591 /* Find the '!' that separates address from the next record. 539 if (NULL == address)
592 * It might not be there, if this is the last record. 540 {
593 */ 541 ctx->ret = GNUNET_SYSERR;
594 exp2 = strstr (&exp1[1], "!"); 542 return 0;
595 if (exp2 == NULL) 543 }
596 exp2 = &ctx->tmp[ctx->tmp_len]; 544 address++;
597 545 end = strchr (address, (int) '!');
598 papi = GPI_plugins_find (ctx->pos); 546 if (NULL == end)
599 if (papi == NULL) 547 {
548 ctx->pos = NULL;
549 end = address + strlen (address);
550 }
551 else
552 {
553 ctx->pos = end;
554 }
555 plugin_name = GNUNET_strndup (tname, address - tname);
556 papi = GPI_plugins_find (plugin_name);
557 if (NULL == papi)
600 { 558 {
601 /* Not an error - we might just not have the right plugin. 559 /* Not an error - we might just not have the right plugin.
602 * Skip this part, advance to the next one and recurse. 560 * Skip this part, advance to the next one and recurse.
603 * But only if this is not the end of string. 561 * But only if this is not the end of string.
604 */ 562 */
605 ctx->pos = exp2 + 1; 563 GNUNET_free (plugin_name);
606 if (ctx->pos - ctx->tmp >= ctx->tmp_len) 564 return 0;
607 return 0;
608 return add_addr_to_hello (cls, max, buffer);
609 } 565 }
610 if (NULL == papi->string_to_address) 566 if (NULL == papi->string_to_address)
611 { 567 {
612 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 568 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
613 _("Plugin `%s' does not support URIs yet\n"), 569 _("Plugin `%s' does not support URIs yet\n"),
614 ctx->pos); 570 ctx->pos);
615 ctx->pos = exp2 + 1; 571 GNUNET_free (plugin_name);
616 if (ctx->pos - ctx->tmp >= ctx->tmp_len) 572 return 0;
617 return 0;
618 return add_addr_to_hello (cls, max, buffer);
619 } 573 }
620 if ((papi->string_to_address != NULL) && (GNUNET_OK == 574 if (GNUNET_OK !=
621 papi->string_to_address (papi->cls, &exp1[1], exp2 - &exp1[1], &addr, 575 papi->string_to_address (papi->cls,
622 &addr_len))) 576 address,
577 end - address,
578 &addr,
579 &addr_len))
623 { 580 {
624 struct GNUNET_HELLO_Address address; 581 GNUNET_free (plugin_name);
625 int ret; 582 return GNUNET_SYSERR;
626
627 /* address.peer is unset - not used by add_address() */
628 address.address_length = addr_len;
629 address.address = addr;
630 address.transport_name = ctx->pos;
631 ret = GNUNET_HELLO_add_address (&address, expire, buffer, max);
632 GNUNET_free (addr);
633 ctx->pos = exp2;
634 return ret;
635 } 583 }
636 return 0; 584 /* address.peer is unset - not used by add_address() */
585 haddr.address_length = addr_len;
586 haddr.address = addr;
587 haddr.transport_name = plugin_name;
588 ret = GNUNET_HELLO_add_address (&haddr, expire, buffer, max);
589 GNUNET_free (addr);
590 GNUNET_free (plugin_name);
591 return ret;
637} 592}
638 593
639 594
640static void 595/**
641parse_hello (const struct GNUNET_CONFIGURATION_Handle *c, 596 * Parse the PUT URI given at the command line and add it to our peerinfo
642 const char *put_uri) 597 * database.
598 *
599 * @param put_uri URI string to parse
600 * @return GNUNET_OK on success, GNUNET_SYSERR if the URI was invalid, GNUNET_NO on other errors
601 */
602static int
603parse_hello_uri (const char *put_uri)
643{ 604{
644 int r; 605 const char *pks;
645 char *scheme_part = NULL; 606 const char *exc;
646 char *path_part = NULL;
647 char *exc;
648 int std_result;
649 struct GNUNET_HELLO_Message *hello; 607 struct GNUNET_HELLO_Message *hello;
650 struct GNUNET_PEERINFO_HelloAddressParsingContext ctx; 608 struct GNUNET_PEERINFO_HelloAddressParsingContext ctx;
651 609
652 r = GNUNET_STRINGS_parse_uri (put_uri, &scheme_part, (const char **) &path_part); 610 if (0 != strncmp (put_uri,
653 if (r == GNUNET_NO) 611 HELLO_URI_PREFIX,
654 return; 612 strlen (HELLO_URI_PREFIX)))
655 if (scheme_part == NULL || strcmp (scheme_part, "gnunet://") != 0) 613 return GNUNET_SYSERR;
656 { 614 pks = &put_uri[strlen (HELLO_URI_PREFIX)];
657 GNUNET_free_non_null (scheme_part); 615 exc = strstr (pks, "!");
658 return; 616 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pks,
659 } 617 (NULL == exc) ? strlen (pks) : (exc - pks),
660 GNUNET_free (scheme_part); 618 (unsigned char *) &my_public_key,
661 619 sizeof (my_public_key)))
662 if (strncmp (path_part, "hello/", 6) != 0) 620 return GNUNET_SYSERR;
663 return;
664
665 path_part = &path_part[6];
666 ctx.tmp = GNUNET_strdup (path_part);
667 ctx.tmp_len = strlen (path_part);
668 exc = strstr (ctx.tmp, "!");
669 if (exc == NULL)
670 exc = ctx.tmp + ctx.tmp_len;
671 ctx.pos = exc; 621 ctx.pos = exc;
622 ctx.ret = GNUNET_OK;
623 hello = GNUNET_HELLO_create (&my_public_key, &add_address_to_hello, &ctx);
672 624
673 std_result = GNUNET_STRINGS_string_to_data (ctx.tmp, exc - ctx.tmp, 625 if (NULL != hello)
674 (unsigned char *) &my_public_key, sizeof (my_public_key));
675 if (std_result != GNUNET_OK)
676 { 626 {
677 GNUNET_free (ctx.tmp); 627 /* WARNING: this adds the address from URI WITHOUT verification! */
678 return; 628 if (GNUNET_OK == ctx.ret)
629 GNUNET_PEERINFO_add_peer (peerinfo, hello);
630 GNUNET_free (hello);
679 } 631 }
680 632
681 hello = GNUNET_HELLO_create (&my_public_key, add_addr_to_hello, &ctx);
682 GNUNET_free (ctx.tmp);
683
684 /* WARNING: this adds the address from URI WITHOUT verification! */
685 GNUNET_PEERINFO_add_peer (peerinfo, hello);
686 GNUNET_free (hello);
687 /* wait 1s to give peerinfo operation a chance to succeed */ 633 /* wait 1s to give peerinfo operation a chance to succeed */
634 /* FIXME: current peerinfo API sucks to require this; not to mention
635 that we get no feedback to determine if the operation actually succeeded */
688 tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, 636 tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
689 &state_machine, NULL); 637 &state_machine, NULL);
638 return ctx.ret;
690} 639}
691 640
692 641
@@ -792,8 +741,6 @@ run (void *cls, char *const *args, const char *cfgfile,
792 } 741 }
793 GNUNET_free (fn); 742 GNUNET_free (fn);
794 GNUNET_CRYPTO_rsa_key_get_public (priv, &my_public_key); 743 GNUNET_CRYPTO_rsa_key_get_public (priv, &my_public_key);
795 fprintf (stderr, "PK: `%s\n",
796 GNUNET_CRYPTO_rsa_public_key_to_string (&my_public_key));
797 GNUNET_CRYPTO_rsa_key_free (priv); 744 GNUNET_CRYPTO_rsa_key_free (priv);
798 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_peer_identity.hashPubKey); 745 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), &my_peer_identity.hashPubKey);
799 } 746 }
@@ -821,7 +768,10 @@ state_machine (void *cls,
821 if (NULL != put_uri) 768 if (NULL != put_uri)
822 { 769 {
823 GPI_plugins_load (cfg); 770 GPI_plugins_load (cfg);
824 parse_hello (cfg, put_uri); 771 if (GNUNET_SYSERR == parse_hello_uri (put_uri))
772 fprintf (stderr,
773 _("Invalid URI `%s'\n"),
774 put_uri);
825 put_uri = NULL; 775 put_uri = NULL;
826 return; 776 return;
827 } 777 }
@@ -853,7 +803,8 @@ state_machine (void *cls,
853 guc = GNUNET_malloc (sizeof (struct GetUriContext)); 803 guc = GNUNET_malloc (sizeof (struct GetUriContext));
854 pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&my_public_key); 804 pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&my_public_key);
855 GNUNET_asprintf (&guc->uri, 805 GNUNET_asprintf (&guc->uri,
856 "gnunet://hello/%s", 806 "%s%s",
807 HELLO_URI_PREFIX,
857 pkey); 808 pkey);
858 GNUNET_free (pkey); 809 GNUNET_free (pkey);
859 GPI_plugins_load (cfg); 810 GPI_plugins_load (cfg);