fixing core API issues
authorChristian Grothoff <christian@grothoff.org>
Wed, 20 Jan 2010 13:51:20 +0000 (13:51 +0000)
committerChristian Grothoff <christian@grothoff.org>
Wed, 20 Jan 2010 13:51:20 +0000 (13:51 +0000)
16 files changed:
BUGS
TODO
src/core/core.h
src/core/core_api.c
src/core/core_api_peer_request.c
src/core/gnunet-service-core.c
src/core/test_core_api.c
src/core/test_core_api_start_only.c
src/fs/gnunet-service-fs.c
src/hostlist/gnunet-daemon-hostlist.c
src/include/gnunet_core_service.h
src/include/gnunet_protocols.h
src/include/gnunet_transport_service.h
src/testing/testing.c
src/topology/gnunet-daemon-topology.c
src/transport/transport_api.c

diff --git a/BUGS b/BUGS
index f5dd633a5f16a9d5f2c680c73148a7bc374ab015..94623b45b4bfed28a71aff111a6fc7e0abcf0b1d 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -82,12 +82,7 @@ sane end-user should care about this codebase yet anyway.
   - better tracking of which config changes actually need to cause process restarts by ARM.
   - have way to specify dependencies between services (to manage ARM restarts better)
 * CORE: 
-  - code currently notifies clients about "encrypted" connections being up well before
-    we get the encrypted PONG; sometimes this may be OK (for topology killing
-    unwanted connnections), but of course not in general.  I suspect we want
-    to signal on PONG and have topology hook directly into transport to
-    kill plaintext connections before they have a chance to become encrypted
-    (may require minor hack in transport API)
+  - test case (test_core_api) hangs for a while (some timeout task not killed somewhere?)
   - [./core/gnunet-service-core.c:469]: (style) struct or union member 'Neighbour::message_queue_size' is never used
   - [./core/test_core_api_start_only.c:50]: (style) struct or union member 'PeerContext::id' is never used
 
diff --git a/TODO b/TODO
index 15691085835e8c1c713943e4e395d376de3104a9..5f031772ac6552f5d1811e620c80c9ce30442964 100644 (file)
--- a/TODO
+++ b/TODO
@@ -12,18 +12,16 @@ away), in order in which they will likely be done:
 * UPNP [Milan]
 
 Urgent items (before announcing ng.gnunet.org):
+* CORE:
+  - test currently fails spectacularly
+  - request disconnect not implemented (needs better transport API)
 * topology
-  - considers peers 'connected' well before they actually are
-    (since core notifies about it too early?);
   - (forced) disconnect does not work (also CORE API issue)
   - needs testing (not sure the current testcase does much...)
 * hostlist
   - test fails (looks like it works, but that's because of a bad
     connectivity notification; somehow core is unable to send
     messages successfully via transport)
