gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r20287 - in gnunet/src: hello include peerinfo-tool transpo


From: gnunet
Subject: [GNUnet-SVN] r20287 - in gnunet/src: hello include peerinfo-tool transport
Date: Mon, 5 Mar 2012 20:56:16 +0100

Author: grothoff
Date: 2012-03-05 20:56:16 +0100 (Mon, 05 Mar 2012)
New Revision: 20287

Modified:
   gnunet/src/hello/hello.c
   gnunet/src/include/gnunet_transport_plugin.h
   gnunet/src/peerinfo-tool/Makefile.am
   gnunet/src/peerinfo-tool/gnunet-peerinfo.c
   gnunet/src/transport/plugin_transport_tcp.c
   gnunet/src/transport/transport.h
Log:
-LRN: experimental HELLO URIs

Modified: gnunet/src/hello/hello.c
===================================================================
--- gnunet/src/hello/hello.c    2012-03-05 19:54:31 UTC (rev 20286)
+++ gnunet/src/hello/hello.c    2012-03-05 19:56:16 UTC (rev 20287)
@@ -641,5 +641,46 @@
   return ret;
 }
 
+/**
+ * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER".
+ * The specific structure of "IDENTIFIER" depends on the module and
+ * maybe differenciated into additional subcategories if applicable.
+ * This module only deals with hello identifiers (MODULE = "hello").
+ * <p>
+ * 
+ * The concrete URI format is:
+ * 
+ * "gnunet://hello/PEER[!YYYYMMDDHHNNSS!<TYPE>!<ADDRESS>]...".
+ * These URIs can be used to add a peer record to peerinfo service.
+ * PEER is the string representation of peer's public key.
+ * YYYYMMDDHHNNSS is the expiration date.
+ * TYPE is a transport type.
+ * ADDRESS is the address, its format depends upon the transport type.
+ * The concrete transport types and corresponding address formats are:
+ * 
+ * <ul><li>
+ * 
+ * <TCP|UDP>!IPADDRESS
+ * IPVDDRESS is either IPV4 .-delimited address in form of 
XXX.XXX.XXX.XXX:PPPPP
+ * or IPV6 :-delimited address, but with '(' and ')' instead of '[' and ']' 
(RFC2396 advises against using square brackets in URIs):
+ * (XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX):PPPPP
+ * PPPPP is the port number. May be 0.
+ * 
+ * </li><li>
+ * 
+ * [add SMTP, HTTP and other addresses here]
+ * 
+ * </li></ul>
+ * 
+ * The encoding for hexadecimal values is defined in the crypto_hash.c
+ * module in the gnunetutil library and discussed there.
+ * 
+ * Examples:
+ * 
+ * 
gnunet://hello/0430205UC7D56PTQK8NV05776671CNN44FK4TL6D0GQ35OMF8MEN4RNMKA5UF6AL3DQO8B1SC5AQF50SQ2MABIRU4HC8H2HAJKJ59JL1JVRJAK308F9GASRFLMGUBB5TQ5AKR94AS5T3MDG8B9O1EMPRKB0HVCG7T6QPP4CDJ913LAEHVJ2DI1TOBB15Q1JIT5ARBOD12U4SIGRFDV3Q7T66G4TBVSJJ90UQF1BG29TGJJKLGEIMSPHHKO544D6EALQ4F2K0416311JC22GVAD48R616I7VK03K7MP7N0RS2MBV1TE9JV8CK1LSQMR7KCDRTLDA6917UGA67DHTGHERIACCGQ54TGSR48RMSGS9BA5HLMOKASFC1I6V4TT09TUGCU8GNDHQF0JF3H7LPV59UL5I38QID040G000!20120302010059!TCP!192.168.0.1:2086!TCP!64.23.8.174:0
+ * 
gnunet://hello/0430205UC7D56PTQK8NV05776671CNN44FK4TL6D0GQ35OMF8MEN4RNMKA5UF6AL3DQO8B1SC5AQF50SQ2MABIRU4HC8H2HAJKJ59JL1JVRJAK308F9GASRFLMGUBB5TQ5AKR94AS5T3MDG8B9O1EMPRKB0HVCG7T6QPP4CDJ913LAEHVJ2DI1TOBB15Q1JIT5ARBOD12U4SIGRFDV3Q7T66G4TBVSJJ90UQF1BG29TGJJKLGEIMSPHHKO544D6EALQ4F2K0416311JC22GVAD48R616I7VK03K7MP7N0RS2MBV1TE9JV8CK1LSQMR7KCDRTLDA6917UGA67DHTGHERIACCGQ54TGSR48RMSGS9BA5HLMOKASFC1I6V4TT09TUGCU8GNDHQF0JF3H7LPV59UL5I38QID040G000!20120302010059!TCP!(2001:db8:85a3:8d3:1319:8a2e:370:7348):2086
+ * 
+ * <p>
+ */
 
 /* end of hello.c */

