gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r10059 - in gnunet/src: include transport util


From: gnunet
Subject: [GNUnet-SVN] r10059 - in gnunet/src: include transport util
Date: Tue, 19 Jan 2010 14:23:04 +0100

Author: nevans
Date: 2010-01-19 14:23:04 +0100 (Tue, 19 Jan 2010)
New Revision: 10059

Added:
   gnunet/src/transport/test_plugin_transport_data_udp.conf
   gnunet/src/transport/test_plugin_transport_udp.c
Modified:
   gnunet/src/include/gnunet_network_lib.h
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_scheduler_lib.h
   gnunet/src/transport/Makefile.am
   gnunet/src/transport/plugin_transport_tcp.c
   gnunet/src/transport/plugin_transport_udp.c
   gnunet/src/util/network.c
   gnunet/src/util/scheduler.c
Log:
moderate udp support, not really tested (:

Modified: gnunet/src/include/gnunet_network_lib.h
===================================================================
--- gnunet/src/include/gnunet_network_lib.h     2010-01-19 11:03:57 UTC (rev 
10058)
+++ gnunet/src/include/gnunet_network_lib.h     2010-01-19 13:23:04 UTC (rev 
10059)
@@ -124,7 +124,28 @@
 int GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc, 
int backlog);
 
 /**
+ * How much data is available to be read on this descriptor?
+ * @param desc socket
+ */
+unsigned int
+GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle * 
desc);
+
+/**
  * Read data from a connected socket (always non-blocking).
+ * @param desc socket
+ * @param buffer buffer
+ * @param length length of buffer
+ * @param src_addr either the source to recv from, or all zeroes
+ *        to be filled in by recvfrom
+ * @param addrlen length of the addr
+ */
+ssize_t
+GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
+                                void *buffer, size_t length,
+                                struct sockaddr *src_addr, socklen_t *addrlen);
+
+/**
+ * Read data from a connected socket (always non-blocking).
  *
  * @param desc socket
  * @param buffer buffer
@@ -248,6 +269,11 @@
 void GNUNET_NETWORK_fdset_copy(struct GNUNET_NETWORK_FDSet *to,
                               const struct GNUNET_NETWORK_FDSet *from);
 
+/*
+ * Return file descriptor for this network handle
+ */
+int
+GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc);
 /**
  * Copy a native fd set
  * @param to destination

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2010-01-19 11:03:57 UTC (rev 
10058)
+++ gnunet/src/include/gnunet_protocols.h       2010-01-19 13:23:04 UTC (rev 
10059)
@@ -242,7 +242,16 @@
  */
 #define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_DATA 43
 
+/*
+ * UDP Ping message
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PING 51
 
+/*
+ * UDP Pong message
+ */
+#define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PONG 52
+
 /**
  * Initial setup message from core client to core.
  */

Modified: gnunet/src/include/gnunet_scheduler_lib.h
===================================================================
--- gnunet/src/include/gnunet_scheduler_lib.h   2010-01-19 11:03:57 UTC (rev 
10058)
+++ gnunet/src/include/gnunet_scheduler_lib.h   2010-01-19 13:23:04 UTC (rev 
10059)
@@ -290,7 +290,7 @@
  * @param sched scheduler to use
  * @param prerequisite_task run this task after the task with the given
  *        task identifier completes (and any of our other
- *        conditions, such as delay, read or write-readyness
+ *        conditions, such as delay, read or write-readiness
  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_TASK to not have any 
dependency
  *        on completion of other tasks (this will cause the task to run as
  *        soon as possible).
@@ -480,7 +480,7 @@
  * @param prio how important is this task?
  * @param prerequisite_task run this task after the task with the given
  *        task identifier completes (and any of our other
- *        conditions, such as delay, read or write-readyness
+ *        conditions, such as delay, read or write-readiness
  *        are satisfied).  Use GNUNET_SCHEDULER_NO_TASK to not have any 
dependency
  *        on completion of other tasks.
  * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for 
"forever",

Modified: gnunet/src/transport/Makefile.am
===================================================================
--- gnunet/src/transport/Makefile.am    2010-01-19 11:03:57 UTC (rev 10058)
+++ gnunet/src/transport/Makefile.am    2010-01-19 13:23:04 UTC (rev 10059)
@@ -48,6 +48,7 @@
 
 plugin_LTLIBRARIES = \
   libgnunet_plugin_transport_tcp.la \
+  libgnunet_plugin_transport_udp.la \
   libgnunet_plugin_transport_template.la 
 # TODO: add udp, http, nat, etc.
 
@@ -67,10 +68,19 @@
 libgnunet_plugin_transport_template_la_LDFLAGS = \
  $(GN_PLUGIN_LDFLAGS)
 
+libgnunet_plugin_transport_udp_la_SOURCES = \
+  plugin_transport_udp.c
+libgnunet_plugin_transport_udp_la_LIBADD = \
+  $(top_builddir)/src/hello/libgnunethello.la \
+  $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
+  $(top_builddir)/src/util/libgnunetutil.la 
+libgnunet_plugin_transport_udp_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
 
 check_PROGRAMS = \
  test_transport_api \
- test_plugin_transport
+ test_plugin_transport \
+ test_plugin_transport_udp
 # TODO: add tests for tcp, udp, http, nat, etc.
 
 TESTS = $(check_PROGRAMS)
@@ -88,6 +98,11 @@
  $(top_builddir)/src/transport/libgnunettransport.la \
  $(top_builddir)/src/util/libgnunetutil.la  
 
+test_plugin_transport_udp_SOURCES = \
+ test_plugin_transport_udp.c
+test_plugin_transport_udp_LDADD = \
+ $(top_builddir)/src/transport/libgnunettransport.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
 
 EXTRA_DIST = \
   test_transport_api_data.conf \

Modified: gnunet/src/transport/plugin_transport_tcp.c
===================================================================
--- gnunet/src/transport/plugin_transport_tcp.c 2010-01-19 11:03:57 UTC (rev 
10058)
+++ gnunet/src/transport/plugin_transport_tcp.c 2010-01-19 13:23:04 UTC (rev 
10059)
@@ -218,7 +218,7 @@
 
   /**
    * Continuation function to call once the message
-   * has been sent.  Can be  NULL if there is no
+   * has been sent.  Can be NULL if there is no
    * continuation to call.
    */
   GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
@@ -514,7 +514,7 @@
 
 /**
  * Function called to notify a client about the socket
- * begin ready to queue more data.  "buf" will be
+ * being ready to queue more data.  "buf" will be
  * NULL and "size" zero if the socket was closed for
  * writing in the meantime.
  *
@@ -1073,7 +1073,7 @@
 static void 
 tcp_plugin_send (void *cls,
                  const struct GNUNET_PeerIdentity *target,   
-                unsigned int priority,
+                 unsigned int priority,
                  const struct GNUNET_MessageHeader *msg,
                  struct GNUNET_TIME_Relative timeout,
                  GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)

Modified: gnunet/src/transport/plugin_transport_udp.c
===================================================================
--- gnunet/src/transport/plugin_transport_udp.c 2010-01-19 11:03:57 UTC (rev 
10058)
+++ gnunet/src/transport/plugin_transport_udp.c 2010-01-19 13:23:04 UTC (rev 
10059)
@@ -22,15 +22,36 @@
  * @file transport/plugin_transport_udp.c
  * @brief Implementation of the UDP transport service
  * @author Christian Grothoff
+ * @author Nathan Evans?
  */
 
+/* Notes for Nate:
+ *  - Use simple network api to open ports and do select and whatnot.
+ *  - For sending, just find session and send away!
+ *  - All that is required is a simple linked list of known peers and
+ *    how to send to them.  Each will have a socket associated with it
+ *    and that's pretty much it!  May want to re-start over with 0.8
+ *    code now that we have a better idea.
+ *  - How often to do select loop?  Do with a recall thing since we
+ *    don't want to use cron jobs?
+ *  - First thing, set up server which listens on a UDP port.
+ *  - Use plugin->env->receive to notify server of message receipt
+ *
+ */
 #include "platform.h"
-#include "gnunet_util.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_connection_lib.h"
+#include "gnunet_os_lib.h"
+#include "gnunet_peerinfo_service.h"
 #include "gnunet_protocols.h"
-#include "gnunet_transport.h"
-#include "gnunet_stats_service.h"
-#include "gnunet_upnp_service.h"
-#include "ip.h"
+#include "gnunet_resolver_service.h"
+#include "gnunet_server_lib.h"
+#include "gnunet_service_lib.h"
+#include "gnunet_signatures.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
+#include "plugin_transport.h"
+#include "transport.h"
 
 #define DEBUG_UDP GNUNET_YES
 
@@ -41,150 +62,200 @@
 #define MESSAGE_SIZE 1472
 
 /**
+ * Handle for request of hostname resolution, non-NULL if pending.
+ */
+static struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
+
+/**
  * Message-Packet header.
  */
-typedef struct
+struct UDPMessage
 {
   /**
    * size of the message, in bytes, including this header.
    */
-  GNUNET_MessageHeader header;
+  struct GNUNET_MessageHeader header;
 
   /**
    * What is the identity of the sender (GNUNET_hash of public key)
    */
-  GNUNET_PeerIdentity sender;
+  struct GNUNET_PeerIdentity sender;
 
-} UDPMessage;
+};
 
