diff options
-rw-r--r-- | src/peerinfo-tool/Makefile.am | 2 | ||||
-rw-r--r-- | src/peerinfo-tool/gnunet-peerinfo.c | 311 |
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 | ||
15 | gnunet_peerinfo_SOURCES = \ | 15 | gnunet_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 | ||
19 | gnunet_peerinfo_LDADD = \ | 19 | gnunet_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 | */ |
124 | struct GNUNET_PEERINFO_HelloAddressParsingContext | 128 | struct 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 | */ | ||
486 | static size_t | 493 | static size_t |
487 | add_addr_to_hello (void *cls, size_t max, void *buffer) | 494 | add_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 | ||
640 | static void | 595 | /** |
641 | parse_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 | */ | ||
602 | static int | ||
603 | parse_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); |