Modified: gnunet/src/include/gnunet_transport_plugin.h
===================================================================
--- gnunet/src/include/gnunet_transport_plugin.h        2012-03-05 19:54:31 UTC 
(rev 20286)
+++ gnunet/src/include/gnunet_transport_plugin.h        2012-03-05 19:56:16 UTC 
(rev 20287)
@@ -423,7 +423,27 @@
                                                          const void *addr,
                                                          size_t addrlen);
 
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store a buffer pointer
+ *        If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @param max size of the buffer
+ * @param buf_len location to store buffer size.
+ *        If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+typedef int (*GNUNET_TRANSPORT_StringToAddress) (void *cls,
+                                                 const char *addr,
+                                                 uint16_t addrlen,
+                                                 void **buf,
+                                                 size_t *added);
 
+
 /**
  * Each plugin is required to return a pointer to a struct of this
  * type as the return value from its entry point.
@@ -477,6 +497,12 @@
   GNUNET_TRANSPORT_AddressToString address_to_string;
 
   /**
+   * Function that will be called to convert a string address
+   * to binary (numeric conversion only).
+   */
+  GNUNET_TRANSPORT_StringToAddress string_to_address;
+
+  /**
    * Function that will be called tell the plugin to create a session
    * object
    */

Modified: gnunet/src/peerinfo-tool/Makefile.am
===================================================================
--- gnunet/src/peerinfo-tool/Makefile.am        2012-03-05 19:54:31 UTC (rev 
20286)
+++ gnunet/src/peerinfo-tool/Makefile.am        2012-03-05 19:56:16 UTC (rev 
20287)
@@ -13,11 +13,14 @@
  gnunet-peerinfo 
 
 gnunet_peerinfo_SOURCES = \
- gnunet-peerinfo.c         
+ gnunet-peerinfo.c \
+ ../transport/gnunet-service-transport_plugins.c
+
 gnunet_peerinfo_LDADD = \
   $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
   $(top_builddir)/src/transport/libgnunettransport.la \
   $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la 
 
 if HAVE_PYTHON_PEXPECT

Modified: gnunet/src/peerinfo-tool/gnunet-peerinfo.c
===================================================================
--- gnunet/src/peerinfo-tool/gnunet-peerinfo.c  2012-03-05 19:54:31 UTC (rev 
20286)
+++ gnunet/src/peerinfo-tool/gnunet-peerinfo.c  2012-03-05 19:56:16 UTC (rev 
20287)
@@ -30,6 +30,8 @@
 #include "gnunet_peerinfo_service.h"
 #include "gnunet_transport_service.h"
 #include "gnunet_program_lib.h"
+#include "gnunet_transport_plugin.h"
+#include "../transport/gnunet-service-transport_plugins.h"
 
 static int no_resolve;
 
@@ -37,8 +39,29 @@
 
 static int get_self;
 