-#define MY_TRANSPORT_NAME "UDP"
-#include "common.c"
+/* Forward definition */
+struct Plugin;
 
-/* *********** globals ************* */
+/**
+ * Session handle for UDP connections.
+ */
+struct Session
+{
 
-static int stat_bytesReceived;
+  /**
+   * Stored in a linked list.
+   */
+  struct Session *next;
 
-static int stat_bytesSent;
+  /**
+   * Pointer to the global plugin struct.
+   */
+  struct Plugin *plugin;
 
-static int stat_bytesDropped;
+  /**
+   * To whom are we talking to (set to our identity
+   */
+  struct GNUNET_PeerIdentity target;
 
-static int stat_udpConnected;
+  /**
+   * Address of the other peer if WE initiated the connection
+   * (and hence can be sure what it is), otherwise NULL.
+   */
+  void *connect_addr;
 
-/**
- * thread that listens for inbound messages
- */
-static struct GNUNET_SelectHandle *selector;
+  /**
+   * Length of connect_addr, can be 0.
+   */
+  size_t connect_alen;
 
-/**
- * the socket that we transmit all data with
- */
-static struct GNUNET_SocketHandle *udp_sock;
+  /*
+   * Random challenge number for validation
+   */
+  int challenge;
 
-static struct GNUNET_LoadMonitor *load_monitor;
+  /*
+   * Have we received validation (performed ping/pong) from this peer?
+   */
+  unsigned int validated;
 
+};
 
 /**
- * The socket of session has data waiting, process!
- *
- * This function may only be called if the tcplock is
- * already held by the caller.
+ * Encapsulation of all of the state of the plugin.
  */
-static int
-select_message_handler (void *mh_cls,
-                        struct GNUNET_SelectHandle *sh,
-                        struct GNUNET_SocketHandle *sock,
-                        void *sock_ctx, const GNUNET_MessageHeader * msg)
+struct Plugin
 {
-  unsigned int len;
-  GNUNET_TransportPacket *mp;
-  const UDPMessage *um;
+  /**
+   * Our environment.
+   */
+  struct GNUNET_TRANSPORT_PluginEnvironment *env;
 
-  len = ntohs (msg->size);
-  if (len <= sizeof (UDPMessage))
-    {
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK,
-                     _("Received malformed message via %s. Ignored.\n"),
-                     "UDP");
-      return GNUNET_SYSERR;
-    }
-  um = (const UDPMessage *) msg;
-  mp = GNUNET_malloc (sizeof (GNUNET_TransportPacket));
-  mp->msg = GNUNET_malloc (len - sizeof (UDPMessage));
-  memcpy (mp->msg, &um[1], len - sizeof (UDPMessage));
-  mp->sender = um->sender;
-  mp->size = len - sizeof (UDPMessage);
-  mp->tsession = NULL;
-  coreAPI->receive (mp);
-  if (stats != NULL)
-    stats->change (stat_bytesReceived, len);
-  return GNUNET_OK;
-}
+  /**
+   * List of open TCP sessions.
+   */
+  struct Session *sessions;
 
-static void *
-select_accept_handler (void *ah_cls,
-                       struct GNUNET_SelectHandle *sh,
-                       struct GNUNET_SocketHandle *sock,
-                       const void *addr, unsigned int addr_len)
-{
-  static int nonnullpointer;
+  /**
+   * Handle for the statistics service.
+   */
+  struct GNUNET_STATISTICS_Handle *statistics;
 
-  if (GNUNET_NO != is_rejected_tester (addr, addr_len))
-    return NULL;
-  return &nonnullpointer;
-}
+  /**
+   * Handle to the network service.
+   */
+  struct GNUNET_SERVICE_Context *service;
 
+  /**
+   * ID of task used to update our addresses when one expires.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier address_update_task;
+
+  /**
+   * ID of select task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier select_task;
+
+  /**
+   * Port that we are actually listening on.
+   */
+  uint16_t open_port;
+
+  /**
+   * Port that the user said we would have visible to the
+   * rest of the world.
+   */
+  uint16_t adv_port;
+
+  /*
+   * FD Read set
+   */
+  struct GNUNET_NETWORK_FDSet * rs;
+
+};
+
 /**
- * Select has been forced to close a connection.
- * Free the associated context.
+ * Message used to ask a peer to validate receipt (to check an address
+ * from a HELLO).  Followed by the address used.  Note that the
+ * recipients response does not affirm that he has this address,
+ * only that he got the challenge message.
  */
-static void
-select_close_handler (void *ch_cls,
-                      struct GNUNET_SelectHandle *sh,
-                      struct GNUNET_SocketHandle *sock, void *sock_ctx)
+struct UDPPingMessage
 {
-  /* do nothing */
-}
 
+  /**
+   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PING
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Random challenge number (in network byte order).
+   */
+  uint32_t challenge GNUNET_PACKED;
+
+
+
+};
+
+
 /**
- * Establish a connection to a remote node.
+ * Message used to validate a HELLO.  The challenge is included in the
+ * confirmation to make matching of replies to requests possible.  The
+ * signature signs the original challenge number, our public key, the
+ * sender's address (so that the sender can check that the address we
+ * saw is plausible for him and possibly detect a MiM attack) and a
+ * timestamp (to limit replay).<p>
  *
- * @param hello the hello-Message for the target node
- * @param tsessionPtr the session handle that is to be set
- * @param may_reuse are we allowed to re-use an existing connection (ignored 
for UDP)
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * This message is followed by the address of the
+ * client that we are observing (which is part of what
+ * is being signed).
  */
