#include "gnunet_nt_lib.h"
#include "gnunet_nat_service.h"
#include "gnunet_statistics_service.h"
+#include "gnunet_ats_transport_service.h"
+#include "transport.h"
#include "gnunet_transport_communication_service.h"
/**
size_t ibuf_off;
};
-
/**
* ID of listen task
*/
*/
static struct ProtoQueue *proto_tail;
+/**
+ * Handle for DNS lookup of bindto address
+ */
+struct GNUNET_RESOLVER_RequestHandle *resolve_request_handle;
+
/**
* We have been notified that our listen socket has something to
queue_finish (queue);
}
-
-/**
- * Convert TCP bind specification to a `struct sockaddr *`
- *
- * @param bindto bind specification to convert
- * @param[out] sock_len set to the length of the address
- * @return converted bindto specification
- */
static struct sockaddr *
-tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
+tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int port, socklen_t *sock_len)
{
+
struct sockaddr *in;
- unsigned int port;
- char dummy[2];
- char *colon;
- char *cp;
- if (1 == sscanf (bindto, "%u%1s", &port, dummy))
- {
- /* interpreting value as just a PORT number */
+ /* interpreting value as just a PORT number */
if (port > UINT16_MAX)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
in = (struct sockaddr *) i6;
}
return in;
+}
+
+static char *
+extract_ipv6_address (char *cp)
+{
+
+ const char *start;
+
+ start = cp;
+ if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
+ {
+ start++; /* skip over '[' */
+ cp[strlen (cp) - 1] = '\0'; /* eat ']' */
}
- cp = GNUNET_strdup (bindto);
- colon = strrchr (cp, ':');
+
+ return start;
+}
+
+static unsigned int
+extract_port(char *colon)
+{
+ unsigned int port;
+ char dummy[2];
if (NULL != colon)
- {
- /* interpet value after colon as port */
- *colon = '\0';
- colon++;
- if (1 == sscanf (colon, "%u%1s", &port, dummy))
{
- /* interpreting value as just a PORT number */
- if (port > UINT16_MAX)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "BINDTO specification `%s' invalid: value too large for port\n",
- bindto);
- GNUNET_free (cp);
- return NULL;
- }
+ /* interpet value after colon as port */
+ *colon = '\0';
+ colon++;
+ if (1 == sscanf (colon, "%u%1s", &port, dummy))
+ {
+ /* interpreting value as just a PORT number */
+ if (port > UINT16_MAX)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Port `%s' invalid: value too large for port\n",
+ port);
+ //GNUNET_free (cp);
+ return NULL;
+ }
+ }
+ else
+ {
+ GNUNET_log (
+ GNUNET_ERROR_TYPE_ERROR,
+ "BINDTO specification invalid: last ':' not followed by number\n");
+ //GNUNET_free (cp);
+ return NULL;
+ }
}
- else
+ else
{
- GNUNET_log (
- GNUNET_ERROR_TYPE_ERROR,
- "BINDTO specification `%s' invalid: last ':' not followed by number\n",
- bindto);
- GNUNET_free (cp);
- return NULL;
+ /* interpret missing port as 0, aka pick any free one */
+ port = 0;
}
- }
- else
- {
- /* interpret missing port as 0, aka pick any free one */
- port = 0;
- }
+
+ return port;
+}
+
+static struct sockaddr *
+tcp_address_to_sockaddr_numeric (socklen_t *sock_len, struct sockaddr_in v4, struct sockaddr_in6 v6, char *colon)
+{
+
+ unsigned int port;
+ struct sockaddr *in;
+
+ port = extract_port(colon);
+
+ if (NULL == port)
+ return NULL;
+
{
/* try IPv4 */
- struct sockaddr_in v4;
- if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
+ if (NULL != &v4.sin_addr)
{
v4.sin_family = AF_INET;
v4.sin_port = htons ((uint16_t) port);
#endif
in = GNUNET_memdup (&v4, sizeof(v4));
*sock_len = sizeof(v4);
- GNUNET_free (cp);
+ //GNUNET_free (cp);
return in;
}
}
{
/* try IPv6 */
- struct sockaddr_in6 v6;
- const char *start;
- start = cp;
- if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
- {
- start++; /* skip over '[' */
- cp[strlen (cp) - 1] = '\0'; /* eat ']' */
- }
- if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+ if (NULL != &v6.sin6_addr)
{
v6.sin6_family = AF_INET6;
v6.sin6_port = htons ((uint16_t) port);
#endif
in = GNUNET_memdup (&v6, sizeof(v6));
*sock_len = sizeof(v6);
- GNUNET_free (cp);
+ //GNUNET_free (cp);
return in;
}
}
- /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
- GNUNET_free (cp);
+ //GNUNET_free (cp);
return NULL;
}
+/**
+ * Convert TCP bind specification to a `struct sockaddr *`
+ *
+ * @param bindto bind specification to convert
+ * @param[out] sock_len set to the length of the address
+ * @return converted bindto specification
+ */
+static struct sockaddr *
+tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
+{
+ struct sockaddr *in;
+ unsigned int port;
+ char dummy[2];
+ char *colon;
+ char *cp;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ const char *start;
+ socklen_t in_len;
+
+ cp = GNUNET_strdup (bindto);
+ start = extract_ipv6_address (cp);
+
+ if (1 == sscanf (bindto, "%u%1s", &port, dummy))
+ {
+ in = tcp_address_to_sockaddr_port_only (bindto, port, sock_len);
+ }
+ else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+ {
+ colon = strrchr (cp, ':');
+ in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, colon);
+ }
+}
+
/**
* Setup cipher for outgoing data stream based on target and
queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
}
-
/**
* Function called by the transport service to initialize a
* message queue given address information about another peer.
* invalid
*/
static int
-mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
+mq_init (void *cls, const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
+ const struct GNUNET_TRANSPORT_CreateQueue *cq)
{
struct Queue *queue;
const char *path;
struct sockaddr *in;
socklen_t in_len;
struct GNUNET_NETWORK_Handle *sock;
+ const char *addr = (const char *) &cq[1];
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connecting to %s\n", address);
- if (0 != strncmp (address,
+ "Connecting to %s\n", addr);
+ if (0 != strncmp (addr,
COMMUNICATOR_ADDRESS_PREFIX "-",
strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
+ path = &addr[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
in = tcp_address_to_sockaddr (path, &in_len);
sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"connect to `%s' failed: %s",
- address,
+ addr,
strerror (errno));
GNUNET_NETWORK_socket_close (sock);
GNUNET_free (in);
return GNUNET_OK;
}
-
/**
* Iterator over all message queues to clean up.
*
}
}
-
-/**
- * Setup communicator and launch network interactions.
- *
- * @param cls NULL (always)
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param c configuration
- */
static void
-run (void *cls,
- char *const *args,
- const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *c)
+init_own_socket (void *cls, struct sockaddr *resolved_in, socklen_t in_len)
{
- char *bindto;
+
struct sockaddr *in;
- socklen_t in_len;
struct sockaddr_storage in_sto;
socklen_t sto_len;
+ struct sockaddr_in *v4;
+ struct sockaddr_in6 *v6;
+ char ipstr[INET6_ADDRSTRLEN];
- (void) cls;
- cfg = c;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg,
- COMMUNICATOR_CONFIG_SECTION,
- "BINDTO",
- &bindto))
- {
- GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- COMMUNICATOR_CONFIG_SECTION,
- "BINDTO");
- return;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (cfg,
- COMMUNICATOR_CONFIG_SECTION,
- "MAX_QUEUE_LENGTH",
- &max_queue_length))
- max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (cfg,
- COMMUNICATOR_CONFIG_SECTION,
- "REKEY_INTERVAL",
- &rekey_interval))
- rekey_interval = DEFAULT_REKEY_INTERVAL;
-
- in = tcp_address_to_sockaddr (bindto, &in_len);
- if (NULL == in)
+ unsigned int port = cls;
+ if (NULL == resolved_in)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to setup TCP socket address with path `%s'\n",
- bindto);
- GNUNET_free (bindto);
+ "Failed to setup TCP socket address\n");
+ //TODO Where do we cancel the request
+ //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+ //TODO check where to free after moving code around
+ //GNUNET_free (bindto);
return;
}
+
+ inet_ntop(resolved_in->sa_family, resolved_in, ipstr, sizeof(ipstr));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "resolved address %s\n",
+ ipstr);
+
listen_sock =
- GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
+ GNUNET_NETWORK_socket_create (resolved_in->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (NULL == listen_sock)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
+ //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
GNUNET_free (in);
- GNUNET_free (bindto);
+ //GNUNET_free (bindto);
return;
}
+
+ if (AF_INET == resolved_in->sa_family)
+ {
+ v4 = GNUNET_new (struct sockaddr_in);
+ v4->sin_family = AF_INET;
+ v4->sin_port = htons ((uint16_t) port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ v4->sin_len = sizeof(struct sockaddr_in);
+#endif
+ in = GNUNET_memdup (v4, sizeof(v4));
+ }else if (AF_INET6 == in->sa_family)
+ {
+ v6 = GNUNET_new (struct sockaddr_in6);
+ v6->sin6_family = AF_INET6;
+ v6->sin6_port = htons ((uint16_t) port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+ v6->sin6_len = sizeof(sizeof(struct sockaddr_in6));
+#endif
+ in = GNUNET_memdup (v6, sizeof(v6));
+ }
+
if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, in, in_len))
{
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto);
+ //GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto);
+ //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
GNUNET_NETWORK_socket_close (listen_sock);
listen_sock = NULL;
GNUNET_free (in);
- GNUNET_free (bindto);
+ //GNUNET_free (bindto);
return;
}
if (GNUNET_OK !=
GNUNET_NETWORK_socket_close (listen_sock);
listen_sock = NULL;
GNUNET_free (in);
- GNUNET_free (bindto);
+ //GNUNET_free (bindto);
}
/* We might have bound to port 0, allowing the OS to figure it out;
thus, get the real IN-address from the socket */
sto_len = in_len;
}
GNUNET_free (in);
- GNUNET_free (bindto);
+ //GNUNET_free (bindto);
in = (struct sockaddr *) &in_sto;
in_len = sto_len;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
GNUNET_ERROR_TYPE_ERROR,
_ (
"Transport service is lacking key configuration settings. Exiting.\n"));
+ GNUNET_RESOLVER_request_cancel (resolve_request_handle);
GNUNET_SCHEDULER_shutdown ();
return;
}
if (NULL == ch)
{
GNUNET_break (0);
+ GNUNET_RESOLVER_request_cancel (resolve_request_handle);
GNUNET_SCHEDULER_shutdown ();
return;
}
&nat_address_cb,
NULL /* FIXME: support reversal: #5529 */,
NULL /* closure */);
+
+}
+
+/**
+ * Setup communicator and launch network interactions.
+ *
+ * @param cls NULL (always)
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ char *bindto;
+ struct sockaddr *in;
+ socklen_t in_len;
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ char *cp;
+ char *colon;
+ char *start;
+ unsigned int port;
+ char dummy[2];
+
+
+ (void) cls;
+ cfg = c;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ COMMUNICATOR_CONFIG_SECTION,
+ "BINDTO",
+ &bindto))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ COMMUNICATOR_CONFIG_SECTION,
+ "BINDTO");
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ COMMUNICATOR_CONFIG_SECTION,
+ "MAX_QUEUE_LENGTH",
+ &max_queue_length))
+ max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (cfg,
+ COMMUNICATOR_CONFIG_SECTION,
+ "REKEY_INTERVAL",
+ &rekey_interval))
+ rekey_interval = DEFAULT_REKEY_INTERVAL;
+
+ cp = GNUNET_strdup (bindto);
+ start = extract_ipv6_address (cp);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We try with path `%s'\n",
+ bindto);
+
+ if (1 == sscanf (bindto, "%u%1s", &port, dummy))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We think it is port only\n");
+ in = tcp_address_to_sockaddr_port_only (bindto, port, &in_len);
+ init_own_socket (bindto, &in, &in_len);
+ }
+ else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We think it is address and port\n");
+ colon = strrchr (cp, ':');
+ in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, &colon);
+ init_own_socket (bindto, &in, &in_len);
+ }else
+ {
+ colon = strrchr (cp, ':');
+ port = extract_port(colon);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "We try to resolve\n");
+ resolve_request_handle = GNUNET_RESOLVER_ip_get (cp,
+ AF_UNSPEC,
+ GNUNET_TIME_UNIT_MINUTES,
+ &init_own_socket,
+ port);
+ }
}