+static int get_uri;
+
+static char *put_uri;
+
 static struct GNUNET_PEERINFO_Handle *peerinfo;
 
+/**
+ * Configuration handle.
+ */
+const struct GNUNET_CONFIGURATION_Handle *GST_cfg;
+
+/**
+ * Statistics handle.
+ */
+struct GNUNET_STATISTICS_Handle *GST_stats;
+
+/**
+ * Configuration handle.
+ */
+struct GNUNET_PeerIdentity GST_my_identity;
+
+struct GNUNET_MessageHeader *our_hello = NULL;
+
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 struct PrintContext
@@ -47,8 +70,20 @@
   char **address_list;
   unsigned int num_addresses;
   uint32_t off;
+  char *uri;
+  size_t uri_len;
 };
 
+/**
+ * Obtain this peers HELLO message.
+ *
+ * @return our HELLO message
+ */
+const struct GNUNET_MessageHeader *
+GST_hello_get ()
+{
+  return (struct GNUNET_MessageHeader *) our_hello;
+}
 
 static void
 dump_pc (struct PrintContext *pc)
@@ -150,6 +185,8 @@
     if (err_msg != NULL)
       FPRINTF (stderr, "%s",  _("Error in communication with PEERINFO 
service\n"));
     GNUNET_PEERINFO_disconnect (peerinfo);
+    GST_plugins_unload ();
+    GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
     return;
   }
   if ((be_quiet) || (NULL == hello))
@@ -169,8 +206,312 @@
   GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &print_address, pc);
 }
 