-static int
-udp_connect (const GNUNET_MessageHello * hello,
-             GNUNET_TSession ** tsessionPtr, int may_reuse)
+struct UDPPongMessage
 {
-  GNUNET_TSession *tsession;
+  /**
+   * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_PONG
+   */
+  struct GNUNET_MessageHeader header;
 
-  tsession = GNUNET_malloc (sizeof (GNUNET_TSession));
-  memset (tsession, 0, sizeof (GNUNET_TSession));
-  tsession->internal = GNUNET_malloc (GNUNET_sizeof_hello (hello));
-  memcpy (tsession->internal, hello, GNUNET_sizeof_hello (hello));
-  tsession->ttype = myAPI.protocol_number;
-  tsession->peer = hello->senderIdentity;
-  *tsessionPtr = tsession;
-  if (stats != NULL)
-    stats->change (stat_udpConnected, 1);
-  return GNUNET_OK;
-}
+  /**
+   * Random challenge number (in network byte order).
+   */
+  uint32_t challenge GNUNET_PACKED;
 
+  /* Length of addr, appended to end of message */
+  unsigned int addrlen;
+};
+
+/* *********** globals ************* */
+
 /**
+ * the socket that we transmit all data with
+ */
+static struct GNUNET_NETWORK_Handle *udp_sock;
+
+
+/**
  * A (core) Session is to be associated with a transport session. The
  * transport service may want to know in order to call back on the
  * core if the connection is being closed.
  *
- * @param tsession the session handle passed along
+ * @param session the session handle passed along
  *   from the call to receive that was made by the transport
  *   layer
  * @return GNUNET_OK if the session could be associated,
  *         GNUNET_SYSERR if not.
  */
 int
-udp_associate (GNUNET_TSession * tsession)
+udp_associate (struct Session * session)
 {
   return GNUNET_SYSERR;         /* UDP connections can never be associated */
 }
@@ -195,18 +266,12 @@
  * @param tsession the session that is closed
  * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
  */
-static int
-udp_disconnect (GNUNET_TSession * tsession)
+void
+udp_disconnect (void *cls,
+                const struct GNUNET_PeerIdentity *
+                target)
 {
-  if (tsession != NULL)
-    {
-      if (tsession->internal != NULL)
-        GNUNET_free (tsession->internal);
-      GNUNET_free (tsession);
-      if (stats != NULL)
-        stats->change (stat_udpConnected, -1);
-    }
-  return GNUNET_OK;
+  return;
 }
 
 /**
@@ -214,385 +279,581 @@
  * restarted later!
  */
 static int
-udp_transport_server_stop ()
+udp_transport_server_stop (void *cls)
 {
-  GNUNET_GE_ASSERT (coreAPI->ectx, udp_sock != NULL);
-  if (selector != NULL)
+  struct Plugin *plugin = cls;
+  GNUNET_assert (udp_sock != NULL);
+  if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
     {
-      GNUNET_select_destroy (selector);
-      selector = NULL;
+      GNUNET_SCHEDULER_cancel (plugin->env->sched, plugin->select_task);
+      plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
     }
-  GNUNET_socket_destroy (udp_sock);
+
+  GNUNET_NETWORK_socket_close (udp_sock);
   udp_sock = NULL;
   return GNUNET_OK;
 }
 
+static struct Session *
+find_session(void *cls, struct Session * session_list, const struct 
GNUNET_PeerIdentity *peer)
+{
+  struct Plugin *plugin = cls;
+  struct Session *pos;
+  pos = session_list;
+
+  while (pos != NULL)
+  {
+    if (memcmp(peer, &pos->target, sizeof(struct GNUNET_PeerIdentity)) == 0)
+      return pos;
+    pos = pos->next;
+  }
+
+  return NULL;
+}
+
 /**
- * Test if the transport would even try to send
- * a message of the given size and importance
- * for the given session.<br>
- * This function is used to check if the core should
- * even bother to construct (and encrypt) this kind
- * of message.
+ * Function that can be used by the transport service to transmit
+ * a message using the plugin.
  *
- * @return GNUNET_YES if the transport would try (i.e. queue
- *         the message or call the OS to send),
- *         GNUNET_NO if the transport would just drop the message,
- *         GNUNET_SYSERR if the size/session is invalid
+ * @param cls closure
+ * @param service_context value passed to the transport-service
+ *        to identify the neighbour
+ * @param target who should receive this message
+ * @param priority how important is the message
+ * @param msg the message to transmit
+ * @param timeout when should we time out (give up) if we can not transmit?
+ * @param cont continuation to call once the message has
+ *        been transmitted (or if the transport is ready
+ *        for the next transmission call; or if the
+ *        peer disconnected...)
+ * @param cont_cls closure for cont
  */
-static int
-udp_test_would_try (GNUNET_TSession * tsession, unsigned int size,
-                    int important)
+static void
+udp_plugin_send (void *cls,
+                 const struct GNUNET_PeerIdentity *target,
+                 unsigned int priority,
+                 const struct GNUNET_MessageHeader *msg,
+                 struct GNUNET_TIME_Relative timeout,
+                 GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
 {
-  const GNUNET_MessageHello *hello;
+  struct Plugin *plugin = cls;
+  struct Session *session;
+  struct UDPMessage *message;
+  int ssize;
+  size_t sent;
 
-  if (udp_sock == NULL)
-    return GNUNET_SYSERR;
-  if (size == 0)
+  session = find_session(plugin, plugin->sessions, target);
+
+  if ((session == NULL) || (udp_sock == NULL))
+    return;
+
+  /* Build the message to be sent */
+  message = GNUNET_malloc(sizeof(struct UDPMessage) + ntohs(msg->size));
+  ssize = sizeof(struct UDPMessage) + ntohs(msg->size);
+
+#if DEBUG_UDP
+  GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+                 ("In udp_send, ssize is %d\n"), ssize);
+#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));
+
+  /* Actually send the message */
+  sent = GNUNET_NETWORK_socket_sendto (udp_sock, message, ssize, 
session->connect_addr,
+                                session->connect_alen);
+
+  if (cont != NULL)
     {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
+      if (sent == GNUNET_SYSERR)
+        cont(cont_cls, target, GNUNET_SYSERR);
+      else
+        cont(cont_cls, target, GNUNET_OK);
     }
-  if (size > myAPI.mtu)
-    {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
-    }
-  hello = (const GNUNET_MessageHello *) tsession->internal;
-  if (hello == NULL)
-    return GNUNET_SYSERR;
-  return GNUNET_YES;
+
+  return;
 }
 
 /**
- * Create a UDP socket.  If possible, use IPv6, otherwise
- * try IPv4.  Update available_protocols accordingly.
+ * We've received a PING from this peer via UDP.
+ * Send back our PONG.
+ *
+ * @param cls closure
+ * @param sender the Identity of the sender
+ * @param message the actual message
  */
-static struct GNUNET_NETWORK_Handle *
-udp_create_socket ()
+static void
+handle_udp_ping (void *cls,
+                 struct GNUNET_PeerIdentity *sender, struct sockaddr_storage * 
addr, size_t addrlen,
+                 const struct GNUNET_MessageHeader *message)
 {
-  struct GNUNET_NETWORK_Handle *desc;
+  struct Plugin *plugin = cls;
+  struct Session *head = plugin->sessions;
+  const struct UDPPingMessage *ping = (const struct UDPPingMessage *)message;
+  struct UDPPongMessage *pong;
+  struct Session *found;
 
-  available_protocols = VERSION_AVAILABLE_NONE;
-  desc = NULL;
-  if (GNUNET_YES !=
-      GNUNET_GC_get_configuration_value_yesno (cfg, "GNUNETD", "DISABLE-IPV6",
-                                               GNUNET_YES))
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("handling ping, challenge is %d\n"), ntohs(ping->challenge));
+#endif
+  found = find_session(plugin, head, sender);
+  if (found != NULL)
     {
-      desc = GNUNET_net_socket (PF_INET6, SOCK_DGRAM, 17);
+      pong = GNUNET_malloc(sizeof(struct UDPPongMessage) + addrlen);
+      pong->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PONG);
+      pong->header.size = htons(sizeof(struct UDPPongMessage) + addrlen);
+      pong->challenge = ping->challenge;
+      memcpy(&pong[1], addr, addrlen);
+      pong->addrlen = htons(addrlen);
+
+      udp_plugin_send(plugin, sender, GNUNET_SCHEDULER_PRIORITY_DEFAULT, 
&pong->header, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30), 
NULL, NULL);
     }
