gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r13670 - in gnunet: . src src/core src/dht src/dv src/fs sr


From: gnunet
Subject: [GNUnet-SVN] r13670 - in gnunet: . src src/core src/dht src/dv src/fs src/hostlist src/include src/testing src/topology
Date: Sat, 13 Nov 2010 21:37:37 +0100

Author: grothoff
Date: 2010-11-13 21:37:37 +0100 (Sat, 13 Nov 2010)
New Revision: 13670

Removed:
   gnunet/src/core/core_api_iterate_peers.c
   gnunet/src/core/core_api_peer_get_info.c
   gnunet/src/core/core_api_peer_request.c
Modified:
   gnunet/TODO
   gnunet/src/Makefile.am
   gnunet/src/core/Makefile.am
   gnunet/src/core/core.h
   gnunet/src/core/core_api.c
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/core/test_core_api.c
   gnunet/src/core/test_core_api_reliability.c
   gnunet/src/core/test_core_api_start_only.c
   gnunet/src/core/test_core_quota_compliance.c
   gnunet/src/dht/gnunet-dht-driver.c
   gnunet/src/dht/gnunet-service-dht.c
   gnunet/src/dv/Makefile.am
   gnunet/src/dv/gnunet-service-dv.c
   gnunet/src/fs/gnunet-service-fs.c
   gnunet/src/hostlist/gnunet-daemon-hostlist.c
   gnunet/src/hostlist/hostlist-client.c
   gnunet/src/hostlist/hostlist-server.c
   gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
   gnunet/src/include/gnunet_core_service.h
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_testing_lib.h
   gnunet/src/include/gnunet_transport_plugin.h
   gnunet/src/include/gnunet_transport_service.h
   gnunet/src/testing/test_testing_topology.c
   gnunet/src/testing/testing.c
   gnunet/src/testing/testing_group.c
   gnunet/src/topology/gnunet-daemon-topology.c
Log:
the big core API/protocol change, breaks all testcases using core, since the 
code is still buggy

Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/TODO 2010-11-13 20:37:37 UTC (rev 13670)
@@ -1,4 +1,11 @@
 0.9.0pre2:
+* BIG CORE REFACTORING:
+  - get testcases to pass again (!)
+  - fix transport service API (ATS!)
+  - fix transport plugin API (ATS!)
+  - actually transmit ATS data through core API
+  - fix FS 'latency' ATS function
+  - fix DV
 * Integration test:
   - test bootstrapping via hostlist + transport/core/dht connect
 

Modified: gnunet/src/Makefile.am
===================================================================
--- gnunet/src/Makefile.am      2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/Makefile.am      2010-11-13 20:37:37 UTC (rev 13670)
@@ -28,7 +28,7 @@
   peerinfo-tool \
   core \
   testing \
-  dv \
+  $(dv) \
   dht \
   hostlist \
   topology \

Modified: gnunet/src/core/Makefile.am
===================================================================
--- gnunet/src/core/Makefile.am 2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/core/Makefile.am 2010-11-13 20:37:37 UTC (rev 13670)
@@ -14,10 +14,7 @@
   libgnunetcore.la
 
 libgnunetcore_la_SOURCES = \
-  core_api.c core.h \
-  core_api_peer_get_info.c \
-  core_api_peer_request.c \
-  core_api_iterate_peers.c
+  core_api.c core.h 
 libgnunetcore_la_LIBADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL) $(XLIB)

Modified: gnunet/src/core/core.h
===================================================================
--- gnunet/src/core/core.h      2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/core/core.h      2010-11-13 20:37:37 UTC (rev 13670)
@@ -22,6 +22,17 @@
  * @file core/core.h
  * @brief common internal definitions for core service
  * @author Christian Grothoff
+ *
+ * TODO:
+ * - bound message queue size
+ * - on disconnect from core, signal disconnect for all peers
+ *   and clean up peer records
+ * - create / destroy peer records on connect/disconnect events
+ * - implement iterator API
+ * - implement re-configure API
+ * - check on peer-related events that connection is known
+ *   (if not, GNUNET_break + reconnect)
+ * - handle atsi records
  */
 #include "gnunet_bandwidth_lib.h"
 #include "gnunet_crypto_lib.h"
@@ -112,9 +123,10 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * Distance to the peer.
+   * Number of ATS key-value pairs that follow this struct
+   * (excluding the 0-terminator).
    */
-  uint32_t distance GNUNET_PACKED;
+  uint32_t ats_count GNUNET_PACKED;
 
   /**
    * Currently observed latency.
@@ -126,6 +138,12 @@
    */
   struct GNUNET_PeerIdentity peer;
 
+  /**
+   * First of the ATS information blocks (we must have at least
+   * one due to the 0-termination requirement).
+   */
+  struct GNUNET_TRANSPORT_ATS_Information ats;
+
 };
 
 
@@ -141,16 +159,12 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * Distance to the peer.
+   * Number of ATS key-value pairs that follow this struct
+   * (excluding the 0-terminator).
    */
-  uint32_t distance GNUNET_PACKED;
+  uint32_t ats_count GNUNET_PACKED;
 
   /**
-   * Currently observed latency.
-   */
-  struct GNUNET_TIME_RelativeNBO latency;
-
-  /**
    * When the peer would time out (unless we see activity)
    */
   struct GNUNET_TIME_AbsoluteNBO timeout;
@@ -170,6 +184,12 @@
    */
   struct GNUNET_PeerIdentity peer;
 
+  /**
+   * First of the ATS information blocks (we must have at least
+   * one due to the 0-termination requirement).
+   */
+  struct GNUNET_TRANSPORT_ATS_Information ats;
+
 };
 
 
@@ -197,7 +217,6 @@
 };
 
 
-
 /**
  * Message sent by the service to clients to notify them about
  * messages being received or transmitted.  This overall message is
@@ -216,9 +235,10 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * Distance to the peer.
+   * Number of ATS key-value pairs that follow this struct
+   * (excluding the 0-terminator).
    */
-  uint32_t distance GNUNET_PACKED;
+  uint32_t ats_count GNUNET_PACKED;
 
   /**
    * Currently observed latency.
@@ -230,6 +250,12 @@
    */
   struct GNUNET_PeerIdentity peer;
 
+  /**
+   * First of the ATS information blocks (we must have at least
+   * one due to the 0-termination requirement).
+   */
+  struct GNUNET_TRANSPORT_ATS_Information ats;
+
 };
 
 
@@ -245,9 +271,9 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * Always zero.
+   * Unique request ID.
    */
-  uint32_t reserved GNUNET_PACKED;
+  uint32_t rim_id GNUNET_PACKED;
 
   /**
    * Limit the number of bytes of outbound traffic to this
@@ -296,10 +322,9 @@
   int32_t reserved_amount GNUNET_PACKED;
 
   /**
-   * Available bandwidth in for this peer.
-   * 0 if we have been disconnected.
+   * Unique request ID.
    */
-  struct GNUNET_BANDWIDTH_Value32NBO bw_in;
+  uint32_t rim_id GNUNET_PACKED;
 
   /**
    * Available bandwidth out for this peer,
@@ -314,7 +339,7 @@
   uint64_t preference;
 
   /**
-   * Identity of the receiver or sender.
+   * Identity of the peer.
    */
   struct GNUNET_PeerIdentity peer;
 
@@ -322,9 +347,87 @@
 
 
 /**
- * Client asking core to transmit a particular message to
- * a particular target.  
+ * Client notifying core about the maximum-priority
+ * message it has in the queue for a particular target.
  */
+struct SendMessageRequest
+{
+  /**
+   * Header with type GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * How important is this message?
+   */
+  uint32_t priority GNUNET_PACKED;
+
+  /**
+   * By what time would the sender really like to see this
+   * message transmitted?
+   */
+  struct GNUNET_TIME_AbsoluteNBO deadline;
+
+  /**
+   * Identity of the intended target.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * How large is the client's message queue for this peer?
+   */
+  uint32_t queue_size GNUNET_PACKED;
+
+  /**
+   * How large is the message?
+   */
+  uint16_t size GNUNET_PACKED;
+
+  /**
+   * Counter for this peer to match SMRs to replies.
+   */
+  uint16_t smr_id GNUNET_PACKED;
+
+};
+
+
+/**
+ * Core notifying client that it is allowed to now 
+ * transmit a message to the given target
+ * (response to GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST).
+ */
+struct SendMessageReady
+{
+  /**
+   * Header with type GNUNET_MESSAGE_TYPE_CORE_SEND_READY
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * How many bytes are allowed for transmission? 
+   * Guaranteed to be at least as big as the requested size,
+   * or ZERO if the request is rejected (will timeout, 
+   * peer disconnected, queue full, etc.).
+   */
+  uint16_t size GNUNET_PACKED;
+
+  /**
+   * smr_id from the request.
+   */
+  uint16_t smr_id GNUNET_PACKED;
+
+  /**
+   * Identity of the intended target.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+};
+
+
+/**
+ * Client asking core to transmit a particular message to a particular
+ * target (responsde to GNUNET_MESSAGE_TYPE_CORE_SEND_READY).
+ */
 struct SendMessage
 {
   /**

Modified: gnunet/src/core/core_api.c
===================================================================
--- gnunet/src/core/core_api.c  2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/core/core_api.c  2010-11-13 20:37:37 UTC (rev 13670)
@@ -23,6 +23,9 @@
  * @brief core service; this is the main API for encrypted P2P
  *        communications
  * @author Christian Grothoff
+ *
+ * TODO:
+ * - implement atsi parsing and passing
  */
 #include "platform.h"
 #include "gnunet_constants.h"
@@ -31,12 +34,124 @@
 
 
 /**
+ * Information we track for each peer.
+ */
+struct PeerRecord
+{
+
+  /**
+   * We generally do NOT keep peer records in a DLL; this
+   * DLL is only used IF this peer's 'pending_head' message
+   * is ready for transmission.  
+   */
+  struct PeerRecord *prev;
+
+  /**
+   * We generally do NOT keep peer records in a DLL; this
+   * DLL is only used IF this peer's 'pending_head' message
+   * is ready for transmission. 
+   */
+  struct PeerRecord *next;
+
+  /**
+   * Peer the record is about.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+  /**
+   * Corresponding core handle.
+   */
+  struct GNUNET_CORE_Handle *ch;
+
+  /**
+   * Head of doubly-linked list of pending requests.
+   * Requests are sorted by deadline *except* for HEAD,
+   * which is only modified upon transmission to core.
+   */
+  struct GNUNET_CORE_TransmitHandle *pending_head;
+
+  /**
+   * Tail of doubly-linked list of pending requests.
+   */
+  struct GNUNET_CORE_TransmitHandle *pending_tail;
+
+  /**
+   * Pending callback waiting for peer information, or NULL for none.
+   */
+  GNUNET_CORE_PeerConfigurationInfoCallback pcic;
+
+  /**
+   * Closure for pcic.
+   */
+  void *pcic_cls;
+
+  /**
+   * Request information ID for the given pcic (needed in case a
+   * request is cancelled after being submitted to core and a new
+   * one is generated; in this case, we need to avoid matching the
+   * reply to the first (cancelled) request to the second request).
+   */
+  uint32_t rim_id;
+
+  /**
+   * ID of timeout task for the 'pending_head' handle
+   * which is the one with the smallest timeout. 
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * Current size of the queue of pending requests.
+   */
+  unsigned int queue_size;
+
+  /**
+   * SendMessageRequest ID generator for this peer.
+   */
+  uint16_t smr_id_gen;
+  
+};
+
+
+/**
+ * Entry in a doubly-linked list of control messages to be transmitted
+ * to the core service.  Control messages include traffic allocation,
+ * connection requests and of course our initial 'init' request.
+ * 
+ * The actual message is allocated at the end of this struct.
+ */
+struct ControlMessage
+{
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ControlMessage *next;
+
+  /**
+   * This is a doubly-linked list.
+   */
+  struct ControlMessage *prev;
+
+  /**
+   * Function to run after successful transmission (or call with
+   * reason 'TIMEOUT' on error).
+   */
+  GNUNET_SCHEDULER_Task cont;
+
+  /**
+   * Closure for 'cont'.
+   */
+  void *cont_cls;
+
+};
+
+
+
+/**
  * Context for the core service connection.
  */
 struct GNUNET_CORE_Handle
 {
 
-
   /**
    * Configuration we're using.
    */
@@ -83,9 +198,9 @@
   const struct GNUNET_CORE_MessageHandler *handlers;
 
   /**
-   * Our connection to the service for notifications.
+   * Our connection to the service.
    */
-  struct GNUNET_CLIENT_Connection *client_notifications;
+  struct GNUNET_CLIENT_Connection *client;
 
   /**
    * Handle for our current transmission request.
@@ -95,41 +210,43 @@
   /**
    * Head of doubly-linked list of pending requests.
    */
-  struct GNUNET_CORE_TransmitHandle *pending_head;
+  struct ControlMessage *pending_head;
 
   /**
    * Tail of doubly-linked list of pending requests.
    */
-  struct GNUNET_CORE_TransmitHandle *pending_tail;
+  struct ControlMessage *pending_tail;
 
   /**
-   * Currently submitted request (or NULL)
+   * Head of doubly-linked list of peers that are core-approved
+   * to send their next message.
    */
-  struct GNUNET_CORE_TransmitHandle *submitted;
+  struct PeerRecord *ready_peer_head;
 
   /**
-   * Currently submitted request based on solicitation (or NULL)
+   * Tail of doubly-linked list of peers that are core-approved
+   * to send their next message.
    */
-  struct GNUNET_CORE_TransmitHandle *solicit_transmit_req;
+  struct PeerRecord *ready_peer_tail;
 
   /**
-   * Buffer where we store a message for transmission in response
-   * to a traffic solicitation (or NULL).
+   * Hash map listing all of the peers that we are currently
+   * connected to.
    */
-  char *solicit_buffer;
+  struct GNUNET_CONTAINER_MultiHashMap *peers;
 
   /**
-   * How long to wait until we time out the connection attempt?
+   * ID of reconnect task (if any).
    */
-  struct GNUNET_TIME_Absolute startup_timeout;
+  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
 
   /**
-   * ID of reconnect task (if any).
+   * Request information ID generator.
    */
-  GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+  uint32_t rim_id_gen;
 
   /**
-   * Number of messages we should queue per target.
+   * Number of messages we are allowed to queue per target.
    */
   unsigned int queue_size;
 
@@ -155,6 +272,7 @@
    * requests?
    */
   int currently_down;
+
 };
 
 
@@ -175,11 +293,17 @@
   struct GNUNET_CORE_TransmitHandle *prev;
 
   /**
-   * Corresponding core handle.
+   * Corresponding peer record.
    */
-  struct GNUNET_CORE_Handle *ch;
+  struct PeerRecord *peer;
 
   /**
+   * Corresponding SEND_REQUEST message.  Only non-NULL 
+   * while SEND_REQUEST message is pending.
+   */
+  struct ControlMessage *cm;
+
+  /**
    * Function that will be called to get the actual request
    * (once we are ready to transmit this request to the core).
    * The function will be called with a NULL buffer to signal
@@ -193,32 +317,11 @@
   void *get_message_cls;
 
   /**
-   * If this entry is for a transmission request, pointer
-   * to the notify callback; otherwise NULL.
-   */
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-
-  /**
-   * Closure for notify.
-   */
-  void *notify_cls;
-
-  /**
-   * Peer the request is about.
-   */
-  struct GNUNET_PeerIdentity peer;
-
-  /**
    * Timeout for this handle.
    */
   struct GNUNET_TIME_Absolute timeout;
 
   /**
-   * ID of timeout task.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
    * How important is this message?
    */
   uint32_t priority;
@@ -228,58 +331,131 @@
    */
   uint16_t msize;
 
+  /**
+   * Send message request ID for this request.
+   */
+  uint16_t smr_id;
 
 };
 
 
+/**
+ * Our current client connection went down.  Clean it up
+ * and try to reconnect!
+ *
+ * @param h our handle to the core service
+ */
 static void
-reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+reconnect (struct GNUNET_CORE_Handle *h);
 
 
 /**
- * Function called when we are ready to transmit our
- * "START" message (or when this operation timed out).
+ * Task schedule to try to re-connect to core.
  *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @param cls the 'struct GNUNET_CORE_Handle'
+ * @param tc task context
  */
-static size_t transmit_start (void *cls, size_t size, void *buf);
+static void
+reconnect_task (void *cls, 
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CORE_Handle *h = cls;
 
+  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  reconnect (h);
+}
 
+
 /**
- * Our current client connection went down.  Clean it up
- * and try to reconnect!
+ * Check the list of pending requests, send the next
+ * one to the core.
  *
- * @param h our handle to the core service
+ * @param h core handle
  */
 static void
-reconnect (struct GNUNET_CORE_Handle *h)
+trigger_next_request (struct GNUNET_CORE_Handle *h);
+
+
+/**
+ * The given request hit its timeout.  Remove from the
+ * doubly-linked list and call the respective continuation.
+ *
+ * @param cls the transmit handle of the request that timed out
+ * @param tc context, can be NULL (!)
+ */
+static void
+transmission_timeout (void *cls, 
+                     const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Control message was sent, mark it as such.
+ *
+ * @param cls the 'struct GNUNET_CORE_TransmitHandle*'
+ * @param tc scheduler context
+ */
+static void
+mark_control_message_sent (void *cls,
+                          const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Reconnecting to CORE service\n");
-#endif
-  if (h->client_notifications != NULL)
-    GNUNET_CLIENT_disconnect (h->client_notifications, GNUNET_NO);
-  h->currently_down = GNUNET_YES;
-  h->client_notifications = GNUNET_CLIENT_connect ("core", h->cfg);
-  if (h->client_notifications == NULL)
-    h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                                     &reconnect_task,
-                                                     h);
-  else
-    h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
-                                                 sizeof (struct InitMessage) +
-                                                 sizeof (uint16_t) * h->hcnt,
-                                                 GNUNET_TIME_UNIT_SECONDS,
-                                                 GNUNET_NO,
-                                                 &transmit_start, h);
+  struct GNUNET_CORE_TransmitHandle *th = cls;
+
+  th->cm = NULL;
 }
 
 
 /**
+ * Send a control message to the peer asking for transmission
+ * of the message in the given peer record.
+ *
+ * @param pr peer to request transmission to
+ */
+static void
+request_next_transmission (struct PeerRecord *pr)
+{
+  struct GNUNET_CORE_Handle *h = pr->ch;
+  struct ControlMessage *cm;
+  struct SendMessageRequest *smr;
+  struct GNUNET_CORE_TransmitHandle *th;
+
+  if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (pr->timeout_task);
+      pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  if (NULL == (th = pr->pending_head))
+    {
+      trigger_next_request (h);
+      return;
+    }
+  GNUNET_assert (pr->prev == NULL);
+  GNUNET_assert (pr->next == NULL);
+  pr->timeout_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_absolute_get_remaining (th->timeout),
+                                                  &transmission_timeout,
+                                                  pr);
+  cm = GNUNET_malloc (sizeof (struct ControlMessage) + 
+                     sizeof (struct SendMessageRequest));
+  cm->cont = &mark_control_message_sent;
+  cm->cont_cls = th;
+  th->cm = cm;
+  smr = (struct SendMessageRequest*) &cm[1];
+  smr->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
+  smr->header.size = htons (sizeof (struct SendMessageRequest));
+  smr->priority = htonl (th->priority);
+  smr->deadline = GNUNET_TIME_absolute_hton (th->timeout);
+  smr->peer = pr->peer;
+  smr->queue_size = htonl (pr->queue_size);
+  smr->size = htons (th->msize);
+  smr->smr_id = htons (th->smr_id = pr->smr_id_gen++);
+  GNUNET_CONTAINER_DLL_insert_after (h->pending_head,
+                                    h->pending_tail,
+                                    h->pending_tail,
+                                    cm);
+  trigger_next_request (h);
+}
+
+
+/**
  * The given request hit its timeout.  Remove from the
  * doubly-linked list and call the respective continuation.
  *
@@ -287,97 +463,225 @@
  * @param tc context, can be NULL (!)
  */
 static void