+static int
+compose_uri (void *cls, const struct GNUNET_HELLO_Address *address,
+             struct GNUNET_TIME_Absolute expiration)
+{
+  struct PrintContext *pc = cls;
+  struct GNUNET_TRANSPORT_PluginFunctions *papi;
+  static const char *addr;
 
+  papi = GST_plugins_find (address->transport_name);
+  if (papi == NULL)
+  {
+    /* Not an error - we might just not have the right plugin. */
+    return GNUNET_OK;
+  }
+
+  addr = papi->address_to_string (papi->cls, address->address, 
address->address_length);
+  if (addr != NULL)
+  {
+    ssize_t l = strlen (addr);
+    if (l > 0)
+    {
+      struct tm *t;
+      time_t seconds;
+      int s;
+      seconds = expiration.abs_value / 1000;
+      t = gmtime(&seconds);
+      pc->uri = GNUNET_realloc (pc->uri, pc->uri_len + 1 + 14 + 1 + strlen 
(address->transport_name) + 1 + l + 1 /* 0 */);
+      s = sprintf (&pc->uri[pc->uri_len], "!%04u%02u%02u%02u%02u%02u!%s!%s",
+          t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
+          address->transport_name, addr);
+      if (s > 0)
+        pc->uri_len += s;
+    }
+  }
+  return GNUNET_OK;
+}
+
 /**
+ * Print information about the peer.
+ */
+static void
+print_my_uri (void *cls, const struct GNUNET_PeerIdentity *peer,
+              const struct GNUNET_HELLO_Message *hello, const char *err_msg)
+{
+  struct GNUNET_CRYPTO_HashAsciiEncoded enc;
+  struct PrintContext *pc = cls;
+  char *pkey;
+
+  if (peer == NULL)
+  {
+    if (err_msg != NULL)
+      FPRINTF (stderr, "%s",  _("Error in communication with PEERINFO 
service\n"));
+    GNUNET_PEERINFO_disconnect (peerinfo);
+    GST_plugins_unload ();
+    GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
+    return;
+  }
+  if ((be_quiet) || (NULL == hello))
+  {
+    GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &enc);
+    printf ("%s\n", (const char *) &enc);
+    if (be_quiet && get_uri != GNUNET_YES)
+      return;
+  }
+  pc->peer = *peer;
+  GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc);
+  GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &compose_uri, pc);
+  printf ("%s\n", pc->uri);
+  GNUNET_free (pc->uri);
+  GNUNET_free (pc);
+}
+
+struct GNUNET_PEERINFO_HelloAddressParsingContext
+{
+  char *tmp;
+  char *pos;
+  size_t tmp_len;
+};
+
+static size_t
+add_addr_to_hello (void *cls, size_t max, void *buffer)
+{
+  struct tm expiration_time;
+  char buf[5];
+  long l;
+  time_t expiration_seconds;
+  struct GNUNET_TIME_Absolute expire;
+
+  struct GNUNET_PEERINFO_HelloAddressParsingContext *ctx = cls;
+  char *exp1, *exp2;
+  struct GNUNET_TRANSPORT_PluginFunctions *papi;
+  void *addr;
+  size_t addr_len;
+
+  /* End of string */
+  if (ctx->pos - ctx->tmp == ctx->tmp_len)
+    return 0;
+
+  /* Parsed past the end of string, OR wrong format */
+  if ((ctx->pos - ctx->tmp > ctx->tmp_len) || ctx->pos[0] != '!')
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+
+  /* Not enough bytes (3 for three '!', 14 for expiration date, and
+   * at least 1 for type and 1 for address (1-byte long address is a joke,
+   * but it is not completely unrealistic. Zero-length address is.
+   */
+  if (ctx->tmp_len - (ctx->pos - ctx->tmp) < 1 /*!*/ * 3 + 14 + /* at least */ 
2)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  /* Go past the first '!', now we're on expiration date */
+  ctx->pos += 1;
+  /* Its length is known, so check for the next '!' right away */
+  if (ctx->pos[14] != '!')
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+
+  memset (&expiration_time, 0, sizeof (struct tm));
+
+  /* This is FAR more strict than strptime(ctx->pos, "%Y%m%d%H%M%S", ...); */
+  /* FIXME: make it a separate function, since expiration is specified to 
every address */
+#define GETNDIGITS(n,cond) \
+  strncpy (buf, &ctx->pos[0], n); \
+  buf[n] = '\0'; \
+  errno = 0; \
+  l = strtol (buf, NULL, 10); \
+  if (errno != 0 || cond) \
+  { \
+    GNUNET_break (0); \
+    return 0; \
+  } \
+  ctx->pos += n;
+
+  GETNDIGITS (4, l < 1900)
+  expiration_time.tm_year = l - 1900;
+
+  GETNDIGITS (2, l < 1 || l > 12)
+  expiration_time.tm_mon = l;
+
+  GETNDIGITS (2, l < 1 || l > 31)
+  expiration_time.tm_mday = l;
+
+  GETNDIGITS (2, l < 0 || l > 23)
+  expiration_time.tm_hour = l;
+
+  GETNDIGITS (2, l < 0 || l > 59)
+  expiration_time.tm_min = l;
+
+  /* 60 - with a leap second */
+  GETNDIGITS (2, l < 0 || l > 60)
+  expiration_time.tm_sec = l;
+
+  expiration_time.tm_isdst = -1;
+
+#undef GETNDIGITS
+
+  expiration_seconds = mktime (&expiration_time);
+  if (expiration_seconds == (time_t) -1)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  expire.abs_value = expiration_seconds * 1000;
+
+  /* Now we're at '!', advance to the transport type */
+  ctx->pos += 1;
+
+  /* Find the next '!' that separates transport type from
+   * the address
+   */
+  exp1 = strstr (ctx->pos, "!");
+  if (exp1 == NULL)
+  {
+    GNUNET_break (0);
+    return 0;
+  }
+  /* We need it 0-terminated */
+  exp1[0] = '\0';
+  /* Find the '!' that separates address from the next record.
+   * It might not be there, if this is the last record.
+   */
+  exp2 = strstr (&exp1[1], "!");
+  if (exp2 == NULL)
+    exp2 = &ctx->tmp[ctx->tmp_len];
+
+  papi = GST_plugins_find (ctx->pos);
+  if (papi == NULL)
+  {
+    /* Not an error - we might just not have the right plugin.
+     * Skip this part, advance to the next one and recurse.
+     * But only if this is not the end of string.
+     */
+    ctx->pos = exp2 + 1;
+    if (ctx->pos - ctx->tmp >= ctx->tmp_len)
+      return 0;
+    return add_addr_to_hello (cls, max, buffer);
+  }
+
+  if (GNUNET_OK == papi->string_to_address (papi->cls, &exp1[1], exp2 - 
&exp1[1], &addr, &addr_len))
+  {
+    struct GNUNET_HELLO_Address address;
+    int ret;
+
+    /* address.peer is unset - not used by add_address() */
+    address.address_length = addr_len;
+    address.address = addr;
+    address.transport_name = ctx->pos;
+    ret = GNUNET_HELLO_add_address (&address, expire, buffer, max);
+    GNUNET_free (addr);
+    ctx->pos = exp2;
+    return ret;
+  }
+  return 0;
+}
+
+void
+parse_hello (const struct GNUNET_CONFIGURATION_Handle *c,
+             const char *put_uri)
+{
+  int r;
+  char *scheme_part = NULL;
+  char *path_part = NULL;
+  char *exc;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
+  int std_result;
+  struct GNUNET_HELLO_Message *hello;
+  struct GNUNET_PEERINFO_HelloAddressParsingContext ctx;
+
+  r = GNUNET_STRINGS_parse_uri (put_uri, &scheme_part, (const char **) 
&path_part);
+  if (r == GNUNET_NO)
+    return;
+  if (scheme_part == NULL || strcmp (scheme_part, "gnunet://") != 0)
+  {
+    GNUNET_free_non_null (scheme_part);
+    return;
+  }
+  GNUNET_free (scheme_part);
+
+  if (strncmp (path_part, "hello/", 6) != 0)
+    return;
+
+  path_part = &path_part[6];
+  ctx.tmp = GNUNET_strdup (path_part);
+  ctx.tmp_len = strlen (path_part);
+  exc = strstr (ctx.tmp, "!");
+  if (exc == NULL)
+    exc = ctx.pos + ctx.tmp_len;
+  ctx.pos = exc;
+
+  std_result = GNUNET_STRINGS_string_to_data (ctx.tmp, exc - ctx.tmp,
+      (unsigned char *) &pub, sizeof (pub));
+  if (std_result != GNUNET_OK)
+  {
+    GNUNET_free (ctx.tmp);
+    return;
+  }
+
+  hello = GNUNET_HELLO_create (&pub, add_addr_to_hello, &ctx);
+  GNUNET_free (ctx.tmp);
+
+  /* WARNING: this adds the address from URI WITHOUT verification! */
+  GNUNET_PEERINFO_add_peer (peerinfo, hello);
+}
+
+static struct GNUNET_TIME_Relative
+receive_stub (void *cls, const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_MessageHeader *message,
+    const struct GNUNET_ATS_Information *ats, uint32_t ats_count,
+    struct Session *session, const char *sender_address,
+    uint16_t sender_address_len)
+{
+  struct GNUNET_TIME_Relative t;
+  t.rel_value = 0;
+  return t;
+}
+
+static void
+address_notification_stub (void *cls, int add_remove,
+    const void *addr, size_t addrlen)
+{
+}
+
+static void
+session_end_stub (void *cls, const struct GNUNET_PeerIdentity *peer,
+    struct Session * session)
+{
+}
+
+static const struct GNUNET_ATS_Information
+address_to_type_stub (void *cls, const struct sockaddr *addr,
+    size_t addrlen)
+{
+  struct GNUNET_ATS_Information t;
+  t.type = 0;
+  t.value = 0;
+  return t;
+}
+
+
+/**
  * Main function that will be run by the scheduler.
  *
  * @param cls closure
@@ -194,14 +535,34 @@
     FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]);
     return;
   }
-  if (get_self != GNUNET_YES)
+  if (put_uri != NULL && get_uri == GNUNET_YES)
   {
+    FPRINTF (stderr, "%s", _("--put-uri and --get-uri are mutually 
exclusive\n"));
+    return;
+  }
+  if (put_uri != NULL || get_uri == GNUNET_YES)
+  {
     peerinfo = GNUNET_PEERINFO_connect (cfg);
     if (peerinfo == NULL)
     {
       FPRINTF (stderr, "%s",  _("Could not access PEERINFO service.  
Exiting.\n"));
       return;
     }
+    GST_cfg = c;
+    GST_stats = GNUNET_STATISTICS_create ("transport", c);
+    /* FIXME: shouldn't we free GST_stats somewhere? */
+    GST_plugins_load (receive_stub, address_notification_stub,
+        session_end_stub, address_to_type_stub);
+  }
+  if (put_uri != NULL)
+  {
+    parse_hello (c, put_uri);
+    GST_plugins_unload ();
+    GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO);
+    return;
+  }
+  if (get_self != GNUNET_YES)
+  {
     GNUNET_PEERINFO_iterate (peerinfo, NULL,
                              GNUNET_TIME_relative_multiply
                              (GNUNET_TIME_UNIT_SECONDS, 5), &print_peer_info,
@@ -233,6 +594,23 @@
       printf ("%s\n", (char *) &enc);
     else
       printf (_("I am peer `%s'.\n"), (const char *) &enc);
+    if (get_uri == GNUNET_YES)
+    {
+      struct PrintContext *pc;
+      char *pkey;
+      ssize_t l, pl;
+      pc = GNUNET_malloc (sizeof (struct PrintContext));
+      pkey = GNUNET_CRYPTO_rsa_public_key_to_string (&pub);
+      pl = strlen ("gnunet://hello/");
+      l = strlen (pkey) + pl;
+      pc->uri = GNUNET_malloc (l + 1);
+      strcpy (pc->uri, "gnunet://hello/");
+      strcpy (&pc->uri[pl], pkey);
+      pc->uri_len = l;
+      GNUNET_PEERINFO_iterate (peerinfo, &pid,
+          GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
+          print_my_uri, pc);
+    }
   }
 }
 
