aboutsummaryrefslogtreecommitdiff
path: root/src/hello/hello.c
diff options
context:
space:
mode:
authorGabor X Toth <*@tg-x.net>2012-11-18 18:09:34 +0000
committerGabor X Toth <*@tg-x.net>2012-11-18 18:09:34 +0000
commita618961d96910d622476341e7efdf6d1180acdd3 (patch)
tree0b6b383f354d1a27b5259a993723cc5a60dced8b /src/hello/hello.c
parentff6b5bb3cfeeaaf353bf734c09619c4adbd02ee6 (diff)
downloadgnunet-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.c358
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
31GNUNET_NETWORK_STRUCT_BEGIN 32GNUNET_NETWORK_STRUCT_BEGIN
32 33
@@ -63,6 +64,46 @@ struct GNUNET_HELLO_Message
63}; 64};
64GNUNET_NETWORK_STRUCT_END 65GNUNET_NETWORK_STRUCT_END
65 66
67
68/**
69 * Context used for building our own URI.
70 */
71struct 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 */
88struct 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 */
742static char *
743map_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 */
775static int
776add_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 */
830char *
831GNUNET_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 */
861static size_t
862add_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 */
1007int
1008GNUNET_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 */