-timeout_request (void *cls, 
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmission_timeout (void *cls, 
+                     const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct GNUNET_CORE_TransmitHandle *th = cls;
+  struct PeerRecord *pr = cls;
+  struct GNUNET_CORE_TransmitHandle *th;
 
-  th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_CONTAINER_DLL_remove (th->ch->pending_head,
-                               th->ch->pending_tail,
+  pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  th = pr->pending_head;
+  GNUNET_CONTAINER_DLL_remove (pr->pending_head,
+                               pr->pending_tail,
                                th);
+  pr->queue_size--;
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Signalling timeout of request for transmission to CORE 
service\n");
 #endif
   GNUNET_assert (0 == th->get_message (th->get_message_cls, 0, NULL));
+  request_next_transmission (pr);
 }
 
 
 /**
- * Function called when we are ready to transmit a request from our
- * request list (or when this operation timed out).
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * Transmit the next message to the core service.
  */
 static size_t
-request_start (void *cls, size_t size, void *buf)
+transmit_message (void *cls,
+                 size_t size, 
+                 void *buf)
 {
   struct GNUNET_CORE_Handle *h = cls;
+  struct ControlMessage *cm;
   struct GNUNET_CORE_TransmitHandle *th;
+  struct PeerRecord *pr;
+  struct SendMessage *sm;
+  const struct GNUNET_MessageHeader *hdr;
+  uint16_t msize;
   size_t ret;
 
-  h->cth = NULL;  
-  th = h->pending_head;
-  if (th == NULL)
-    return 0;
+  h->cth = NULL;
   if (buf == NULL)
     {
-      if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+      reconnect (h);
+      return 0;
+    }
+  /* first check for control messages */
+  if (NULL != (cm = h->pending_head))
+    {
+      hdr = (const struct GNUNET_MessageHeader*) &cm[1];
+      msize = ntohs (hdr->size);
+      if (size < msize)
        {
-         GNUNET_SCHEDULER_cancel(th->timeout_task);
-         th->timeout_task = GNUNET_SCHEDULER_NO_TASK;  
+         trigger_next_request (h);
+         return 0;
        }
-      timeout_request (th, NULL);
-      return 0;
+      memcpy (buf, hdr, msize);
+      GNUNET_CONTAINER_DLL_remove (h->pending_head,
+                                  h->pending_tail,
+                                  cm);
+      if (NULL != cm->cont)
+       GNUNET_SCHEDULER_add_now (cm->cont, cm->cont_cls);
+      GNUNET_free (cm);
+      trigger_next_request (h);
+      return msize;
     }
-  GNUNET_CONTAINER_DLL_remove (h->pending_head,
-                              h->pending_tail,
-                              th);
-  GNUNET_assert (h->submitted == NULL);
-  h->submitted = th;
-  GNUNET_assert (size >= th->msize);
-  ret = th->get_message (th->get_message_cls, size, buf);
-  GNUNET_assert (ret <= size);
+  /* now check for 'ready' P2P messages */
+  if (NULL != (pr = h->ready_peer_head))
+    {
+      th = pr->pending_head;
+      if (size < th->msize + sizeof (struct SendMessage))
+       {
+         trigger_next_request (h);
+         return 0;
+       }
+      GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
+                                  h->ready_peer_tail,
+                                  pr);
+      GNUNET_CONTAINER_DLL_remove (pr->pending_head,
+                                  pr->pending_tail,
+                                  th);
+      pr->queue_size--;
+      if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+       {
+         GNUNET_SCHEDULER_cancel (pr->timeout_task);
+         pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+       }
+
+      sm = (struct SendMessage *) buf;
+      sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND);
+      sm->priority = htonl (th->priority);
+      sm->deadline = GNUNET_TIME_absolute_hton (th->timeout);
+      sm->peer = pr->peer;
+      ret = th->get_message (th->get_message_cls,
+                            size - sizeof (struct SendMessage),
+                            &sm[1]);
+
+      if (0 == ret)
+       {
 #if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Transmitting %u bytes to core\n",
-             ret);
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Size of clients message to peer %s is 0!\n",
+                     GNUNET_i2s(&pr->peer));
 #endif
-  return ret;
+         /* client decided to send nothing! */
+         request_next_transmission (pr);
+         return 0;       
+       }
+#if DEBUG_CORE
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Produced SEND message to core with %u bytes payload\n",
+                 (unsigned int) ret);
+#endif
+      GNUNET_assert (ret >= sizeof (struct GNUNET_MessageHeader));
+      if (ret + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+       {
+         GNUNET_break (0);
+         request_next_transmission (pr);
+         return 0;
+       }
+      ret += sizeof (struct SendMessage);
+      sm->header.size = htons (ret);
+      GNUNET_assert (ret <= size);
+      GNUNET_free (th);
+      request_next_transmission (pr);
+      return ret;
+    }
+  return 0;
 }
 
 
 /**
  * Check the list of pending requests, send the next
  * one to the core.
+ *
+ * @param h core handle
  */
 static void
 trigger_next_request (struct GNUNET_CORE_Handle *h)
 {
+  uint16_t msize;
+
+  if (GNUNET_YES == h->currently_down)
+    return;
+  if (NULL != h->cth)
+    return;
+  if (h->pending_head != NULL)
+    msize = ntohs (((struct GNUNET_MessageHeader*) 
&h->pending_head[1])->size);    
+  else if (h->ready_peer_head != NULL)
+    msize = h->ready_peer_head->pending_head->msize + sizeof (struct 
SendMessage);    
+  else
+    return; /* no pending message */
+  h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client,
+                                               msize,
+                                               GNUNET_TIME_UNIT_FOREVER_REL,
+                                               GNUNET_NO,
+                                               &transmit_message, h);
+}
+
+
+
+
+/**
+ * Notify clients about disconnect and free 
+ * the entry for connected peer.
+ *
+ * @param cls the 'struct GNUNET_CORE_Handle*'
+ * @param key the peer identity (not used)
+ * @param value the 'struct PeerRecord' to free.
+ * @return GNUNET_YES (continue)
+ */
+static int
+disconnect_and_free_peer_entry (void *cls,
+                               const GNUNET_HashCode *key,
+                               void *value)
+{
+  struct GNUNET_CORE_Handle *h = cls;
   struct GNUNET_CORE_TransmitHandle *th;
+  struct PeerRecord *pr = value;
 
-  if (h->currently_down)
+  while (NULL != (th = pr->pending_head))
     {
-#if DEBUG_CORE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "In trigger_next_request, connection currently down...\n");
-#endif
-      return;                     /* connection temporarily down */
+      GNUNET_CONTAINER_DLL_remove (pr->pending_head,
+                                  pr->pending_tail,
+                                  th);
+      pr->queue_size--;
+      GNUNET_assert (0 == 
+                    th->get_message (th->get_message_cls,
+                                     0, NULL));
+      GNUNET_free (th);
     }
-  if (NULL == (th = h->pending_head))
-    return;                     /* no requests pending */
-  GNUNET_assert (NULL == h->cth);
-  h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
-                                               th->msize,
-                                               
GNUNET_TIME_absolute_get_remaining
-                                               (th->timeout), 
-                                               GNUNET_NO,
-                                               &request_start,
-                                               h);
+  if (pr->pcic != NULL)
+    {
+      // FIXME: call pcic callback!
+    }
+  if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (pr->timeout_task);
+      pr->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  GNUNET_assert (pr->queue_size == 0);
+  if ( (pr->prev != NULL) ||
+       (pr->next != NULL) ||
+       (h->ready_peer_head == pr) )
+    GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
+                                h->ready_peer_tail,
+                                pr);
+  if (h->disconnects != NULL)
+    h->disconnects (h->cls,
+                   &pr->peer);    
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (h->peers,
+                                                      key,
+                                                      pr));
+  GNUNET_assert (pr->pending_head == NULL);
+  GNUNET_assert (pr->pending_tail == NULL);
+  GNUNET_assert (pr->ch = h);
+  GNUNET_assert (pr->queue_size == 0);
+  GNUNET_assert (pr->timeout_task == GNUNET_SCHEDULER_NO_TASK);
+  GNUNET_free (pr);  
+  return GNUNET_YES;
 }
 
 
@@ -388,18 +692,28 @@
  * @param msg the message received from the core service
  */
 static void
-main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+main_notify_handler (void *cls, 
+                    const struct GNUNET_MessageHeader *msg)
 {
   struct GNUNET_CORE_Handle *h = cls;
-  unsigned int hpos;
+  const struct InitReplyMessage *m;
   const struct ConnectNotifyMessage *cnm;
   const struct DisconnectNotifyMessage *dnm;
   const struct NotifyTrafficMessage *ntm;
   const struct GNUNET_MessageHeader *em;
+  const struct ConfigurationInfoMessage *cim;
   const struct PeerStatusNotifyMessage *psnm;
+  const struct SendMessageReady *smr;
+  const struct GNUNET_CORE_MessageHandler *mh;
+  GNUNET_CORE_StartupCallback init;
+  GNUNET_CORE_PeerConfigurationInfoCallback pcic;
+  struct GNUNET_PeerIdentity my_identity;
+  struct PeerRecord *pr;
+  struct GNUNET_CORE_TransmitHandle *th;
+  unsigned int hpos;
+  int trigger;
   uint16_t msize;
   uint16_t et;
-  const struct GNUNET_CORE_MessageHandler *mh;
 
   if (msg == NULL)
     {
@@ -417,37 +731,85 @@
 #endif
   switch (ntohs (msg->type))
     {
+    case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY:
+      if (ntohs (msg->size) != sizeof (struct InitReplyMessage))
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      m = (const struct InitReplyMessage *) msg;
+      GNUNET_break (0 == ntohl (m->reserved));
+      /* start our message processing loop */
+#if DEBUG_CORE
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Successfully connected to core service, starting processing 
loop.\n");
+#endif
+      if (GNUNET_YES == h->currently_down)
+       {
+         h->currently_down = GNUNET_NO;
+         trigger_next_request (h);
+       }
+      if (NULL != (init = h->init))
+       {
+         /* mark so we don't call init on reconnect */
+         h->init = NULL;
+         GNUNET_CRYPTO_hash (&m->publicKey,
+                             sizeof (struct
+                                     GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                             &my_identity.hashPubKey);
+         init (h->cls, h, &my_identity, &m->publicKey);
+       }
+      break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
-      if (NULL == h->connects)
-        {
-          GNUNET_break (0);
-          break;
-        }
       if (msize != sizeof (struct ConnectNotifyMessage))
         {
           GNUNET_break (0);
           break;
         }
       cnm = (const struct ConnectNotifyMessage *) msg;
-      h->connects (h->cls,
-                  &cnm->peer,
-                  GNUNET_TIME_relative_ntoh (cnm->latency),
-                  ntohl (cnm->distance));
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &cnm->peer.hashPubKey);
+      if (pr != NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      pr = GNUNET_malloc (sizeof (struct PeerRecord));
+      pr->peer = cnm->peer;
+      pr->ch = h;
+      GNUNET_assert (GNUNET_YES ==
+                    GNUNET_CONTAINER_multihashmap_put (h->peers,
+                                                       &cnm->peer.hashPubKey,
+                                                       pr,
+                                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+      if (NULL != h->connects)
+       h->connects (h->cls,
+                    &cnm->peer,
+                    NULL /* FIXME: atsi! */);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
-      if (NULL == h->disconnects)
-        {
-          GNUNET_break (0);
-          break;
-        }
       if (msize != sizeof (struct DisconnectNotifyMessage))
         {
           GNUNET_break (0);
           break;
         }
       dnm = (const struct DisconnectNotifyMessage *) msg;
-      h->disconnects (h->cls,
-                     &dnm->peer);
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &dnm->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      trigger = ( (pr->prev != NULL) ||
+                 (pr->next != NULL) ||
+                 (h->ready_peer_head == pr) );
+      disconnect_and_free_peer_entry (h, &dnm->peer.hashPubKey, pr);
+      if (trigger)
+       trigger_next_request (h);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE:
       if (NULL == h->status_events)
@@ -461,13 +823,20 @@
           break;
         }
       psnm = (const struct PeerStatusNotifyMessage *) msg;
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &psnm->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
       h->status_events (h->cls,
                        &psnm->peer,
-                       GNUNET_TIME_relative_ntoh (psnm->latency),
-                       ntohl (psnm->distance),
                        psnm->bandwidth_in,
                        psnm->bandwidth_out,
-                       GNUNET_TIME_absolute_ntoh (psnm->timeout));
+                       GNUNET_TIME_absolute_ntoh (psnm->timeout),
+                       NULL /* FIXME: atsi */);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
       if (msize <
@@ -486,6 +855,14 @@
                  ntohs (em->size),
                  GNUNET_i2s (&ntm->peer));
 #endif
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &ntm->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
       if ((GNUNET_NO == h->inbound_hdr_only) &&
           (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
         {
@@ -506,8 +883,7 @@
             }
           if (GNUNET_OK !=
               h->handlers[hpos].callback (h->cls, &ntm->peer, em,
-                                         GNUNET_TIME_relative_ntoh 
(ntm->latency),
-                                         ntohl (ntm->distance)))
+                                         NULL /* FIXME: atsi */))
             {
               /* error in processing, do not process other messages! */
               break;
@@ -515,8 +891,7 @@
         }
       if (NULL != h->inbound_notify)
         h->inbound_notify (h->cls, &ntm->peer, em,
-                          GNUNET_TIME_relative_ntoh (ntm->latency),
-                          ntohl (ntm->distance));
+                          NULL /* FIXME: atsi */);
       break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
       if (msize <
@@ -528,6 +903,14 @@
         }
       ntm = (const struct NotifyTrafficMessage *) msg;
       em = (const struct GNUNET_MessageHeader *) &ntm[1];
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &ntm->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
       if ((GNUNET_NO == h->outbound_hdr_only) &&
           (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
         {
@@ -540,159 +923,157 @@
           break;
         }
       h->outbound_notify (h->cls, &ntm->peer, em,
-                         GNUNET_TIME_relative_ntoh (ntm->latency),
-                         ntohl (ntm->distance));
+                         NULL /* FIXME: atsi? */);
       break;
+    case GNUNET_MESSAGE_TYPE_CORE_SEND_READY:
+      if (msize != sizeof (struct SendMessageReady))
+        {
+          GNUNET_break (0);
+          break;
+        }
+      smr = (const struct SendMessageReady *) msg;
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &smr->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      th = pr->pending_head;
+      if (ntohs (smr->smr_id) != th->smr_id)
+       {
+         /* READY message is for expired or cancelled message,
+            ignore! (we should have already sent another request) */
+         break;
+       }
+      if ( (pr->prev != NULL) ||
+          (pr->next != NULL) ||
+          (h->ready_peer_head == pr) )
+       {
+         /* we should not already be on the ready list... */
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      GNUNET_CONTAINER_DLL_insert (h->ready_peer_head,
+                                  h->ready_peer_tail,
+                                  pr);
+      trigger_next_request (h);
+      break;
+    case GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO:
+      if (ntohs (msg->size) != sizeof (struct ConfigurationInfoMessage))
+       {
+         GNUNET_break (0);
+         break;
+       }
+      cim = (const struct ConfigurationInfoMessage*) msg;
+      pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                             &cim->peer.hashPubKey);
+      if (pr == NULL)
+       {
+         GNUNET_break (0);
+         reconnect (h);
+         return;
+       }
+      if (pr->rim_id != ntohl (cim->rim_id))
+       break;
+      pcic = pr->pcic;
+      pr->pcic = NULL;
+      if (pcic != NULL)
+       pcic (pr->pcic_cls,
+             &pr->peer,
+             cim->bw_out,
+             ntohl (cim->reserved_amount),
+             GNUNET_ntohll (cim->preference));
+      break;
     default:
       GNUNET_break (0);
       break;
     }
-  GNUNET_CLIENT_receive (h->client_notifications,
+  GNUNET_CLIENT_receive (h->client,
                          &main_notify_handler, h, 
GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
 /**
- * Function called when we are ready to transmit our
- * "START" message (or when this operation timed out).
+ * Task executed once we are done transmitting the INIT message.
+ * Starts our 'receive' loop.
  *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @param cls the 'struct GNUNET_CORE_Handle'
+ * @param tc task context
  */
-static size_t transmit_start (void *cls, size_t size, void *buf);
-
-
-/**
- * Function called on the first message received from
- * the service (contains our public key, etc.).
- * Should trigger calling the init callback
- * and then start our regular message processing.
- *
- * @param cls closure
- * @param msg message received, NULL on timeout or fatal error
- */
 static void
-init_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+init_done_task (void *cls, 
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CORE_Handle *h = cls;
-  const struct InitReplyMessage *m;
-  GNUNET_CORE_StartupCallback init;
-  struct GNUNET_PeerIdentity my_identity;
 
-  if ((msg == NULL) ||
-      (ntohs (msg->size) != sizeof (struct InitReplyMessage)) ||
-      (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY))
+  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE))
     {
-      if (msg != NULL)
+      if (h->client != NULL)
        {
-         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                     _
-                     ("Error connecting to core service (failed to receive 
`%s' message, got message of type %u and size %u).\n"),
-                     "INIT_REPLY",
-                     ntohs (msg->type),
-                     ntohs (msg->size));
-         GNUNET_break (0);
+         GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
+         h->client = NULL;
        }
-      else
-       {
-#if DEBUG_CORE
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     _("Failed to connect to core service, will retry.\n"));
-#endif
-       }
-      transmit_start (h, 0, NULL);
+      h->reconnect_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_UNIT_SECONDS,
+                                                       &reconnect_task,
+                                                       h);
       return;
     }
-  m = (const struct InitReplyMessage *) msg;
-  GNUNET_break (0 == ntohl (m->reserved));
-  /* start our message processing loop */
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Successfully connected to core service, starting processing 
loop.\n");
-#endif
-  h->currently_down = GNUNET_NO;
-  trigger_next_request (h);
-  GNUNET_CLIENT_receive (h->client_notifications,
-                         &main_notify_handler, h, 
GNUNET_TIME_UNIT_FOREVER_REL);
-  if (NULL != (init = h->init))
-    {
-      /* mark so we don't call init on reconnect */
-      h->init = NULL;
-      GNUNET_CRYPTO_hash (&m->publicKey,
-                          sizeof (struct
-                                  GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                          &my_identity.hashPubKey);
-      init (h->cls, h, &my_identity, &m->publicKey);
-    }
+  GNUNET_CLIENT_receive (h->client,
+                         &main_notify_handler, 
+                        h, 
+                        GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
-static void
-reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CORE_Handle *h = cls;
-  h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  reconnect (h);
-}
-
-
 /**
- * Function called when we are ready to transmit our
- * "START" message (or when this operation timed out).
+ * Our current client connection went down.  Clean it up
+ * and try to reconnect!
  *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * @param h our handle to the core service
  */
-static size_t
-transmit_start (void *cls, size_t size, void *buf)
+static void
+reconnect (struct GNUNET_CORE_Handle *h)
 {
-  struct GNUNET_CORE_Handle *h = cls;
+  struct ControlMessage *cm;
   struct InitMessage *init;
+  uint32_t opt;
+  uint16_t msize;
   uint16_t *ts;
-  uint16_t msize;
-  uint32_t opt;
   unsigned int hpos;
-  struct GNUNET_TIME_Relative delay;
 
-  h->cth = NULL;
-  if (size == 0)
+#if DEBUG_CORE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Reconnecting to CORE service\n");
+#endif
+  if (h->client != NULL)
     {
-      if ((h->init == NULL) ||
-          (GNUNET_TIME_absolute_get ().abs_value < 
h->startup_timeout.abs_value))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                      _("Failed to connect to core service, retrying.\n"));
-          delay = GNUNET_TIME_absolute_get_remaining (h->startup_timeout);
-          if ((h->init == NULL) || (delay.rel_value > 1000))
-            delay = GNUNET_TIME_UNIT_SECONDS;
-          if (h->init == NULL)
-            h->startup_timeout =
-              GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
-          h->reconnect_task =
-            GNUNET_SCHEDULER_add_delayed (delay, &reconnect_task, h);
-          return 0;
-        }
-      /* timeout on initial connect */
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _("Failed to connect to core service, giving up.\n"));
-      h->init (h->cls, NULL, NULL, NULL);
-      GNUNET_CORE_disconnect (h);
-      return 0;
+      GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
+      h->client = NULL;
+      GNUNET_CONTAINER_multihashmap_iterate (h->peers,
+                                            &disconnect_and_free_peer_entry,
+                                            h);
     }
+  h->currently_down = GNUNET_YES;
+  h->client = GNUNET_CLIENT_connect ("core", h->cfg);
+  if (h->client == NULL)
+    {
+      h->reconnect_task = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_UNIT_SECONDS,
+                                                       &reconnect_task,
+                                                       h);
+      return;
+    }
   msize = h->hcnt * sizeof (uint16_t) + sizeof (struct InitMessage);
-  GNUNET_assert (size >= msize);
-  init = buf;
+  cm = GNUNET_malloc (sizeof (struct ControlMessage) +
+                     msize);
+  cm->cont = &init_done_task;
+  cm->cont_cls = h;
+  init = (struct InitMessage*) &cm[1];
   init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
   init->header.size = htons (msize);
-  opt = GNUNET_CORE_OPTION_NOTHING;
-  if (h->connects != NULL)
-    opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
-  if (h->disconnects != NULL)
-    opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT;
+  opt = GNUNET_CORE_OPTION_SEND_CONNECT | GNUNET_CORE_OPTION_SEND_DISCONNECT;
   if (h->status_events != NULL)
     opt |= GNUNET_CORE_OPTION_SEND_STATUS_CHANGE;
   if (h->inbound_notify != NULL)
@@ -710,25 +1091,23 @@
         opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND;
     }
   init->options = htonl (opt);
-  ts = (uint16_t *) & init[1];
+  ts = (uint16_t *) &init[1];
   for (hpos = 0; hpos < h->hcnt; hpos++)
     ts[hpos] = htons (h->handlers[hpos].type);
-  GNUNET_CLIENT_receive (h->client_notifications,
-                         &init_reply_handler,
-                         h,
-                         GNUNET_TIME_absolute_get_remaining
-                         (h->startup_timeout));
-  return sizeof (struct InitMessage) + h->hcnt * sizeof (uint16_t);
+  GNUNET_CONTAINER_DLL_insert (h->pending_head,
+                              h->pending_tail,
+                              cm);
+  trigger_next_request (h);
 }
 
 
+
 /**
  * Connect to the core service.  Note that the connection may
  * complete (or fail) asynchronously.
  *
  * @param cfg configuration to use
  * @param queue_size size of the per-peer message queue
- * @param timeout after how long should we give up trying to connect to the 
core service?
  * @param cls closure for the various callbacks that follow (including 
handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
  *        connected to the core service; note that timeout is only meaningful 
if init is not NULL
@@ -750,7 +1129,6 @@
 struct GNUNET_CORE_Handle *
 GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                     unsigned int queue_size,
-                     struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
@@ -766,6 +1144,7 @@
 
   h = GNUNET_malloc (sizeof (struct GNUNET_CORE_Handle));
   h->cfg = cfg;
+  h->queue_size = queue_size;
   h->cls = cls;
   h->init = init;
   h->connects = connects;
@@ -776,133 +1155,57 @@
   h->inbound_hdr_only = inbound_hdr_only;
   h->outbound_hdr_only = outbound_hdr_only;
   h->handlers = handlers;
-  h->queue_size = queue_size;
-  h->client_notifications = GNUNET_CLIENT_connect ("core", cfg);
-  if (h->client_notifications == NULL)
-    {
-      GNUNET_free (h);
-      return NULL;
-    }
-  h->startup_timeout = GNUNET_TIME_relative_to_absolute (timeout);
   h->hcnt = 0;
   while (handlers[h->hcnt].callback != NULL)
     h->hcnt++;
   GNUNET_assert (h->hcnt <
                  (GNUNET_SERVER_MAX_MESSAGE_SIZE -
                   sizeof (struct InitMessage)) / sizeof (uint16_t));
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Trying to connect to core service in next %llu ms.\n",
-              timeout.rel_value);
-#endif
-  h->cth =
-    GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
-                                         sizeof (struct InitMessage) +
-                                         sizeof (uint16_t) * h->hcnt, timeout,
-                                        GNUNET_YES,
-                                         &transmit_start, h);
+  reconnect (h);
   return h;
 }
 
 
 /**
- * Disconnect from the core service.
+ * Disconnect from the core service.  This function can only 
+ * be called *after* all pending 'GNUNET_CORE_notify_transmit_ready'
+ * requests have been explicitly cancelled.
  *
  * @param handle connection to core to disconnect
  */
 void
 GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
 {
-  if (handle->cth != NULL)
-    GNUNET_CLIENT_notify_transmit_ready_cancel (handle->cth);
-  if (handle->solicit_transmit_req != NULL)
-    GNUNET_CORE_notify_transmit_ready_cancel (handle->solicit_transmit_req);
+  struct ControlMessage *cm;
+  
   if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (handle->reconnect_task);
-  if (handle->client_notifications != NULL)
-    GNUNET_CLIENT_disconnect (handle->client_notifications, GNUNET_NO);
-  GNUNET_break (handle->pending_head == NULL);
-  GNUNET_free_non_null (handle->solicit_buffer);
-  GNUNET_free (handle);
-}
-
-
-/**
- * Build the message requesting data transmission.
- */
-static size_t
-produce_send (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_CORE_TransmitHandle *th = cls;
-  struct GNUNET_CORE_Handle *h;
-  struct SendMessage *sm;
-  size_t dt;
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-  void *notify_cls;
-
-  h = th->ch;
-  if (buf == NULL)
     {
-      /* timeout or error */
-#if DEBUG_CORE
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "P2P transmission request for `%4s' timed out.\n",
-                 GNUNET_i2s(&th->peer));
-#endif
-      GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
-      GNUNET_CORE_notify_transmit_ready_cancel (th);
-      if ((h->pending_head == th) && (h->cth != NULL)) /* Request hasn't been 
canceled yet! */
-        {
-          GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth);
-          h->cth = NULL;
-          trigger_next_request (h);
-        }
-      /* Otherwise this request timed out, but another is actually queued for 
sending, so don't try to send another! */
-      return 0;
+      GNUNET_SCHEDULER_cancel (handle->reconnect_task);
+      handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
     }
-  sm = (struct SendMessage *) buf;
-  sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND);
-  sm->priority = htonl (th->priority);
-  sm->deadline = GNUNET_TIME_absolute_hton (th->timeout);
-  sm->peer = th->peer;
-  notify = th->notify;
-  notify_cls = th->notify_cls;
-  GNUNET_CORE_notify_transmit_ready_cancel (th);
-  trigger_next_request (h);
-  size = GNUNET_MIN (size,
-                    GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE);
-  GNUNET_assert (size >= sizeof (struct SendMessage));
-  dt = notify (notify_cls, size - sizeof (struct SendMessage), &sm[1]);
-  if (0 == dt)
+  if (handle->cth != NULL)
     {
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Size of clients message to peer %s is 0!\n",
-              GNUNET_i2s(&sm->peer));
-#endif
-      /* client decided to send nothing! */
-      return 0;
+      GNUNET_CLIENT_notify_transmit_ready_cancel (handle->cth);
+      handle->cth = NULL;
     }
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Produced SEND message to core with %u bytes payload\n",
-             dt);
-#endif
-  GNUNET_assert (dt >= sizeof (struct GNUNET_MessageHeader));
-  if (dt + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+  if (handle->client != NULL)
     {
-      GNUNET_break (0);
-      return 0;
+      GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
+      handle->client = NULL;
     }
-#if DEBUG_CORE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Preparing for P2P transmission of %u bytes to `%4s'.\n",
-             dt,
-             GNUNET_i2s(&sm->peer));
-#endif
-  sm->header.size = htons (dt + sizeof (struct SendMessage));
-  GNUNET_assert (dt + sizeof (struct SendMessage) <= size);
-  return dt + sizeof (struct SendMessage);
+  while (NULL != (cm = handle->pending_head))
+    {
+      GNUNET_CONTAINER_DLL_remove (handle->pending_head,
+                                  handle->pending_tail,
+                                  cm);
+      GNUNET_free (cm);
+    }
+  GNUNET_CONTAINER_multihashmap_iterate (handle->peers,
+                                        &disconnect_and_free_peer_entry,
+                                        handle);
+  GNUNET_CONTAINER_multihashmap_destroy (handle->peers);
+  GNUNET_break (handle->ready_peer_head == NULL);
+  GNUNET_free (handle);
 }
 
 
