gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r5823 - in GNUnet: . contrib src/applications src/applicati


From: gnunet
Subject: [GNUnet-SVN] r5823 - in GNUnet: . contrib src/applications src/applications/topology_default src/include src/server
Date: Sat, 8 Dec 2007 17:19:28 -0700 (MST)

Author: grothoff
Date: 2007-12-08 17:19:28 -0700 (Sat, 08 Dec 2007)
New Revision: 5823

Removed:
   GNUnet/src/applications/topology_f2f/
Modified:
   GNUnet/ChangeLog
   GNUnet/UPDATING
   GNUnet/configure.ac
   GNUnet/contrib/config-daemon.scm
   GNUnet/src/applications/Makefile.am
   GNUnet/src/applications/topology_default/topology.c
   GNUnet/src/include/gnunet_topology_service.h
   GNUnet/src/server/connection.c
   GNUnet/src/server/gnunet-update.c
   GNUnet/todo
Log:
Implementing feature 1018 -- target number of friendly connections -- also 
integrating f2f and default topology implementations, eliminating redundant code

Modified: GNUnet/ChangeLog
===================================================================
--- GNUnet/ChangeLog    2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/ChangeLog    2007-12-09 00:19:28 UTC (rev 5823)
@@ -1,3 +1,9 @@
+Sat Dec  8 15:15:53 MST 2007
+       Integrated F2F topology into main topology module 
+       (options are used to choose between F2F-only (old F2F), 
+        minimum number of friend connections (NEW) or entirely
+        arbitrary connection set (default)).
+
 Thu Dec  6 20:51:17 MST 2007
        The SMTP transport is working again.
 

Modified: GNUnet/UPDATING
===================================================================
--- GNUnet/UPDATING     2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/UPDATING     2007-12-09 00:19:28 UTC (rev 5823)
@@ -12,6 +12,8 @@
 ==============
 
 Run gnunet-update.
+Run "gnunet-setup -d", some options have changed and some are
+new.  You might want to consider enabling the HTTP transport.
 
 
 0.7.2b to 0.7.2c

Modified: GNUnet/configure.ac
===================================================================
--- GNUnet/configure.ac 2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/configure.ac 2007-12-09 00:19:28 UTC (rev 5823)
@@ -750,7 +750,6 @@
 src/applications/template/Makefile
 src/applications/testing/Makefile
 src/applications/topology_default/Makefile
-src/applications/topology_f2f/Makefile
 src/applications/tracekit/Makefile
 src/applications/traffic/Makefile
 src/applications/transport/Makefile

Modified: GNUnet/contrib/config-daemon.scm
===================================================================
--- GNUnet/contrib/config-daemon.scm    2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/contrib/config-daemon.scm    2007-12-09 00:19:28 UTC (rev 5823)
@@ -616,20 +616,42 @@
   "topology"
   (_ "Which topology should be used?")
   (_ 
-"Which topology should be used?  The only options at the moment are 
\"topology_default\" and \"topology_f2f\".  In default mode, GNUnet will try to 
connect to a diverse set of peers, and welcome connections from anyone.  In f2f 
(friend-to-friend) mode, GNUnet will only allow connections from peers that are 
explicitly listed in a FRIENDS file.  Note that you can list peers in the 
FRIENDS file that run in default mode.
-
-Use f2f only if you have (trustworthy) friends that use GNUnet and are afraid 
of establishing (direct) connections to unknown peers." )
+"Which topology should be used?  The only option at the moment is 
\"topology_default\"" )
   '()
   #t
   "topology_default"
-  (list "SC" "topology_default" "topology_f2f")
-  'advanced) )
+  (list "SC" "topology_default")
+  'rare) )
 
 
 ;; f2f menu
 