-  if (NULL == desc)
-    {
-      desc = GNUNET_net_socket (PF_INET, SOCK_DGRAM, 17);
-      if (NULL == desc)
-        {
-          GNUNET_GE_LOG_STRERROR (coreAPI->ectx,
-                                  GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
-                                  GNUNET_GE_BULK, "socket");
-          return GNUNET_SYSERR;
-        }
-      available_protocols = VERSION_AVAILABLE_IPV4;
-    }
-  else
-    {
-      available_protocols = VERSION_AVAILABLE_IPV6 | VERSION_AVAILABLE_IPV4;
-    }
-  return desc;
+
+  return;
+
 }
 
 /**
- * Send a message to the specified remote node.
+ * We've received a PONG from this peer via UDP.
+ * Great. Call validate func if we haven't already
+ * received a PONG.
  *
- * @param tsession the GNUNET_MessageHello identifying the remote node
- * @param message what to send
- * @param size the size of the message
- * @param important is this message "important" to override typical transmit 
limits?
- * @return GNUNET_SYSERR on error, GNUNET_OK on success
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
  */
-static int
-udp_send (GNUNET_TSession * tsession,
-          const void *message, const unsigned int size, int important)
+static void
+handle_udp_pong (void *cls,
+                 struct GNUNET_PeerIdentity *sender,
+                 const struct GNUNET_MessageHeader *message)
 {
-  const GNUNET_MessageHello *hello;
-  const HostAddress *haddr;
-  UDPMessage *mp;
-  struct sockaddr_in serverAddrv4;
-  struct sockaddr_in6 serverAddrv6;
-  struct sockaddr *serverAddr;
-  socklen_t addrlen;
-  unsigned short available;
-  int ok;
-  int ssize;
-  size_t sent;
+  struct Plugin *plugin = cls;
+  const struct UDPPongMessage *pong = (struct UDPPongMessage *)message;
+  struct Session *found;
+  unsigned int addr_len;
+  struct sockaddr_storage addr;
 
-  GNUNET_GE_ASSERT (NULL, tsession != NULL);
-  if (udp_sock == NULL)
-    return GNUNET_SYSERR;
-  if (size == 0)
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("handling pong\n"));
+#endif
+  found = find_session(plugin, plugin->sessions, sender);
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("found->challenge %d, pong->challenge %d\n"), found->challenge, 
ntohs(pong->challenge));
+#endif
+  if ((found != NULL) && (found->challenge == ntohs(pong->challenge)))
     {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
+      found->validated = GNUNET_YES;
+      addr_len = ntohs(pong->addrlen);
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("found associated ping, addr is %u bytes\n"), addr_len);
+#endif
+      memcpy(&addr, &pong[1], addr_len);
+      plugin->env->notify_validation(plugin->env->cls, "udp", sender, 
ntohs(pong->challenge), (char *)&addr);
     }
-  if (size > myAPI.mtu)
+  else
     {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
+
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("Session not found!\n"));
+#endif
     }
-  hello = (const GNUNET_MessageHello *) tsession->internal;
-  if (hello == NULL)
-    return GNUNET_SYSERR;
+  return;
+}
 
-  haddr = (const HostAddress *) &hello[1];
-  available = ntohs (haddr->availability) & available_protocols;
-  if (available == VERSION_AVAILABLE_NONE)
-    return GNUNET_SYSERR;
-  if (available == (VERSION_AVAILABLE_IPV4 | VERSION_AVAILABLE_IPV6))
+static void
+udp_plugin_select (void *cls,
+                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Plugin *plugin = cls;
+  struct GNUNET_TIME_Relative timeout  = 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500);
+  char * buf;
+  struct UDPMessage *msg;
+  const struct GNUNET_MessageHeader *hdr;
+  struct GNUNET_PeerIdentity *sender;
+  unsigned int buflen;
+  socklen_t fromlen;
+  struct sockaddr_storage addr;
+  ssize_t ret;
+
+   do
     {
-      if (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 2) == 0)
-        available = VERSION_AVAILABLE_IPV4;
-      else
-        available = VERSION_AVAILABLE_IPV6;
-    }
-  ssize = size + sizeof (UDPMessage);
-  mp = GNUNET_malloc (ssize);
-  mp->header.size = htons (ssize);
-  mp->header.type = 0;
-  mp->sender = *(coreAPI->my_identity);
-  memcpy (&mp[1], message, size);
-  ok = GNUNET_SYSERR;
+      buflen = GNUNET_NETWORK_socket_recvfrom_amount(udp_sock);
 
-  if ((available & VERSION_AVAILABLE_IPV4) > 0)
-    {
-      memset (&serverAddrv4, 0, sizeof (serverAddrv4));
-#if HAVE_SOCKADDR_IN_SIN_LEN
-      serverAddrv4.sin_len = sizeof (serverAddrv4);
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("we expect to read %u bytes\n"), buflen);
 #endif
-      serverAddrv4.sin_family = AF_INET;
-      serverAddrv4.sin_port = haddr->port;
-      memcpy (&serverAddrv4.sin_addr, &haddr->ipv4, sizeof (struct in_addr));
-      addrlen = sizeof (serverAddrv4);
-      serverAddr = (struct sockaddr *) &serverAddrv4;
-    }
-  else
-    {
-      memset (&serverAddrv6, 0, sizeof (serverAddrv6));
-#if HAVE_SOCKADDR_IN_SIN_LEN
-      serverAddrv6.sin6_len = sizeof (serverAddrv6);
+
+      if (buflen == GNUNET_NO)
+        return;
+
+      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
-      serverAddrv6.sin6_family = AF_INET;
-      serverAddrv6.sin6_port = haddr->port;
-      memcpy (&serverAddrv6.sin6_addr, &haddr->ipv6,
-              sizeof (struct in6_addr));
-      addrlen = sizeof (serverAddrv6);
-      serverAddr = (struct sockaddr *) &serverAddrv6;
-    }
-#ifndef MINGW
-  if (GNUNET_YES == GNUNET_socket_send_to (udp_sock,
-                                           GNUNET_NC_NONBLOCKING,
-                                           mp,
-                                           ssize, &sent,
-                                           (const char *) serverAddr,
-                                           addrlen))
-#else
-  sent =
-    win_ols_sendto (udp_sock, mp, ssize, (const char *) serverAddr, addrlen);
-  if (sent != SOCKET_ERROR)
+
+      memset(&addr, 0, fromlen);
+      ret = GNUNET_NETWORK_socket_recvfrom(udp_sock, buf, buflen, (struct 
sockaddr *)&addr, &fromlen);
+
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("socket_recv returned %u, src_addr_len is %u\n"), ret, fromlen);
 #endif