@@ -926,62 +1229,490 @@
  */
 struct GNUNET_CORE_TransmitHandle *
 GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
-                                   unsigned int priority,
+                                   uint32_t priority,
                                    struct GNUNET_TIME_Relative maxdelay,
                                    const struct GNUNET_PeerIdentity *target,
                                    size_t notify_size,
                                    GNUNET_CONNECTION_TransmitReadyNotify 
notify,
                                    void *notify_cls)
 {
+  struct PeerRecord *pr;
   struct GNUNET_CORE_TransmitHandle *th;
+  struct GNUNET_CORE_TransmitHandle *pos;
+  struct GNUNET_CORE_TransmitHandle *prev;
+  struct GNUNET_CORE_TransmitHandle *minp;
 
+  pr = GNUNET_CONTAINER_multihashmap_get (handle->peers,
+                                         &target->hashPubKey);
+  if (NULL == pr)
+    {
+      /* attempt to send to peer that is not connected */
+      GNUNET_break (0);
+      return NULL;
+    }
   GNUNET_assert (notify_size + sizeof (struct SendMessage) <
                  GNUNET_SERVER_MAX_MESSAGE_SIZE);
   th = GNUNET_malloc (sizeof (struct GNUNET_CORE_TransmitHandle));
-  th->ch = handle;
-  GNUNET_CONTAINER_DLL_insert_after (handle->pending_head,
-                                    handle->pending_tail,
-                                    handle->pending_tail,
-                                    th);
-  th->get_message = &produce_send;
-  th->get_message_cls = th;
-  th->notify = notify;
-  th->notify_cls = notify_cls;
-  th->peer = *target;
+  th->peer = pr;
+  th->get_message = notify;
+  th->get_message_cls = notify_cls;
   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
-  th->timeout_task = GNUNET_SCHEDULER_add_delayed (maxdelay,
-                                                   &timeout_request, th);
   th->priority = priority;
-  th->msize = sizeof (struct SendMessage) + notify_size;
+  th->msize = notify_size;
+  /* bound queue size */
+  if (pr->queue_size == handle->queue_size)
+    {
+      /* find lowest-priority entry */
+      minp = pr->pending_head;
+      prev = minp->next;
+      while (prev != NULL)
+       {
+         if (prev->priority < minp->priority)
+           minp = prev;
+         prev = prev->next;
+       }
+      if (minp == NULL) 
+       {
+         GNUNET_break (handle->queue_size != 0);
+         GNUNET_break (pr->queue_size == 0);
+         return NULL;
+       }
+      if (priority <= minp->priority)
+       return NULL; /* priority too low */
+      GNUNET_CONTAINER_DLL_remove (pr->pending_head,
+                                  pr->pending_tail,
+                                  minp);
+      pr->queue_size--;
+      GNUNET_assert (0 ==
+                    minp->get_message (minp->get_message_cls,
+                                       0, NULL));
+      GNUNET_free (minp);
+    }
+
+  /* Order entries by deadline, but SKIP 'HEAD' if
+     we're in the 'ready_peer_*' DLL */
+  pos = pr->pending_head;
+  if ( (pr->prev != NULL) ||
+       (pr->next != NULL) ||
+       (pr == handle->ready_peer_head) )
+    {
+      GNUNET_assert (pos != NULL);
+      pos = pos->next; /* skip head */
+    }
+
+  /* insertion sort */
+  prev = pos;
+  while ( (pos != NULL) &&
+         (pos->timeout.abs_value < th->timeout.abs_value) )      
+    {
+      prev = pos;
+      pos = pos->next;
+    }
+  GNUNET_CONTAINER_DLL_insert_after (pr->pending_head,
+                                    pr->pending_tail,
+                                    prev,
+                                    th);
+  pr->queue_size++;
   /* was the request queue previously empty? */
-  if ( (handle->pending_head == th) &&
-       (handle->cth == NULL) )
-    trigger_next_request (handle);
+  if (pr->pending_head == th) 
+    request_next_transmission (pr);
   return th;
 }
 
 
 /**
  * Cancel the specified transmission-ready notification.
- *s
+ *
  * @param th handle that was returned by "notify_transmit_ready".
  */
 void
 GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle
                                           *th)
 {
-  struct GNUNET_CORE_Handle *h = th->ch;
+  struct PeerRecord *pr = th->peer;
+  struct GNUNET_CORE_Handle *h = pr->ch;
+  int was_head;
   
-  if (h->submitted == th)
-    h->submitted = NULL;
-  else    
-    GNUNET_CONTAINER_DLL_remove (h->pending_head,
-                                h->pending_tail,
-                                th);    
-  if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (th->timeout_task);
+  was_head = (pr->pending_head == th);
+  GNUNET_CONTAINER_DLL_remove (pr->pending_head,
+                              pr->pending_tail,
+                              th);    
+  if (th->cm != NULL)
+    {
+      /* we're currently in the control queue, remove */
+      GNUNET_CONTAINER_DLL_remove (h->pending_head,
+                                  h->pending_tail,
+                                  th->cm);
+      GNUNET_free (th->cm);      
+    }
   GNUNET_free (th);
+  if (was_head)
+    {
+      if ( (pr->prev != NULL) ||
+          (pr->next != NULL) ||
+          (pr == h->ready_peer_head) )
+       {
+         /* the request that was 'approved' by core was
+            cancelled before it could be transmitted; remove
+            us from the 'ready' list */
+         GNUNET_CONTAINER_DLL_remove (h->ready_peer_head,
+                                      h->ready_peer_tail,
+                                      pr);
+       }
+      request_next_transmission (pr);
+    }
 }
 
 
+/* ****************** GNUNET_CORE_peer_request_connect ******************** */
+
+/**
+ * Handle for a request to the core to connect to
+ * a particular peer.  Can be used to cancel the request
+ * (before the 'cont'inuation is called).
+ */
+struct GNUNET_CORE_PeerRequestHandle
+{
+
+  /**
+   * Link to control message.
+   */
+  struct ControlMessage *cm;
+
+  /**
+   * Core handle used.
+   */
+  struct GNUNET_CORE_Handle *h;
+
+  /**
+   * Continuation to run when done.
+   */
+  GNUNET_SCHEDULER_Task cont;
+
+  /**
+   * Closure for 'cont'.
+   */
+  void *cont_cls;
+
+};
+
+
+
+/**
+ * Continuation called when the control message was transmitted.
+ * Calls the original continuation and frees the remaining
+ * resources.
+ *
+ * @param cls the 'struct GNUNET_CORE_PeerRequestHandle'
+ * @param tc scheduler context
+ */
+static void
+peer_request_connect_cont (void *cls,
+                          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_CORE_PeerRequestHandle *ret = cls;
+  
+  if (ret->cont != NULL)
+    ret->cont (ret->cont_cls, tc);
+  GNUNET_free (ret);
+}
+
+
+/**
+ * Request that the core should try to connect to a particular peer.
+ * Once the request has been transmitted to the core, the continuation
+ * function will be called.  Note that this does NOT mean that a
+ * connection was successfully established -- it only means that the
+ * core will now try.  Successful establishment of the connection
+ * will be signalled to the 'connects' callback argument of
+ * 'GNUNET_CORE_connect' only.  If the core service does not respond
+ * to our connection attempt within the given time frame, 'cont' will
+ * be called with the TIMEOUT reason code.
+ *
+ * @param h core handle
+ * @param timeout how long to try to talk to core
+ * @param peer who should we connect to
+ * @param cont function to call once the request has been completed (or timed 
out)
+ * @param cont_cls closure for cont
+ * @return NULL on error (cont will not be called), otherwise handle for 
cancellation
+ */
+struct GNUNET_CORE_PeerRequestHandle *
+GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
+                                 struct GNUNET_TIME_Relative timeout,
+                                 const struct GNUNET_PeerIdentity * peer,
+                                 GNUNET_SCHEDULER_Task cont,
+                                 void *cont_cls)
+{
+  struct GNUNET_CORE_PeerRequestHandle *ret;
+  struct ControlMessage *cm;
+  struct ConnectMessage *msg;
+  
+  cm = GNUNET_malloc (sizeof (struct ControlMessage) + 
+                     sizeof (struct ConnectMessage));
+  msg = (struct ConnectMessage*) &cm[1];
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT);
+  msg->header.size = htons (sizeof (struct ConnectMessage));
+  msg->reserved = htonl (0);
+  msg->timeout = GNUNET_TIME_relative_hton (timeout);
+  msg->peer = *peer;
+  GNUNET_CONTAINER_DLL_insert (h->pending_head,
+                              h->pending_tail,
+                              cm);
+  ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
+  ret->h = h;
+  ret->cm = cm;
+  ret->cont = cont;
+  ret->cont_cls = cont_cls;
+  cm->cont = &peer_request_connect_cont;
+  cm->cont_cls = ret;
+  if (h->pending_head == cm)
+    trigger_next_request (h);
+  return ret;
+}
+
+
+/**
+ * Cancel a pending request to connect to a particular peer.  Must not
+ * be called after the 'cont' function was invoked.
+ *
+ * @param req request handle that was returned for the original request
+ */
+void
+GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle 
*req)
+{
+  struct GNUNET_CORE_Handle *h = req->h;
+  struct ControlMessage *cm = req->cm;
+
+  GNUNET_CONTAINER_DLL_remove (h->pending_head,
+                              h->pending_tail,
+                              cm);
+  GNUNET_free (cm);
+  GNUNET_free (req);
+}
+
+
+/* ****************** GNUNET_CORE_peer_change_preference ******************** 
*/
+
+
+struct GNUNET_CORE_InformationRequestContext 
+{
+  
+  /**
+   * Our connection to the service.
+   */
+  struct GNUNET_CORE_Handle *h;
+
+  /**
+   * Function to call with the information.
+   */
+  GNUNET_CORE_PeerConfigurationInfoCallback info;
+
+  /**
+   * Closure for info.
+   */
+  void *info_cls;
+
+  /**
+   * Link to control message, NULL if CM was sent.
+   */ 
+  struct ControlMessage *cm;
+
+  /**
+   * Link to peer record.
+   */
+  struct PeerRecord *pr;
+};
+
+
+/**
+ * CM was sent, remove link so we don't double-free.
+ *
+ * @param cls the 'struct GNUNET_CORE_InformationRequestContext'
+ * @param tc scheduler context
+ */
+static void
+change_preference_send_continuation (void *cls,
+                                    const struct GNUNET_SCHEDULER_TaskContext 
*tc)
+{
+  struct GNUNET_CORE_InformationRequestContext *irc = cls;
+
+  irc->cm = NULL;
+}
+
+
+/**
+ * Obtain statistics and/or change preferences for the given peer.
+ *
+ * @param h core handle
+ * @param peer identifies the peer
+ * @param timeout after how long should we give up (and call "info" with NULL
+ *                for "peer" to signal an error)?
+ * @param bw_out set to the current bandwidth limit (sending) for this peer,
+ *                caller should set "bw_out" to "-1" to avoid changing
+ *                the current value; otherwise "bw_out" will be lowered to
+ *                the specified value; passing a pointer to "0" can be used to 
force
+ *                us to disconnect from the peer; "bw_out" might not increase
+ *                as specified since the upper bound is generally
+ *                determined by the other peer!
+ * @param amount reserve N bytes for receiving, negative
+ *                amounts can be used to undo a (recent) reservation;
+ * @param preference increase incoming traffic share preference by this amount;
+ *                in the absence of "amount" reservations, we use this
+ *                preference value to assign proportional bandwidth shares
+ *                to all connected peers
+ * @param info function to call with the resulting configuration information
+ * @param info_cls closure for info
+ * @return NULL on error
+ */
+struct GNUNET_CORE_InformationRequestContext *
+GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h,
+                                   const struct GNUNET_PeerIdentity *peer,
+                                   struct GNUNET_TIME_Relative timeout,
+                                   struct GNUNET_BANDWIDTH_Value32NBO bw_out,
+                                   int32_t amount,
+                                   uint64_t preference,
+                                   GNUNET_CORE_PeerConfigurationInfoCallback 
info,
+                                   void *info_cls)
+{
+  struct GNUNET_CORE_InformationRequestContext *irc;
+  struct PeerRecord *pr;
+  struct RequestInfoMessage *rim;
+  struct ControlMessage *cm;
+
+  pr = GNUNET_CONTAINER_multihashmap_get (h->peers,
+                                         &peer->hashPubKey);
+  if (NULL == pr)
+    {
+      /* attempt to change preference on peer that is not connected */
+      GNUNET_break (0);
+      return NULL;
+    }
+  if (pr->pcic != NULL)
+    {
+      /* second change before first one is done */
+      GNUNET_break (0);
+      return NULL;
+    }
+  irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext));
+  irc->h = h;
+  irc->info = info;
+  irc->info_cls = info_cls;
+  cm = GNUNET_malloc (sizeof (struct ControlMessage) +
+                     sizeof (struct RequestInfoMessage));
+  cm->cont = &change_preference_send_continuation;
+  cm->cont_cls = irc;
+  irc->cm = cm;
+  rim = (struct RequestInfoMessage*) &cm[1];
+  rim->header.size = htons (sizeof (struct RequestInfoMessage));
+  rim->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO);
+  rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++);
+  rim->limit_outbound = bw_out;
+  rim->reserve_inbound = htonl (amount);
+  rim->preference_change = GNUNET_htonll(preference);
+  rim->peer = *peer;
+  GNUNET_CONTAINER_DLL_insert (h->pending_head,
+                              h->pending_tail,
+                              cm); 
+  pr->pcic = info;
+  pr->pcic_cls = info_cls;
+  return irc;
+}
+
+
+/**
+ * Cancel request for getting information about a peer.
+ * Note that an eventual change in preference, trust or bandwidth
+ * assignment MAY have already been committed at the time, 
+ * so cancelling a request is NOT sure to undo the original
+ * request.  The original request may or may not still commit.
+ * The only thing cancellation ensures is that the callback
+ * from the original request will no longer be called.
+ *
+ * @param irc context returned by the original GNUNET_CORE_peer_get_info call
+ */
+void
+GNUNET_CORE_peer_change_preference_cancel (struct 
GNUNET_CORE_InformationRequestContext *irc)
+{
+  struct GNUNET_CORE_Handle *h = irc->h;
+  struct PeerRecord *pr = irc->pr;
+
+  if (irc->cm != NULL)
+    {
+      GNUNET_CONTAINER_DLL_remove (h->pending_head,
+                                  h->pending_tail,
+                                  irc->cm);
+      GNUNET_free (irc->cm);
+    }
+  pr->pcic = NULL;
+  pr->pcic_cls = NULL;
+  GNUNET_free (irc);
+}
+
+
+/* ********************* GNUNET_CORE_iterate_peers *********************** */
+
+/**
+ * Context for 'iterate_peers' helper function.
+ */
+struct IterationContext
+{
+  /**
+   * Callback to call.
+   */
+  GNUNET_CORE_ConnectEventHandler peer_cb;
+
+  /**
+   * Closure for 'peer_cb'.
+   */
+  void *cb_cls;
+};
+
+
+/**
+ * Call callback for each peer.
+ *
+ * @param cls the 'struct IterationContext'
+ * @param hc peer identity, not used
+ * @param value the 'struct PeerRecord'
+ * @return GNUNET_YES (continue iteration)
+ */
+static int
+iterate_peers (void *cls,
+              const GNUNET_HashCode *hc,
+              void *value)
+{
+  struct IterationContext *ic = cls;
+  struct PeerRecord *pr = value;
+
+  ic->peer_cb (ic->cb_cls,
+              &pr->peer,
+              NULL /* FIXME: pass atsi? */);
+  return GNUNET_YES;
+}
+
+
+/**
+ * Obtain statistics and/or change preferences for the given peer.
+ *
+ * @param h handle to core
+ * @param peer_cb function to call with the peer information
+ * @param cb_cls closure for peer_cb
+ * @return GNUNET_OK if iterating, GNUNET_SYSERR on error
+ */
+int
+GNUNET_CORE_iterate_peers (struct GNUNET_CORE_Handle *h,
+                           GNUNET_CORE_ConnectEventHandler peer_cb,
+                           void *cb_cls)
+{
+  struct IterationContext ic;
+
+  ic.peer_cb = peer_cb;
+  ic.cb_cls = cb_cls;
+  GNUNET_CONTAINER_multihashmap_iterate (h->peers,
+                                        &iterate_peers,
+                                        &ic);
+  return GNUNET_OK;
+}
+
+
 /* end of core_api.c */