-(define (f2f builder)
+(define (f2f-minimum builder)
  (builder
+ "F2F"
+ "MINIMUM"
+ (_ "Minimum number of connected friends before this peer is allowed to 
connect to peers that are not listed as friends")
+ (_ "Note that this option does not guarantee that the peer will be able to 
connect to the specified number of friends.  Also, if the peer had connected to 
a sufficient number of friends and then established non-friend connections, 
some of the friends may drop out of the network, temporarily resulting in 
having fewer than the specified number of friends connected while being 
connected to non-friends.  However, it is guaranteed that the peer itself will 
never choose to drop a friend's connection if this would result in dropping 
below the specified number of friends (unless that number is higher than the 
overall connection target).")
+ '()
+ #t
+ 0
+ (cons 0 1024)
+ 'f2fr) )
+
+(define (f2f-restrict builder)
+ (builder
+ "F2F"
+ "FRIENDS-ONLY"
+ (_ "If set to YES, the peer is only allowed to connect to other peers that 
are explicitly specified as friends")
+ (_ "Use YES only if you have (trustworthy) friends that use GNUnet and are 
afraid of establishing (direct) connections to unknown peers")
+ '()
+ #t
+ #f
+ #f
+ 'advanced) )
+
+(define (f2f-friends builder)
+ (builder
   "F2F"
   "FRIENDS"
   (_ "List of friends for friend-to-friend topology")
@@ -640,6 +662,21 @@
   '()
   'f2f) )
 
+(define (f2f builder)
+ (builder
+  "F2F"
+  ""
+ (_ "Friend-to-Friend Topology Specification")
+ (_ "Settings for restricting connections to friends")
+ (list
+    (f2f-restrict builder) 
+    (f2f-minimum builder) 
+    (f2f-friends builder) 
+ )
+  #t
+  #f
+  #f
+  'advanced) )
 
 ;; mysql menu
 
@@ -1452,7 +1489,9 @@
      (rare (get-option ctx "Meta" "RARE"))
      (nobasiclimit (not (get-option ctx "LOAD" "BASICLIMITING")))
      (experimental (get-option ctx "Meta" "EXPERIMENTAL"))
-     (f2f (string= (get-option ctx "MODULES" "topology") "topology_f2f") )
+     (f2fr (string= (get-option ctx "F2F" "RESTRICT") "NO") )
+     (f2f (or (string= (get-option ctx "F2F" "RESTRICT") "YES") 
+              (not (eq? (get-option ctx "F2F" "MINIMUM") 0) ) ) )
      (tcp-port-nz (eq? (get-option ctx "TCP" "PORT") 0) )
      (udp-port-nz (eq? (get-option ctx "UDP" "PORT") 0) )
      (http-port-nz (eq? (get-option ctx "HTTP" "PORT") 0) )
@@ -1475,6 +1514,7 @@
             ((eq? i 'rare)         (change-visible ctx a b (and advanced 
rare)))
             ((eq? i 'experimental) (change-visible ctx a b (and advanced 
experimental)))
             ((eq? i 'f2f)          (change-visible ctx a b f2f))
+            ((eq? i 'f2fr)         (change-visible ctx a b f2fr))
             ((eq? i 'mysql)        (change-visible ctx a b mysql))
             ((eq? i 'fs-loaded)    (change-visible ctx a b fs-loaded))
             ((eq? i 'nat-unlimited)(change-visible ctx a b nat-unlimited))

Modified: GNUnet/src/applications/Makefile.am
===================================================================
--- GNUnet/src/applications/Makefile.am 2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/src/applications/Makefile.am 2007-12-09 00:19:28 UTC (rev 5823)
@@ -33,7 +33,6 @@
  tbench \
  template \
  topology_default \
- topology_f2f \
  tracekit \
  traffic \
  transport \

Modified: GNUnet/src/applications/topology_default/topology.c
===================================================================
--- GNUnet/src/applications/topology_default/topology.c 2007-12-08 07:06:30 UTC 
(rev 5822)
+++ GNUnet/src/applications/topology_default/topology.c 2007-12-09 00:19:28 UTC 
(rev 5823)
@@ -32,6 +32,7 @@
 
 #include "platform.h"
 #include "gnunet_core.h"
+#include "gnunet_directories.h"
 #include "gnunet_protocols.h"
 #include "gnunet_identity_service.h"
 #include "gnunet_state_service.h"
@@ -84,6 +85,29 @@
 static double saturation = 0.0;
 
 /**
+ * Array of our friends.
+ */
+static GNUNET_PeerIdentity *friends;
+
+/**
+ * Number of friends that we have.
+ */
+static unsigned int friendCount;
+
+/**
+ * Minimum number of friends to have in the
+ * connection set.
+ */
+static unsigned int minimum_friend_count;
+
+/**
+ * Flag to disallow non-friend connections (pure F2F mode).
+ */
+static int friends_only;
+
+
+
+/**
  * Record for state maintanance between scanHelperCount,
  * scanHelperSelect and scanForHosts.
  */
@@ -384,15 +408,192 @@
   return saturation;
 }
 
+static int 
+is_friend (const GNUNET_PeerIdentity  * peer) {
+  unsigned int i;
+
+  for (i=0;i<friendCount;i++)
+    if (0 == memcmp (&friends[i], peer, sizeof (GNUNET_PeerIdentity))) 
+      return 1;
+  return 0;
+}
+
+static void
+friend_counter (const GNUNET_PeerIdentity * peer,
+               void * cls) {
+  unsigned int * cnt = cls;
+
+  if (is_friend(peer))
+    (*cnt)++;
+}
+
+static unsigned int
+count_connected_friends(GNUNET_ConnectionIterator connectionIterator,
+                       void * cls) {
+  unsigned int i;
+
+  i = 0;
+  connectionIterator(&friend_counter, &i, cls);
+  return i;
+}
+
 static int
+core_wrapper(GNUNET_NodeIteratorCallback callback,
+            void * cb_arg,
+            void * unused) {
+  return coreAPI->forAllConnectedNodes(callback, cb_arg);
+}
+
+static int
 allowConnection (const GNUNET_PeerIdentity * peer)
 {
   if ((coreAPI->myIdentity != NULL) &&
       (0 == memcmp (coreAPI->myIdentity, peer, sizeof (GNUNET_PeerIdentity))))
     return GNUNET_SYSERR;       /* disallow connections to self */
-  return GNUNET_OK;             /* allow everything else */
+  if (is_friend(peer))
+    return GNUNET_OK;
+  if (friends_only)
+    return GNUNET_SYSERR; 
+  if (count_connected_friends(&core_wrapper, NULL) >= minimum_friend_count)
+    return GNUNET_OK;
+  return GNUNET_SYSERR;
 }
 
+/**
+ * Would it be ok to drop the connection to this
+ * peer?
+ */
+static int
+isConnectionGuarded (const GNUNET_PeerIdentity * peer,
+                    GNUNET_ConnectionIterator connectionIterator,
+                    void * cls) {
+  if (! is_friend(peer))
+    return GNUNET_NO;
+  if (count_connected_friends(connectionIterator, cls) <= minimum_friend_count)
+    return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+static unsigned int
+countGuardedConnections() {
+  return minimum_friend_count;
+}
+
+/**
+ * @return 0 on success.
+ */
+static int
+rereadConfiguration (void *ctx,
+                     struct GNUNET_GC_Configuration *cfg,
+                     struct GNUNET_GE_Context *ectx,
+                     const char *section, const char *option)
+{
+  char *fn;
+  char *data;
+  unsigned long long size;
+  size_t pos;
+  GNUNET_EncName enc;
+  GNUNET_HashCode hc;
+  unsigned long long opt;
+
+  if (0 != strcmp (section, "F2F"))
+    return 0;
+  friends_only = GNUNET_GC_get_configuration_value_yesno (cfg,
+                                                         "F2F",
+                                                         "FRIENDS-ONLY",
+                                                         GNUNET_NO);
+  if (friends_only == GNUNET_SYSERR)
+    return GNUNET_SYSERR; /* invalid */
+  opt = 0;
+  GNUNET_GC_get_configuration_value_number (cfg,
+                                           "F2F",
+                                           "MINIMUM",
+                                           0,
+                                           1024 * 1024,
+                                           0,
+                                           &opt);
+  minimum_friend_count = (unsigned int) opt;
+  GNUNET_array_grow (friends, friendCount, 0);
+  fn = NULL;
+  GNUNET_GC_get_configuration_value_filename (cfg,
+                                              "F2F",
+                                              "FRIENDS",
+                                              
GNUNET_DEFAULT_DAEMON_VAR_DIRECTORY
+                                              "/friends", &fn);
+  if ((0 == GNUNET_disk_file_test (ectx, fn))
+      || (GNUNET_OK != GNUNET_disk_file_size (ectx, fn, &size, GNUNET_YES)))
+    {
+      GNUNET_GE_LOG (ectx,
+                     GNUNET_GE_USER | GNUNET_GE_ADMIN | GNUNET_GE_ERROR |
+                     GNUNET_GE_IMMEDIATE,
+                     "Could not read friends list `%s'\n", fn);
+      GNUNET_free (fn);
+      return GNUNET_SYSERR;
+    }
+  data = GNUNET_malloc (size);
+  if (size != GNUNET_disk_file_read (ectx, fn, size, data))
+    {
+      GNUNET_GE_LOG (ectx,
+                     GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
+                     _("Failed to read friends list from `%s'\n"), fn);
+      GNUNET_free (fn);
+      GNUNET_free (data);
+      return GNUNET_SYSERR;
+    }
+  GNUNET_free (fn);
+  pos = 0;
+  while ((pos < size) && isspace (data[pos]))
+    pos++;
+  while (pos <= size - sizeof (GNUNET_EncName))
+    {
+      memcpy (&enc, &data[pos], sizeof (GNUNET_EncName));
+      if (!isspace (enc.encoding[sizeof (GNUNET_EncName) - 1]))
+        {
+          GNUNET_GE_LOG (ectx,
+                         GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                         _
+                         ("Syntax error in topology specification, skipping 
bytes.\n"));
+          continue;
+        }
+      enc.encoding[sizeof (GNUNET_EncName) - 1] = '\0';
+      if (GNUNET_OK == GNUNET_enc_to_hash ((char *) &enc, &hc))
+        {
+          GNUNET_array_grow (friends, friendCount, friendCount + 1);
+          friends[friendCount - 1].hashPubKey = hc;
+        }
+      else
+        {
+          GNUNET_GE_LOG (ectx,
+                         GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                         _
+                         ("Syntax error in topology specification, skipping 
bytes `%s'.\n"),
+                         &enc);
+        }
+      pos = pos + sizeof (GNUNET_EncName);
+      while ((pos < size) && isspace (data[pos]))
+        pos++;
+    }
+  if ( (minimum_friend_count > friendCount)  &&
+       (friends_only == GNUNET_NO) )
+    {
+      GNUNET_GE_LOG (ectx,
+                    GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                    _
+                    ("Fewer friends specified than required by minimum friend 
count. Will only connect to friends.\n"));
+    }
+  if ( (minimum_friend_count > coreAPI->getSlotCount())  &&
+       (friends_only == GNUNET_NO) )
+    {
+      GNUNET_GE_LOG (ectx,
+                    GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,
+                    _
+                    ("More friendly connections required than target total 
number of connections.\n"));
+    }
+
+  return 0;
+}
+
+
 GNUNET_Topology_ServiceAPI *
 provide_module_topology_default (GNUNET_CoreAPIForPlugins * capi)
 {
@@ -423,12 +624,26 @@
       transport = NULL;
       return NULL;
     }
-  GNUNET_cron_add_job (capi->cron,
+ if (0 != GNUNET_GC_attach_change_listener (coreAPI->cfg,
+                                           &rereadConfiguration, NULL))
+    {
+      GNUNET_GE_BREAK (coreAPI->ectx, 0);
+      capi->releaseService (identity);
+      identity = NULL;
+      capi->releaseService (transport);
+      transport = NULL;
+      capi->releaseService (pingpong);
+      pingpong = NULL;
+      return NULL;
+    }
+ GNUNET_cron_add_job (capi->cron,
                        &cronCheckLiveness,
                        LIVE_SCAN_FREQUENCY, LIVE_SCAN_FREQUENCY, NULL);
   api.estimateNetworkSize = &estimateNetworkSize;
   api.getSaturation = &estimateSaturation;
   api.allowConnectionFrom = &allowConnection;
+  api.isConnectionGuarded = &isConnectionGuarded;
+  api.countGuardedConnections = &countGuardedConnections;
   return &api;
 }
 
@@ -437,6 +652,7 @@
 {
   GNUNET_cron_del_job (coreAPI->cron, &cronCheckLiveness, LIVE_SCAN_FREQUENCY,
                        NULL);
+  GNUNET_GC_detach_change_listener (coreAPI->cfg, &rereadConfiguration, NULL);
   coreAPI->releaseService (identity);
   identity = NULL;
   coreAPI->releaseService (transport);

Modified: GNUnet/src/include/gnunet_topology_service.h
===================================================================
--- GNUnet/src/include/gnunet_topology_service.h        2007-12-08 07:06:30 UTC 
(rev 5822)
+++ GNUnet/src/include/gnunet_topology_service.h        2007-12-09 00:19:28 UTC 
(rev 5823)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+     (C) 2004, 2005, 2006, 2007 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
@@ -37,6 +37,10 @@
 #endif
 #endif
 
+typedef int (*GNUNET_ConnectionIterator)(GNUNET_NodeIteratorCallback method,
+                                        void * ni_arg,
+                                        void * cls);
+
 /**
  * @brief topology service API
  *
@@ -80,6 +84,21 @@
    */
   int (*allowConnectionFrom) (const GNUNET_PeerIdentity * peer);
 
+  /**
+   * Do we have to try to keep this connection?
+   * @return GNUNET_OK if the connection should be kept, GNUNET_NO if
+   *         the topology does not care, GNUNET_SYSERR if topology
+   *         would like to see the connection dropped.
+   */
+  int (*isConnectionGuarded) (const GNUNET_PeerIdentity * peer,
+                             GNUNET_ConnectionIterator iterator,
+                             void * cls);
+  
+  /**
+   * How many connections are currently guarded by the
+   * topology?
+   */
+  unsigned int (*countGuardedConnections) (void);
 
 } GNUNET_Topology_ServiceAPI;
 

Modified: GNUnet/src/server/connection.c
===================================================================
--- GNUnet/src/server/connection.c      2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/src/server/connection.c      2007-12-09 00:19:28 UTC (rev 5823)
@@ -2256,6 +2256,26 @@
   return CONNECTION_MAX_HOSTS_ / 2;
 }
 
+static int
+remaining_connection_iterator(GNUNET_NodeIteratorCallback callback,
+                             void * cb_arg,
+                             void * cls) {
+  UTL_Closure *utl = cls;
+  unsigned int u;
+  unsigned int r;
+  
+  r = 0;
+  for (u = 0; u < utl->pos; u++) 
+    if (utl->e[u]->idealized_limit >= MIN_BPM_PER_PEER) 
+      {
+       r++;
+       if (callback != NULL)
+         callback(&utl->e[u]->session.sender,
+                  cb_arg);
+      } 
+  return r;
+}
+
 /**
  * Schedule the available inbound bandwidth among the peers.  Note
  * that this function is called A LOT (dozens of times per minute), so
@@ -2275,6 +2295,7 @@
   unsigned int u;
   unsigned int v;
   unsigned int minCon;
+  unsigned int guardCon;
   long long schedulableBandwidth;
   long long decrementSB;
   long long *adjustedRR;
@@ -2360,6 +2381,9 @@
 
   /* compute how much bandwidth we can bargain with */
   minCon = minConnect ();
+  guardCon = topology->countGuardedConnections();
+  if (guardCon > minCon)
+    minCon = guardCon;
   if (minCon > activePeerCount)
     minCon = activePeerCount;
   if (max_bpm > minCon * MIN_BPM_PER_PEER)
@@ -2492,12 +2516,21 @@
               if ((share > adjustedRR[u] * 2) && (firstRound == GNUNET_YES))
                 share = adjustedRR[u] * 2;
               /* always allow allocating MIN_BPM_PER_PEER */
-              if ((share < MIN_BPM_PER_PEER) && (minCon > 0))
-                {
+              if ( (share < MIN_BPM_PER_PEER) && 
+                  ( (minCon > 0) &&
+                    ( (guardCon < minCon) ||
+                      
(topology->isConnectionGuarded(&entries[u]->session.sender,
+                                                     
&remaining_connection_iterator,
+                                                     &utl)) ) ) ) 
+               {
                   /* use one of the minCon's to keep the connection! */
                   share += MIN_BPM_PER_PEER;
                   decrementSB -= MIN_BPM_PER_PEER;      /* do not count */
                   minCon--;
+                 if (topology->isConnectionGuarded(&entries[u]->session.sender,
+                                                   
&remaining_connection_iterator,
+                                                   &utl) )
+                   guardCon--;
                 }
               if (share > entries[u]->idealized_limit)
                 {

Modified: GNUnet/src/server/gnunet-update.c
===================================================================
--- GNUnet/src/server/gnunet-update.c   2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/src/server/gnunet-update.c   2007-12-09 00:19:28 UTC (rev 5823)
@@ -184,6 +184,7 @@
 {
   int i;
   struct GNUNET_CronManager *cron;
+  char * topo;
 
   uapi.updateModule = &updateModule;
   uapi.requestService = &requestService;
@@ -191,6 +192,33 @@
   uapi.ectx = ectx;
   uapi.cfg = cfg;
 
+  GNUNET_GC_get_configuration_value_string(cfg,
+                                          "MODULES",
+                                          "topology",
+                                          "topology_default",
+                                          &topo);
+  /* Code specific for update from 0.7.2c to 0.7.3 */
+  if (0 == strcmp(topo, "topology_f2f")) 
+    {
+      GNUNET_GC_set_configuration_value_string(cfg,
+                                              ectx,
+                                              "MODULES",
+                                              "topology",
+                                              "topology_default");
+      GNUNET_GC_set_configuration_value_string(cfg,
+                                              ectx,
+                                              "F2F",
+                                              "FRIENDS-ONLY",
+                                              "YES");
+      if (GNUNET_OK == GNUNET_GC_write_configuration(cfg,
+                                                    cfgFilename))
+       fprintf(stdout,
+               "Updated F2F configuration options successfully.\n");
+      else
+       fprintf(stdout,
+               "Failed to write configuration with updated F2F 
configuration.\n");
+    }
+
   cron = cron_create (ectx);
   if (initCore (ectx, cfg, cron, NULL) != GNUNET_OK)
     {
@@ -201,6 +229,8 @@
       return;
     }
 
+  
+
   /* enforce filesystem limits */
   capFSQuotaSize (ectx, cfg);
 

Modified: GNUnet/todo
===================================================================
--- GNUnet/todo 2007-12-08 07:06:30 UTC (rev 5822)
+++ GNUnet/todo 2007-12-09 00:19:28 UTC (rev 5823)
@@ -3,17 +3,14 @@
 Annotations:
   RC == Release Critical
 
-0.7.3 [8'07] (aka "features"):
-- http transport needs more testing (still not 100% sure it is working)
-- fix strange crash-bug(s) in gnunetd and gnunet-setup
-- chat support basics [RC]
+0.7.3 [12'07] (aka "features"):
+- mysql implementation of dstore
 - Testcases:
   * more XFS/DHT
   * tracekit
   * RPC
-  * chat
 
-0.8.0 [12'07] (aka "advanced features"):
+0.8.0 [2'08] (aka "advanced features"):
 - gnunet-chat [ RC ]
 - Insert/Index a "shared directory" automatically [Nils]
   See also: https://gnunet.org/drupal/?q=node/97 [RC]
@@ -21,10 +18,7 @@
   a keyword of the document has been requested (so we would 
   add a special block to the datastore and then trigger
   gnunet-insert only if the file is actually needed!)
-- guard friendly connection count (#1018) [RC]
 - power insert [#854]
-- old/new features:
-  * SMTP transport (libesmtp)
 
 1.0.0 (aka "userfriendly"):
 - implement testbed for profiling
@@ -35,7 +29,6 @@
   as keyword (to allow getting meta-data from URI only) [RC]
 - support NAT-PMP (in addition to UPnP)
 - SMTP logger 
-- mysql implementation of dstore
 
 
 





reply via email to

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