-    {
-      ok = GNUNET_OK;
-      if (stats != NULL)
-        stats->change (stat_bytesSent, sent);
+
+      if (ret <= 0)
+        {
+          GNUNET_free(buf);
+          return;
+        }
+
+      msg = (struct UDPMessage *)buf;
+
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("header reports message size of %d\n"), ntohs(msg->header.size));
+
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("header reports message type of %d\n"), ntohs(msg->header.type));
+#endif
+      /*if (ntohs(hdr->size) < sizeof(struct UDPMessage))
+        {
+          GNUNET_free(buf);
+          GNUNET_NETWORK_fdset_zero(plugin->rs);
+          GNUNET_NETWORK_fdset_set(plugin->rs, udp_sock);
+          break;
+        }*/
+      hdr = (const struct GNUNET_MessageHeader *)&msg[1];
+      sender = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
+      memcpy(sender, &msg->sender, sizeof(struct GNUNET_PeerIdentity));
+
+#if DEBUG_UDP
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("msg reports message size of %d\n"), ntohs(hdr->size));
+
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("msg reports message type of %d\n"), ntohs(hdr->type));
+#endif
+
+      if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PING)
+        {
+          handle_udp_ping(plugin, sender, &addr, fromlen, hdr);
+        }
+
+      if (ntohs(hdr->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PONG)
+        {
+          handle_udp_pong(plugin, sender, hdr);
+        }
+
+      GNUNET_free(buf);
+
     }
-  else
-    {
-      if (stats != NULL)
-        stats->change (stat_bytesDropped, ssize);
-    }
-  GNUNET_free (mp);
-  return ok;
+    while (GNUNET_NETWORK_socket_select (plugin->rs,
+                                         NULL,
+                                         NULL,
+                                         timeout) > 0 && 
GNUNET_NETWORK_fdset_isset(plugin->rs, udp_sock));
+
+    plugin->select_task = GNUNET_SCHEDULER_add_select(plugin->env->sched, 
GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_SCHEDULER_NO_TASK,
+      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, NULL, &udp_plugin_select, 
plugin);
+
 }
 
 /**
- * Start the server process to receive inbound traffic.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * Create a UDP socket.  If possible, use IPv6, otherwise
+ * try IPv4.
  */
-static int
-udp_transport_server_start ()
+static struct GNUNET_NETWORK_Handle *
+udp_transport_server_start (void *cls)
 {
+  struct Plugin *plugin = cls;
+  struct GNUNET_NETWORK_Handle *desc;
   struct sockaddr_in serverAddrv4;
   struct sockaddr_in6 serverAddrv6;
   struct sockaddr *serverAddr;
   socklen_t addrlen;
-  GNUNET_NETWORK_Handle *desc;
-  const int on = 1;
-  unsigned short port;
 
-  GNUNET_GE_ASSERT (coreAPI->ectx, selector == NULL);
-  /* initialize UDP network */
-  port = get_port ();
-  if (port != 0)
+  desc = NULL;
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "GNUNETD", 
"DISABLE-IPV6"))
     {
-      desc = udp_create_socket ();
+      desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 17);
+      if (desc != NULL)
+        {
+          memset (&serverAddrv6, 0, sizeof (serverAddrv6));
+  #if HAVE_SOCKADDR_IN_SIN_LEN
+          serverAddrv6.sin6_len = sizeof (serverAddrv6);
+  #endif
+          serverAddrv6.sin6_family = AF_INET6;
+          serverAddrv6.sin6_addr = in6addr_any;
+          serverAddrv6.sin6_port = htons (plugin->open_port);
+          addrlen = sizeof (serverAddrv6);
+          serverAddr = (struct sockaddr *) &serverAddrv6;
+        }
+    }
+  if (NULL == desc)
+    {
+      desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 17);
       if (NULL == desc)
-        return GNUNET_SYSERR;
-      if (GNUNET_net_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof 
(on)) < 0)
         {
-          GNUNET_GE_DIE_STRERROR (coreAPI->ectx,
-                                  GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
-                                  GNUNET_GE_IMMEDIATE, "setsockopt");
-          return GNUNET_SYSERR;
+          GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG,
+                         "udp",
+                         "socket");
+          return NULL;
         }
-      if (available_protocols == VERSION_AVAILABLE_IPV4)
+      else
         {
           memset (&serverAddrv4, 0, sizeof (serverAddrv4));
-#if HAVE_SOCKADDR_IN_SIN_LEN
+  #if HAVE_SOCKADDR_IN_SIN_LEN
           serverAddrv4.sin_len = sizeof (serverAddrv4);
-#endif
+  #endif
           serverAddrv4.sin_family = AF_INET;
           serverAddrv4.sin_addr.s_addr = INADDR_ANY;
-          serverAddrv4.sin_port = htons (port);
+          serverAddrv4.sin_port = htons (plugin->open_port);
           addrlen = sizeof (serverAddrv4);
           serverAddr = (struct sockaddr *) &serverAddrv4;
         }
-      else
-        {
-          memset (&serverAddrv6, 0, sizeof (serverAddrv6));
-#if HAVE_SOCKADDR_IN_SIN_LEN
-          serverAddrv6.sin6_len = sizeof (serverAddrv6);
-#endif
-          serverAddrv6.sin6_family = AF_INET6;
-          serverAddrv6.sin6_addr = in6addr_any;
-          serverAddrv6.sin6_port = htons (port);
-          addrlen = sizeof (serverAddrv6);
-          serverAddr = (struct sockaddr *) &serverAddrv6;
-        }
-      if (GNUNET_net_bind (desc, serverAddr, addrlen) < 0)
-        {
-          GNUNET_GE_LOG_STRERROR (coreAPI->ectx,
-                                  GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
-                                  GNUNET_GE_IMMEDIATE, "bind");
-          GNUNET_GE_LOG (coreAPI->ectx,
-                         GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
-                         GNUNET_GE_IMMEDIATE,
-                         _("Failed to bind to %s port %d.\n"),
-                         MY_TRANSPORT_NAME, port);
-          if (0 != GNUNET_net_close (&desc))
-            GNUNET_GE_LOG_STRERROR (coreAPI->ectx,
-                                    GNUNET_GE_ERROR | GNUNET_GE_USER |
-                                    GNUNET_GE_ADMIN | GNUNET_GE_BULK,
-                                    "close");
-          return GNUNET_SYSERR;
-        }
-      selector = GNUNET_select_create ("udp", GNUNET_YES, coreAPI->ectx, 
load_monitor, desc, addrlen, 0,        /* timeout */
-                                       &select_message_handler,
-                                       NULL,
-                                       &select_accept_handler,
-                                       NULL,
-                                       &select_close_handler,
-                                       NULL, 64 * 1024,
-                                       16 /* max sockets */ );
-      if (selector == NULL)
-        return GNUNET_SYSERR;
     }
-  desc = udp_create_socket ();
-  if (NULL == desc)
+
+  if (desc != NULL)
     {
-      GNUNET_GE_LOG_STRERROR (coreAPI->ectx,
-                              GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
-                              GNUNET_GE_BULK, "socket");
-      GNUNET_select_destroy (selector);
-      selector = NULL;
-      return GNUNET_SYSERR;
+      GNUNET_assert(GNUNET_NETWORK_socket_bind(desc, serverAddr, addrlen) == 
GNUNET_OK);
     }