@@ -257,6 +635,12 @@
     {'s', "self", NULL,
      gettext_noop ("output our own identity only"),
      0, &GNUNET_GETOPT_set_one, &get_self},
+    {'g', "get-hello", NULL,
+     gettext_noop ("also output HELLO uri(s)"),
+     0, &GNUNET_GETOPT_set_one, &get_uri},
+    {'p', "put-hello", "HELLO",
+     gettext_noop ("add given HELLO uri to the database"),
+     1, &GNUNET_GETOPT_set_string, &put_uri},
     GNUNET_GETOPT_OPTION_END
   };
   return (GNUNET_OK ==

Modified: gnunet/src/transport/plugin_transport_tcp.c
===================================================================
--- gnunet/src/transport/plugin_transport_tcp.c 2012-03-05 19:54:31 UTC (rev 
20286)
+++ gnunet/src/transport/plugin_transport_tcp.c 2012-03-05 19:56:16 UTC (rev 
20287)
@@ -537,7 +537,110 @@
   return rbuf;
 }
 
+#define MAX_IPV6_ADDRLEN 47
 
+int
+tcp_string_to_address_ipv6 (void *cls, const char *addr, uint16_t addrlen,
+    void **buf, size_t *added)
+{
+  char zt_addr[MAX_IPV6_ADDRLEN + 1];
+  int ret;
+  char *port_colon;
+  unsigned int port;
+  struct IPv6TcpAddress *ipv6addr;
+
+  if (addrlen < 6)
+    return GNUNET_SYSERR;
+
+  memset (zt_addr, 0, MAX_IPV6_ADDRLEN + 1);
+  strncpy (zt_addr, addr, addrlen <= MAX_IPV6_ADDRLEN ? addrlen : 
MAX_IPV6_ADDRLEN);
+
+  port_colon = strrchr (zt_addr, ':');
+  if (port_colon == NULL)
+    return GNUNET_SYSERR;
+  ret = sscanf (port_colon, ":%u", &port);
+  if (ret != 1 || port > 65535)
+    return GNUNET_SYSERR;
+  port_colon[0] = '\0';
+
+  ipv6addr = GNUNET_malloc (sizeof (struct IPv6TcpAddress));
+  ret = inet_pton (AF_INET6, zt_addr, &ipv6addr->ipv6_addr);
+  if (ret <= 0)
+  {
+    GNUNET_free (ipv6addr);
+    return GNUNET_SYSERR;
+  }
+  ipv6addr->t6_port = port;
+  *buf = ipv6addr;
+  *added = sizeof (struct IPv6TcpAddress);
+  return GNUNET_OK;
+}
+
+#define MAX_IPV4_ADDRLEN 21
+
+int
+tcp_string_to_address_ipv4 (void *cls, const char *addr, uint16_t addrlen,
+    void **buf, size_t *added)
+{
+  unsigned int temps[5];
+  unsigned int port;
+  int cnt;
+  char zt_addr[MAX_IPV4_ADDRLEN + 1];
+  struct IPv4TcpAddress *ipv4addr;
+
+  if (addrlen < 9)
+    return GNUNET_SYSERR;
+
+  memset (zt_addr, 0, MAX_IPV4_ADDRLEN + 1);
+  strncpy (zt_addr, addr, addrlen <= MAX_IPV4_ADDRLEN ? addrlen : 
MAX_IPV4_ADDRLEN);
+
+  cnt = sscanf (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], 
&temps[3], &port);
+  if (cnt != 5)
+    return GNUNET_SYSERR;
+
+  for (cnt = 0; cnt < 4; cnt++)
+    if (temps[cnt] > 0xFF)
+      return GNUNET_SYSERR;
+  if (port > 65535)
+    return GNUNET_SYSERR;
+
+  ipv4addr = GNUNET_malloc (sizeof (struct IPv4TcpAddress));
+  ipv4addr->ipv4_addr = 
+      htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
+             temps[3]);
+  ipv4addr->t4_port = htonl (port);
+  *buf = ipv4addr;
+  *added = sizeof (struct IPv4TcpAddress);
+  return GNUNET_OK;
+}
+
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ * @param max size of the buffer
+ * @param added location to store the number of bytes in the buffer.
+ *        If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+int
+tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+    void **buf, size_t *added)
+{
+  if (addrlen < 1)
+    return GNUNET_SYSERR;
+
+  if (addr[0] == '(')
+    return tcp_string_to_address_ipv6 (cls, addr, addrlen, buf, added);
+  else
+    return tcp_string_to_address_ipv4 (cls, addr, addrlen, buf, added);
+}
+
+
 struct SessionClientCtx
 {
   const struct GNUNET_SERVER_Client *client;
@@ -2084,6 +2187,7 @@
   api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
   api->check_address = &tcp_plugin_check_address;
   api->address_to_string = &tcp_address_to_string;
+  api->string_to_address = &tcp_string_to_address;
   plugin->service = service;
   if (service != NULL)
   {

Modified: gnunet/src/transport/transport.h
===================================================================
--- gnunet/src/transport/transport.h    2012-03-05 19:54:31 UTC (rev 20286)
+++ gnunet/src/transport/transport.h    2012-03-05 19:56:16 UTC (rev 20287)
@@ -289,7 +289,7 @@
 {
 
   /**
-   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP
+   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING
    */
   struct GNUNET_MessageHeader header;
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]