Deleted: gnunet/src/core/core_api_iterate_peers.c
===================================================================
--- gnunet/src/core/core_api_iterate_peers.c    2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/core_api_iterate_peers.c    2010-11-13 20:37:37 UTC (rev 
13670)
@@ -1,169 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 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 3, 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 core/core_api_iterate_peers.c
- * @brief implementation of the peer_iterate function
- * @author Christian Grothoff
- * @author Nathan Evans
- */
-#include "platform.h"
-#include "gnunet_core_service.h"
-#include "core.h"
-
-
-struct GNUNET_CORE_RequestContext
-{
-  
-  /**
-   * Our connection to the service.
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * Handle for transmitting a request.
-   */
-  struct GNUNET_CLIENT_TransmitHandle *th;
-
-  /**
-   * Function called with the peer.
-   */
-  GNUNET_CORE_ConnectEventHandler peer_cb;
-
-  /**
-   * Closure for peer_cb.
-   */
-  void *cb_cls;
-
-};
-
-
-/**
- * Receive reply from core service with information about a peer.
- *
- * @param cls our 'struct  GNUNET_CORE_RequestContext *'
- * @param msg NULL on error or last entry
- */
-static void
-receive_info (void *cls,
-             const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CORE_RequestContext *request_context = cls;
-  const struct ConnectNotifyMessage *connect_message;
-
-
-  /* Handle last message or error case, disconnect and clean up */
-  if ( (msg == NULL) ||
-      ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) &&
-      (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader))) )
-    {
-      if (request_context->peer_cb != NULL)
-       request_context->peer_cb (request_context->cb_cls,
-                               NULL, GNUNET_TIME_relative_get_zero(), 0);
-      GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO);
-      GNUNET_free (request_context);
-      return;
-    }
-
-  /* Handle incorrect message type or size, disconnect and clean up */
-  if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) ||
-       (ntohs (msg->size) != sizeof (struct ConnectNotifyMessage)) )
-    {
-      GNUNET_break (0);
-      if (request_context->peer_cb != NULL)
-        request_context->peer_cb (request_context->cb_cls,
-                               NULL, GNUNET_TIME_relative_get_zero(), 0);
-      GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO);
-      GNUNET_free (request_context);
-      return;
-    }
-
-  /* Normal case */
-  connect_message = (const struct ConnectNotifyMessage *) msg;
-  if (request_context->peer_cb != NULL)
-    request_context->peer_cb (request_context->cb_cls,
-                           &connect_message->peer,
-                           GNUNET_TIME_relative_ntoh(connect_message->latency),
-                           ntohl (connect_message->distance));
-
-  GNUNET_CLIENT_receive(request_context->client, &receive_info, 
request_context, GNUNET_TIME_relative_get_forever());
-}
-
-/**
- * Function called to notify a client about the socket
- * begin ready to queue more data.  "buf" will be
- * NULL and "size" zero if the socket was closed for
- * writing in the meantime.
- *
- * @param cls closure
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */
-static size_t
-transmit_request(void *cls,
-                 size_t size, void *buf)
-{
-  struct GNUNET_MessageHeader *msg;
-  if ((size < sizeof(struct GNUNET_MessageHeader)) || (buf == NULL))
-    return 0;
-
-  msg = (struct GNUNET_MessageHeader *)buf;
-  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
-  return sizeof(struct GNUNET_MessageHeader);
-}
-
-/**
- * Obtain statistics and/or change preferences for the given peer.
- *
- * @param cfg configuration to use
- * @param peer_cb function to call with the peer information
- * @param cb_cls closure for peer_cb
- * @return GNUNET_OK if iterating, GNUNET_SYSERR on error
- */
-int
-GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                           GNUNET_CORE_ConnectEventHandler peer_cb,
-                           void *cb_cls)
-{
-  struct GNUNET_CORE_RequestContext *request_context;
-  struct GNUNET_CLIENT_Connection *client;
-
-  client = GNUNET_CLIENT_connect ("core", cfg);
-  if (client == NULL)
-    return GNUNET_SYSERR;
-  request_context = GNUNET_malloc (sizeof (struct GNUNET_CORE_RequestContext));
-  request_context->client = client;
-  request_context->peer_cb = peer_cb;
-  request_context->cb_cls = cb_cls;
-
-  /*GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response 
(client,
-                                                                      
&request_message,
-                                                                      
GNUNET_TIME_relative_get_forever(),
-                                                                      
GNUNET_YES,
-                                                                      
&receive_info,
-                                                                      
request_context));*/
-  request_context->th = GNUNET_CLIENT_notify_transmit_ready(client, 
sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_relative_get_forever(), 
GNUNET_YES, &transmit_request, NULL);
-  GNUNET_CLIENT_receive(client, &receive_info, request_context, 
GNUNET_TIME_relative_get_forever());
-  return GNUNET_OK;
-}
-
-/* end of core_api_iterate_peers.c */

Deleted: gnunet/src/core/core_api_peer_get_info.c
===================================================================
--- gnunet/src/core/core_api_peer_get_info.c    2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/core_api_peer_get_info.c    2010-11-13 20:37:37 UTC (rev 
13670)
@@ -1,175 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 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 3, 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 core/core_api_peer_get_info.c
- * @brief implementation of the peer_change_preference functions 
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_core_service.h"
-#include "core.h"
-
-
-struct GNUNET_CORE_InformationRequestContext 
-{
-  
-  /**
-   * Our connection to the service.
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-  /**
-   * Function to call with the information.
-   */
-  GNUNET_CORE_PeerConfigurationInfoCallback info;
-
-  /**
-   * Closure for info.
-   */
-  void *info_cls;
-
-};
-
-
-/**
- * Receive reply from core service with information about a peer.
- *
- * @param cls our 'struct  GNUNET_CORE_InformationRequestContext *'
- * @param msg NULL on error (i.e. timeout)
- */
-static void
-receive_info (void *cls,
-             const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_CORE_InformationRequestContext *irc = cls;
-  const struct ConfigurationInfoMessage *cim;
-  static struct GNUNET_BANDWIDTH_Value32NBO zbw; /* zero bandwidth */
-
-  if (msg == NULL)
-    {
-      if (irc->info != NULL)
-       irc->info (irc->info_cls, 
-                  NULL, zbw, zbw, 0, 0);     
-      GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
-      GNUNET_free (irc);
-      return;
-    }
-  if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO) ||
-       (ntohs (msg->size) != sizeof (struct ConfigurationInfoMessage)) )
-    {
-      GNUNET_break (0);
-      if (irc->info != NULL)
-       irc->info (irc->info_cls, 
-                  NULL, zbw, zbw, 0, 0);     
-      GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
-      GNUNET_free (irc);
-      return;
-    }
-  cim = (const struct ConfigurationInfoMessage*) msg;
-  if (irc->info != NULL)
-    irc->info (irc->info_cls,
-              &cim->peer,
-              cim->bw_in,
-              cim->bw_out,
-              ntohl (cim->reserved_amount),
-              GNUNET_ntohll (cim->preference));  
-  GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
-  GNUNET_free (irc);
-}
-
-
-/**
- * Obtain statistics and/or change preferences for the given peer.
- *
- * @param cfg configuration to use
- * @param peer identifies the peer
- * @param timeout after how long should we give up (and call "info" with NULL
- *                for "peer" to signal an error)?
- * @param bw_out set to the current bandwidth limit (sending) for this peer,
- *                caller should set "bw_out" to "-1" to avoid changing
- *                the current value; otherwise "bw_out" will be lowered to
- *                the specified value; passing a pointer to "0" can be used to 
force
- *                us to disconnect from the peer; "bw_out" might not increase
- *                as specified since the upper bound is generally
- *                determined by the other peer!
- * @param amount reserve N bytes for receiving, negative
- *                amounts can be used to undo a (recent) reservation;
- * @param preference increase incoming traffic share preference by this amount;
- *                in the absence of "amount" reservations, we use this
- *                preference value to assign proportional bandwidth shares
- *                to all connected peers
- * @param info function to call with the resulting configuration information
- * @param info_cls closure for info
- * @return NULL on error
- */
-struct GNUNET_CORE_InformationRequestContext *
-GNUNET_CORE_peer_change_preference (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
-                                   const struct GNUNET_PeerIdentity *peer,
-                                   struct GNUNET_TIME_Relative timeout,
-                                   struct GNUNET_BANDWIDTH_Value32NBO bw_out,
-                                   int32_t amount,
-                                   uint64_t preference,
-                                   GNUNET_CORE_PeerConfigurationInfoCallback 
info,
-                                   void *info_cls)
-{
-  struct GNUNET_CORE_InformationRequestContext *irc;
-  struct RequestInfoMessage rim;
-  struct GNUNET_CLIENT_Connection *client;
-  int retry;
-
-  client = GNUNET_CLIENT_connect ("core", cfg);
-  if (client == NULL)
-    return NULL;
-  irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext));
-  irc->client = client;
-  irc->info = info;
-  irc->info_cls = info_cls;
-  rim.header.size = htons (sizeof (struct RequestInfoMessage));
-  rim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO);
-  rim.reserved = htonl (0);
-  rim.limit_outbound = bw_out;
-  rim.reserve_inbound = htonl (amount);
-  rim.preference_change = GNUNET_htonll(preference);
-  rim.peer = *peer;
-  retry = ( (amount == 0) && (preference == 0) ) ? GNUNET_YES : GNUNET_NO;
-  GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client,
-                                                                      
&rim.header,
-                                                                      timeout,
-                                                                      retry,
-                                                                      
&receive_info,
-                                                                      irc));  
-  return irc;
-}
-
-
-/**
- * Cancel request for getting information about a peer.
- *
- * @param irc context returned by the original GNUNET_CORE_peer_get_info call
- */
-void
-GNUNET_CORE_peer_change_preference_cancel (struct 
GNUNET_CORE_InformationRequestContext *irc)
-{
-  GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO);
-  GNUNET_free (irc);
-}
-
-/* end of core_api_peer_get_info.c */

Deleted: gnunet/src/core/core_api_peer_request.c
===================================================================
--- gnunet/src/core/core_api_peer_request.c     2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/core_api_peer_request.c     2010-11-13 20:37:37 UTC (rev 
13670)
@@ -1,179 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009, 2010 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 3, 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 core/core_api_peer_request.c
- * @brief implementation of the peer_request functions 
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_core_service.h"
-#include "core.h"
-
-
-/**
- * Handle for a request to the core to connect to
- * a particular peer.  Can be used to cancel the request
- * (before the 'cont'inuation is called).
- */
-struct GNUNET_CORE_PeerRequestHandle
-{
-
-  /**
-   * Our connection to the service.
-   */
-  struct GNUNET_CLIENT_Connection *client;
-
-
-  /**
-   * Function to call once done.
-   */
-  GNUNET_SCHEDULER_Task cont;
-  
-  /**
-   * Closure for 'cont'.
-   */
-  void *cont_cls;
-
-  /**
-   * When to time out.
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
-   * Identity of the peer to connect to.
-   */
-  struct GNUNET_PeerIdentity peer;
-       
-  /**
-   * Message type to use.
-   */
-  uint16_t type;
-};
-
-
-/**
- * Transmit the request to the core service.
- *
- * @param cls our 'struct GNUNET_CORE_PeerRequestHandle'
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
- */ 
-static size_t
-send_request (void *cls,
-             size_t size,
-             void *buf)
-{
-  struct GNUNET_CORE_PeerRequestHandle * prh = cls;
-  struct ConnectMessage msg;
-
-  if (buf == NULL)
-    {
-      if (prh->cont != NULL)
-        GNUNET_SCHEDULER_add_continuation (prh->cont,
-                                          prh->cont_cls,
-                                          GNUNET_SCHEDULER_REASON_TIMEOUT);
-      GNUNET_CLIENT_disconnect (prh->client, GNUNET_NO);
-      GNUNET_free (prh);
-      return 0;
-    }
-  GNUNET_assert (size >= sizeof (struct ConnectMessage));
-  msg.header.type = htons (prh->type);
-  msg.header.size = htons (sizeof (struct ConnectMessage));
-  msg.reserved = htonl (0);
-  msg.timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining 
(prh->timeout));
-  msg.peer = prh->peer;
-  memcpy (buf, &msg, sizeof (msg));
-  if (prh->cont != NULL)
-    {
-      GNUNET_SCHEDULER_add_continuation (prh->cont,
-                                         prh->cont_cls,
-                                         GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-    }
-  GNUNET_CLIENT_disconnect (prh->client, GNUNET_YES);
-  GNUNET_free (prh);
-  return sizeof (msg);
-}
-
-
-/**
- * Request that the core should try to connect to a particular peer.
- * Once the request has been transmitted to the core, the continuation
- * function will be called.  Note that this does NOT mean that a
- * connection was successfully established -- it only means that the
- * core will now try.  Successful establishment of the connection
- * will be signalled to the 'connects' callback argument of
- * 'GNUNET_CORE_connect' only.  If the core service does not respond
- * to our connection attempt within the given time frame, 'cont' will
- * be called with the TIMEOUT reason code.
- *
- * @param cfg configuration to use
- * @param timeout how long to try to talk to core
- * @param peer who should we connect to
- * @param cont function to call once the request has been completed (or timed 
out)
- * @param cont_cls closure for cont
- * @return NULL on error (cont will not be called), otherwise handle for 
cancellation
- */
-struct GNUNET_CORE_PeerRequestHandle *
-GNUNET_CORE_peer_request_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
-                                 struct GNUNET_TIME_Relative timeout,
-                                 const struct GNUNET_PeerIdentity * peer,
-                                 GNUNET_SCHEDULER_Task cont,
-                                 void *cont_cls)
-{
-  struct GNUNET_CORE_PeerRequestHandle *ret;
-  struct GNUNET_CLIENT_Connection *client;
-  
-  client = GNUNET_CLIENT_connect ("core", cfg);
-  if (client == NULL)
-    return NULL;
-  ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
-  ret->client = client;
-  ret->cont = cont;
-  ret->cont_cls = cont_cls;
-  ret->peer = *peer;
-  ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT;
-  ret->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  GNUNET_CLIENT_notify_transmit_ready (client,
-                                      sizeof (struct ConnectMessage),
-                                      timeout,
-                                      GNUNET_YES,
-                                      &send_request,
-                                      ret);
-  return ret;
-}
-
-
-/**
- * Cancel a pending request to connect to a particular peer.  Must not
- * be called after the 'cont' function was invoked.
- *
- * @param req request handle that was returned for the original request
- */
-void
-GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle 
*req)
-{
-  GNUNET_CLIENT_disconnect (req->client, GNUNET_NO);
-  GNUNET_free (req);
-}
-
-
-/* end of core_api_peer_request.c */

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/gnunet-service-core.c       2010-11-13 20:37:37 UTC (rev 
13670)
@@ -391,6 +391,15 @@
 };
 
 
+/**
+ * Record kept for each request for transmission issued by a 
+ * client that is still pending.
+ */
+struct ClientActiveRequest;
+
+/**
+ * Data kept per neighbouring peer.
+ */
 struct Neighbour
 {
   /**
@@ -416,6 +425,18 @@
   struct MessageEntry *encrypted_tail;
 
   /**
+   * Head of list of requests from clients for transmission to 
+   * this peer.
+   */
+  struct ClientActiveRequest *active_client_request_head;
+
+  /**
+   * Tail of list of requests from clients for transmission to 
+   * this peer.
+   */
+  struct ClientActiveRequest *active_client_request_tail;
+
+  /**
    * Handle for pending requests for transmission to this peer
    * with the transport service.  NULL if no request is pending.
    */
@@ -517,11 +538,6 @@
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   * Last latency observed from this peer.
-   */
-  struct GNUNET_TIME_Relative last_latency;
-
-  /**
    * At what frequency are we currently re-trying SET_KEY messages?
    */
   struct GNUNET_TIME_Relative set_key_retry_frequency;
@@ -588,11 +604,6 @@
   uint32_t ping_challenge;
 
   /**
-   * What was the last distance to this peer as reported by the transports?
-   */
-  uint32_t last_distance;
-
-  /**
    * What is our connection status?
    */
   enum PeerStateMachine status;
@@ -628,6 +639,12 @@
   const uint16_t *types;
 
   /**
+   * Map of peer identities to active transmission requests of this
+   * client to the peer (of type 'struct ClientActiveRequest').
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *requests;
+
+  /**
    * Options for messages this client cares about,
    * see GNUNET_CORE_OPTION_ values.
    */
@@ -643,6 +660,59 @@
 
 
 /**
+ * Record kept for each request for transmission issued by a 
+ * client that is still pending.
+ */
+struct ClientActiveRequest
+{
+
+  /**
+   * Active requests are kept in a doubly-linked list of
+   * the respective target peer.
+   */
+  struct ClientActiveRequest *next;
+
+  /**
+   * Active requests are kept in a doubly-linked list of
+   * the respective target peer.
+   */
+  struct ClientActiveRequest *prev;
+
+  /**
+   * Handle to the client.
+   */
+  struct Client *client;
+
+  /**
+   * By what time would the client want to see this message out?
+   */
+  struct GNUNET_TIME_Absolute deadline;
+
+  /**
+   * How important is this request.
+   */
+  uint32_t priority;
+
+  /**
+   * How many more requests does this client have?
+   */
+  uint32_t queue_size;
+
+  /**
+   * How many bytes does the client intend to send?
+   */
+  uint16_t msize;
+
+  /**
+   * Unique request ID (in big endian).
+   */
+  uint16_t smr_id;
+  
+};
+
+
+
+/**
  * Our public key.
  */
 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
@@ -917,8 +987,6 @@
 #endif
   psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
   psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
-  psnm.distance = htonl (n->last_distance);
-  psnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
   psnm.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add 
(n->last_activity,
                                                                      
GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
   psnm.bandwidth_in = n->bw_in;
@@ -933,46 +1001,127 @@
                            GNUNET_NO);
 }
 
+
 /**
- * Handle CORE_ITERATE_PEERS request.
+ * Go over our message queue and if it is not too long, go
+ * over the pending requests from clients for this
+ * neighbour and send some clients a 'READY' notification.
+ *
+ * @param n which peer to process
  */
 static void