-* CORE:
-  - core notifies about connects "too early" (when we have not yet
-    succeeded with the full key exchange) [see also: BUGS]
 * FS (basic anonymous FS only)
   - implement FS service (P2P operations)
     + how to send queries (soliciting is not there in core; do we
@@ -51,6 +49,8 @@ Urgent items (before announcing ng.gnunet.org):
     [=> eliminate for need to tell ARM about service starts most of the time!]
 * HELLO:
   - need function to test "equivalency" of HELLOs; use in topology!
+* CORE:
+  - outbound message monitoring not supported
 * Module features to implement:
   - advanced FS API parts
     + namespaces: fundamental namespace API
index f9117ef4c975ac61f9ac995dfaff2a9f97ca0f00..30130b84b20112ceb21ba739740bf669eed0196e 100644 (file)
  * transmitted to the client.
  */
 #define GNUNET_CORE_OPTION_NOTHING             0
-#define GNUNET_CORE_OPTION_SEND_CONNECT        1
-#define GNUNET_CORE_OPTION_SEND_DISCONNECT     2
-#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   4
-#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND    8
-#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16
-#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  32
+#define GNUNET_CORE_OPTION_SEND_PRE_CONNECT    1
+#define GNUNET_CORE_OPTION_SEND_CONNECT        2
+#define GNUNET_CORE_OPTION_SEND_DISCONNECT     4
+#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   8
+#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND   16
+#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
+#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  64
 
 
 /**
@@ -278,4 +279,31 @@ struct SendMessage
 };
 
 
+/**
+ * Client asking core to transmit a particular message to a particular
+ * target.  There is no response from the core to this type of request
+ * (however, if an actual connection is created or destroyed, be it
+ * because of this type request or not, the core generally needs to
+ * notify the clients).
+ */
+struct ConnectMessage
+{
+  /**
+   * Header with type GNUNET_MESSAGE_TYPE_REQUEST_CONNECT or
+   * GNUNET_MESSAGE_TYPE_REQUEST_DISCONNECT.
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * For alignment.
+   */
+  uint32_t reserved GNUNET_PACKED;
+
+  /**
+   * Identity of the other peer.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+};
+
 /* end of core.h */
index b485b4181f277dea986e8d2df2c2aa502a69e784..a9cbd58569a9ebf4598df0868351e2a20734ab48 100644 (file)
@@ -55,6 +55,12 @@ struct GNUNET_CORE_Handle
    */
   GNUNET_CORE_StartupCallback init;
 
+  /**
+   * Function to call whenever we're notified about a peer connecting
+   * (pre-connects, no session key exchange yet).
+   */
+  GNUNET_CORE_ClientEventHandler pre_connects;
+
   /**
    * Function to call whenever we're notified about a peer connecting.
    */
@@ -395,6 +401,21 @@ main_handler (void *cls, const struct GNUNET_MessageHeader *msg)
 #endif
   switch (ntohs (msg->type))
     {
+    case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT:
+      if (NULL == h->pre_connects)
+        {
+          GNUNET_break (0);
+          break;
+        }
+      if (msize != sizeof (struct ConnectNotifyMessage))
+        {
+          GNUNET_break (0);
+          break;
+        }
+      cnm = (const struct ConnectNotifyMessage *) msg;
+      h->pre_connects (h->cls,
+                      &cnm->peer);
+      break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
       if (NULL == h->connects)
         {
@@ -655,6 +676,8 @@ transmit_start (void *cls, size_t size, void *buf)
   init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
   init->header.size = htons (msize);
   opt = GNUNET_CORE_OPTION_NOTHING;
+  if (h->pre_connects != NULL)
+    opt |= GNUNET_CORE_OPTION_SEND_PRE_CONNECT;
   if (h->connects != NULL)
     opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
   if (h->disconnects != NULL)
@@ -696,6 +719,7 @@ transmit_start (void *cls, size_t size, void *buf)
  * @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
+ * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -716,6 +740,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
                      struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
+                     GNUNET_CORE_ClientEventHandler pre_connects,
                      GNUNET_CORE_ClientEventHandler connects,
                      GNUNET_CORE_ClientEventHandler disconnects,
                      GNUNET_CORE_MessageCallback inbound_notify,
@@ -731,6 +756,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
   h->cfg = cfg;
   h->cls = cls;
   h->init = init;
+  h->pre_connects = pre_connects;
   h->connects = connects;
   h->disconnects = disconnects;
   h->inbound_notify = inbound_notify;
index e873a5a9d1cd5637ac6350abe7efe5ee6ef73150..58837c77386827dba3e0c048b59767ae81252968 100644 (file)
 #include "core.h"
 
 
+/**
+ * Handle for a request to the core to connect or disconnect
+ * from 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;
+
+  /**
+   * Scheduler.
+   */
+  struct GNUNET_SCHEDULER_Handle *sched;
+
+  /**
+   * Function to call once done.
+   */
+  GNUNET_SCHEDULER_Task cont;
+  
+  /**
+   * Closure for 'cont'.
+   */
+  void *cont_cls;
+
+  /**
+   * Identity of the peer to connect/disconnect.
+   */
+  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)
+    {
+      GNUNET_SCHEDULER_add_continuation (prh->sched,
+                                        prh->cont,
+                                        prh->cont_cls,
+                                        GNUNET_SCHEDULER_REASON_TIMEOUT);
+      GNUNET_CLIENT_disconnect (prh->client);
+      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.peer = prh->peer;
+  memcpy (buf, &msg, sizeof (msg));
+  GNUNET_SCHEDULER_add_continuation (prh->sched,
+                                    prh->cont,
+                                    prh->cont_cls,
+                                    GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+  GNUNET_CLIENT_disconnect (prh->client);
+  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 sched scheduler to use
+ * @param cfg configuration to use
+ * @param timeout how long to try to talk to core
+ * @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_SCHEDULER_Handle *sched,
+                                 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 (sched, "core", cfg);
+  if (client == NULL)
+    return NULL;
+  ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
+  ret->client = client;
+  ret->sched = sched;
+  ret->cont = cont;
+  ret->cont_cls = cont_cls;
+  ret->peer = *peer;
+  ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT;
+  GNUNET_CLIENT_notify_transmit_ready (client,
+                                      sizeof (struct ConnectMessage),
+                                      timeout,
+                                      GNUNET_YES,
+                                      &send_request,
+                                      ret);
+  return ret;
+}
+
+
+/**
+ * Request that the core should try to disconnect from 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 cut -- it only means that the
+ * core will now try.  Typically this will work pretty much
+ * immediately, but it is at least in theory also possible that a
+ * reconnect is also triggered rather quickly.  Successful creation
+ * and destruction of connections will be signalled to the 'connects'
+ * and 'disconnects' callback arguments 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 sched scheduler to use
+ * @param cfg configuration to use
+ * @param timeout how long to try to talk to core
+ * @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_disconnect (struct GNUNET_SCHEDULER_Handle *sched,
+                                    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 (sched, "core", cfg);
+  if (client == NULL)
+    return NULL;
+  ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle));
+  ret->client = client;
+  ret->sched = sched;
+  ret->cont = cont;
+  ret->cont_cls = cont_cls;
+  ret->peer = *peer;
+  ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT;
+  GNUNET_CLIENT_notify_transmit_ready (client,
+                                      sizeof (struct ConnectMessage),
+                                      timeout,
+                                      GNUNET_YES,
+                                      &send_request,
+                                      ret);
+  return ret;
+}
+
+
+/**
+ * Cancel a pending request to connect or disconnect from/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_cancel (struct GNUNET_CORE_PeerRequestHandle *req)
+{
+  GNUNET_CLIENT_disconnect (req->client);
+  GNUNET_free (req);
+}
 
 
 /* end of core_api_peer_request.c */
index 557a3f8ea1ba9727cc3e670d90783e058a45f0b3..71771905ec47cfb6f5f28ae011b70555e05fc2e4 100644 (file)
  * @brief high-level P2P messaging
  * @author Christian Grothoff
  *
+ * TODO:
+ * - not all GNUNET_CORE_OPTION_SEND_* flags are fully supported yet
+ *   (i.e. no SEND_XXX_OUTBOUND).
+ * - 'REQUEST_DISCONNECT' is not implemented (transport API is lacking!)
+ *
  * Considerations for later:
  * - check that hostkey used by transport (for HELLOs) is the
  *   same as the hostkey that we are using!
@@ -911,14 +916,17 @@ send_to_client (struct Client *client,
  * Send a message to all of our current clients.
  */
 static void
-send_to_all_clients (const struct GNUNET_MessageHeader *msg, int can_drop)
+send_to_all_clients (const struct GNUNET_MessageHeader *msg, 
+                    int can_drop,
+                    int options)
 {
   struct Client *c;
 
   c = clients;
   while (c != NULL)
     {
-      send_to_client (c, msg, can_drop);
+      if (0 != (c->options & options))
+       send_to_client (c, msg, can_drop);
       c = c->next;
     }
 }
@@ -1984,6 +1992,66 @@ handle_client_send (void *cls,
 }
 
 
+/**
+ * Handle CORE_REQUEST_CONNECT request.
+ *
+ * @param cls unused
+ * @param client the client issuing the request
+ * @param message the "struct ConnectMessage"
+ */
+static void
+handle_client_request_connect (void *cls,
+                              struct GNUNET_SERVER_Client *client,
+                              const struct GNUNET_MessageHeader *message)
+{
+  const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
+  struct Neighbour *n;
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  n = find_neighbour (&cm->peer);
+  if (n != NULL)
+    return; /* already connected, or at least trying */
+#if DEBUG_CORE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Core received `%s' request for `%4s', will try to establish connection\n",
+             "REQUEST_CONNECT",
+             GNUNET_i2s (&cm->peer));
+#endif
+  /* ask transport to connect to the peer */
+  /* FIXME: timeout zero OK? need for cancellation? */
+  GNUNET_TRANSPORT_notify_transmit_ready (transport,
+                                         &cm->peer,
+                                         0, 0,
+                                         GNUNET_TIME_UNIT_ZERO,
+                                         NULL,
+                                         NULL);
+}
+
+
+/**
+ * Handle CORE_REQUEST_DISCONNECT request.
+ *
+ * @param cls unused
+ * @param client the client issuing the request
+ * @param message the "struct ConnectMessage"
+ */
+static void
+handle_client_request_disconnect (void *cls,
+                                 struct GNUNET_SERVER_Client *client,
+                                 const struct GNUNET_MessageHeader *message)
+{
+  const struct ConnectMessage *cm = (const struct ConnectMessage*) message;
+  struct Neighbour *n;
+
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  n = find_neighbour (&cm->peer);
+  if (n == NULL)
+    return; /* done */
+  /* FIXME: implement disconnect! */
+}
+
+
+
 /**
  * List of handlers for the messages understood by this
  * service.
@@ -1996,15 +2064,20 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = {
    sizeof (struct RequestInfoMessage)},
   {&handle_client_send, NULL,
    GNUNET_MESSAGE_TYPE_CORE_SEND, 0},
+  {&handle_client_request_connect, NULL,
+   GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT,
+   sizeof (struct ConnectMessage)},
+  {&handle_client_request_disconnect, NULL,
+   GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT,
+   sizeof (struct ConnectMessage)},
   {NULL, NULL, 0, 0}
 };
 
 
 /**
- * PEERINFO is giving us a HELLO for a peer.  Add the
- * public key to the neighbour's struct and retry
- * send_key.  Or, if we did not get a HELLO, just do
- * nothing.
+ * PEERINFO is giving us a HELLO for a peer.  Add the public key to
+ * the neighbour's struct and retry send_key.  Or, if we did not get a
+ * HELLO, just do nothing.
  *
  * @param cls NULL
  * @param peer the peer for which this is the HELLO
@@ -2073,6 +2146,9 @@ send_key (struct Neighbour *n)
   struct PingMessage pp;
   struct PingMessage *pm;
 
+  if ( (n->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) ||
+       (n->pitr != NULL) )
+    return; /* already in progress */
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asked to perform key exchange with `%4s'.\n",
@@ -2481,6 +2557,7 @@ static void
 handle_pong (struct Neighbour *n, const struct PingMessage *m)
 {
   struct PingMessage t;
+  struct ConnectNotifyMessage cnm;
 
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2533,7 +2610,12 @@ handle_pong (struct Neighbour *n, const struct PingMessage *m)
         {
           GNUNET_SCHEDULER_cancel (sched, n->retry_set_key_task);
           n->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
-        }
+        }      
+      cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
+      cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+      cnm.reserved = htonl (0);
+      cnm.peer = n->peer;
+      send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_CONNECT);
       process_encrypted_neighbour_queue (n);
       break;
     case PEER_STATE_KEY_CONFIRMED:
@@ -2599,7 +2681,7 @@ deliver_message (struct Neighbour *sender,
   while (cpos != NULL)
     {
       deliver_full = GNUNET_NO;
-      if (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)
+      if (0 != (cpos->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))
         deliver_full = GNUNET_YES;
       else
         {
@@ -3033,10 +3115,11 @@ handle_transport_notify_connect (void *cls,
 #endif
   schedule_quota_update (n);
   cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
-  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+  cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT);
   cnm.reserved = htonl (0);
   cnm.peer = *peer;
-  send_to_all_clients (&cnm.header, GNUNET_YES);
+  send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_PRE_CONNECT);
+  send_key (n);
 }
 
 
@@ -3127,7 +3210,7 @@ handle_transport_notify_disconnect (void *cls,
   cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
   cnm.reserved = htonl (0);
   cnm.peer = *peer;
-  send_to_all_clients (&cnm.header, GNUNET_YES);
+  send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_DISCONNECT);
   free_neighbour (n);
 }
 
index 3de162a82ace61b87349ba7d883e7851d0b8d340..acece654519df6a465b24140138739eed9dc69d5 100644 (file)
@@ -215,6 +215,7 @@ init_notify (void *cls,
                            TIMEOUT,
                            &p2,
                            &init_notify,
+                          NULL,
                            &connect_notify,
                            &disconnect_notify,
                            &inbound_notify,
@@ -305,6 +306,7 @@ run (void *cls,
                        TIMEOUT,
                        &p1,
                        &init_notify,
+                      NULL,
                        &connect_notify,
                        &disconnect_notify,
                        &inbound_notify,
index bf5db63c0d85d9ca12431ae14ee6f157bc4c2054..8b5e867bcb9642bd64401edcbcbb419a0e07812b 100644 (file)
@@ -125,6 +125,7 @@ init_notify (void *cls,
                            TIMEOUT,
                            &p2,
                            &init_notify,
+                          NULL,
                            &connect_notify,
                            &disconnect_notify,
                            &inbound_notify,
@@ -178,6 +179,7 @@ run (void *cls,
                        TIMEOUT,
                        &p1,
                        &init_notify,
+                      NULL,
                        &connect_notify,
                        &disconnect_notify,
                        &inbound_notify,
index 71e59f11538a664e0cdb84aeb6d0ee53e9f8fb7a..4ce618bf7f891881fa21592f0a20cf98bef75d55 100644 (file)
@@ -3325,6 +3325,7 @@ run (void *cls,
                              GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              NULL,
+                             NULL,
                              &peer_connect_handler,
                              &peer_disconnect_handler,
                              NULL, GNUNET_NO,
index fd1068839a096958a73a976366f74443c917ec16..b8cf93d5a5288e3832022bb4969d8cd756d5824f 100644 (file)
@@ -191,7 +191,7 @@ run (void *cls,
                              GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              &core_init,
-                             ch, dh,
+                             NULL, ch, dh,
                              NULL, GNUNET_NO,
                              NULL, GNUNET_NO,
                              handlers);
index 94656b916e1271cd372b7efd85d3ed32e0e99085..cffdf0a1423b040f9f44f6c5041b63acb30078d5 100644 (file)
@@ -138,6 +138,7 @@ typedef void
  * @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
+ * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
@@ -158,6 +159,7 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
                      struct GNUNET_TIME_Relative timeout,
                      void *cls,
                      GNUNET_CORE_StartupCallback init,
+                    GNUNET_CORE_ClientEventHandler pre_connects,
                      GNUNET_CORE_ClientEventHandler connects,
                      GNUNET_CORE_ClientEventHandler disconnects,
                      GNUNET_CORE_MessageCallback inbound_notify,
@@ -175,27 +177,77 @@ GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
 void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle);
 
 
-// FIXME
+/**
+ * Handle for a request to the core to connect or disconnect
+ * from a particular peer.  Can be used to cancel the request
+ * (before the 'cont'inuation is called).
+ */
 struct GNUNET_CORE_PeerRequestHandle;
 
-// FIXME
+
+/**
+ * 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 sched scheduler to use
+ * @param cfg configuration to use
+ * @param timeout how long to try to talk to core
+ * @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_SCHEDULER_Handle *sched,
-                                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                        const struct GNUNET_PeerIdentity * peer,
-                                        GNUNET_SCHEDULER_Task cont,
-                                        void *cont_cls);
+                                 const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                 struct GNUNET_TIME_Relative timeout,
+                                 const struct GNUNET_PeerIdentity * peer,
+                                 GNUNET_SCHEDULER_Task cont,
+                                 void *cont_cls);
 
 
-// FIXME
+/**
+ * Request that the core should try to disconnect from 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 cut -- it only means that the
+ * core will now try.  Typically this will work pretty much
+ * immediately, but it is at least in theory also possible that a
+ * reconnect is also triggered rather quickly.  Successful creation
+ * and destruction of connections will be signalled to the 'connects'
+ * and 'disconnects' callback arguments 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 sched scheduler to use
+ * @param cfg configuration to use
+ * @param timeout how long to try to talk to core
+ * @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_disconnect (struct GNUNET_SCHEDULER_Handle *sched,
-                                           const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                           const struct GNUNET_PeerIdentity * peer,
-                                           GNUNET_SCHEDULER_Task cont,
-                                           void *cont_cls);
+                                    const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                    struct GNUNET_TIME_Relative timeout,
+                                    const struct GNUNET_PeerIdentity * peer,
+                                    GNUNET_SCHEDULER_Task cont,
+                                    void *cont_cls);
 
-// FIXME
+
+/**
+ * Cancel a pending request to connect or disconnect from/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_cancel (struct GNUNET_CORE_PeerRequestHandle *req);
 
index cdf5d0df37db9fa317b0917c460d12823c702c43..28535587dbd44f8294a88ce0257c93ca5382de9b 100644 (file)
@@ -263,40 +263,57 @@ extern "C"
 #define GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY 65
 
 /**
- * Notify clients about new peer-to-peer connections.
+ * Notify clients about new peer-to-peer connections (before
+ * key exchange and authentication).
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 66
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT 66
+
+/**
+ * Notify clients about new peer-to-peer connections (triggered
+ * after key exchange).
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 67
 
 /**
  * Notify clients about peer disconnecting.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 67
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68
 
 /**
  * Notify clients about incoming P2P messages.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 68
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 69
 
 /**
  * Notify clients about outgoing P2P transmissions.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 69
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 70
 
 /**
  * Request from client to "configure" P2P connection.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 70
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 71
 
 /**
  * Response from server about (possibly updated) P2P
  * connection configuration.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 71
+#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 72
 
 /**
  * Request from client with message to transmit.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_SEND 72
+#define GNUNET_MESSAGE_TYPE_CORE_SEND 73
+
+/**
+ * Request from client asking to connect to a peer.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 74
+
+/**
+ * Request from client asking to disconnect from a peer.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_DISCONNECT 75
 
 
 /**
index 726e03a9517efb14ab36d8347b4e1e64c2e47a14..344de582fb37b0328276f5779c70454514477b7e 100644 (file)
@@ -138,10 +138,8 @@ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle);
  *
  * @param handle connection to transport service
  * @param target who's bandwidth quota is being changed
- * @param quota_in incoming bandwidth quota in bytes per ms; 0 can
- *        be used to force all traffic to be discarded
- * @param quota_out outgoing bandwidth quota in bytes per ms; 0 can
- *        be used to force all traffic to be discarded
+ * @param quota_in incoming bandwidth quota in bytes per ms
+ * @param quota_out outgoing bandwidth quota in bytes per ms
  * @param timeout how long to wait until signaling failure if
  *        we can not communicate the quota change
  * @param cont continuation to call when done, will be called
@@ -195,8 +193,9 @@ struct GNUNET_TRANSPORT_TransmitHandle
 
 
 /**
- * Cancel the specified transmission-ready
- * notification.
+ * Cancel the specified transmission-ready notification.
+ *
+ * @param h handle of the transmission notification request to cancel
  */
 void
 GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct
index cc584e74a73ca22113c2678922a1cda7496a9658..489252411b5d99caf462511bf4a0664700c9b53e 100644 (file)
@@ -434,7 +434,7 @@ start_fsm (void *cls,
                                       ARM_START_WAIT,
                                       d,
                                       &testing_init,
-                                      NULL, NULL, 
+                                      NULL, NULL, NULL,
                                       NULL, GNUNET_NO,
                                       NULL, GNUNET_NO,
                                       no_handlers);     
index bc2f3ec7f054b7e8beef63e84dd7d145c170ae2b..9f23fdc5065e7df1547f67e80222c8fcb0bdd7f6 100644 (file)
@@ -1289,6 +1289,7 @@ run (void *cls,
                                GNUNET_TIME_UNIT_FOREVER_REL,
                                NULL,
                                &core_init,
+                               NULL,
                                &connect_notify,
                                &disconnect_notify,
                                NULL, GNUNET_NO,
index 155347bf0c607c7a4a4de3dec1f9e3afa7a9fdcd..e17ba742e48084f8836d06951b4451bcf7944505 100644 (file)
  * @file transport/transport_api.c
  * @brief library to access the low-level P2P IO service
  * @author Christian Grothoff
- *
- * TODO:
- * - set_quota with low bandwidth should cause peer
- *   disconnects (currently never does that) (MINOR)
  */
 #include "platform.h"
 #include "gnunet_client_lib.h"
@@ -395,7 +391,8 @@ transport_notify_ready (void *cls, size_t size, void *buf)
           GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task);
           th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
         }
-      GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
+      if (NULL != th->notify)
+       GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
       GNUNET_free (th);
       if (h->connect_ready_head != NULL)
         schedule_transmission (h);      /* FIXME: is this ok? */
@@ -427,7 +424,8 @@ transport_notify_ready (void *cls, size_t size, void *buf)
           GNUNET_assert (n->transmit_handle == th);
           n->transmit_handle = NULL;
         }
-      ret += th->notify (th->notify_cls, size, &cbuf[ret]);
+      if (NULL != th->notify)
+       ret += th->notify (th->notify_cls, size, &cbuf[ret]);
       GNUNET_free (th);
       if (n != NULL)
         n->last_sent += ret;
@@ -585,7 +583,8 @@ peer_transmit_timeout (void *cls,
               GNUNET_i2s (&th->target));
 #endif
   remove_from_any_list (th);
-  th->notify (th->notify_cls, 0, NULL);
+  if (NULL != th->notify)
+    th->notify (th->notify_cls, 0, NULL);
   GNUNET_free (th);
 }
 
@@ -735,10 +734,8 @@ send_set_quota (void *cls, size_t size, void *buf)
  *
  * @param handle connection to transport service
  * @param target who's bandwidth quota is being changed
- * @param quota_in incoming bandwidth quota in bytes per ms; 0 can
- *        be used to force all traffic to be discarded
- * @param quota_out outgoing bandwidth quota in bytes per ms; 0 can
- *        be used to force all traffic to be discarded
+ * @param quota_in incoming bandwidth quota in bytes per ms
+ * @param quota_out outgoing bandwidth quota in bytes per ms
  * @param timeout how long to wait until signaling failure if
  *        we can not communicate the quota change
  * @param cont continuation to call when done, will be called
@@ -992,7 +989,8 @@ request_connect (void *cls, size_t size, void *buf)
           GNUNET_SCHEDULER_cancel (h->sched, th->notify_delay_task);
           th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
         }
-      th->notify (th->notify_cls, 0, NULL);
+      if (NULL != th->notify)
+       GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
       GNUNET_free (th);
       return 0;
     }
@@ -1288,7 +1286,8 @@ schedule_request (struct GNUNET_TRANSPORT_TransmitHandle *th)
                       duration.value, GNUNET_i2s (&th->target));
 #endif
           remove_from_wait_list (th);
-          th->notify (th->notify_cls, 0, NULL);
+         if (NULL != th->notify)
+           GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
           GNUNET_free (th);
           return;
         }
@@ -1472,7 +1471,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
           GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task);
           th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
         }
-      th->notify (th->notify_cls, 0, NULL);
+      if (NULL != th->notify)
+       GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
       GNUNET_free (th);
     }
   while (NULL != (th = handle->connect_wait_head))
@@ -1483,7 +1483,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
           GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task);
           th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
         }
-      th->notify (th->notify_cls, 0, NULL);
+      if (NULL != th->notify)
+       GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
       GNUNET_free (th);
     }
   while (NULL != (n = handle->neighbours))
@@ -1496,7 +1497,8 @@ GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
               GNUNET_SCHEDULER_cancel (handle->sched, th->notify_delay_task);
               th->notify_delay_task = GNUNET_SCHEDULER_NO_TASK;
             }
-          th->notify (th->notify_cls, 0, NULL);
+         if (NULL != th->notify)
+           GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));        
           GNUNET_free (th);
         }
       GNUNET_free (n);
@@ -1788,16 +1790,19 @@ client_notify_wrapper (void *cls, size_t size, void *buf)
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Transmission request could not be satisfied.\n");
 #endif
-      ret = ctw->notify (ctw->notify_cls, 0, NULL);
-      GNUNET_assert (ret == 0);
+      if (NULL != ctw->notify)
+       GNUNET_assert (0 == ctw->notify (ctw->notify_cls, 0, NULL));
       GNUNET_free (ctw);
       return 0;
     }
   GNUNET_assert (size >= sizeof (struct OutboundMessage));
   obm = buf;
-  ret = ctw->notify (ctw->notify_cls,
-                     size - sizeof (struct OutboundMessage),
-                     (void *) &obm[1]);
+  if (ctw->notify != NULL)
+    ret = ctw->notify (ctw->notify_cls,
+                      size - sizeof (struct OutboundMessage),
+                      (void *) &obm[1]);
+  else
+    ret = 0;
   if (ret == 0)
     {
       /* Need to reset flag, no SEND means no SEND_OK! */