-  udp_sock = GNUNET_socket_create (coreAPI->ectx, load_monitor, desc);
-  GNUNET_GE_ASSERT (coreAPI->ectx, udp_sock != NULL);
+
+  plugin->rs = GNUNET_NETWORK_fdset_create ();
+
+  GNUNET_NETWORK_fdset_zero(plugin->rs);
+  GNUNET_NETWORK_fdset_set(plugin->rs, desc);
+
+  plugin->select_task = GNUNET_SCHEDULER_add_select(plugin->env->sched, 
GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_SCHEDULER_NO_TASK,
+      GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, NULL, &udp_plugin_select, 
plugin);
+
+  return desc;
+}
+
+/**
+ * Function that can be used by the transport service to validate that
+ * another peer is reachable at a particular address (even if we
+ * already have a connection to this peer, this function is required
+ * to establish a new one).
+ *
+ * @param cls closure
+ * @param target who should receive this message
+ * @param challenge challenge code to use
+ * @param addrlen length of the address
+ * @param addr the address
+ * @param timeout how long should we try to transmit these?
+ * @return GNUNET_OK if the transmission has been scheduled
+ */
+static int
+udp_plugin_validate (void *cls,
+                    const struct GNUNET_PeerIdentity *target,
+                    uint32_t challenge,
+                    struct GNUNET_TIME_Relative timeout,
+                    const void *addr, size_t addrlen)
+{
+  struct Plugin *plugin = cls;
+  struct Session *new_session;
+  struct UDPPongMessage *msg;
+
+  if (addrlen <= 0)
+    return GNUNET_SYSERR;
+
+  new_session = GNUNET_malloc(sizeof(struct Session));
+  new_session->connect_addr = GNUNET_malloc(addrlen);
+  memcpy(new_session->connect_addr, addr, addrlen);
+  new_session->connect_alen = addrlen;
+#if DEBUG_UDP
+  if (memcmp(target, plugin->env->my_identity, sizeof(struct 
GNUNET_PeerIdentity)) == 0)
+    {
+      GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+              ("definitely adding self to session list... hmmm\n"));
+    }
+#endif
+  memcpy(&new_session->target, target, sizeof(struct GNUNET_PeerIdentity));
+  new_session->challenge = challenge;
+  new_session->validated = GNUNET_NO;
+  new_session->next = plugin->sessions;
+  plugin->sessions = new_session;
+
+  msg = GNUNET_malloc (sizeof (struct UDPPongMessage));
+  msg->header.size = htons(sizeof(struct UDPPongMessage));
+  msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_PING);
+  msg->challenge = htons(challenge);
+#if DEBUG_UDP
+  GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+                 ("In validate, header size is %d, type %d, challenge %u\n"), 
ntohs(msg->header.size), ntohs(msg->header.type), ntohl(msg->challenge));
+#endif
+  udp_plugin_send(plugin, target, GNUNET_SCHEDULER_PRIORITY_DEFAULT, 
&msg->header, timeout, NULL, NULL);
+
   return GNUNET_OK;
 }
 
 /**
+ * Convert the transports address to a nice, human-readable
+ * format.
+ *
+ * @param cls closure
+ * @param type name of the transport that generated the address
+ * @param addr one of the addresses of the host, NULL for the last address
+ *        the specific address format depends on the transport
+ * @param addrlen length of the address
+ * @param numeric should (IP) addresses be displayed in numeric form?
+ * @param timeout after how long should we give up?
+ * @param asc function to call on each string
+ * @param asc_cls closure for asc
+ */
+static void
+udp_plugin_address_pretty_printer (void *cls,
+                                   const char *type,
+                                   const void *addr,
+                                   size_t addrlen,
+                                   int numeric,
+                                   struct GNUNET_TIME_Relative timeout,
+                                   GNUNET_TRANSPORT_AddressStringCallback asc,
+                                   void *asc_cls)
+{
+
+}
+
+/**
+ * Set a quota for receiving data from the given peer; this is a
+ * per-transport limit.  The transport should limit its read/select
+ * calls to stay below the quota (in terms of incoming data).
+ *
+ * @param cls closure
+ * @param target the peer for whom the quota is given
+ * @param quota_in quota for receiving/sending data in bytes per ms
+ */
+static void
+udp_plugin_set_receive_quota (void *cls,
+                              const struct GNUNET_PeerIdentity *target,
+                              uint32_t quota_in)
+{
+
+}
+
+/**
+ * Another peer has suggested an address for this
+ * peer and transport plugin.  Check that this could be a valid
+ * address.  If so, consider adding it to the list
+ * of addresses.
+ *
+ * @param cls closure
+ * @param addr pointer to the address
+ * @param addrlen length of addr
+ * @return GNUNET_OK if this is a plausible address for this peer
+ *         and transport
+ */
+static int
+udp_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
+{
+
+  return GNUNET_SYSERR;
+}
+
+
+/**
  * The exported method. Makes the core api available via a global and
  * returns the udp transport API.
  */
-GNUNET_TransportAPI *
-inittransport_udp (GNUNET_CoreAPIForTransport * core)
+void *
+libgnunet_plugin_transport_udp_init (void *cls)
 {
   unsigned long long mtu;
 
-  cfg = core->cfg;
-  load_monitor = core->load_monitor;
-  GNUNET_GE_ASSERT (coreAPI->ectx, sizeof (UDPMessage) == 68);
-  GNUNET_GE_ASSERT (coreAPI->ectx, sizeof (HostAddress) == 24);
-  coreAPI = core;
-  if (-1 == GNUNET_GC_get_configuration_value_number (cfg,
-                                                      "UDP",
-                                                      "MTU",
-                                                      sizeof (UDPMessage)
-                                                      +
-                                                      
GNUNET_P2P_MESSAGE_OVERHEAD
-                                                      +
-                                                      sizeof
-                                                      (GNUNET_MessageHeader) +
-                                                      32, 65500,
-                                                      MESSAGE_SIZE, &mtu))
+  struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
+  struct GNUNET_TRANSPORT_PluginFunctions *api;
+  struct Plugin *plugin;
+  struct GNUNET_SERVICE_Context *service;
+  unsigned long long aport;
+  unsigned long long bport;
+
+  service = GNUNET_SERVICE_start ("transport-udp", env->sched, env->cfg);
+  if (service == NULL)
     {
+      GNUNET_log_from(GNUNET_ERROR_TYPE_WARNING, "udp", _
+      ("Failed to start service for `%s' transport plugin.\n"), "udp");
       return NULL;
     }
+    aport = 0;
+    if ((GNUNET_OK !=
+         GNUNET_CONFIGURATION_get_value_number (env->cfg,
+                                                "transport-udp",
+                                                "PORT",
+                                                &bport)) ||
+        (bport > 65535) ||
+        ((GNUNET_OK ==
+          GNUNET_CONFIGURATION_get_value_number (env->cfg,
+                                                 "transport-udp",
+                                                 "ADVERTISED-PORT",
+                                                 &aport)) && (aport > 65535)))
+      {
+        GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+                         "udp",
+                         _
+                         ("Require valid port number for service `%s' in 
configuration!\n"),
+                         "transport-udp");
+        GNUNET_SERVICE_stop (service);
+        return NULL;
+      }
+    if (aport == 0)
+      aport = bport;
+
+  mtu = 1240;
   if (mtu < 1200)
-    GNUNET_GE_LOG (coreAPI->ectx,
-                   GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE,
-                   _("MTU %llu for `%s' is probably too low!\n"), mtu, "UDP");
-  lock = GNUNET_mutex_create (GNUNET_NO);
-  if (0 !=
-      GNUNET_GC_attach_change_listener (cfg, &reload_configuration, NULL))
-    {
-      GNUNET_mutex_destroy (lock);
-      lock = NULL;
-      return NULL;
-    }
-  if (GNUNET_GC_get_configuration_value_yesno (cfg, "UDP", "UPNP", GNUNET_YES)
-      == GNUNET_YES)
-    {
-      upnp = coreAPI->service_request ("upnp");
-      if (upnp == NULL)
-        GNUNET_GE_LOG (coreAPI->ectx,
-                       GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE,
-                       "The UPnP service could not be loaded. To disable UPnP, 
set the "
-                       "configuration option \"UPNP\" in section \"%s\" to 
\"NO\"\n",
-                       "UDP");
-    }
-  stats = coreAPI->service_request ("stats");
-  if (stats != NULL)
-    {
-      stat_bytesReceived
-        = stats->create (gettext_noop ("# bytes received via UDP"));
-      stat_bytesSent = stats->create (gettext_noop ("# bytes sent via UDP"));
-      stat_bytesDropped
-        = stats->create (gettext_noop ("# bytes dropped by UDP (outgoing)"));
-      stat_udpConnected
-        = stats->create (gettext_noop ("# UDP connections (right now)"));
-    }
-  myAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_UDP;
-  myAPI.mtu = mtu - sizeof (UDPMessage);
-  myAPI.cost = 20000;
-  myAPI.hello_verify = &verify_hello;
-  myAPI.hello_create = &create_hello;
-  myAPI.connect = &udp_connect;
-  myAPI.send = &udp_send;
-  myAPI.associate = &udp_associate;
-  myAPI.disconnect = &udp_disconnect;
-  myAPI.server_start = &udp_transport_server_start;
-  myAPI.server_stop = &udp_transport_server_stop;
-  myAPI.hello_to_address = &hello_to_address;
-  myAPI.send_now_test = &udp_test_would_try;
+    GNUNET_log_from(GNUNET_ERROR_TYPE_INFO,
+                    "udp",
+                    _("MTU %llu for `%s' is probably too low!\n"), mtu, "UDP");
 
-  return &myAPI;
+  plugin = GNUNET_malloc (sizeof (struct Plugin));
+  plugin->open_port = bport;
+  plugin->adv_port = aport;
+  plugin->env = env;
+  plugin->statistics = NULL;
+  api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+  plugin->sessions = NULL;
+  api->cls = plugin;
+
+  api->validate = &udp_plugin_validate;
+  api->send = &udp_plugin_send;
+  api->disconnect = &udp_disconnect;
+  api->address_pretty_printer = &udp_plugin_address_pretty_printer;
+  api->set_receive_quota = &udp_plugin_set_receive_quota;
+  api->address_suggested = &udp_plugin_address_suggested;
+  api->cost_estimate = 17;      /* TODO: ATS */
+  plugin->service = service;
+
+  udp_sock = udp_transport_server_start(plugin);
+
+  GNUNET_assert(udp_sock != NULL);
+
+  return api;
 }
 