-handle_client_iterate_peers (void *cls,
-                    struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
+schedule_peer_messages (struct Neighbour *n)
 {
+  struct SendMessageReady smr;
+  struct ClientActiveRequest *car;
+  struct ClientActiveRequest *pos;
+  struct Client *c;
+  struct MessageEntry *mqe;
+  unsigned int queue_size;
+  
+  /* check if neighbour queue is empty enough! */
+  queue_size = 0;
+  mqe = n->messages;
+  while (mqe != NULL) 
+    {
+      queue_size++;
+      mqe = mqe->next;
+    }
+  if (queue_size >= MAX_PEER_QUEUE_SIZE)
+    return; /* queue still full */
+  /* find highest priority request */
+  pos = n->active_client_request_head;
+  car = NULL;
+  while (pos != NULL)
+    {
+      if ( (car == NULL) ||
+          (pos->priority > car->priority) )
+       car = pos;
+      pos = pos->next;
+    }
+  if (car == NULL)
+    return; /* no pending requests */
+  c = car->client;
+  GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
+                              n->active_client_request_tail,
+                              car);
+  GNUNET_CONTAINER_multihashmap_remove (c->requests,
+                                       &n->peer.hashPubKey,
+                                       car);  
+  smr.header.size = htons (sizeof (struct SendMessageReady));
+  smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
+  smr.size = htons (car->msize);
+  smr.smr_id = car->smr_id;
+  smr.peer = n->peer;
+  send_to_client (c, &smr.header, GNUNET_NO);
+  GNUNET_free (car);
+}
+
+
+/**
+ * Handle CORE_SEND_REQUEST message.
+ */
+static void
+handle_client_send_request (void *cls,
+                           struct GNUNET_SERVER_Client *client,
+                           const struct GNUNET_MessageHeader *message)
+{
+  const struct SendMessageRequest *req;
   struct Neighbour *n;
-  struct ConnectNotifyMessage cnm;
-  struct GNUNET_MessageHeader done_msg;
-  struct GNUNET_SERVER_TransmitContext *tc;
+  struct Client *c;
+  struct ClientActiveRequest *car;
 
-  /* notify new client about existing neighbours */
-  cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
-  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  n = neighbours;
-  while (n != NULL)
+  req = (const struct SendMessageRequest*) message;
+  n = find_neighbour (&req->peer);
+  if ( (n == NULL) ||
+       (GNUNET_YES != n->is_connected) )
+    { 
+      /* neighbour must have disconnected since request was issued,
+        ignore (client will realize it once it processes the 
+        disconnect notification) */
+      GNUNET_STATISTICS_update (stats, 
+                               gettext_noop ("# send requests dropped 
(disconnected)"), 
+                               1, 
+                               GNUNET_NO);
+      GNUNET_SERVER_receive_done (client, GNUNET_OK);
+      return;
+    }
+  c = clients;
+  while ( (c != NULL) &&
+         (c->client_handle != client) )
+    c = c->next;
+  if (c == NULL)
     {
-      if (n->status == PEER_STATE_KEY_CONFIRMED)
-        {
-#if DEBUG_CORE_CLIENT
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
-#endif
-          cnm.distance = htonl (n->last_distance);
-          cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
-          cnm.peer = n->peer;
-          GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
-          /*send_to_client (c, &cnm.header, GNUNET_NO);*/
-        }
-      n = n->next;
+      /* client did not send INIT first! */
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
     }
-
-  GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
-  GNUNET_SERVER_transmit_context_run (tc,
-                                      GNUNET_TIME_UNIT_FOREVER_REL);
+  if (c->requests == NULL)
+    c->requests = GNUNET_CONTAINER_multihashmap_create (16);
+  car = GNUNET_CONTAINER_multihashmap_get (c->requests,
+                                          &req->peer.hashPubKey);
+  if (car == NULL)
+    {
+      /* create new entry */
+      car = GNUNET_malloc (sizeof (struct ClientActiveRequest));
+      GNUNET_assert (GNUNET_OK ==
+                    GNUNET_CONTAINER_multihashmap_put (c->requests,
+                                                       &req->peer.hashPubKey,
+                                                       car,
+                                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
+      GNUNET_CONTAINER_DLL_insert (n->active_client_request_head,
+                                  n->active_client_request_tail,
+                                  car);
+      car->client = c;
+    }
+  car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
+  car->priority = ntohl (req->priority);
+  car->queue_size = ntohl (req->queue_size);
+  car->msize = ntohs (req->size);
+  car->smr_id = req->smr_id;
+  schedule_peer_messages (n);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
 
@@ -1064,8 +1213,6 @@
              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                          "Sending `%s' message to client.\n", 
"NOTIFY_CONNECT");
 #endif
-             cnm.distance = htonl (n->last_distance);
-             cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
              cnm.peer = n->peer;
              send_to_client (c, &cnm.header, GNUNET_NO);
            }
@@ -1077,6 +1224,33 @@
 
 
 /**
+ * Free client request records.
+ *
+ * @param cls NULL
+ * @param key identity of peer for which this is an active request
+ * @param value the 'struct ClientActiveRequest' to free
+ * @return GNUNET_YES (continue iteration)
+ */
+static int
+destroy_active_client_request (void *cls,
+                              const GNUNET_HashCode *key,
+                              void *value)
+{
+  struct ClientActiveRequest *car = cls;
+  struct Neighbour *n;
+  struct GNUNET_PeerIdentity peer;
+
+  peer.hashPubKey = *key;
+  n = find_neighbour (&peer);
+  GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
+                              n->active_client_request_tail,
+                              car);
+  GNUNET_free (car);
+  return GNUNET_YES;
+}
+
+
+/**
  * A client disconnected, clean up.
  *
  * @param cls closure
@@ -1100,18 +1274,27 @@
   while (pos != NULL)
     {
       if (client == pos->client_handle)
-        {
-          if (prev == NULL)
-            clients = pos->next;
-          else
-            prev->next = pos->next;
-          GNUNET_free (pos);
-          return;
-        }
+        break;
       prev = pos;
       pos = pos->next;
     }
-  /* client never sent INIT */
+  if (pos == NULL)
+    {
+      /* client never sent INIT */
+      return;
+    }
+  if (prev == NULL)
+    clients = pos->next;
+  else
+    prev->next = pos->next;
+  if (pos->requests != NULL)
+    {
+      GNUNET_CONTAINER_multihashmap_iterate (pos->requests,
+                                            &destroy_active_client_request,
+                                            NULL);
+      GNUNET_CONTAINER_multihashmap_destroy (pos->requests);
+    }
+  GNUNET_free (pos);
 }
 
 
@@ -1192,7 +1375,7 @@
                  (int) got_reserv);
 #endif
       cim.reserved_amount = htonl (got_reserv);
-      cim.bw_in = n->bw_in;
+      cim.rim_id = rcm->rim_id;
       cim.bw_out = n->bw_out;
       cim.preference = n->current_preference;
     }
@@ -1221,6 +1404,7 @@
 free_neighbour (struct Neighbour *n)
 {
   struct MessageEntry *m;
+  struct ClientActiveRequest *car;
 
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1249,6 +1433,16 @@
                                   m);
       GNUNET_free (m);
     }
+  while (NULL != (car = n->active_client_request_head))
+    {
+      GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
+                                  n->active_client_request_tail,
+                                  car);
+      GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
+                                           &n->peer.hashPubKey,
+                                           car);
+      GNUNET_free (car);
+    }
   if (NULL != n->th)
     {
       GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
@@ -1894,8 +2088,6 @@
       return 0;
     }
   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND);
-  ntm->distance = htonl (n->last_distance);
-  ntm->latency = GNUNET_TIME_relative_hton (n->last_latency);
   ntm->peer = n->peer;
   pos = n->messages;
   prev = NULL;
@@ -1985,7 +2177,9 @@
   struct MessageEntry *pos;
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Relative delta;
+  int disc;
 
+  disc = GNUNET_NO;
   now = GNUNET_TIME_absolute_get ();
   prev = NULL;
   pos = n->messages;
@@ -2004,12 +2198,19 @@
            n->messages = next;
          else
            prev->next = next;
+         GNUNET_STATISTICS_update (stats, 
+                                   gettext_noop ("# messages discarded 
(expired prior to transmission)"), 
+                                   1, 
+                                   GNUNET_NO);
+         disc = GNUNET_YES;
          GNUNET_free (pos);
        }
       else
        prev = pos;
       pos = next;
     }
+  if (GNUNET_YES == disc)
+    schedule_peer_messages (n);
 }
 
 
@@ -2217,6 +2418,7 @@
                                     n->encrypted_tail,
                                     me);
   process_encrypted_neighbour_queue (n);
+  schedule_peer_messages (n);
 }
 
 
@@ -2342,8 +2544,15 @@
               (unsigned int) msize, 
              GNUNET_i2s (&sm->peer));
 #endif
+  discard_expired_messages (n);
   /* bound queue size */
-  discard_expired_messages (n);
+  /* NOTE: this entire block to bound the queue size should be
+     obsolete with the new client-request code and the
+     'schedule_peer_messages' mechanism; we still have this code in
+     here for now as a sanity check for the new mechanmism;
+     ultimately, we should probably simply reject SEND messages that
+     are not 'approved' (or provide a new core API for very unreliable
+     delivery that always sends with priority 0).  Food for thought. */
   min_prio = UINT32_MAX;
   min_prio_entry = NULL;
   min_prio_prev = NULL;
@@ -2367,7 +2576,8 @@
       /* queue full */
       if (ntohl(sm->priority) <= min_prio)
        {
-         /* discard new entry */
+         /* discard new entry; this should no longer happen! */
+         GNUNET_break (0);
 #if DEBUG_CORE
          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                      "Queue full (%u/%u), discarding new request (%u bytes of 
type %u)\n",
@@ -2376,7 +2586,9 @@
                      (unsigned int) msize,
                      (unsigned int) ntohs (message->type));
 #endif
-         GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded CORE_SEND 
requests"), 1, GNUNET_NO);
+         GNUNET_STATISTICS_update (stats, 
+                                   gettext_noop ("# discarded CORE_SEND 
requests"), 
+                                   1, GNUNET_NO);
 
          if (client != NULL)
            GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -3087,8 +3299,6 @@
         }      
       cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
       cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
-      cnm.distance = htonl (n->last_distance);
-      cnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
       cnm.peer = n->peer;
       send_to_all_clients (&cnm.header, GNUNET_YES, 
GNUNET_CORE_OPTION_SEND_CONNECT);
       process_encrypted_neighbour_queue (n);
@@ -3308,8 +3518,6 @@
   ntm = (struct NotifyTrafficMessage *) buf;
   ntm->header.size = htons (msize + sizeof (struct NotifyTrafficMessage));
   ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND);
-  ntm->distance = htonl (sender->last_distance);
-  ntm->latency = GNUNET_TIME_relative_hton (sender->last_latency);
   ntm->peer = sender->peer;
   memcpy (&ntm[1], m, msize);
   send_to_client (client, &ntm->header, GNUNET_YES);
@@ -3602,9 +3810,7 @@
   n = find_neighbour (peer);
   if (n == NULL)
     n = create_neighbour (peer);
-  changed = (latency.rel_value != n->last_latency.rel_value) || (distance != 
n->last_distance);
-  n->last_latency = latency;
-  n->last_distance = distance;
+  changed = GNUNET_YES; /* FIXME... */
   up = (n->status == PEER_STATE_KEY_CONFIRMED);
   type = ntohs (message->type);
   size = ntohs (message->size);
@@ -3832,8 +4038,6 @@
                            1, 
                            GNUNET_NO);
   n->is_connected = GNUNET_YES;      
-  n->last_latency = latency;
-  n->last_distance = distance;
   GNUNET_BANDWIDTH_tracker_init (&n->available_send_window,
                                 n->bw_out,
                                 MAX_WINDOW_TIME_S);
@@ -3868,6 +4072,7 @@
 {
   struct DisconnectNotifyMessage cnm;
   struct Neighbour *n;
+  struct ClientActiveRequest *car;
   struct GNUNET_TIME_Relative left;
 
 #if DEBUG_CORE
@@ -3890,6 +4095,17 @@
       send_to_all_clients (&cnm.header, GNUNET_YES, 
GNUNET_CORE_OPTION_SEND_DISCONNECT);
     }
   n->is_connected = GNUNET_NO;
+  while (NULL != (car = n->active_client_request_head))
+    {
+      GNUNET_CONTAINER_DLL_remove (n->active_client_request_head,
+                                  n->active_client_request_tail,
+                                  car);
+      GNUNET_CONTAINER_multihashmap_remove (car->client->requests,
+                                           &n->peer.hashPubKey,
+                                           car);
+      GNUNET_free (car);
+    }
+
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# peers connected (transport)"), 
                            -1, 
@@ -3964,9 +4180,9 @@
     {&handle_client_request_info, NULL,
      GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
      sizeof (struct RequestInfoMessage)},
