#include "plugin_transport.h"
#include "transport.h"
-#define DEBUG_UDP GNUNET_NO
+#define DEBUG_UDP GNUNET_YES
/*
* Transport cost to peer, always 1 for UDP (direct connection)
*/
static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
+/**
+ * How long until we give up on transmitting the welcome message?
+ */
+#define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
+
/**
* Message-Packet header.
*/
*/
struct GNUNET_SERVICE_Context *service;
+ /**
+ * Handle for request of hostname resolution, non-NULL if pending.
+ */
+ struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
+
/**
* ID of task used to update our addresses when one expires.
*/
*
* @param cls closure
* @param target who should receive this message (ignored by UDP)
- * @param msg the message to transmit
+ * @param msgbuf one or more GNUNET_MessageHeader(s) strung together
+ * @param msgbufsize the size of the msgbuf to send
* @param priority how important is the message (ignored by UDP)
* @param timeout when should we time out (give up) if we can not transmit?
* @param addr the addr to send the message to, needs to be a sockaddr for us
static ssize_t
udp_plugin_send (void *cls,
const struct GNUNET_PeerIdentity *target,
- const struct GNUNET_MessageHeader *msg,
+ char *msgbuf,
+ size_t msgbuf_size,
unsigned int priority,
struct GNUNET_TIME_Relative timeout,
const void *addr,
ssize_t sent;
GNUNET_assert(udp_sock != NULL);
- GNUNET_assert(addr != NULL);
+
+ if ((addr == NULL) || (addrlen == 0))
+ {
+#if DEBUG_UDP
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
+ ("udp_plugin_send called without address, returning!\n"));
+#endif
+ cont (cont_cls, target, GNUNET_OK);
+ return 0; /* Can never send if we don't have an address!! */
+ }
/* Build the message to be sent */
- message = GNUNET_malloc (sizeof (struct UDPMessage) + ntohs (msg->size));
- ssize = sizeof (struct UDPMessage) + ntohs (msg->size);
+ message = GNUNET_malloc (sizeof (struct UDPMessage) + msgbuf_size);
+ ssize = sizeof (struct UDPMessage) + msgbuf_size;
#if DEBUG_UDP
GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
- ("In udp_send, ssize is %d\n"), ssize);
+ ("In udp_send, ssize is %d, sending message to %s\n"), ssize, GNUNET_a2s((const struct sockaddr *)addr, addrlen));
#endif
message->header.size = htons (ssize);
message->header.type = htons (0);
memcpy (&message->sender, plugin->env->my_identity,
sizeof (struct GNUNET_PeerIdentity));
- memcpy (&message[1], msg, ntohs (msg->size));
+ memcpy (&message[1], msgbuf, msgbuf_size);
/* Actually send the message */
sent =
if (sent == GNUNET_SYSERR)
cont (cont_cls, target, GNUNET_SYSERR);
else
- cont (cont_cls, target, GNUNET_OK);
+ {
+#if DEBUG_UDP
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
+ ("Sucessfully sent message, calling transmit continuation!\n"));
+#endif
+ cont (cont_cls, target, GNUNET_OK);
+ }
}
GNUNET_free (message);
return sent;
}
+/**
+ * Add the IP of our network interface to the list of
+ * our external IP addresses.
+ */
+static int
+process_interfaces (void *cls,
+ const char *name,
+ int isDefault,
+ const struct sockaddr *addr, socklen_t addrlen)
+{
+ struct Plugin *plugin = cls;
+ int af;
+ struct sockaddr_in *v4;
+ struct sockaddr_in6 *v6;
+
+ af = addr->sa_family;
+ if (af == AF_INET)
+ {
+ v4 = (struct sockaddr_in *) addr;
+ v4->sin_port = htons (plugin->adv_port);
+ }
+ else
+ {
+ GNUNET_assert (af == AF_INET6);
+ v6 = (struct sockaddr_in6 *) addr;
+ v6->sin6_port = htons (plugin->adv_port);
+ }
+ GNUNET_log_from (GNUNET_ERROR_TYPE_INFO |
+ GNUNET_ERROR_TYPE_BULK,
+ "udp", _("Found address `%s' (%s)\n"),
+ GNUNET_a2s (addr, addrlen), name);
+ plugin->env->notify_address (plugin->env->cls,
+ "udp",
+ addr, addrlen, GNUNET_TIME_UNIT_FOREVER_REL);
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called by the resolver for each address obtained from DNS
+ * for our own hostname. Add the addresses to the list of our
+ * external IP addresses.
+ *
+ * @param cls closure
+ * @param addr one of the addresses of the host, NULL for the last address
+ * @param addrlen length of the address
+ */
+static void
+process_hostname_ips (void *cls,
+ const struct sockaddr *addr, socklen_t addrlen)
+{
+ struct Plugin *plugin = cls;
+
+ if (addr == NULL)
+ {
+ plugin->hostname_dns = NULL;
+ return;
+ }
+ process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen);
+}
+
+
/*
* @param cls the plugin handle
* @param tc the scheduling context (for rescheduling this function again)
socklen_t fromlen;
struct sockaddr_storage addr;
ssize_t ret;
+ int offset;
+ int count;
+ int tsize;
+ char *msgbuf;
+ const struct GNUNET_MessageHeader *currhdr;
do
{
buf = GNUNET_malloc (buflen);
fromlen = sizeof (addr);
-#if DEBUG_UDP
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
- ("src_addr_len is %u\n"), fromlen);
-#endif
+
memset (&addr, 0, fromlen);
ret =
GNUNET_NETWORK_socket_recvfrom (udp_sock, buf, buflen,
break;
}
hdr = (const struct GNUNET_MessageHeader *) &msg[1];
+ msgbuf = (char *)&msg[1];
sender = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
memcpy (sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity));
+ offset = 0;
+ count = 0;
+ tsize = ntohs (msg->header.size) - sizeof(struct UDPMessage);
+ while (offset < tsize)
+ {
+ currhdr = (struct GNUNET_MessageHeader *)&msgbuf[offset];
#if DEBUG_UDP
GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
- ("msg reports message size of %d\n"),
- ntohs (hdr->size));
-
+ ("processing msg %d: type %d, size %d at offset %d\n"),
+ count, ntohs(currhdr->type), ntohs(currhdr->size), offset);
+#endif
+ plugin->env->receive (plugin->env->cls,
+ sender, currhdr, UDP_DIRECT_DISTANCE, (char *)&addr, fromlen);
+ offset += ntohs(currhdr->size);
+#if DEBUG_UDP
GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "udp", _
- ("msg reports message type of %d\n"),
- ntohs (hdr->type));
+ ("offset now %d, tsize %d\n"),
+ offset, tsize);
#endif
- plugin->env->receive (plugin->env->cls,
- sender, &msg->header, UDP_DIRECT_DISTANCE, (char *)&addr, fromlen);
+ count++;
+ }
GNUNET_free (sender);
GNUNET_free (buf);
v6 = (struct sockaddr_in6 *) buf;
v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port)));
}
-#if DEBUG_TCP
+#if DEBUG_UDP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
"tcp",
"Informing transport service about my address `%s'.\n",
plugin->service = service;
+ /* FIXME: do the two calls below periodically again and
+ not just once (since the info we get might change...) */
+ GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
+ plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (env->sched,
+ env->cfg,
+ AF_UNSPEC,
+ HOSTNAME_RESOLVE_TIMEOUT,
+ &process_hostname_ips,
+ plugin);
+
udp_sock = udp_transport_server_start (plugin);
GNUNET_assert (udp_sock != NULL);