-void
-donetransport_udp ()
+void *
+libgnunet_plugin_transport_udp_done (void *cls)
 {
-  do_shutdown ();
+  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
+  struct Plugin *plugin = api->cls;
+
+  udp_transport_server_stop(plugin);
+  if (NULL != hostname_dns)
+    {
+      GNUNET_RESOLVER_request_cancel (hostname_dns);
+      hostname_dns = NULL;
+    }
+  GNUNET_SERVICE_stop (plugin->service);
+  GNUNET_free (plugin);
+  GNUNET_free (api);
+  return NULL;
 }
 
-/* end of udp.c */
+/* end of plugin_transport_udp.c */

Added: gnunet/src/transport/test_plugin_transport_data_udp.conf
===================================================================
--- gnunet/src/transport/test_plugin_transport_data_udp.conf                    
        (rev 0)
+++ gnunet/src/transport/test_plugin_transport_data_udp.conf    2010-01-19 
13:23:04 UTC (rev 10059)
@@ -0,0 +1,24 @@
+[PATHS]
+SERVICEHOME = /tmp/test-gnunetd-plugin-transport/
+
+[resolver]
+PORT = 2364
+
+[transport]
+PORT = 2365
+PLUGINS = udp
+
+[arm]
+PORT = 2366
+
+[statistics]
+PORT = 2367
+
+[transport-udp]
+PORT = 2368
+
+[peerinfo]
+PORT = 2369
+
+[testing]
+WEAKRANDOM = YES

Added: gnunet/src/transport/test_plugin_transport_udp.c
===================================================================
--- gnunet/src/transport/test_plugin_transport_udp.c                            
(rev 0)
+++ gnunet/src/transport/test_plugin_transport_udp.c    2010-01-19 13:23:04 UTC 
(rev 10059)
@@ -0,0 +1,358 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file transport/test_transport_api.c
+ * @brief testcase for transport_api.c
+ * @author Sailor Siraj
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_getopt_lib.h"
+#include "gnunet_hello_lib.h"
+#include "gnunet_os_lib.h"
+#include "gnunet_peerinfo_service.h"
+#include "gnunet_plugin_lib.h"
+#include "gnunet_protocols.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_signatures.h"
+#include "plugin_transport.h"
+#include "transport.h"
+
+#define VERBOSE GNUNET_NO
+
+/**
+ * How long until we give up on transmitting the message?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+/**
+ * Our public key.
+ */
+static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
+
+/**
+ * Our identity.
+ */
+static struct GNUNET_PeerIdentity my_identity;
+
+/**
+ * Our private key.
+ */
+static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
+
+/**
+ * Our scheduler.
+ */
+struct GNUNET_SCHEDULER_Handle *sched;
+
+/**
+ * Our configuration.
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Number of neighbours we'd like to have.
+ */
+static uint32_t max_connect_per_transport;
+
+/**
+ * Environment for this plugin.
+ */
+struct GNUNET_TRANSPORT_PluginEnvironment env;
+
+/**
+ *handle for the api provided by this plugin
+ */
+struct GNUNET_TRANSPORT_PluginFunctions *api;
+
+/**
+ * Did the test pass or fail?
+ */
+static int ok;
+
+/**
+ * Initialize Environment for this plugin
+ */
+static void
+receive(void *cls,
+        struct GNUNET_TIME_Relative
+        latency,
+        const struct GNUNET_PeerIdentity
+        * peer,
+        const struct GNUNET_MessageHeader
+        * message)
+{
+  /* do nothing */
+}
+
+void notify_address(void *cls,
+                    const char *name,
+                    const void *addr,
+                    size_t addrlen,
+                    struct
+                    GNUNET_TIME_Relative
+                    expires)
+{
+}
+
+/**
+ * Function called when the service shuts
+ * down.  Unloads our plugins.
+ *
+ * @param cls closure
+ * @param cfg configuration to use
+ */
+static void
+unload_plugins (void *cls,
+                const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  GNUNET_assert (NULL == GNUNET_PLUGIN_unload 
("libgnunet_plugin_transport_udp",api));
+  if (my_private_key != NULL)
+    GNUNET_CRYPTO_rsa_key_free (my_private_key);
+
+}
+
+
+static void
+unload_task (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  unload_plugins (NULL, cfg);
+}
+
+
+static GNUNET_SCHEDULER_TaskIdentifier validation_timeout_task;
+
+
+static void
+validation_notification (void *cls,
+                         const char *name,
+                         const struct GNUNET_PeerIdentity *peer,
+                         uint32_t challenge,
+                         const char *sender_addr)
+{
+  if (validation_timeout_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (sched, validation_timeout_task);
+      validation_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+
+  GNUNET_assert (challenge == 42);
+
+  ok = 0; /* if the last test succeeded, report success */
+
+  GNUNET_SCHEDULER_add_continuation (sched,
+                                     &unload_task,
+                                     (void*) cfg,
+                                     GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+}
+
+
+static void
+validation_failed (void *cls,
+                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  validation_timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_break (0); /* output error */
+  /* the "validation_notification" was not called
+     in a timely fashion; we should set an error
+     code for main and shut down */
+  unload_plugins (NULL, cfg);
+}
+
+
+/**
+ * Simple example test that invokes
+ * the "validate" function of the plugin
+ * and tries to see if the plugin would
+ * succeed to validate its own address.
+ * (This test is not well-written since
+ *  we hand-compile the address which
+ *  kind-of works for TCP but would not
+ *  work for other plugins; we should ask
+ *  the plugin about its address instead...).
+ */
+/* FIXME: won't work on IPv6 enabled systems where IPv4 mapping
+ * isn't enabled (eg. FreeBSD > 4)
+ */
+static void
+test_validation ()
+{
+  struct sockaddr_in soaddr;
+
+  memset (&soaddr, 0, sizeof(soaddr));
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  soaddr.sin_len = sizeof (soaddr);
+#endif
+  soaddr.sin_family = AF_INET;
+  soaddr.sin_port = htons(2368 /* FIXME: get from config! */);
+  soaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+  /* add job to catch failure (timeout) */
+  validation_timeout_task =
+    GNUNET_SCHEDULER_add_delayed (sched,
+                                  TIMEOUT,
+                                  &validation_failed,
+                                  NULL);
+
+  api->validate (api->cls,
+                 &my_identity,
+                 42,
+                 TIMEOUT,
+                 &soaddr,
+                 sizeof(soaddr));
+}
+
+
+static void setup_plugin_environment()
+{
+  env.cfg  = cfg;
+  env.sched = sched;
+  env.my_public_key = &my_public_key;
+  env.my_private_key = my_private_key;
+  env.my_identity = &my_identity;
+  env.cls=&env;
+  env.receive=&receive;
+  env.notify_address=&notify_address;
+  env.notify_validation = &validation_notification;
+  env.max_connections = max_connect_per_transport;
+}
+static int retx;
+
+/**
+ * Runs the test.
+ *
+ * @param cls closure
+ * @param s scheduler to use
+ * @param c configuration to use
+ */
+static void
+run (void *cls,
+     struct GNUNET_SCHEDULER_Handle *s,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  unsigned long long tneigh;
+  char *keyfile;
+  char *libname;
+
+  sched = s;
+  cfg = c;
+  /* parse configuration */
+  if ((GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_number (c,
+                                              "TRANSPORT",
+                                              "NEIGHBOUR_LIMIT",
+                                              &tneigh)) ||
+      (GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_filename (c,
+                                                "GNUNETD",
+                                                "HOSTKEY", &keyfile)))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Transport service is lacking key configuration settings.  
Exiting.\n"));
+      GNUNET_SCHEDULER_shutdown (s);
+      return;
+    }
+  max_connect_per_transport = (uint32_t) tneigh;
+  my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+  GNUNET_free (keyfile);
+  if (my_private_key == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Transport service could not access hostkey.  
Exiting.\n"));
+      GNUNET_SCHEDULER_shutdown (s);
+      return;
+    }
+  GNUNET_CRYPTO_rsa_key_get_public (my_private_key,
+                                    &my_public_key);
+  GNUNET_CRYPTO_hash (&my_public_key,
+                      sizeof (my_public_key),
+                      &my_identity.hashPubKey);
+
+  /* load plugins... */
+  setup_plugin_environment();
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              _("Loading udp transport plugin\n"));
+  GNUNET_asprintf (&libname, "libgnunet_plugin_transport_udp");
+
+  api = GNUNET_PLUGIN_load(libname, &env);
+  GNUNET_free (libname);
+  if (api == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Failed to load transport plugin for udp\n"));
+      /* FIXME: set some error code for main */
+      return;
+    }
+  test_validation ();
+}
+
+
+/**
+ * The main function for the transport service.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  int ret;
+  char *const argv_prog[] = {
+    "test_plugin_transport",
+    "-c",
+    "test_plugin_transport_data_udp.conf",
+    "-L",
+#if VERBOSE
+    "DEBUG",
+#else
+    "WARNING",
+#endif
+    NULL
+  };
+  GNUNET_log_setup ("test-plugin-transport",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ok = 1; /* set to fail */
+  ret = (GNUNET_OK ==
+          GNUNET_PROGRAM_run (5,
+                              argv_prog,
+                              "test-plugin-transport",
+                              "testcase",
+                              options,
+                              &run, NULL)) ? ok : 1;
+  GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-plugin-transport");
+  return ret;
+}
+
+/* end of test_plugin_transport_udp.c */