-    {&handle_client_iterate_peers, NULL,
-     GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
-     sizeof (struct GNUNET_MessageHeader)},
+    {&handle_client_send_request, NULL,
+     GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
+     sizeof (struct SendMessageRequest)},
     {&handle_client_send, NULL,
      GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
     {&handle_client_request_connect, NULL,

Modified: gnunet/src/core/test_core_api.c
===================================================================
--- gnunet/src/core/test_core_api.c     2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/core/test_core_api.c     2010-11-13 20:37:37 UTC (rev 13670)
@@ -38,11 +38,6 @@
 
 #define START_ARM GNUNET_YES
 
-/**
- * How long until we give up on transmitting the message?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-
 #define MTYPE 12345
 
 struct PeerContext
@@ -103,8 +98,7 @@
 static void
 connect_notify (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct PeerContext *pc = cls;
   GNUNET_assert (pc->connect_status == 0);
@@ -130,8 +124,7 @@
 inbound_notify (void *cls,
                 const struct GNUNET_PeerIdentity *other,
                 const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other));
@@ -143,8 +136,7 @@
 outbound_notify (void *cls,
                  const struct GNUNET_PeerIdentity *other,
                  const struct GNUNET_MessageHeader *message,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Core notifies about outbound data for `%4s'.\n",
@@ -160,8 +152,7 @@
 process_mtype (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_MessageHeader *message,
-              struct GNUNET_TIME_Relative latency,
-              uint32_t distance)
+              const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Receiving message from `%4s'.\n", GNUNET_i2s (peer));
@@ -220,7 +211,6 @@
       OKPP;
       /* connect p2 */
       GNUNET_CORE_connect (p2.cfg, 1,
-                           TIMEOUT,
                            &p2,
                            &init_notify,                        
                            &connect_notify,
@@ -311,7 +301,6 @@
   setup_peer (&p1, "test_core_api_peer1.conf");
   setup_peer (&p2, "test_core_api_peer2.conf");
   GNUNET_CORE_connect (p1.cfg, 1,
-                       TIMEOUT,
                        &p1,
                        &init_notify,
                       &connect_notify,

Modified: gnunet/src/core/test_core_api_reliability.c
===================================================================
--- gnunet/src/core/test_core_api_reliability.c 2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/test_core_api_reliability.c 2010-11-13 20:37:37 UTC (rev 
13670)
@@ -148,8 +148,7 @@
 static void
 connect_notify (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct PeerContext *pc = cls;
   GNUNET_assert (pc->connect_status == 0);
@@ -175,8 +174,7 @@
 inbound_notify (void *cls,
                 const struct GNUNET_PeerIdentity *other,
                 const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 #if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -190,8 +188,7 @@
 outbound_notify (void *cls,
                  const struct GNUNET_PeerIdentity *other,
                  const struct GNUNET_MessageHeader *message,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 #if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -215,8 +212,7 @@
 process_mtype (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_MessageHeader *message,
-              struct GNUNET_TIME_Relative latency,
-              uint32_t distance)
+              const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   static int n;
   unsigned int s;
@@ -366,7 +362,6 @@
       OKPP;
       /* connect p2 */
       GNUNET_CORE_connect (p2.cfg, 1,
-                           TIMEOUT,
                            &p2,
                            &init_notify,                        
                            &connect_notify,
@@ -456,7 +451,6 @@
   setup_peer (&p1, "test_core_api_peer1.conf");
   setup_peer (&p2, "test_core_api_peer2.conf");
   GNUNET_CORE_connect (p1.cfg, 1,
-                       TIMEOUT,
                        &p1,
                        &init_notify,
                       &connect_notify,

Modified: gnunet/src/core/test_core_api_start_only.c
===================================================================
--- gnunet/src/core/test_core_api_start_only.c  2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/core/test_core_api_start_only.c  2010-11-13 20:37:37 UTC (rev 
13670)
@@ -35,12 +35,6 @@
 
 #define START_ARM GNUNET_YES
 
-
-/**
- * How long until we give up on transmitting the message?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
 #define MTYPE 12345
 
 struct PeerContext
@@ -71,8 +65,7 @@
 static void
 connect_notify (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 }
 
@@ -88,8 +81,7 @@
 inbound_notify (void *cls,
                 const struct GNUNET_PeerIdentity *other,
                 const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   return GNUNET_OK;
 }
@@ -99,8 +91,7 @@
 outbound_notify (void *cls,
                  const struct GNUNET_PeerIdentity *other,
                  const struct GNUNET_MessageHeader *message,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   return GNUNET_OK;
 }
@@ -126,7 +117,6 @@
     {
       /* connect p2 */
       GNUNET_CORE_connect (p2.cfg, 1,
-                           TIMEOUT,
                            &p2,
                            &init_notify,                        
                            &connect_notify,
@@ -173,7 +163,6 @@
   setup_peer (&p1, "test_core_api_peer1.conf");
   setup_peer (&p2, "test_core_api_peer2.conf");
   GNUNET_CORE_connect (p1.cfg, 1,
-                       TIMEOUT,
                        &p1,
                        &init_notify,
                       &connect_notify,

Modified: gnunet/src/core/test_core_quota_compliance.c
===================================================================
--- gnunet/src/core/test_core_quota_compliance.c        2010-11-12 15:53:17 UTC 
(rev 13669)
+++ gnunet/src/core/test_core_quota_compliance.c        2010-11-13 20:37:37 UTC 
(rev 13670)
@@ -191,8 +191,7 @@
 inbound_notify (void *cls,
                 const struct GNUNET_PeerIdentity *other,
                 const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   total_bytes_recv += ntohs (message->size);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -207,8 +206,7 @@
 outbound_notify (void *cls,
                  const struct GNUNET_PeerIdentity *other,
                  const struct GNUNET_MessageHeader *message,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 #if DEBUG_CONNECTIONS
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -238,38 +236,37 @@
 measurement_end (void *cls,
           const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-         struct GNUNET_TIME_Relative duration;
-
-         measure_task  = GNUNET_SCHEDULER_NO_TASK;
-         if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-               return;
-
-         if (err_task != GNUNET_SCHEDULER_NO_TASK)
-                 GNUNET_SCHEDULER_cancel (err_task);
-         if (send_task != GNUNET_SCHEDULER_NO_TASK)
-                 GNUNET_SCHEDULER_cancel (send_task);
-
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority 
CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority 
CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
-
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request 
bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request 
bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority 
CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
-         GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority 
CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
-         measurement_running = GNUNET_NO;
-         duration = GNUNET_TIME_absolute_get_difference(start_time, 
GNUNET_TIME_absolute_get());
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                         "\nQuota compliance: \n"\
-                         "Receive rate: %10llu kB/s\n"
-                         "Send rate   : %10llu kB/s\n"\
-                         "Quota       : %10llu kB/s\n",
-                         (total_bytes_recv/(duration.rel_value / 1000)/1024),
-                         (total_bytes_sent/(duration.rel_value / 
1000)/1024),current_quota_p1_in/1024);
-
-
-      GNUNET_SCHEDULER_add_now (&terminate_task, NULL);
+  struct GNUNET_TIME_Relative duration;
+  
+  measure_task  = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  
+  if (err_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (err_task);
+  if (send_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (send_task);
+  
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND 
requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
+  
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request 
bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request 
bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND 
request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1);
+  GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND 
request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2);
+  measurement_running = GNUNET_NO;
+  duration = GNUNET_TIME_absolute_get_difference(start_time, 
GNUNET_TIME_absolute_get());
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             "\nQuota compliance: \n"                  \
+             "Receive rate: %10llu kB/s\n"
+             "Send rate   : %10llu kB/s\n"                     \
+             "Quota       : %10llu kB/s\n",
+             (total_bytes_recv/(duration.rel_value / 1000)/1024),
+             (total_bytes_sent/(duration.rel_value / 1000)/1024),
+             current_quota_p1_in/1024);
+  GNUNET_SCHEDULER_add_now (&terminate_task, NULL);
 }
 
 static size_t
@@ -279,17 +276,19 @@
 send_tsk (void *cls,
           const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-        send_task = GNUNET_SCHEDULER_NO_TASK;
-
-         ch = GNUNET_CORE_notify_transmit_ready (p1.ch,
-                                                                0,
-                                                                FAST_TIMEOUT,
-                                                                &p2.id,
-                                                                sizeof (struct 
TestMessage) + MEASUREMENT_MSG_SIZE,
-                                                                
&transmit_ready, &p1);
+  send_task = GNUNET_SCHEDULER_NO_TASK;
+  
+  ch = GNUNET_CORE_notify_transmit_ready (p1.ch,
+                                         0,
+                                         FAST_TIMEOUT,
+                                         &p2.id,
+                                         sizeof (struct TestMessage) + 
MEASUREMENT_MSG_SIZE,
+                                         &transmit_ready, &p1);
 }
 
-static void measure (unsigned long long quota_p1, unsigned long long quota_p2 )
+
+static void 
+measure (unsigned long long quota_p1, unsigned long long quota_p2)
 {
 #if VERBOSE
   if ((is_asymmetric_send_constant == GNUNET_YES) || 
(is_asymmetric_recv_constant == GNUNET_YES))
@@ -316,11 +315,11 @@
   total_bytes = 0;
   total_bytes_sent = 0;
   ch = GNUNET_CORE_notify_transmit_ready (p1.ch,
-                                              0,
-                                              TIMEOUT,
-                                              &p2.id,
-                                              sizeof (struct TestMessage) + 
MEASUREMENT_MSG_SIZE,
-                                              &transmit_ready, &p1);
+                                         0,
+                                         TIMEOUT,
+                                         &p2.id,
+                                         sizeof (struct TestMessage) + 
MEASUREMENT_MSG_SIZE,
+                                         &transmit_ready, &p1);
 }
 
 static int tr_n;
@@ -330,8 +329,7 @@
 process_mtype (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_MessageHeader *message,
-              struct GNUNET_TIME_Relative latency,
-              uint32_t distance)
+              const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   static int n;
   unsigned int s;
@@ -453,7 +451,6 @@
       OKPP;
       /* connect p2 */
       GNUNET_CORE_connect (p2.cfg, 1,
-                           TIMEOUT,
                            &p2,
                            &init_notify,                        
                            &connect_notify,
@@ -534,7 +531,6 @@
   setup_peer (&p1, "test_core_quota_peer1.conf");
   setup_peer (&p2, "test_core_quota_peer2.conf");
   GNUNET_CORE_connect (p1.cfg, 1,
-                       TIMEOUT,
                        &p1,
                        &init_notify,
                        &connect_notify,
@@ -606,7 +602,7 @@
 {
   int ret;
 
-  GNUNET_log_setup ("test-core-api",
+  GNUNET_log_setup ("test-core-quota-compliance",
 #if VERBOSE
                     "DEBUG",
 #else

Modified: gnunet/src/dht/gnunet-dht-driver.c
===================================================================
--- gnunet/src/dht/gnunet-dht-driver.c  2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/dht/gnunet-dht-driver.c  2010-11-13 20:37:37 UTC (rev 13670)
@@ -854,8 +854,6 @@
 log_topology_cb (void *cls,
                 const struct GNUNET_PeerIdentity *first,
                 const struct GNUNET_PeerIdentity *second,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance,
                 const char *emsg)
 {
   struct TopologyIteratorContext *topo_ctx = cls;
@@ -1286,8 +1284,6 @@
 count_peers_churn_cb (void *cls,
                      const struct GNUNET_PeerIdentity *first,
                      const struct GNUNET_PeerIdentity *second,
-                     struct GNUNET_TIME_Relative latency,
-                     uint32_t distance,
                      const char *emsg)
 {
   struct FindPeerContext *find_peer_context = cls;
@@ -1958,8 +1954,6 @@
 count_peers_cb (void *cls,
                const struct GNUNET_PeerIdentity *first,
                const struct GNUNET_PeerIdentity *second,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance,
                const char *emsg)
 {
   struct FindPeerContext *find_peer_context = cls;

Modified: gnunet/src/dht/gnunet-service-dht.c
===================================================================
--- gnunet/src/dht/gnunet-service-dht.c 2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/dht/gnunet-service-dht.c 2010-11-13 20:37:37 UTC (rev 13670)
@@ -285,19 +285,21 @@
   struct GNUNET_CORE_InformationRequestContext *info_ctx;
 
   /**
-   * What is the average latency for replies received?
+   * What is the identity of the peer?
    */
-  struct GNUNET_TIME_Relative latency;
+  struct GNUNET_PeerIdentity id;
 
+#if 0
   /**
-   * What is the identity of the peer?
+   * What is the average latency for replies received?
    */
-  struct GNUNET_PeerIdentity id;
+  struct GNUNET_TIME_Relative latency;
 
   /**
    * Transport level distance to peer.
    */
   unsigned int distance;
+#endif
 
   /**
    * Holds matching bits from peer to current target,
@@ -1380,7 +1382,6 @@
  *
  * @param cls closure
  * @param peer identifies the peer
- * @param bpm_in set to the current bandwidth limit (receiving) for this peer
  * @param bpm_out set to the current bandwidth limit (sending) for this peer
  * @param amount set to the amount that was actually reserved or unreserved;
  *               either the full requested amount or zero (no partial 
reservations)
@@ -1389,7 +1390,6 @@
 static void
 update_core_preference_finish (void *cls,
                                const struct GNUNET_PeerIdentity * peer,
-                               struct GNUNET_BANDWIDTH_Value32NBO bpm_in,
                                struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
                                int amount, uint64_t preference)
 {
@@ -1416,7 +1416,7 @@
       matching = 63;
     }
   preference = 1LL << matching;
-  peer->info_ctx = GNUNET_CORE_peer_change_preference (cfg,
+  peer->info_ctx = GNUNET_CORE_peer_change_preference (coreAPI,
                                                        &peer->id,
                                                        
GNUNET_TIME_relative_get_forever(),
                                                        
GNUNET_BANDWIDTH_value_init (UINT32_MAX),
@@ -1433,23 +1433,23 @@
  * @param peer GNUNET_PeerIdentity of the peer to add
  * @param bucket the already figured out bucket to add
  *        the peer to
- * @param latency the core reported latency of this peer
- * @param distance the transport level distance to this peer
+ * @param atsi performance information
  *
  * @return the newly added PeerInfo
  */
 static struct PeerInfo *
 add_peer(const struct GNUNET_PeerIdentity *peer,
          unsigned int bucket,
-         struct GNUNET_TIME_Relative latency,
-         unsigned int distance)
+         const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct PeerInfo *new_peer;
   GNUNET_assert(bucket < MAX_BUCKETS);
   GNUNET_assert(peer != NULL);
   new_peer = GNUNET_malloc(sizeof(struct PeerInfo));
+#if 0
   new_peer->latency = latency;
   new_peer->distance = distance;
+#endif
 
   memcpy(&new_peer->id, peer, sizeof(struct GNUNET_PeerIdentity));
 
@@ -1769,8 +1769,7 @@
 static struct PeerInfo *
 try_add_peer(const struct GNUNET_PeerIdentity *peer,
              unsigned int bucket,
-             struct GNUNET_TIME_Relative latency,
-             unsigned int distance)
+            const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   int peer_bucket;
   struct PeerInfo *new_peer;
@@ -1781,7 +1780,7 @@
   peer_bucket = find_current_bucket(&peer->hashPubKey);
 
   GNUNET_assert(peer_bucket >= lowest_bucket);
-  new_peer = add_peer(peer, peer_bucket, latency, distance);
+  new_peer = add_peer(peer, peer_bucket, atsi);
 
   if ((k_buckets[lowest_bucket].peers_size) >= bucket_size)
     enable_next_bucket();
@@ -1991,7 +1990,8 @@
         {
           increment_stats(STAT_HELLOS_PROVIDED);
           GNUNET_TRANSPORT_offer_hello(transport_handle, hello_msg);
-          GNUNET_CORE_peer_request_connect(cfg, 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &new_peer, NULL, 
NULL);
+          GNUNET_CORE_peer_request_connect(coreAPI, 
+                                          
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &new_peer, NULL, 
NULL);
         }
       }
     }
@@ -2420,7 +2420,8 @@
         {
           increment_stats(STAT_HELLOS_PROVIDED);
           GNUNET_TRANSPORT_offer_hello(transport_handle, other_hello);
-          GNUNET_CORE_peer_request_connect(cfg, 
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &peer_id, NULL, 
NULL);
+          GNUNET_CORE_peer_request_connect(coreAPI, 
+                                          
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &peer_id, NULL, 
NULL);
          route_message (find_msg, msg_ctx);
          GNUNET_free (other_hello);
           return;
@@ -4228,7 +4229,7 @@
 handle_dht_p2p_route_request (void *cls,
                              const struct GNUNET_PeerIdentity *peer,
                              const struct GNUNET_MessageHeader *message,
-                             struct GNUNET_TIME_Relative latency, uint32_t 
distance)
+                             const struct GNUNET_TRANSPORT_ATS_Information 
*atsi)
 {
 #if DEBUG_DHT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -4284,7 +4285,7 @@
 handle_dht_p2p_route_result (void *cls,
                             const struct GNUNET_PeerIdentity *peer,
                             const struct GNUNET_MessageHeader *message,
-                            struct GNUNET_TIME_Relative latency, uint32_t 
distance)
+                            const struct GNUNET_TRANSPORT_ATS_Information 
*atsi)
 {
 #if DEBUG_DHT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -4472,13 +4473,12 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with peer
- * @param distance reported distance (DV) to peer
+ * @param atsi performance data
  */
-void handle_core_connect (void *cls,
-                          const struct GNUNET_PeerIdentity * peer,
-                          struct GNUNET_TIME_Relative latency,
-                          uint32_t distance)
+static void 
+handle_core_connect (void *cls,
+                    const struct GNUNET_PeerIdentity * peer,
+                    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct PeerInfo *ret;
 
@@ -4497,8 +4497,7 @@
     GNUNET_DATACACHE_put(datacache, &peer->hashPubKey, sizeof(struct 
GNUNET_PeerIdentity), (const char *)peer, GNUNET_BLOCK_TYPE_DHT_HELLO, 
GNUNET_TIME_absolute_get_forever());
   ret = try_add_peer(peer,
                      find_current_bucket(&peer->hashPubKey),
-                     latency,
-                     distance);
+                     atsi);
   if (ret != NULL)
     {
       newly_found_peers++;
@@ -4517,9 +4516,10 @@
  * @param cls closure
  * @param peer peer identity this notification is about
  */
-void handle_core_disconnect (void *cls,
-                             const struct
-                             GNUNET_PeerIdentity * peer)
+static void
+handle_core_disconnect (void *cls,
+                       const struct
+                       GNUNET_PeerIdentity * peer)
 {
   struct PeerInfo *to_remove;
   int current_bucket;
@@ -4563,7 +4563,6 @@
   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
   coreAPI = GNUNET_CORE_connect (cfg,    /* Main configuration */
                                 1, /* queue size */
-                                 GNUNET_TIME_UNIT_FOREVER_REL,
                                  NULL,  /* Closure passed to DHT functions */
                                  &core_init,    /* Call core_init once 
connected */
                                  &handle_core_connect,  /* Handle connects */

Modified: gnunet/src/dv/Makefile.am
===================================================================
--- gnunet/src/dv/Makefile.am   2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/dv/Makefile.am   2010-11-13 20:37:37 UTC (rev 13670)
@@ -28,7 +28,7 @@
 
 bin_PROGRAMS = \
  gnunet-service-dv
- 
+
 gnunet_service_dv_SOURCES = \
  gnunet-service-dv.c         
 gnunet_service_dv_LDADD = \

Modified: gnunet/src/dv/gnunet-service-dv.c
===================================================================
--- gnunet/src/dv/gnunet-service-dv.c   2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/dv/gnunet-service-dv.c   2010-11-13 20:37:37 UTC (rev 13670)
@@ -1311,11 +1311,11 @@
  * @param latency the latency of the connection we received the message from
  * @param distance the distance to the immediate peer
  */
-static int handle_dv_data_message (void *cls,
-                                   const struct GNUNET_PeerIdentity * peer,
-                                   const struct GNUNET_MessageHeader * message,
-                                   struct GNUNET_TIME_Relative latency,
-                                   uint32_t distance)
+static int 
+handle_dv_data_message (void *cls,
+                       const struct GNUNET_PeerIdentity * peer,
+                       const struct GNUNET_MessageHeader * message,
+                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
   const struct GNUNET_MessageHeader *packed_message;
@@ -1919,14 +1919,12 @@
 static int handle_dv_gossip_message (void *cls,
                                      const struct GNUNET_PeerIdentity *peer,
                                      const struct GNUNET_MessageHeader 
*message,
-                                     struct GNUNET_TIME_Relative latency,
-                                     uint32_t distance);
+                                     const struct 
GNUNET_TRANSPORT_ATS_Information *atsi);
 
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity 
*peer,
                                          const struct GNUNET_MessageHeader 
*message,
-                                         struct GNUNET_TIME_Relative latency,
-                                         uint32_t distance);
+                                        const struct 
GNUNET_TRANSPORT_ATS_Information *atsi);
 /** End forward declarations **/
 
 
@@ -2327,7 +2325,8 @@
  *         not added)
  */
 static struct DistantNeighbor *
-addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct 
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
+addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer,
+                  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
                    unsigned int referrer_peer_id,
                    struct DirectNeighbor *referrer, unsigned int cost)
 {
@@ -2466,7 +2465,10 @@
 #if DEBUG_DV_MESSAGES
                   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: learned about peer 
%llu from which we have a previous unknown message, processing!\n", 
my_short_id, referrer_peer_id);
 #endif
-                  handle_dv_data_message(NULL, 
&referrer->pending_messages[i].sender, referrer->pending_messages[i].message, 
referrer->pending_messages[i].latency, referrer->pending_messages[i].distance);
+                  handle_dv_data_message(NULL, 
&referrer->pending_messages[i].sender, 
+                                        referrer->pending_messages[i].message, 
+                                        referrer->pending_messages[i].latency, 
+                                        
referrer->pending_messages[i].distance);
                   GNUNET_free(referrer->pending_messages[i].message);
                   referrer->pending_messages[i].sender_id = 0;
                 }
@@ -2521,14 +2523,12 @@
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
- * @param latency the latency of the connection we received the message from
- * @param distance the distance to the immediate peer
+ * @param atsi performance data
  */
 static int handle_dv_disconnect_message (void *cls,
                                          const struct GNUNET_PeerIdentity 
*peer,
                                          const struct GNUNET_MessageHeader 
*message,
-                                         struct GNUNET_TIME_Relative latency,
-                                         uint32_t distance)
+                                        const struct 
GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *referrer;
   struct DistantNeighbor *distant;
@@ -2570,14 +2570,13 @@
  * @param cls closure
  * @param peer peer which sent the message (immediate sender)
  * @param message the message
- * @param latency the latency of the connection we received the message from
- * @param distance the distance to the immediate peer
+ * @param atsi performance data
  */
-static int handle_dv_gossip_message (void *cls,
-                                     const struct GNUNET_PeerIdentity *peer,
-                                     const struct GNUNET_MessageHeader 
*message,
-                                     struct GNUNET_TIME_Relative latency,
-                                     uint32_t distance)
+static int 
+handle_dv_gossip_message (void *cls,
+                         const struct GNUNET_PeerIdentity *peer,
+                         const struct GNUNET_MessageHeader *message,
+                         const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *referrer;
   p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo 
*)message;
@@ -2623,9 +2622,10 @@
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
-static int add_all_extended_peers (void *cls,
-                                   const GNUNET_HashCode * key,
-                                   void *value)
+static int 
+add_all_extended_peers (void *cls,
+                       const GNUNET_HashCode * key,
+                       void *value)
 {
   struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls;
   struct DistantNeighbor *distant = (struct DistantNeighbor *)value;
@@ -2660,9 +2660,10 @@
  *         iterate,
  *         GNUNET_NO if not.
  */
-static int gossip_all_to_all_iterator (void *cls,
-                                      const GNUNET_HashCode * key,
-                                      void *abs_value)
+static int 
+gossip_all_to_all_iterator (void *cls,
+                           const GNUNET_HashCode * key,
+                           void *abs_value)
 {
   struct DirectNeighbor *direct = abs_value;
 
@@ -2704,9 +2705,10 @@
  *
  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
  */
-static int add_all_direct_neighbors (void *cls,
-                                     const GNUNET_HashCode * key,
-                                     void *value)
+static int 
+add_all_direct_neighbors (void *cls,
+                         const GNUNET_HashCode * key,
+                         void *value)
 {
   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
   struct DirectNeighbor *to = (struct DirectNeighbor *)cls;
@@ -2832,13 +2834,12 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with peer
- * @param distance reported distance (DV) to peer
+ * @param atsi performance data
  */
-void handle_core_connect (void *cls,
-                          const struct GNUNET_PeerIdentity * peer,
-                          struct GNUNET_TIME_Relative latency,
-                          uint32_t distance)
+static void 
+handle_core_connect (void *cls,
+                    const struct GNUNET_PeerIdentity * peer,
+                    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct DirectNeighbor *neighbor;
   struct DistantNeighbor *about;
@@ -2994,7 +2995,6 @@
   coreAPI =
   GNUNET_CORE_connect (cfg,
                       1,
-                       GNUNET_TIME_relative_get_forever(),
                        NULL, /* FIXME: anything we want to pass around? */
                        &core_init,
                        &handle_core_connect,

Modified: gnunet/src/fs/gnunet-service-fs.c
===================================================================
--- gnunet/src/fs/gnunet-service-fs.c   2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/fs/gnunet-service-fs.c   2010-11-13 20:37:37 UTC (rev 13670)
@@ -1556,25 +1556,39 @@
 
 
 /**
+ * Find latency information in 'atsi'.
+ *
+ * @param atsi performance data
+ * @return connection latency
+ */
+static struct GNUNET_TIME_Relative
+get_latency (const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+  /* FIXME: extract latency data from 'atsi' */
+  return GNUNET_TIME_UNIT_SECONDS;
+}
+
+
+/**
  * Method called whenever a given peer connects.
  *
  * @param cls closure, not used
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance information
  */
 static void 
 peer_connect_handler (void *cls,
                      const struct
                      GNUNET_PeerIdentity * peer,
-                     struct GNUNET_TIME_Relative latency,
-                     uint32_t distance)
+                     const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct ConnectedPeer *cp;
   struct MigrationReadyBlock *pos;
   char *fn;
   uint32_t trust;
+  struct GNUNET_TIME_Relative latency;
 
+  latency = get_latency (atsi);
   cp = GNUNET_CONTAINER_multihashmap_get (connected_peers,
                                          &peer->hashPubKey);
   if (NULL != cp)
@@ -1612,25 +1626,25 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
  * @param bandwidth_in available amount of inbound bandwidth
  * @param bandwidth_out available amount of outbound bandwidth
  * @param timeout absolute time when this peer will time out
  *        unless we see some further activity from it
+ * @param atsi status information
  */
 static void
 peer_status_handler (void *cls,
                     const struct
                     GNUNET_PeerIdentity * peer,
-                    struct GNUNET_TIME_Relative latency,
-                    uint32_t distance,
                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
-                    struct GNUNET_TIME_Absolute timeout)
+                    struct GNUNET_TIME_Absolute timeout,
+                    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct ConnectedPeer *cp;
+  struct GNUNET_TIME_Relative latency;
 
+  latency = get_latency (atsi);
   cp = GNUNET_CONTAINER_multihashmap_get (connected_peers,
                                          &peer->hashPubKey);
   if (cp == NULL)
@@ -2529,7 +2543,6 @@
  *
  * @param cls the requests "struct PendingRequest*"
  * @param peer identifies the peer
- * @param bpm_in set to the current bandwidth limit (receiving) for this peer
  * @param bpm_out set to the current bandwidth limit (sending) for this peer
  * @param amount set to the amount that was actually reserved or unreserved
  * @param preference current traffic preference for the given peer
@@ -2538,7 +2551,6 @@
 target_reservation_cb (void *cls,
                       const struct
                       GNUNET_PeerIdentity * peer,
-                      struct GNUNET_BANDWIDTH_Value32NBO bpm_in,
                       struct GNUNET_BANDWIDTH_Value32NBO bpm_out,
                       int amount,
                       uint64_t preference)
@@ -2984,7 +2996,7 @@
       cp = GNUNET_CONTAINER_multihashmap_get (connected_peers,
                                              &psc.target.hashPubKey);
       GNUNET_assert (NULL != cp);
-      pr->irc = GNUNET_CORE_peer_change_preference (cfg,
+      pr->irc = GNUNET_CORE_peer_change_preference (core,
                                                    &psc.target,
                                                    
GNUNET_CONSTANTS_SERVICE_TIMEOUT, 
                                                    GNUNET_BANDWIDTH_value_init 
(UINT32_MAX),
@@ -2999,7 +3011,7 @@
       /* force forwarding */
       static struct GNUNET_BANDWIDTH_Value32NBO zerobw;
       target_reservation_cb (pr, &psc.target,
-                            zerobw, zerobw, 0, 0.0);
+                            zerobw, 0, 0.0);
     }
 }
 
@@ -3467,8 +3479,7 @@
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance information
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -3476,8 +3487,7 @@
 handle_p2p_put (void *cls,
                const struct GNUNET_PeerIdentity *other,
                const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   const struct PutMessage *put;
   uint16_t msize;
@@ -3608,8 +3618,7 @@
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance information
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -3617,8 +3626,7 @@
 handle_p2p_migration_stop (void *cls,
                           const struct GNUNET_PeerIdentity *other,
                           const struct GNUNET_MessageHeader *message,
-                          struct GNUNET_TIME_Relative latency,
-                          uint32_t distance)
+                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct ConnectedPeer *cp; 
   const struct MigrationStopMessage *msm;
@@ -3955,8 +3963,7 @@
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance information
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -3964,8 +3971,7 @@
 handle_p2p_get (void *cls,
                const struct GNUNET_PeerIdentity *other,
                const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct PendingRequest *pr;
   struct ConnectedPeer *cp;
@@ -4491,7 +4497,6 @@
   requests_by_expiration_heap = GNUNET_CONTAINER_heap_create 
(GNUNET_CONTAINER_HEAP_ORDER_MIN); 
   core = GNUNET_CORE_connect (cfg,
                              1, /* larger? */
-                             GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              NULL,
                              &peer_connect_handler,

Modified: gnunet/src/hostlist/gnunet-daemon-hostlist.c
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-11-12 15:53:17 UTC 
(rev 13669)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-11-13 20:37:37 UTC 
(rev 13670)
@@ -141,13 +141,12 @@
  * Core handler for p2p hostlist advertisements
  */
 static int advertisement_handler (void *cls,
-                             const struct GNUNET_PeerIdentity * peer,
-                             const struct GNUNET_MessageHeader * message,
-                             struct GNUNET_TIME_Relative latency,
-                             uint32_t distance)
+                                 const struct GNUNET_PeerIdentity * peer,
+                                 const struct GNUNET_MessageHeader * message,
+                                 const struct GNUNET_TRANSPORT_ATS_Information 
*atsi)
 {
   GNUNET_assert (NULL != client_adv_handler);
-  return (*client_adv_handler) (cls, peer, message, latency, distance);
+  return (*client_adv_handler) (cls, peer, message, atsi);
 }
 
 
@@ -156,23 +155,21 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other'
+ * @param atsi performance data
  */
 static void
 connect_handler (void *cls,
                  const struct
                  GNUNET_PeerIdentity * peer,
-                 struct GNUNET_TIME_Relative latency,
-                 uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "A new peer connected, notifying client and server\n");
   if ( NULL != client_ch)
-    (*client_ch) (cls, peer, latency, distance);
+    (*client_ch) (cls, peer, atsi);
 #if HAVE_MHD
   if ( NULL != server_ch)
-    (*server_ch) (cls, peer, latency, distance);
+    (*server_ch) (cls, peer, atsi);
 #endif
 }
 
@@ -270,7 +267,6 @@
 
   core = GNUNET_CORE_connect (cfg,
                              1,
-                             GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              &core_init,
                              &connect_handler, &disconnect_handler, NULL,

Modified: gnunet/src/hostlist/hostlist-client.c
===================================================================
--- gnunet/src/hostlist/hostlist-client.c       2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/hostlist/hostlist-client.c       2010-11-13 20:37:37 UTC (rev 
13670)
@@ -1137,15 +1137,13 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  */
 static void
 handler_connect (void *cls,
                 const struct
                 GNUNET_PeerIdentity * peer,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   GNUNET_assert (stat_connection_count < UINT_MAX);
   stat_connection_count++;
@@ -1181,17 +1179,15 @@
  * @param cls closure (always NULL)
  * @param peer the peer sending the message
  * @param message the actual message
- * @param latency latency
- * @param distance distance
+ * @param atsi performance data
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
 handler_advertisement (void *cls,
-    const struct GNUNET_PeerIdentity * peer,
-    const struct GNUNET_MessageHeader * message,
-    struct GNUNET_TIME_Relative latency,
-    uint32_t distance)
+                      const struct GNUNET_PeerIdentity * peer,
+                      const struct GNUNET_MessageHeader * message,
+                      const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   size_t size;
   size_t uri_size;

Modified: gnunet/src/hostlist/hostlist-server.c
===================================================================
--- gnunet/src/hostlist/hostlist-server.c       2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/hostlist/hostlist-server.c       2010-11-13 20:37:37 UTC (rev 
13670)
@@ -376,15 +376,13 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other'
+ * @param atsi performance data
  */
 static void
 connect_handler (void *cls,
                  const struct
                  GNUNET_PeerIdentity * peer,
-                 struct GNUNET_TIME_Relative latency,
-                 uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   size_t size;
 

Modified: gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
===================================================================
--- gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c  2010-11-12 
15:53:17 UTC (rev 13669)
+++ gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c  2010-11-13 
20:37:37 UTC (rev 13670)
@@ -283,11 +283,11 @@
 /**
  * Core handler for p2p hostlist advertisements
  */
-static int ad_arrive_handler (void *cls,
-                             const struct GNUNET_PeerIdentity * peer,
-                             const struct GNUNET_MessageHeader * message,
-                             struct GNUNET_TIME_Relative latency,
-                             uint32_t distance)
+static int 
+ad_arrive_handler (void *cls,
+                  const struct GNUNET_PeerIdentity * peer,
+                  const struct GNUNET_MessageHeader * message,
+                  const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   char *hostname;
   char *expected_uri;
@@ -371,7 +371,6 @@
 
   p->core = GNUNET_CORE_connect (p->cfg,
                                 1,
-                                GNUNET_TIME_UNIT_FOREVER_REL,
                                 NULL,
                                 NULL,
                                 NULL, NULL, NULL,

Modified: gnunet/src/include/gnunet_core_service.h
===================================================================
--- gnunet/src/include/gnunet_core_service.h    2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/include/gnunet_core_service.h    2010-11-13 20:37:37 UTC (rev 
13670)
@@ -37,6 +37,7 @@
 #endif
 
 #include "gnunet_util_lib.h"
+#include "gnunet_transport_service.h"
 
 /**
  * Version number of GNUnet-core API.
@@ -55,35 +56,32 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data for the connection
  */
 typedef void (*GNUNET_CORE_ConnectEventHandler) (void *cls,
                                                 const struct
-                                                GNUNET_PeerIdentity * peer,
-                                                struct GNUNET_TIME_Relative 
latency,
-                                                uint32_t distance);
+                                                GNUNET_PeerIdentity *peer,
+                                                const struct 
GNUNET_TRANSPORT_ATS_Information *atsi);
 
+
 /**
  * Method called whenever a given peer has a status change.
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param timeout absolute time when this peer will time out
+ *        unless we see some further activity from it
  * @param bandwidth_in available amount of inbound bandwidth
  * @param bandwidth_out available amount of outbound bandwidth
- * @param timeout absolute time when this peer will time out
- *        unless we see some further activity from it
+ * @param atsi performance data for the connection
  */
 typedef void (*GNUNET_CORE_PeerStatusEventHandler) (void *cls,
                                                    const struct
                                                    GNUNET_PeerIdentity * peer,
-                                                   struct GNUNET_TIME_Relative 
latency,
-                                                   uint32_t distance,
                                                    struct 
GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
                                                    struct 
GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
-                                                   struct GNUNET_TIME_Absolute 
timeout);
+                                                   struct GNUNET_TIME_Absolute 
timeout,
+                                                   const struct 
GNUNET_TRANSPORT_ATS_Information *atsi);
 
 
 /**
@@ -94,29 +92,26 @@
  */
 typedef void (*GNUNET_CORE_DisconnectEventHandler) (void *cls,
                                                    const struct
-                                                   GNUNET_PeerIdentity * peer);
+                                                   GNUNET_PeerIdentity *peer);
 
 
 /**
  * Functions with this signature are called whenever a message is
  * received or transmitted.
  *
- * @param cls closure
+ * @param cls closure (set from GNUNET_CORE_connect)
  * @param peer the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data for the connection
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 typedef int
   (*GNUNET_CORE_MessageCallback) (void *cls,
-                                  const struct GNUNET_PeerIdentity * other,
-                                  const struct GNUNET_MessageHeader *
-                                  message,
-                                 struct GNUNET_TIME_Relative latency,
-                                 uint32_t distance);
+                                  const struct GNUNET_PeerIdentity *other,
+                                  const struct GNUNET_MessageHeader *message,
+                                 const struct GNUNET_TRANSPORT_ATS_Information 
*atsi);
 
 
 /**
@@ -180,7 +175,6 @@
  *
  * @param cfg configuration to use
  * @param queue_size size of the per-peer message queue
- * @param timeout after how long should we give up trying to connect to the 
core service?
  * @param cls closure for the various callbacks that follow (including 
handlers in the handlers array)
  * @param init callback to call on timeout or once we have successfully
  *        connected to the core service; note that timeout is only meaningful 
if init is not NULL
@@ -217,7 +211,6 @@
 struct GNUNET_CORE_Handle *
 GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                     unsigned int queue_size,
-                     struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
@@ -231,7 +224,9 @@
 
 
 /**
- * Disconnect from the core service.
+ * Disconnect from the core service.    This function can only 
+ * be called *after* all pending 'GNUNET_CORE_notify_transmit_ready'
+ * requests have been explicitly cancelled.
  *
  * @param handle connection to core to disconnect
  */
@@ -257,7 +252,7 @@
  * to our connection attempt within the given time frame, 'cont' will
  * be called with the TIMEOUT reason code.
  *
- * @param cfg configuration to use
+ * @param h core handle
  * @param timeout how long to try to talk to core
  * @param peer who should we connect to
  * @param cont function to call once the request has been completed (or timed 
out)
@@ -265,7 +260,7 @@
  * @return NULL on error (cont will not be called), otherwise handle for 
cancellation
  */
 struct GNUNET_CORE_PeerRequestHandle *
-GNUNET_CORE_peer_request_connect (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h,
                                  struct GNUNET_TIME_Relative timeout,
                                  const struct GNUNET_PeerIdentity * peer,
                                  GNUNET_SCHEDULER_Task cont,
@@ -283,14 +278,11 @@
 
 
 /**
- * Function called with statistics about the given peer.
+ * Function called with perference change information about the given peer.
  *
  * @param cls closure
  * @param peer identifies the peer
- * @param bpm_in set to the current bandwidth limit (receiving) for this peer
- * @param bpm_out set to the current bandwidth limit (sending) for this peer
- * @param latency current latency estimate, "FOREVER" if we have been
- *                disconnected
+ * @param bandwidth_out available amount of outbound bandwidth
  * @param amount set to the amount that was actually reserved or unreserved;
  *               either the full requested amount or zero (no partial 
reservations)
  * @param preference current traffic preference for the given peer
@@ -299,8 +291,7 @@
   (*GNUNET_CORE_PeerConfigurationInfoCallback) (void *cls,
                                                 const struct
                                                 GNUNET_PeerIdentity * peer,
-                                                struct 
GNUNET_BANDWIDTH_Value32NBO bpm_in,
-                                                struct 
GNUNET_BANDWIDTH_Value32NBO bpm_out,
+                                               struct 
GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
                                                int amount,
                                                 uint64_t preference);
 
@@ -314,8 +305,9 @@
 
 /**
  * Obtain statistics and/or change preferences for the given peer.
+ * You can only have one such pending request per peer.
  *
- * @param cfg configuration to use
+ * @param h core handle
  * @param peer identifies the peer
  * @param timeout after how long should we give up (and call "info" with NULL
  *                for "peer" to signal an error)?
@@ -337,7 +329,7 @@
  * @return NULL on error
  */
 struct GNUNET_CORE_InformationRequestContext *
-GNUNET_CORE_peer_change_preference (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h,
                                    const struct GNUNET_PeerIdentity *peer,
                                    struct GNUNET_TIME_Relative timeout,
                                    struct GNUNET_BANDWIDTH_Value32NBO bw_out,
@@ -349,25 +341,33 @@
 
 /**
  * Cancel request for getting information about a peer.
+ * Note that an eventual change in preference, trust or bandwidth
+ * assignment MAY have already been committed at the time, 
+ * so cancelling a request is NOT sure to undo the original
+ * request.  The original request may or may not still commit.
+ * The only thing cancellation ensures is that the callback
+ * from the original request will no longer be called.
  *
  * @param irc context returned by the original GNUNET_CORE_peer_get_info call
  */
 void
 GNUNET_CORE_peer_change_preference_cancel (struct 
GNUNET_CORE_InformationRequestContext *irc);
 
+
 /**
- * Obtain statistics and/or change preferences for the given peer.
+ * Iterate over all connected peers.
  *
- * @param cfg configuration to use
+ * @param h core handle
  * @param peer_cb function to call with the peer information
  * @param cb_cls closure for peer_cb
- * @return GNUNET_OK if iterating, GNUNET_SYSERR on error
+ * @return GNUNET_OK on success, GNUNET_SYSERR on errors
  */
 int
-GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
+GNUNET_CORE_iterate_peers (struct GNUNET_CORE_Handle *h,
                            GNUNET_CORE_ConnectEventHandler peer_cb,
                            void *cb_cls);
 
+
 /**
  * Handle for a transmission request.
  */

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/include/gnunet_protocols.h       2010-11-13 20:37:37 UTC (rev 
13670)
@@ -357,21 +357,28 @@
 #define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 73
 
 /**
- * Request from client with message to transmit.
+ * Request from client to transmit message.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_SEND 74
+#define GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST 74
 
 /**
- * Request from client asking to connect to a peer.
+ * Confirmation from core that message can now be sent
  */
-#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 75
+#define GNUNET_MESSAGE_TYPE_CORE_SEND_READY 75
 
 /**
- * Request from client asking to call back with all connected peers.
+ * Client with message to transmit (after SEND_READY confirmation
+ * was received).
  */
-#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS 76
+#define GNUNET_MESSAGE_TYPE_CORE_SEND 76
 
 /**
+ * Request from client asking to connect to a peer.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 77
+
+
+/**
  * Session key exchange between peers.
  */
 #define GNUNET_MESSAGE_TYPE_CORE_SET_KEY 80

Modified: gnunet/src/include/gnunet_testing_lib.h
===================================================================
--- gnunet/src/include/gnunet_testing_lib.h     2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/include/gnunet_testing_lib.h     2010-11-13 20:37:37 UTC (rev 
13670)
@@ -395,8 +395,6 @@
 typedef void (*GNUNET_TESTING_NotifyTopology)(void *cls,
                                               const struct GNUNET_PeerIdentity 
*first,
                                               const struct GNUNET_PeerIdentity 
*second,
-                                              struct GNUNET_TIME_Relative 
latency,
-                                              uint32_t distance,
                                               const char *emsg);
 
 /**

Modified: gnunet/src/include/gnunet_transport_plugin.h
===================================================================
--- gnunet/src/include/gnunet_transport_plugin.h        2010-11-12 15:53:17 UTC 
(rev 13669)
+++ gnunet/src/include/gnunet_transport_plugin.h        2010-11-13 20:37:37 UTC 
(rev 13670)
@@ -36,342 +36,7 @@
 #include "gnunet_statistics_service.h"
 #include "gnunet_transport_service.h"
 
-
 /**
- *  The structs defined here are used by the transport plugin to tell ATS about
- *  the transport's properties like cost and quality and on the other side
- *  the structs are used by highlevel components to communicate the constraints
- *  they have for a transport to ATS
- *
- *                             +---+
- *  +-----------+ Constraints  |   |  Plugin properties +---------+
- *  | Highlevel |------------> |ATS| <------------------|Transport|
- *  | Component | ATS struct   |   |    ATS struct      | Plugin  |
- *  +-----------+              |   |                    +---------+
- *                             +---+
- *
- */
-
-#define GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR 0
-
-/**
- * Enum defining all known property types for ATS
- * Enum values are used in the GNUNET_TRANSPORT_ATS_Information struct as 
(key,value)-pair
- *
- * Cost are always stored in uint32_t, so all units used to define costs
- * have to be normalized to fit in uint32_t [0 .. 4.294.967.295]
- *
- * To keep the elements ordered
- *    1..1024 : Values with a relation to cost
- * 1025..2048 : Values with a relation to quality
- * 2049..3072 : Values with a relation to availability
- *
- */
-enum GNUNET_TRANSPORT_ATS_Property
-{
-
-       /* Cost related values */
-       /* =================== */
-
-       /**
-        * Volume based cost in financial units to transmit data
-        *
-        * Note: This value is not bound to a specific currency or unit and only
-        * used locally.
-        * "cent" just refers the smallest amount of money in the respective
-        * currency.
-        *
-        * Unit: [cent/MB]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        * LAN:  0 [cent/MB]
-        * 2G : 10 [cent/MB]
-        */
-       GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_VOLUME = 1,
-
-       /**
-        * Time based cost in financial units to transmit data
-        *
-        * Note: This value is not bound to a specific currency or unit and only
-        * used locally.
-        * "cent" just refers the smallest amount of money in the respective
-        * currency.
-        *
-        * Unit: [cent/h]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        * LAN   :  0 [cent/h]
-        * Dialup: 10 [cent/h]
-        */
-       GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_TIME = 2,
-
-       /**
-        * Computational costs
-        *
-        * Effort of preparing data to be sent with this transport
-        * Includes encoding, encryption and conversion of data
-        * Partial values can be summed up: c_sum = c_enc + c_enc + c_conv
-        * Resulting values depend on local system properties, e.g. CPU
-        *
-        * Unit: [ms/GB]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        *
-        * HTTPS with AES CBC-256:      7,382
-        * HTTPS with AES CBC-128:      5,279
-        * HTTPS with RC4-1024:         2,652
-        */
-       GNUNET_TRANSPORT_ATS_COST_COMPUTATIONAL = 3,
-
-       /**
-        * Energy consumption
-        *
-        * Energy consumption using this transport when sending with a certain
-        * power at a certain bitrate. This is only an approximation based on:
-        * Energy consumption E = P / D
-        *
-        * with:
-        * Power P in Watt (J/s)
-        * Datarate D in MBit/s
-        *
-        * Conversion between power P and dBm used by WLAN in radiotap's dBm TX 
power:
-        *
-        * Lp(dbm) = 10 log10 (P/ 1mW)
-        *
-        * => P = 1 mW  * 10^(Lp(dbm)/10)
-        *
-        * Unit: [mJ/MB]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        *
-        * LAN:       0
-        * WLAN:      89 (600 mW @ 802.11g /w 54 MBit/s)
-        * Bluetooth: 267 (100 mW @ BT2.0 EDR /w 3 MBit/s)
-        */
-       GNUNET_TRANSPORT_ATS_COST_ENERGY_CONSUMPTION = 4,
-
-       /**
-        * Connect cost
-        * How many bytes are transmitted to initiate a new connection using
-        * this transport?
-        *
-        * Unit: [bytes]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        *
-        * UDP (No connection)      :
-        *     0 bytes
-        * TCP (TCP 3-Way handshake):
-        *   220 bytes Ethernet,  172 bytes TCP/IP,  122 bytes TCP
-        * HTTP (TCP + Header)      :
-        *   477 bytes Ethernet,  429 bytes TCP/IP,  374 bytes TCP,  278 bytes 
HTTP
-        * HTTPS  HTTP+TLS Handshake:
-        *  2129 bytes Ethernet, 1975 bytes TCP/IP, 1755 bytes TCP, 1403 bytes 
HTTPS
-        *
-        * */
-       GNUNET_TRANSPORT_ATS_COST_CONNECT = 5,
-
-       /**
-        * Bandwidth cost
-        *
-        * How many bandwidth is available to consume?
-        * Used to calculate which impact sending data with this transport has
-        *
-        * Unit: [kB/s]
-        *
-        * Interpretation: more is better
-        *
-        * Examples:
-        * LAN:     12,800  (100 MBit/s)
-        * WLAN:    6,912   (54 MBit/s)
-        * Dial-up: 8       (64 Kbit/s)
-        *
-        */
-       GNUNET_TRANSPORT_ATS_COST_BANDWITH_AVAILABLE = 6,
-
-       /**
-        *  Network overhead
-        *
-        * How many bytes are sent over the wire when 1 kilobyte (1024 bytes)
-        * of application data is transmitted?
-        * A factor used with connect cost, bandwidth cost and energy cost
-        * to describe the overhead produced by the transport protocol
-        *
-        * Unit: [bytes/kb]
-        *
-        * Interpretation: less is better
-        *
-        * Examples:
-        *
-        * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb]
-        * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb]
-        * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8  = 1090 [bytes/kb]
-        * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8  = 1110 [bytes/kb]
-        */
-       GNUNET_TRANSPORT_ATS_COST_NETWORK_OVERHEAD = 7,
-
-
-       /* Quality related values */
-       /* ====================== */
-
-    /* Physical layer quality properties */
-
-       /**
-        * Signal strength on physical layer
-        *
-        * Unit: [dBm]
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_PHY_SIGNAL_STRENGTH = 1025,
-
-       /**
-        * Collision rate on physical layer
-        *
-        * Unit: [B/s]
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_PHY_COLLISION_RATE = 1026,
-
-       /**
-        * Error rate on physical layer
-        *
-        * Unit: [B/s]
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_PHY_ERROR_RATE = 1027,
-
-    /* Network layer quality properties */
-
-       /**
-        * Delay
-        * Time between when the time packet is sent and the packet arrives
-        *
-        * Unit: [μs]
-        *
-        * Examples:
-        *
-        * LAN   :  180
-        * Dialup: 4000
-        * WLAN  : 7000
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY = 1028,
-
-       /**
-        * Jitter
-        * Time variations of the delay
-        * 1st derivative of a delay function
-        *
-        * Unit: [μs]
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_JITTER = 1029,
-
-       /**
-        * Error rate on network layer
-        *
-        * Unit: [B/s]
-        *
-        * Examples:
-        *
-        * LAN       :    0
-        * WLAN      :  400
-        * Bluetooth :  100
-        * Note: This numbers are just assumptions as an example, not
-        * measured or somehow determined
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_ERRORRATE = 1030,
-
-       /**
-        * Drop rate on network layer
-     * Bytes actively dismissed by a network component during transmission
-     * Reasons for dropped data can be full queues, congestion, quota 
violations...
-        *
-        * Unit: [B/s]
-        *
-        * Examples:
-        *
-        * LAN       :    0
-        * WLAN      :  400
-        * Bluetooth :  100
-        * Note: This numbers are just assumptions as an example, not
-        * measured or somehow determined
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_DROPRATE = 1031,
-
-       /**
-        * Loss rate on network layer
-        * Bytes lost during transmission
-        * Reasons can be collisions, ...
-        *
-        * Unit: [B/s]
-        *
-        * Examples:
-        *
-        * LAN       :    0
-        * WLAN      :   40
-        * Bluetooth :   10
-        * Note: This numbers are just assumptions as an example, not measured
-        * or somehow determined
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_LOSSRATE = 1032,
-
-       /**
-        * Throughput on network layer
-        *
-        * Unit: [kB/s]
-        *
-        * Examples:
-        *
-        * LAN   : 3400
-        * WLAN  : 1200
-        * Dialup:        4
-        *
-        */
-       GNUNET_TRANSPORT_ATS_QUALITY_NET_THROUGHPUT = 1033,
-
-       /* Availability related values */
-       /* =========================== */
-
-       /**
-        * Is a peer reachable?
-        */
-       GNUNET_TRANSPORT_ATS_AVAILABILITY_REACHABLE = 2048,
-
-       /**
-        * Is there a connection established to a peer using this transport
-        */
-       GNUNET_TRANSPORT_ATS_AVAILABILITY_CONNECTED = 2049
-};
-
-/**
- * This structure will be used by plugins to communicate costs to ATS or by
- * higher level components to tell ATS their constraints.
- * Always a pair of (GNUNET_TRANSPORT_ATS_Property, uint32_t value).
- * Value is always uint32_t, so all units used to define costs have to
- * be normalized to fit uint32_t.
- */
-struct GNUNET_TRANSPORT_ATS_Information
-{
-       /**
-        * ATS property type
-        */
-       uint32_t type;
-
-       /**
-        * ATS property value
-        */
-       uint32_t value;
-};
-
-
-
-/**
  * Opaque pointer that plugins can use to distinguish specific
  * connections to a given peer.  Typically used by stateful plugins to
  * allow the service to refer to specific streams instead of a more

Modified: gnunet/src/include/gnunet_transport_service.h
===================================================================
--- gnunet/src/include/gnunet_transport_service.h       2010-11-12 15:53:17 UTC 
(rev 13669)
+++ gnunet/src/include/gnunet_transport_service.h       2010-11-13 20:37:37 UTC 
(rev 13670)
@@ -47,7 +47,345 @@
  */
 #define GNUNET_TRANSPORT_VERSION 0x00000000
 
+
 /**
+ * Enum defining all known property types for ATS Enum values are used
+ * in the GNUNET_TRANSPORT_ATS_Information struct as
+ * (key,value)-pairs.
+ *
+ * Cost are always stored in uint32_t, so all units used to define costs
+ * have to be normalized to fit in uint32_t [0 .. 4.294.967.295]
+ *
+ * To keep the elements ordered
+ *    1..1024 : Values with a relation to cost
+ * 1025..2048 : Values with a relation to quality
+ * 2049..3072 : Values with a relation to availability
+ *
+ */
+enum GNUNET_TRANSPORT_ATS_Property
+{
+
+  /**
+   * End of the array.
+   */
+  GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR = 0,
+
+  /* Cost related values */
+  /* =================== */
+
+  /**
+   * Volume based cost in financial units to transmit data
+   *
+   * Note: This value is not bound to a specific currency or unit and only
+   * used locally.
+   * "cent" just refers the smallest amount of money in the respective
+   * currency.
+   *
+   * Unit: [cent/MB]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   * LAN:  0 [cent/MB]
+   * 2G : 10 [cent/MB]
+   */
+  GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_VOLUME = 1,
+  
+  /**
+   * Time based cost in financial units to transmit data
+   *
+   * Note: This value is not bound to a specific currency or unit and only
+   * used locally.
+   * "cent" just refers the smallest amount of money in the respective
+   * currency.
+   *
+   * Unit: [cent/h]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   * LAN   :  0 [cent/h]
+   * Dialup: 10 [cent/h]
+   */
+  GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_TIME = 2,
+  
+  /**
+   * Computational costs
+   *
+   * Effort of preparing data to be sent with this transport
+   * Includes encoding, encryption and conversion of data
+   * Partial values can be summed up: c_sum = c_enc + c_enc + c_conv
+   * Resulting values depend on local system properties, e.g. CPU
+   *
+   * Unit: [ms/GB]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   *
+   * HTTPS with AES CBC-256:   7,382
+   * HTTPS with AES CBC-128:   5,279
+   * HTTPS with RC4-1024:      2,652
+   */
+  GNUNET_TRANSPORT_ATS_COST_COMPUTATIONAL = 3,
+  
+  /**
+   * Energy consumption
+   *
+   * Energy consumption using this transport when sending with a certain
+   * power at a certain bitrate. This is only an approximation based on:
+   * Energy consumption E = P / D
+   *
+   * with:
+   * Power P in Watt (J/s)
+   * Datarate D in MBit/s
+   *
+   * Conversion between power P and dBm used by WLAN in radiotap's dBm TX 
power:
+   *
+   * Lp(dbm) = 10 log10 (P/ 1mW)
+   *
+   * => P = 1 mW  * 10^(Lp(dbm)/10)
+   *
+   * Unit: [mJ/MB]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   *
+   * LAN:       0
+   * WLAN:      89 (600 mW @ 802.11g /w 54 MBit/s)
+   * Bluetooth: 267 (100 mW @ BT2.0 EDR /w 3 MBit/s)
+   */
+  GNUNET_TRANSPORT_ATS_COST_ENERGY_CONSUMPTION = 4,
+  
+  /**
+   * Connect cost
+   * How many bytes are transmitted to initiate a new connection using
+   * this transport?
+   *
+   * Unit: [bytes]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   *
+   * UDP (No connection)      :
+   *     0 bytes
+   * TCP (TCP 3-Way handshake):
+   *   220 bytes Ethernet,  172 bytes TCP/IP,  122 bytes TCP
+   * HTTP (TCP + Header)      :
+   *   477 bytes Ethernet,  429 bytes TCP/IP,  374 bytes TCP,  278 bytes HTTP
+   * HTTPS  HTTP+TLS Handshake:
+   *  2129 bytes Ethernet, 1975 bytes TCP/IP, 1755 bytes TCP, 1403 bytes HTTPS
+   *
+   * */
+  GNUNET_TRANSPORT_ATS_COST_CONNECT = 5,
+  
+  /**
+   * Bandwidth cost
+   *
+   * How many bandwidth is available to consume?
+   * Used to calculate which impact sending data with this transport has
+   *
+   * Unit: [kB/s]
+   *
+   * Interpretation: more is better
+   *
+   * Examples:
+   * LAN:     12,800  (100 MBit/s)
+   * WLAN:    6,912   (54 MBit/s)
+   * Dial-up: 8       (64 Kbit/s)
+   *
+   */
+  GNUNET_TRANSPORT_ATS_COST_BANDWITH_AVAILABLE = 6,
+  
+  /**
+   *  Network overhead
+   *
+   * How many bytes are sent over the wire when 1 kilobyte (1024 bytes)
+   * of application data is transmitted?
+   * A factor used with connect cost, bandwidth cost and energy cost
+   * to describe the overhead produced by the transport protocol
+   *
+   * Unit: [bytes/kb]
+   *
+   * Interpretation: less is better
+   *
+   * Examples:
+   *
+   * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb]
+   * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb]
+   * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8  = 1090 [bytes/kb]
+   * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8  = 1110 [bytes/kb]
+   */
+  GNUNET_TRANSPORT_ATS_COST_NETWORK_OVERHEAD = 7,
+  
+  
+  /* Quality related values */
+  /* ====================== */
+  
+  /* Physical layer quality properties */
+  
+  /**
+   * Signal strength on physical layer
+   *
+   * Unit: [dBm]
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_PHY_SIGNAL_STRENGTH = 1025,
+  
+  /**
+   * Collision rate on physical layer
+   *
+   * Unit: [B/s]
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_PHY_COLLISION_RATE = 1026,
+  
+  /**
+   * Error rate on physical layer
+   *
+   * Unit: [B/s]
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_PHY_ERROR_RATE = 1027,
+  
+  /* Network layer quality properties */
+  
+  /**
+   * Delay
+   * Time between when the time packet is sent and the packet arrives
+   *
+   * Unit: [μs]
+   *
+   * Examples:
+   *
+   * LAN   :  180
+   * Dialup: 4000
+   * WLAN  : 7000
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY = 1028,
+  
+  /**
+   * Jitter
+   * Time variations of the delay
+   * 1st derivative of a delay function
+   *
+   * Unit: [μs]
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_JITTER = 1029,
+  
+  /**
+   * Error rate on network layer
+   *
+   * Unit: [B/s]
+   *
+   * Examples:
+   *
+   * LAN       :    0
+   * WLAN      :  400
+   * Bluetooth :  100
+   * Note: This numbers are just assumptions as an example, not
+   * measured or somehow determined
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_ERRORRATE = 1030,
+  
+  /**
+   * Drop rate on network layer
+   * Bytes actively dismissed by a network component during transmission
+   * Reasons for dropped data can be full queues, congestion, quota 
violations...
+   *
+   * Unit: [B/s]
+   *
+   * Examples:
+   *
+   * LAN       :    0
+   * WLAN      :  400
+   * Bluetooth :  100
+   * Note: This numbers are just assumptions as an example, not
+   * measured or somehow determined
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_DROPRATE = 1031,
+  
+  /**
+   * Loss rate on network layer
+   * Bytes lost during transmission
+   * Reasons can be collisions, ...
+   *
+   * Unit: [B/s]
+   *
+   * Examples:
+   *
+   * LAN       :    0
+   * WLAN      :   40
+   * Bluetooth :   10
+   * Note: This numbers are just assumptions as an example, not measured
+   * or somehow determined
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_LOSSRATE = 1032,
+  
+  /**
+   * Throughput on network layer
+   *
+   * Unit: [kB/s]
+   *
+   * Examples:
+   *
+   * LAN   : 3400
+   * WLAN  : 1200
+   * Dialup:     4
+   *
+   */
+  GNUNET_TRANSPORT_ATS_QUALITY_NET_THROUGHPUT = 1033,
+  
+  /* Availability related values */
+  /* =========================== */
+  
+  /**
+   * Is a peer reachable?
+   */
+  GNUNET_TRANSPORT_ATS_AVAILABILITY_REACHABLE = 2048,
+  
+  /**
+   * Is there a connection established to a peer using this transport
+   */
+  GNUNET_TRANSPORT_ATS_AVAILABILITY_CONNECTED = 2049
+
+};
+
+
+/**
+ * struct used to communicate the transport's properties like cost and
+ * quality of service as well as high-level constraints on resource
+ * consumption.
+ *
+ *                             +---+
+ *  +-----------+ Constraints  |   |  Plugin properties +---------+
+ *  | Highlevel |------------> |ATS| <------------------|Transport|
+ *  | Component | ATS struct   |   |    ATS struct      | Plugin  |
+ *  +-----------+              |   |                    +---------+
+ *                             +---+
+ *
+ * This structure will be used by transport plugins to communicate
+ * costs to ATS or by higher level components to tell ATS their
+ * constraints.  Always a pair of (GNUNET_TRANSPORT_ATS_Property,
+ * uint32_t value).  Value is always uint32_t, so all units used to
+ * define costs have to be normalized to fit uint32_t.
+ */
+struct GNUNET_TRANSPORT_ATS_Information
+{
+  /**
+   * ATS property type, in network byte order.
+   */
+  uint32_t type;
+  
+  /**
+   * ATS property value, in network byte order.
+   */
+  uint32_t value;
+};
+
+
+
+
+/**
  * Function called by the transport for each received message.
  *
  * @param cls closure

Modified: gnunet/src/testing/test_testing_topology.c
===================================================================
--- gnunet/src/testing/test_testing_topology.c  2010-11-12 15:53:17 UTC (rev 
13669)
+++ gnunet/src/testing/test_testing_topology.c  2010-11-13 20:37:37 UTC (rev 
13670)
@@ -298,8 +298,6 @@
 static void topology_cb (void *cls,
                   const struct GNUNET_PeerIdentity *first,
                   const struct GNUNET_PeerIdentity *second,
-                  struct GNUNET_TIME_Relative latency,
-                  uint32_t distance,
                   const char *emsg)
 {
   FILE *outfile = cls;
@@ -329,8 +327,7 @@
 process_mtype (void *cls,
                const struct GNUNET_PeerIdentity *peer,
                const struct GNUNET_MessageHeader *message,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+              const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   char *dotOutFileNameFinished;
   FILE *dotOutFileFinished;
@@ -522,7 +519,6 @@
    */
   pos->peer2handle = GNUNET_CORE_connect (pos->peer2->cfg,
                                          1,
-                                         TIMEOUT,
                                          pos,
                                          &init_notify_peer2,
                                          NULL,
@@ -564,7 +560,6 @@
    */
   pos->peer1handle = GNUNET_CORE_connect (pos->peer1->cfg,
                                          1,
-                                          TIMEOUT,
                                           pos,
                                           &init_notify_peer1,
                                           NULL, NULL,

Modified: gnunet/src/testing/testing.c
===================================================================
--- gnunet/src/testing/testing.c        2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/testing/testing.c        2010-11-13 20:37:37 UTC (rev 13670)
@@ -545,7 +545,9 @@
       d->phase = SP_START_CORE;
       d->server = GNUNET_CORE_connect (d->cfg,
                                       1,
+#if NO_MORE_TIMEOUT_FIXME
                                        ARM_START_WAIT,
+#endif
                                        d,
                                        &testing_init,
                                        NULL, NULL, NULL,
@@ -1347,8 +1349,15 @@
     {
       if (ctx->cb != NULL)
         {
-          ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance, 
ctx->d1->cfg,
-                   ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
+          ctx->cb (ctx->cb_cls, 
+                  &ctx->d1->id,
+                  &ctx->d2->id, 
+                  ctx->distance, 
+                  ctx->d1->cfg,
+                   ctx->d2->cfg,
+                  ctx->d1, 
+                  ctx->d2, 
+                  NULL);
         }
     }
   else if (remaining.rel_value > 0)
@@ -1397,25 +1406,24 @@
  *
  * @param cls our "struct ConnectContext"
  * @param peer identity of the peer that has connected
- * @param latency the round trip latency of the connection to this peer
- * @param distance distance the transport level distance to this peer
+ * @param atsi performance information
  *
  */
 static void
-connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, struct 
GNUNET_TIME_Relative latency,
-                uint32_t distance)
+connect_notify (void *cls, 
+               const struct GNUNET_PeerIdentity * peer, 
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct ConnectContext *ctx = cls;
 
   if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
     {
       ctx->connected = GNUNET_YES;
-      ctx->distance = distance;
+      ctx->distance = 0; /* FIXME: distance */
       GNUNET_SCHEDULER_cancel(ctx->timeout_task);
       ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result,
                                                    ctx);
     }
-
 }
 
 #if CONNECT_CORE2
@@ -1424,20 +1432,20 @@
  *
  * @param cls our "struct ConnectContext"
  * @param peer identity of the peer that has connected
- * @param latency the round trip latency of the connection to this peer
- * @param distance distance the transport level distance to this peer
+ * @param atsi performance information
  *
  */
 static void
-connect_notify_core2 (void *cls, const struct GNUNET_PeerIdentity * peer, 
struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+connect_notify_core2 (void *cls, 
+                     const struct GNUNET_PeerIdentity * peer, 
+                     const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct ConnectContext *ctx = cls;
 
   if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0)
     {
       ctx->connected = GNUNET_YES;
-      ctx->distance = distance;
+      ctx->distance = 0; /* FIXME: distance */
       GNUNET_SCHEDULER_cancel(ctx->timeout_task);
       ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result,
                                                     ctx);
@@ -1477,7 +1485,7 @@
       GNUNET_assert(hello != NULL);
       GNUNET_TRANSPORT_offer_hello (ctx->d2th, hello);
 
-      ctx->connect_request_handle = GNUNET_CORE_peer_request_connect 
(ctx->d2->cfg,
+      ctx->connect_request_handle = GNUNET_CORE_peer_request_connect 
(ctx->d2->server,
                                                                       
GNUNET_TIME_relative_divide(ctx->relative_timeout,
                                                                                
                   ctx->max_connect_attempts + 1),
                                                                       
&ctx->d1->id,
@@ -1539,7 +1547,9 @@
 
   ctx->d1core = GNUNET_CORE_connect (d1->cfg,
                                     1,
+#if NO_MORE_TIMEOUT_FIXME
                                      timeout,
+#endif
                                      ctx,
                                      NULL,
                                      &connect_notify, NULL, NULL,
@@ -1557,7 +1567,9 @@
 #if CONNECT_CORE2
   ctx->d2core = GNUNET_CORE_connect (d2->cfg,
                                     1,
+#if NO_MORE_TIMEOUT_FIXME
                                      timeout,
+#endif
                                      ctx,
                                      NULL,
                                      NULL, NULL, NULL,
@@ -1620,7 +1632,9 @@
 
   ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg,
                                     1,
+#if NO_MORE_TIMEOUT_FIXME
                                      
GNUNET_TIME_absolute_get_remaining(ctx->timeout),
+#endif
                                      ctx,
                                      NULL,
                                      &connect_notify, NULL, NULL,

Modified: gnunet/src/testing/testing_group.c
===================================================================
--- gnunet/src/testing/testing_group.c  2010-11-12 15:53:17 UTC (rev 13669)
+++ gnunet/src/testing/testing_group.c  2010-11-13 20:37:37 UTC (rev 13670)
@@ -3104,7 +3104,7 @@
 static void
 internal_topology_callback(void *cls,
                            const struct GNUNET_PeerIdentity *peer,
-                           struct GNUNET_TIME_Relative latency, uint32_t 
distance)
+                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct CoreContext *core_ctx = cls;
   struct TopologyIterateContext *iter_ctx = core_ctx->iter_context;
@@ -3118,12 +3118,14 @@
     }
   else
     {
-      iter_ctx->topology_cb(iter_ctx->cls, &core_ctx->daemon->id, peer, 
latency, distance, NULL);
+      iter_ctx->topology_cb(iter_ctx->cls, &core_ctx->daemon->id,
+                           peer, NULL);
     }
 
   if (iter_ctx->completed == iter_ctx->total)
     {
-      iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, 
GNUNET_TIME_relative_get_zero(), 0, NULL);
+      iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, 
+                           NULL);
       /* Once all are done, free the iteration context */
       GNUNET_free(iter_ctx);
     }
@@ -3157,8 +3159,8 @@
                       _("Creating connection, outstanding_connections is 
%d\n"), outstanding_connects);
 #endif
       topology_context->connected++;
-      if (GNUNET_OK != GNUNET_CORE_iterate_peers (core_context->daemon->cfg, 
&internal_topology_callback, core_context))
-        internal_topology_callback(core_context, NULL, 
GNUNET_TIME_relative_get_zero(), 0);
+      if (GNUNET_OK != GNUNET_CORE_iterate_peers 
(core_context->daemon->server, &internal_topology_callback, core_context))
+        internal_topology_callback(core_context, NULL, NULL);
 
     }
 }
@@ -3195,7 +3197,7 @@
     }
   if (total_count == 0)
     {
-      cb(cls, NULL, NULL, GNUNET_TIME_relative_get_zero(), 0, "Cannot iterate 
over topology, no running peers!");
+      cb(cls, NULL, NULL, "Cannot iterate over topology, no running peers!");
       GNUNET_free(topology_context);
     }
   else

Modified: gnunet/src/topology/gnunet-daemon-topology.c
===================================================================
--- gnunet/src/topology/gnunet-daemon-topology.c        2010-11-12 15:53:17 UTC 
(rev 13669)
+++ gnunet/src/topology/gnunet-daemon-topology.c        2010-11-13 20:37:37 UTC 
(rev 13670)
@@ -413,7 +413,7 @@
                            gettext_noop ("# connect requests issued to core"),
                            1,
                            GNUNET_NO);
-  pos->connect_req = GNUNET_CORE_peer_request_connect (cfg,
+  pos->connect_req = GNUNET_CORE_peer_request_connect (handle,
                                                       GNUNET_TIME_UNIT_MINUTES,
                                                       &pos->pid,
                                                       
&connect_completed_callback,
@@ -689,15 +689,13 @@
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  */
 static void 
 connect_notify (void *cls,
                const struct
                GNUNET_PeerIdentity * peer,
-               struct GNUNET_TIME_Relative latency,
-               uint32_t distance)
+               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct Peer *pos;
 
@@ -1167,8 +1165,7 @@
  * @param other the other peer involved (sender or receiver, NULL
  *        for loopback messages where we are both sender and receiver)
  * @param message the actual HELLO message
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
@@ -1177,8 +1174,7 @@
                        const struct GNUNET_PeerIdentity * other,
                        const struct GNUNET_MessageHeader *
                        message,
-                       struct GNUNET_TIME_Relative latency,
-                       uint32_t distance)
+                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct Peer *peer;
   struct GNUNET_PeerIdentity pid;
@@ -1379,7 +1375,6 @@
                                        NULL);
   handle = GNUNET_CORE_connect (cfg,
                                1,
-                               GNUNET_TIME_UNIT_FOREVER_REL,
                                NULL,
                                &core_init,
                                &connect_notify,




reply via email to

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