towards a new conveniance API
authorChristian Grothoff <christian@grothoff.org>
Thu, 21 Jan 2010 21:03:45 +0000 (21:03 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 21 Jan 2010 21:03:45 +0000 (21:03 +0000)
TODO
src/include/gnunet_server_lib.h
src/peerinfo/gnunet-service-peerinfo.c
src/util/Makefile.am
src/util/server.c
src/util/server_nc.c [new file with mode: 0644]

diff --git a/TODO b/TODO
index 1d975e95af6314d127347c30eac201d8cf6d3b7b..992f61f8070563cd1cfa7feb0e574371776b548a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -12,24 +12,40 @@ away), in order in which they will likely be done:
 * UPNP [Milan]
 
 Urgent items (before announcing ng.gnunet.org):
+* UTIL:
+  - provide higher-level convenience API for servers/services that
+    need to send a stream of notifications to clients; instead
+    of having each service queue messages and "send when ready", 
+    simply have a way to add a client to the notification set
+    and to 'notify client' or 'notify all clients'
+    (useful for peerinfo (new hellos), transport (our hello; blacklist), 
+     core (misc monitoring features), statistics (change notifications)
+     and likely others)
+  - server/service API change for ARM inetd'ing
+    (listen as well as support for start with multiple, already
+     bound & listening sockets!)
+* TRANSPORT:
+  - main service not implemented [Nate]
+  - blacklist not implemented [Christian]
+  - testcases crash & burn (no surprise)
 * CORE:
-  - test currently fails spectacularly
-  - request disconnect not implemented 
-  - request connect not working
-  - various notification options not implemented
-* topology
-  - (forced) disconnect does not work as implemented (still?)
-  - needs testing (not sure the current testcase does much...)
-* testing:
-  - timeout_hello_task is not used but should be (so we can fail 
-    properly)
+  - request disconnect not implemented [Christian]
+  - various notification options not implemented [Christian]
+  - test currently fails spectacularly [segv of transport service]
+    => need transport to work first!
+  - request connect not working [Christian, need transport first]
+* PEERINFO:
+  - make sue we also trigger notifications whenever HELLOs expire
+* TOPOLOGY:
+  - needs testing [need transport first]
+* TESTING:
   - check that 'GNUNET_TRANSPORT_get_hello' is associated with
-    a TIMEOUT task wherever else appropriate (other testcases
-    in particular!)
-* hostlist
+    a cancel request wherever appropriate (other testcases
+    in particular!) [Christian]
+* 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)
+    messages successfully via transport) [need transport first]
 * FS (basic anonymous FS only)
   - implement FS service (P2P operations)
     + how to send queries (soliciting is not there in core; do we
index ecfead5ab84fd51e5e95b473f814ccd15923b0c8..100dc965937f94cb7c3a302739679ec3a2a694fb 100644 (file)
@@ -138,6 +138,8 @@ struct GNUNET_SERVER_Handle *GNUNET_SERVER_create (struct
 
 /**
  * Free resources held by this server.
+ *
+ * @param s server to destroy
  */
 void GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s);
 
@@ -192,6 +194,7 @@ struct GNUNET_CONNECTION_TransmitHandle
  * @param client client we were processing a message of
  * @param success GNUNET_OK to keep the connection open and
  *                          continue to receive
+ *                GNUNET_NO to close the connection (normal behavior)
  *                GNUNET_SYSERR to close the connection (signal
  *                          serious error)
  */
@@ -413,6 +416,18 @@ void GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
                                       callback, void *callback_cls);
 
 