Modified: gnunet/src/util/network.c
===================================================================
--- gnunet/src/util/network.c   2010-01-19 11:03:57 UTC (rev 10058)
+++ gnunet/src/util/network.c   2010-01-19 13:23:04 UTC (rev 10059)
@@ -355,12 +355,68 @@
 
 
 /**
+ * How much data is available to be read on this descriptor?
+ *
+ * Returns GNUNET_NO if no data is available, or on error!
+ * @param desc socket
+ */
+unsigned int
+GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle * 
desc)
+{
+  int error;
+  unsigned int pending;
+
+  /* How much is there to be read? */
+  error = ioctl(desc->fd, FIONREAD, &pending);
+  GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
+            ("pending is %u bytes, error is %d\n"), pending, error);
+
+  if (error == 0)
+    return pending;
+  else
+    return GNUNET_NO;
+}
+
+/**
  * Read data from a connected socket (always non-blocking).
  * @param desc socket
  * @param buffer buffer
  * @param length length of buffer
+ * @param src_addr either the source to recv from, or all zeroes
+ *        to be filled in by recvfrom
+ * @param addrlen length of the addr
  */
 ssize_t
+GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
+                                void *buffer, size_t length,
+                                struct sockaddr *src_addr, socklen_t *addrlen)
+{
+  int ret;
+  int flags;
+  flags = 0;
+
+#ifdef MSG_DONTWAIT
+  flags |= MSG_DONTWAIT;
+
+#endif /*  */
+  ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
+
+#ifdef MINGW
+  if (SOCKET_ERROR == ret)
+    SetErrnoFromWinsockError (WSAGetLastError ());
+
+#endif /*  */
+  return ret;
+}
+
+
+/**
+ * Read data from a connected socket (always non-blocking).
+ * @param desc socket
+ * @param buffer buffer
+ * @param length length of buffer
+ */
+ssize_t
 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
                             void *buffer, size_t length)
 {
@@ -643,6 +699,12 @@
 #endif
 }
 
+int
+GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
+{
+  return desc->fd;
+}
+
 /**
  * Copy a native fd set
  *

Modified: gnunet/src/util/scheduler.c
===================================================================
--- gnunet/src/util/scheduler.c 2010-01-19 11:03:57 UTC (rev 10058)
+++ gnunet/src/util/scheduler.c 2010-01-19 13:23:04 UTC (rev 10059)
@@ -365,7 +365,7 @@
     {
 #if DEBUG_TASKS
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Checking readyness of task: %llu / %p\n",
+                  "Checking readiness of task: %llu / %p\n",
                   pos->id, pos->callback_cls);
 #endif
       next = pos->next;
@@ -406,7 +406,7 @@
       pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN;
       /* we don't move the task into the ready queue yet; check_ready
          will do that later, possibly adding additional
-         readyness-factors */
+         readiness-factors */
       pos = pos->next;
     }
   for (i=0;i<GNUNET_SCHEDULER_PRIORITY_COUNT;i++)
@@ -417,7 +417,7 @@
          pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN;
          /* we don't move the task into the ready queue yet; check_ready
             will do that later, possibly adding additional
-            readyness-factors */
+            readiness-factors */
          pos = pos->next;
        }
     }  
@@ -773,7 +773,7 @@
  * @param sched scheduler to use
  * @param prerequisite_task run this task after the task with the given
  *        task identifier completes (and any of our other
- *        conditions, such as delay, read or write-readyness
+ *        conditions, such as delay, read or write-readiness
  *        are satisfied).  Use  GNUNET_SCHEDULER_NO_TASK to not have any 
dependency
  *        on completion of other tasks (this will cause the task to run as
  *        soon as possible).
@@ -1044,7 +1044,7 @@
  * @param prio how important is this task?
  * @param prerequisite_task run this task after the task with the given
  *        task identifier completes (and any of our other
- *        conditions, such as delay, read or write-readyness
+ *        conditions, such as delay, read or write-readiness
  *        are satisfied).  Use GNUNET_SCHEDULER_NO_TASK to not have any 
dependency
  *        on completion of other tasks.
  * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for 
"forever",





reply via email to

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