diff options
author | Gabor X Toth <*@tg-x.net> | 2012-11-18 18:09:34 +0000 |
---|---|---|
committer | Gabor X Toth <*@tg-x.net> | 2012-11-18 18:09:34 +0000 |
commit | a618961d96910d622476341e7efdf6d1180acdd3 (patch) | |
tree | 0b6b383f354d1a27b5259a993723cc5a60dced8b /src/hello/hello.c | |
parent | ff6b5bb3cfeeaaf353bf734c09619c4adbd02ee6 (diff) | |
download | gnunet-a618961d96910d622476341e7efdf6d1180acdd3.tar.gz gnunet-a618961d96910d622476341e7efdf6d1180acdd3.zip |
moved hello uri functions to hello lib
Diffstat (limited to 'src/hello/hello.c')
-rw-r--r-- | src/hello/hello.c | 358 |
1 files changed, 356 insertions, 2 deletions
diff --git a/src/hello/hello.c b/src/hello/hello.c index 6529c9333..428c4139c 100644 --- a/src/hello/hello.c +++ b/src/hello/hello.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "gnunet_hello_lib.h" | 27 | #include "gnunet_hello_lib.h" |
28 | #include "gnunet_protocols.h" | 28 | #include "gnunet_protocols.h" |
29 | #include "gnunet_util_lib.h" | 29 | #include "gnunet_util_lib.h" |
30 | #include "gnunet_transport_plugin.h" | ||
30 | 31 | ||
31 | GNUNET_NETWORK_STRUCT_BEGIN | 32 | GNUNET_NETWORK_STRUCT_BEGIN |
32 | 33 | ||
@@ -63,6 +64,46 @@ struct GNUNET_HELLO_Message | |||
63 | }; | 64 | }; |
64 | GNUNET_NETWORK_STRUCT_END | 65 | GNUNET_NETWORK_STRUCT_END |
65 | 66 | ||
67 | |||
68 | /** | ||
69 | * Context used for building our own URI. | ||
70 | */ | ||
71 | struct GNUNET_HELLO_ComposeUriContext | ||
72 | { | ||
73 | /** | ||
74 | * Final URI. | ||
75 | */ | ||
76 | char *uri; | ||
77 | |||
78 | /** | ||
79 | * Function for finding transport plugins by name. | ||
80 | */ | ||
81 | GNUNET_HELLO_TransportPluginsFind plugins_find; | ||
82 | }; | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Context for 'add_address_to_hello'. | ||
87 | */ | ||
88 | struct GNUNET_HELLO_ParseUriContext | ||
89 | { | ||
90 | /** | ||
91 | * Position in the URI with the next address to parse. | ||
92 | */ | ||
93 | const char *pos; | ||
94 | |||
95 | /** | ||
96 | * Set to GNUNET_SYSERR to indicate parse errors. | ||
97 | */ | ||
98 | int ret; | ||
99 | |||
100 | /** | ||
101 | * Function for finding transport plugins by name. | ||
102 | */ | ||
103 | GNUNET_HELLO_TransportPluginsFind plugins_find; | ||
104 | }; | ||
105 | |||
106 | |||
66 | /** | 107 | /** |
67 | * Copy the given address information into | 108 | * Copy the given address information into |
68 | * the given buffer using the format of HELLOs. | 109 | * the given buffer using the format of HELLOs. |
@@ -650,10 +691,10 @@ GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg) | |||
650 | * | 691 | * |
651 | * The concrete URI format is: | 692 | * The concrete URI format is: |
652 | * | 693 | * |
653 | * "gnunet://hello/PEER[!YYYYMMDDHHNNSS!<TYPE>!<ADDRESS>]...". | 694 | * "gnunet://hello/PEER[!YYYYMMDDHHMMSS!<TYPE>!<ADDRESS>]...". |
654 | * These URIs can be used to add a peer record to peerinfo service. | 695 | * These URIs can be used to add a peer record to peerinfo service. |
655 | * PEER is the string representation of peer's public key. | 696 | * PEER is the string representation of peer's public key. |
656 | * YYYYMMDDHHNNSS is the expiration date. | 697 | * YYYYMMDDHHMMSS is the expiration date. |
657 | * TYPE is a transport type. | 698 | * TYPE is a transport type. |
658 | * ADDRESS is the address, its format depends upon the transport type. | 699 | * ADDRESS is the address, its format depends upon the transport type. |
659 | * The concrete transport types and corresponding address formats are: | 700 | * The concrete transport types and corresponding address formats are: |
@@ -683,4 +724,317 @@ GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg) | |||
683 | * <p> | 724 | * <p> |
684 | */ | 725 | */ |
685 | 726 | ||
727 | |||
728 | /* ************************* Compose HELLO URI ************************** */ | ||
729 | |||
730 | |||
731 | /** | ||
732 | * Replace all characters in the input 'in' according | ||
733 | * to the mapping. The mapping says to map each character | ||
734 | * in 'oldchars' to the corresponding character (by offset) | ||
735 | * in 'newchars'. | ||
736 | * | ||
737 | * @param in input string to remap | ||
738 | * @param oldchars characters to replace | ||
739 | * @param newchars replacement characters, must have same length as 'oldchars' | ||
740 | * @return copy of string with replacement applied. | ||
741 | */ | ||
742 | static char * | ||
743 | map_characters (const char *in, | ||
744 | const char *oldchars, | ||
745 | const char *newchars) | ||
746 | { | ||
747 | char *ret; | ||
748 | const char *off; | ||
749 | size_t i; | ||
750 | |||
751 | GNUNET_assert (strlen (oldchars) == strlen (newchars)); | ||
752 | ret = GNUNET_strdup (in); | ||
753 | i = 0; | ||
754 | while (ret[i] != '\0') | ||
755 | { | ||
756 | off = strchr (oldchars, ret[i]); | ||
757 | if (NULL != off) | ||
758 | ret[i] = newchars[off - oldchars]; | ||
759 | i++; | ||
760 | } | ||
761 | return ret; | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Function that is called on each address of this peer. | ||
767 | * Expands the corresponding URI string. | ||
768 | * | ||
769 | * @param cls the 'GNUNET_HELLO_GetUriContext' | ||
770 | * @param address address to add | ||
771 | * @param expiration expiration time for the address | ||
772 | * @param plugins_find Function to find transport plugins by name | ||
773 | * @return GNUNET_OK (continue iteration). | ||
774 | */ | ||
775 | static int | ||
776 | add_address_to_uri (void *cls, const struct GNUNET_HELLO_Address *address, | ||
777 | struct GNUNET_TIME_Absolute expiration) | ||
778 | { | ||
779 | struct GNUNET_HELLO_ComposeUriContext *ctx = cls; | ||
780 | struct GNUNET_TRANSPORT_PluginFunctions *papi; | ||
781 | const char *addr; | ||
782 | char *uri_addr; | ||
783 | char *ret; | ||
784 | char tbuf[16] = ""; | ||
785 | struct tm *t; | ||
786 | time_t seconds; | ||
787 | |||
788 | papi = ctx->plugins_find (address->transport_name); | ||
789 | if (papi == NULL) | ||
790 | { | ||
791 | /* Not an error - we might just not have the right plugin. */ | ||
792 | return GNUNET_OK; | ||
793 | } | ||
794 | if (NULL == papi->address_to_string) | ||
795 | { | ||
796 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
797 | "URI conversion not implemented for plugin `%s'\n", | ||
798 | address->transport_name); | ||
799 | return GNUNET_OK; | ||
800 | } | ||
801 | addr = papi->address_to_string (papi->cls, address->address, address->address_length); | ||
802 | if ( (addr == NULL) || (strlen(addr) == 0) ) | ||
803 | return GNUNET_OK; | ||
804 | /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved | ||
805 | characters in URIs */ | ||
806 | uri_addr = map_characters (addr, "[]", "()"); | ||
807 | seconds = expiration.abs_value / 1000; | ||
808 | t = gmtime (&seconds); | ||
809 | |||
810 | GNUNET_asprintf (&ret, | ||
811 | "%s!%s!%s!%s", | ||
812 | ctx->uri, | ||
813 | strftime (tbuf, sizeof (tbuf), "%Y%m%d%H%M%S", t) ? tbuf : "0", | ||
814 | address->transport_name, | ||
815 | uri_addr); | ||
816 | GNUNET_free (uri_addr); | ||
817 | GNUNET_free (ctx->uri); | ||
818 | ctx->uri = ret; | ||
819 | return GNUNET_OK; | ||
820 | } | ||
821 | |||
822 | |||
823 | /** | ||
824 | * Compose a hello URI string from a hello message. | ||
825 | * | ||
826 | * @param hello Hello message | ||
827 | * @param plugins_find Function to find transport plugins by name | ||
828 | * @return Hello URI string | ||
829 | */ | ||
830 | char * | ||
831 | GNUNET_HELLO_compose_uri (const struct GNUNET_HELLO_Message *hello, | ||
832 | GNUNET_HELLO_TransportPluginsFind plugins_find) | ||
833 | { | ||
834 | struct GNUNET_HELLO_ComposeUriContext ctx; | ||
835 | ctx.plugins_find = plugins_find; | ||
836 | |||
837 | char *pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&(hello->publicKey)); | ||
838 | GNUNET_asprintf (&(ctx.uri), | ||
839 | "%s%s", | ||
840 | GNUNET_HELLO_URI_PREFIX, | ||
841 | pkey); | ||
842 | GNUNET_free (pkey); | ||
843 | |||
844 | GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &add_address_to_uri, &ctx); | ||
845 | return ctx.uri; | ||
846 | } | ||
847 | |||
848 | |||
849 | /* ************************* Parse HELLO URI ********************* */ | ||
850 | |||
851 | |||
852 | /** | ||
853 | * We're building a HELLO. Parse the next address from the | ||
854 | * parsing context and append it. | ||
855 | * | ||
856 | * @param cls the 'struct GNUNET_HELLO_AddressParsingContext' | ||
857 | * @param max number of bytes available for HELLO construction | ||
858 | * @param buffer where to copy the next address (in binary format) | ||
859 | * @return number of bytes added to buffer | ||
860 | */ | ||
861 | static size_t | ||
862 | add_address_to_hello (void *cls, size_t max, void *buffer) | ||
863 | { | ||
864 | struct GNUNET_HELLO_ParseUriContext *ctx = cls; | ||
865 | const char *tname; | ||
866 | const char *address; | ||
867 | char *uri_address; | ||
868 | char *plugin_address; | ||
869 | const char *end; | ||
870 | char *plugin_name; | ||
871 | struct tm expiration_time; | ||
872 | time_t expiration_seconds; | ||
873 | struct GNUNET_TIME_Absolute expire; | ||
874 | struct GNUNET_TRANSPORT_PluginFunctions *papi; | ||
875 | void *addr; | ||
876 | size_t addr_len; | ||
877 | struct GNUNET_HELLO_Address haddr; | ||
878 | size_t ret; | ||
879 | |||
880 | if (NULL == ctx->pos) | ||
881 | return 0; | ||
882 | if ('!' != ctx->pos[0]) | ||
883 | { | ||
884 | ctx->ret = GNUNET_SYSERR; | ||
885 | GNUNET_break (0); | ||
886 | return 0; | ||
887 | } | ||
888 | ctx->pos++; | ||
889 | |||
890 | if ('0' == ctx->pos[0] && '!' == ctx->pos[1]) | ||
891 | { | ||
892 | expire = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
893 | tname = ctx->pos + 1; | ||
894 | } | ||
895 | else | ||
896 | { | ||
897 | memset (&expiration_time, 0, sizeof (expiration_time)); | ||
898 | tname = strptime (ctx->pos, | ||
899 | "%Y%m%d%H%M%S", | ||
900 | &expiration_time); | ||
901 | if (NULL == tname) | ||
902 | { | ||
903 | ctx->ret = GNUNET_SYSERR; | ||
904 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
905 | _("Failed to parse HELLO message: missing expiration time\n")); | ||
906 | GNUNET_break (0); | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | expiration_seconds = mktime (&expiration_time); | ||
911 | if (expiration_seconds == (time_t) -1) | ||
912 | { | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
914 | _("Failed to parse HELLO message: invalid expiration time\n")); | ||
915 | ctx->ret = GNUNET_SYSERR; | ||
916 | GNUNET_break (0); | ||
917 | return 0; | ||
918 | } | ||
919 | expire.abs_value = expiration_seconds * 1000; | ||
920 | } | ||
921 | if ('!' != tname[0]) | ||
922 | { | ||
923 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
924 | _("Failed to parse HELLO message: malformed\n")); | ||
925 | ctx->ret = GNUNET_SYSERR; | ||
926 | GNUNET_break (0); | ||
927 | return 0; | ||
928 | } | ||
929 | tname++; | ||
930 | address = strchr (tname, (int) '!'); | ||
931 | if (NULL == address) | ||
932 | { | ||
933 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
934 | _("Failed to parse HELLO message: missing transport plugin\n")); | ||
935 | ctx->ret = GNUNET_SYSERR; | ||
936 | GNUNET_break (0); | ||
937 | return 0; | ||
938 | } | ||
939 | address++; | ||
940 | end = strchr (address, (int) '!'); | ||
941 | ctx->pos = end; | ||
942 | plugin_name = GNUNET_strndup (tname, address - (tname+1)); | ||
943 | papi = ctx->plugins_find (plugin_name); | ||
944 | if (NULL == papi) | ||
945 | { | ||
946 | /* Not an error - we might just not have the right plugin. | ||
947 | * Skip this part, advance to the next one and recurse. | ||
948 | * But only if this is not the end of string. | ||
949 | */ | ||
950 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
951 | _("Plugin `%s' not found\n"), | ||
952 | plugin_name); | ||
953 | GNUNET_free (plugin_name); | ||
954 | GNUNET_break (0); | ||
955 | return 0; | ||
956 | } | ||
957 | if (NULL == papi->string_to_address) | ||
958 | { | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
960 | _("Plugin `%s' does not support URIs yet\n"), | ||
961 | plugin_name); | ||
962 | GNUNET_free (plugin_name); | ||
963 | GNUNET_break (0); | ||
964 | return 0; | ||
965 | } | ||
966 | uri_address = GNUNET_strndup (address, end - address); | ||
967 | /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved | ||
968 | characters in URIs; need to convert back to '[]' for the plugin */ | ||
969 | plugin_address = map_characters (uri_address, "()", "[]"); | ||
970 | GNUNET_free (uri_address); | ||
971 | if (GNUNET_OK != | ||
972 | papi->string_to_address (papi->cls, | ||
973 | plugin_address, | ||
974 | strlen (plugin_address) + 1, | ||
975 | &addr, | ||
976 | &addr_len)) | ||
977 | { | ||
978 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
979 | _("Failed to parse `%s' as an address for plugin `%s'\n"), | ||
980 | plugin_address, | ||
981 | plugin_name); | ||
982 | GNUNET_free (plugin_name); | ||
983 | GNUNET_free (plugin_address); | ||
984 | return 0; | ||
985 | } | ||
986 | GNUNET_free (plugin_address); | ||
987 | /* address.peer is unset - not used by add_address() */ | ||
988 | haddr.address_length = addr_len; | ||
989 | haddr.address = addr; | ||
990 | haddr.transport_name = plugin_name; | ||
991 | ret = GNUNET_HELLO_add_address (&haddr, expire, buffer, max); | ||
992 | GNUNET_free (addr); | ||
993 | GNUNET_free (plugin_name); | ||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | |||
998 | /** | ||
999 | * Parse a hello URI string to a hello message. | ||
1000 | * | ||
1001 | * @param uri URI string to parse | ||
1002 | * @param pubkey Pointer to struct where public key is parsed | ||
1003 | * @param hello Pointer to struct where hello message is parsed | ||
1004 | * @param plugins_find Function to find transport plugins by name | ||
1005 | * @return GNUNET_OK on success, GNUNET_SYSERR if the URI was invalid, GNUNET_NO on other errors | ||
1006 | */ | ||
1007 | int | ||
1008 | GNUNET_HELLO_parse_uri (const char *uri, | ||
1009 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey, | ||
1010 | struct GNUNET_HELLO_Message **hello, | ||
1011 | GNUNET_HELLO_TransportPluginsFind plugins_find) | ||
1012 | { | ||
1013 | const char *pks; | ||
1014 | const char *exc; | ||
1015 | struct GNUNET_HELLO_ParseUriContext ctx; | ||
1016 | |||
1017 | if (0 != strncmp (uri, | ||
1018 | GNUNET_HELLO_URI_PREFIX, | ||
1019 | strlen (GNUNET_HELLO_URI_PREFIX))) | ||
1020 | return GNUNET_SYSERR; | ||
1021 | pks = &uri[strlen (GNUNET_HELLO_URI_PREFIX)]; | ||
1022 | exc = strstr (pks, "!"); | ||
1023 | |||
1024 | if (GNUNET_OK != | ||
1025 | GNUNET_STRINGS_string_to_data (pks, | ||
1026 | (NULL == exc) ? strlen (pks) : (exc - pks), | ||
1027 | (unsigned char *) pubkey, | ||
1028 | sizeof (*pubkey))) | ||
1029 | return GNUNET_SYSERR; | ||
1030 | |||
1031 | ctx.pos = exc; | ||
1032 | ctx.ret = GNUNET_OK; | ||
1033 | ctx.plugins_find = plugins_find; | ||
1034 | *hello = GNUNET_HELLO_create (pubkey, &add_address_to_hello, &ctx); | ||
1035 | |||
1036 | return ctx.ret; | ||
1037 | } | ||
1038 | |||
1039 | |||
686 | /* end of hello.c */ | 1040 | /* end of hello.c */ |