+/**
+ * Ask the server to stop notifying us whenever a client disconnects.
+ *
+ * @param server the server manageing the clients
+ * @param callback function to call on disconnect
+ * @param callback_cls closure for callback
+ */
+void GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
+                                            GNUNET_SERVER_DisconnectCallback
+                                            callback, void *callback_cls);
+
+
 /**
  * Ask the server to disconnect from the given client.
  * This is the same as returning GNUNET_SYSERR from a message
@@ -440,6 +455,7 @@ GNUNET_SERVER_ignore_shutdown (struct GNUNET_SERVER_Handle *h,
                               int do_ignore);
 
 
+
 /**
  * The tansmit context is the key datastructure for a conveniance API
  * used for transmission of complex results to the client followed
@@ -490,6 +506,81 @@ GNUNET_SERVER_transmit_context_run (struct GNUNET_SERVER_TransmitContext *tc,
 
 
 
+/**
+ * The notification context is the key datastructure for a conveniance
+ * API used for transmission of notifications to the client until the
+ * client disconnects (or the notification context is destroyed, in
+ * which case we disconnect these clients).  Essentially, all
+ * (notification) messages are queued up until the client is able to
+ * read them.
+ */
+struct GNUNET_SERVER_NotificationContext;
+
+
+/**
+ * Create a new notification context.
+ *
+ * @param server server for which this function creates the context
+ * @param queue_length maximum number of messages to keep in
+ *        the notification queue; optional messages are dropped
+ *        it the queue gets longer than this number of messages
+ * @return handle to the notification context
+ */
+struct GNUNET_SERVER_NotificationContext *
+GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
+                                          unsigned int queue_length);
+
+
+/**
+ * Destroy the context, force disconnect for all clients.
+ *
+ * @param nc context to destroy.
+ */
+void
+GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc);
+
+
+/**
+ * Add a client to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to add
+ */
+void
+GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc,
+                                       struct GNUNET_SERVER_Client *client);
+
+
+/**
+ * Send a message to a particular client; must have
+ * already been added to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to transmit to
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc,
+                                           struct GNUNET_SERVER_Client *client,
+                                           const struct GNUNET_MessageHeader *msg,
+                                           int can_drop);
+
+
+/**
+ * Send a message to all clients of this context.
+ *
+ * @param nc context to modify
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc,
+                                             const struct GNUNET_MessageHeader *msg,
+                                             int can_drop);
+
+
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
index f0d8b060668307f7c414c6ec0c8057031c50c2d8..2f3e2c8e16dabe04179a1a6a82eac9f8550452f0 100644 (file)
@@ -103,6 +103,7 @@ struct PendingEntry
    * Entry to tell the client about.
    */
   struct HostEntry *he;
+
 };
 
 
@@ -131,6 +132,7 @@ struct NotifyList
    * Handle for a transmit ready request.
    */
   struct GNUNET_CONNECTION_TransmitHandle *transmit_ctx;
+
 };
 
 
index d4c35ccdb4de4e73ab6bd6a401c8b1ac60b3fb7d..037ab64b2c0878f051ddc1bc1d5e64e4de86ca62 100644 (file)
@@ -59,6 +59,7 @@ libgnunetutil_la_SOURCES = \
   resolver_api.c \
   scheduler.c \
   server.c \
+  server_nc.c \
   server_tc.c \
   service.c \
   signal.c \
index 036c8a44198ccd30932e971c4bf3b6e6800b98ec..adc19ecb7ad08888078ecf0625aa9ec80045024d 100644 (file)
@@ -1117,6 +1117,44 @@ GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server,
 }
 
 
+/**
+ * Ask the server to stop notifying us whenever a client disconnects.
+ *
+ * @param server the server manageing the clients
+ * @param callback function to call on disconnect
+ * @param callback_cls closure for callback
+ */
+void
+GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server,
+                                       GNUNET_SERVER_DisconnectCallback callback,
+                                       void *callback_cls)
+{
+  struct NotifyList *pos;
+  struct NotifyList *prev;
+
+  prev = NULL;
+  pos = server->disconnect_notify_list;
+  while (pos != NULL)
+    {
+      if ( (pos->callback == callback) &&
+          (pos->callback_cls == callback_cls ) )
+       break;
+      prev = pos;
+      pos = pos->next;
+    }
+  if (pos == NULL)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  if (prev == NULL)
+    server->disconnect_notify_list = pos->next;
+  else
+    prev->next = pos->next;
+  GNUNET_free (pos);
+}
+
+
 /**
  * Ask the server to disconnect from the given client.
  * This is the same as returning GNUNET_SYSERR from a message
@@ -1171,6 +1209,7 @@ GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
  * @param client client we were processing a message of
  * @param success GNUNET_OK to keep the connection open and
  *                          continue to receive
+ *                GNUNET_NO to close the connection (normal behavior)
  *                GNUNET_SYSERR to close the connection (signal
  *                          serious error)
  */
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
new file mode 100644 (file)
index 0000000..89e59b7
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+     This file is part of GNUnet.
+     (C) 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 2, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/server_nc.c
+ * @brief convenience functions for transmission of
+ *        a notification stream 
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_connection_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_server_lib.h"
+#include "gnunet_time_lib.h"
+
+
+struct PendingMessageList
+{
+
+  struct PendingMessageList *next;
+
+  const struct GNUNET_MessageHeader *msg;
+
+  int can_drop;
+
+};
+
+
+struct ClientList
+{
+
+  struct ClientList *next;
+
+  struct GNUNET_SERVER_Client *client;
+
+  struct GNUNET_CONNECTION_TransmitHandle *th;
+
+  struct PendingMessageList *pending;
+
+  unsigned int num_pending;
+
+};
+
+
+/**
+ * The notification context is the key datastructure for a conveniance
+ * API used for transmission of notifications to the client until the
+ * client disconnects (or the notification context is destroyed, in
+ * which case we disconnect these clients).  Essentially, all
+ * (notification) messages are queued up until the client is able to
+ * read them.
+ */
+struct GNUNET_SERVER_NotificationContext
+{
+
+  struct GNUNET_SERVER_Handle *server;
+
+  struct ClientList *clients;
+
+  unsigned int queue_length;
+
+};
+
+
+static void
+handle_client_disconnect (void *cls,
+                         struct GNUNET_SERVER_Client *client)
+{
+  struct GNUNET_SERVER_NotificationContext *nc = cls;
+  struct ClientList *pos;
+  struct ClientList *prev;
+  struct PendingMessageList *pml;
+
+  prev = NULL;
+  pos = nc->clients;
+  while (NULL != pos)
+    {
+      if (pos->client == client)
+       break;
+      prev = pos;
+      pos = pos->next;
+    }
+  if (pos == NULL)
+    return;
+  if (prev == NULL)
+    nc->clients = pos->next;
+  else
+    prev->next = pos->next;
+  while (NULL != (pml = pos->pending))
+    {
+      pos->pending = pml->next;
+      GNUNET_free (pml);
+    }
+  GNUNET_free (pos);
+}
+
+
+/**
+ * Create a new notification context.
+ *
+ * @param server server for which this function creates the context
+ * @param queue_length maximum number of messages to keep in
+ *        the notification queue; optional messages are dropped
+ *        it the queue gets longer than this number of messages
+ * @return handle to the notification context
+ */
+struct GNUNET_SERVER_NotificationContext *
+GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server,
+                                          unsigned int queue_length)
+{
+  struct GNUNET_SERVER_NotificationContext *ret;
+
+  ret = GNUNET_malloc (sizeof (struct GNUNET_SERVER_NotificationContext));
+  ret->server = server;
+  ret->queue_length = queue_length;
+  GNUNET_SERVER_disconnect_notify (server,
+                                  &handle_client_disconnect,
+                                  ret);
+  return ret;
+}
+
+
+/**
+ * Destroy the context, force disconnect for all clients.
+ *
+ * @param nc context to destroy.
+ */
+void
+GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc)
+{
+  struct ClientList *pos;
+  struct PendingMessageList *pml;
+
+  while (NULL != (pos = nc->clients))
+    {
+      nc->clients = pos->next;
+      GNUNET_SERVER_receive_done (pos->client, GNUNET_NO);
+      GNUNET_SERVER_client_drop (pos->client); 
+      while (NULL != (pml = pos->pending))
+       {
+         pos->pending = pml->next;
+         GNUNET_free (pml);
+       }
+      GNUNET_free (pos);
+    }
+  GNUNET_SERVER_disconnect_notify_cancel (nc->server,
+                                         &handle_client_disconnect,
+                                         nc);
+  GNUNET_free (nc);
+}
+
+
+/**
+ * Add a client to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to add
+ */
+void
+GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc,
+                                       struct GNUNET_SERVER_Client *client)
+{
+}
+
+
+/**
+ * Send a message to a particular client; must have
+ * already been added to the notification context.
+ *
+ * @param nc context to modify
+ * @param client client to transmit to
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc,
+                                           struct GNUNET_SERVER_Client *client,
+                                           const struct GNUNET_MessageHeader *msg,
+                                           int can_drop)
+{
+}
+
+
+/**
+ * Send a message to all clients of this context.
+ *
+ * @param nc context to modify
+ * @param msg message to send
+ * @param can_drop can this message be dropped due to queue length limitations
+ */
+void
+GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc,
+                                             const struct GNUNET_MessageHeader *msg,
+                                             int can_drop)
+{
+}
+
+
+/* end of server_nc.c */