diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
index e8bda1a293e684f0f302d5be6770bf699425a5e4..e62bd25004d6e77ba6173878e40f45048723ec58 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java
@@ -8,12 +8,10 @@ package net.i2p.i2ptunnel.web;
  *
  */
 
-import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
-import java.util.Set;
 import java.util.StringTokenizer;
 
 import net.i2p.i2ptunnel.TunnelController;
@@ -107,15 +105,15 @@ public class EditBean extends IndexBean {
     }
     
     public boolean getReduce(int tunnel) {
-        return false;
+        return getBooleanProperty(tunnel, "i2cp.reduceOnIdle");
     }
     
     public int getReduceCount(int tunnel) {
-        return getProperty(tunnel, "inbound.reduceQuantity", 1);
+        return getProperty(tunnel, "i2cp.reduceQuantity", 1);
     }
     
     public int getReduceTime(int tunnel) {
-        return getProperty(tunnel, "reduceIdleTime", 20);
+        return getProperty(tunnel, "i2cp.reduceIdleTime", 20*60*1000) / (60*1000);
     }
     
     public int getCert(int tunnel) {
@@ -131,31 +129,31 @@ public class EditBean extends IndexBean {
     }
     
     public boolean getEncrypt(int tunnel) {
-        return false;
+        return getBooleanProperty(tunnel, "i2cp.encryptLeaseSet");
     }
     
     public String getEncryptKey(int tunnel) {
-        return getProperty(tunnel, "encryptKey", "");
+        return getProperty(tunnel, "i2cp.leaseSetKey", "");
     }
     
     public boolean getAccess(int tunnel) {
-        return false;
+        return getBooleanProperty(tunnel, "i2cp.enableAccessList");
     }
     
     public String getAccessList(int tunnel) {
-        return getProperty(tunnel, "accessList", "");
+        return getProperty(tunnel, "i2cp.accessList", "").replaceAll(",", "\n");
     }
     
     public boolean getClose(int tunnel) {
-        return false;
+        return getBooleanProperty(tunnel, "i2cp.closeOnIdle");
     }
     
     public int getCloseTime(int tunnel) {
-        return getProperty(tunnel, "closeIdleTime", 30);
+        return getProperty(tunnel, "i2cp.closeIdleTime", 30*60*1000) / (60*1000);
     }
     
     public boolean getNewDest(int tunnel) {
-        return false;
+        return getBooleanProperty(tunnel, "i2cp.newDestOnResume");
     }
     
     private int getProperty(int tunnel, String prop, int def) {
@@ -183,6 +181,17 @@ public class EditBean extends IndexBean {
         return def;
     }
     
+    /** default is false */
+    private boolean getBooleanProperty(int tunnel, String prop) {
+        TunnelController tun = getController(tunnel);
+        if (tun != null) {
+            Properties opts = getOptions(tun);
+            if (opts != null)
+                return Boolean.valueOf(opts.getProperty(prop)).booleanValue();
+        }
+        return false;
+    }
+    
     public String getI2CPHost(int tunnel) {
         TunnelController tun = getController(tunnel);
         if (tun != null)
@@ -199,14 +208,6 @@ public class EditBean extends IndexBean {
             return "7654";
     }
 
-    private static final String noShowProps[] = {
-        "inbound.length", "outbound.length", "inbound.lengthVariance", "outbound.lengthVariance",
-        "inbound.backupQuantity", "outbound.backupQuantity", "inbound.quantity", "outbound.quantity",
-        "inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize"
-        };
-    private static final Set noShowSet = new HashSet(noShowProps.length);
-    static { noShowSet.addAll(Arrays.asList(noShowProps)); }
-
     public String getCustomOptions(int tunnel) {
         TunnelController tun = getController(tunnel);
         if (tun != null) {
@@ -216,7 +217,7 @@ public class EditBean extends IndexBean {
             int i = 0;
             for (Iterator iter = opts.keySet().iterator(); iter.hasNext(); ) {
                 String key = (String)iter.next();
-                if (noShowSet.contains(key))
+                if (_noShowSet.contains(key))
                     continue;
                 String val = opts.getProperty(key);
                 if (i != 0) buf.append(' ');
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
index 1500150e3e6e4b6882f714f2b50b05072e71dc78..1aca37bf5321d9c1baf2a9b71f1452fe9a34536f 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
@@ -8,13 +8,19 @@ package net.i2p.i2ptunnel.web;
  *
  */
 
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.StringTokenizer;
 
 import net.i2p.I2PAppContext;
 import net.i2p.i2ptunnel.TunnelController;
 import net.i2p.i2ptunnel.TunnelControllerGroup;
+import net.i2p.util.ConcurrentHashSet;
 import net.i2p.util.Log;
 
 /**
@@ -57,6 +63,8 @@ public class IndexBean {
     private boolean _sharedClient;
     private boolean _privKeyGenerate;
     private boolean _removeConfirmed;
+    private Set<String> _booleanOptions;
+    private Map<String, String> _otherOptions;
     
     public static final int RUNNING = 1;
     public static final int STARTING = 2;
@@ -85,6 +93,8 @@ public class IndexBean {
         } catch (NumberFormatException nfe) {}
         _nextNonce = _context.random().nextLong();
         System.setProperty(PROP_NONCE, Long.toString(_nextNonce));
+        _booleanOptions = new ConcurrentHashSet(4);
+        _otherOptions = new ConcurrentHashMap(4);
     }
     
     public long getNextNonce() { return _nextNonce; }
@@ -326,6 +336,7 @@ public class IndexBean {
         return ( ("client".equals(type)) || 
         		("httpclient".equals(type)) ||
         		("sockstunnel".equals(type)) ||
+        		("connectclient".equals(type)) ||
         		("ircclient".equals(type)));
     }
     
@@ -360,6 +371,7 @@ public class IndexBean {
         else if ("server".equals(internalType)) return "Standard server";
         else if ("httpserver".equals(internalType)) return "HTTP server";
         else if ("sockstunnel".equals(internalType)) return "SOCKS proxy";
+        else if ("connectclient".equals(internalType)) return "CONNECT/SSL/HTTPS proxy";
         else return internalType;
     }
     
@@ -406,13 +418,12 @@ public class IndexBean {
     public String getClientDestination(int tunnel) {
         TunnelController tun = getController(tunnel);
         if (tun == null) return "";
-        if ("client".equals(tun.getType())||"ircclient".equals(tun.getType())) {
-            if (tun.getTargetDestination() != null)
-                return tun.getTargetDestination();
-            else
-                return "";
-        }
-        else return tun.getProxyList();
+        String rv;
+        if ("client".equals(tun.getType())||"ircclient".equals(tun.getType()))
+            rv = tun.getTargetDestination();
+        else
+            rv = tun.getProxyList();
+        return rv != null ? rv : "";
     }
     
     public String getServerTarget(int tunnel) {
@@ -429,11 +440,8 @@ public class IndexBean {
             String rv = tun.getMyDestination();
             if (rv != null)
                 return rv;
-            else
-                return "";
-        } else {
-            return "";
         }
+        return "";
     }
     
     public String getDestHashBase32(int tunnel) {
@@ -442,11 +450,8 @@ public class IndexBean {
             String rv = tun.getMyDestHashBase32();
             if (rv != null)
                 return rv;
-            else
-                return "";
-        } else {
-            return "";
         }
+        return "";
     }
     
     ///
@@ -568,6 +573,49 @@ public class IndexBean {
         _profile = profile; 
     }
 
+    public void setReduce(String moo) {
+        _booleanOptions.add("i2cp.reduceOnIdle");
+    }
+    public void setClose(String moo) {
+        _booleanOptions.add("i2cp.closeOnIdle");
+    }
+    public void setEncrypt(String moo) {
+        _booleanOptions.add("i2cp.encryptLeaseSet");
+    }
+    public void setAccess(String moo) {
+        _booleanOptions.add("i2cp.enableAccessList");
+    }
+    public void setNewDest(String moo) {
+        _booleanOptions.add("i2cp.newDestOnResume");
+    }
+
+    public void setReduceTime(String val) {
+        if (val != null) {
+            try {
+                _otherOptions.put("i2cp.reduceIdleTime", "" + (Integer.parseInt(val.trim()) * 60*1000));
+            } catch (NumberFormatException nfe) {}
+        }
+    }
+    public void setReduceCount(String val) {
+        if (val != null)
+            _otherOptions.put("i2cp.reduceQuantity", val.trim());
+    }
+    public void setEncryptKey(String val) {
+        if (val != null)
+            _otherOptions.put("i2cp.leaseSetKey", val.trim());
+    }
+    public void setAccessList(String val) {
+        if (val != null)
+            _otherOptions.put("i2cp.accessList", val.trim().replaceAll("\r\n", ",").replaceAll("\n", ",").replaceAll(" ", ","));
+    }
+    public void setCloseTime(String val) {
+        if (val != null) {
+            try {
+                _otherOptions.put("i2cp.closeIdleTime", "" + (Integer.parseInt(val.trim()) * 60*1000));
+            } catch (NumberFormatException nfe) {}
+        }
+    }
+
     /**
      * Based on all provided data, create a set of configuration parameters 
      * suitable for use in a TunnelController.  This will replace (not add to)
@@ -593,6 +641,11 @@ public class IndexBean {
                  config.setProperty("option.outbound.nickname", _name);
             }
             config.setProperty("sharedClient", _sharedClient + "");
+            for (String p : _booleanClientOpts)
+                config.setProperty("option." + p, "" + _booleanOptions.contains(p));
+            for (String p : _otherClientOpts)
+                if (_otherOptions.containsKey(p))
+                    config.setProperty("option." + p, _otherOptions.get(p));
         } else {
             // generic server stuff
             if (_targetHost != null)
@@ -601,9 +654,14 @@ public class IndexBean {
                 config.setProperty("targetPort", _targetPort);
             if (_privKeyFile != null)
                 config.setProperty("privKeyFile", _privKeyFile);
+            for (String p : _booleanServerOpts)
+                config.setProperty("option." + p, "" + _booleanOptions.contains(p));
+            for (String p : _otherServerOpts)
+                if (_otherOptions.containsKey(p))
+                    config.setProperty("option." + p, _otherOptions.get(p));
         }
 
-        if ("httpclient".equals(_type)) {
+        if ("httpclient".equals(_type) || "connectclient".equals(_type)) {
             if (_proxyList != null)
                 config.setProperty("proxyList", _proxyList);
         } else if ("ircclient".equals(_type) || "client".equals(_type)) {
@@ -617,6 +675,32 @@ public class IndexBean {
         return config;
     }
     
+    private static final String _noShowOpts[] = {
+        "inbound.length", "outbound.length", "inbound.lengthVariance", "outbound.lengthVariance",
+        "inbound.backupQuantity", "outbound.backupQuantity", "inbound.quantity", "outbound.quantity",
+        "inbound.nickname", "outbound.nickname", "i2p.streaming.connectDelay", "i2p.streaming.maxWindowSize"
+        };
+    private static final String _booleanClientOpts[] = {
+        "i2cp.reduceOnIdle", "i2cp.closeOnIdle", "i2cp.newDestOnResume"
+        };
+    private static final String _booleanServerOpts[] = {
+        "i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", "i2cp.enableAccessList"
+        };
+    private static final String _otherClientOpts[] = {
+        "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime"
+        };
+    private static final String _otherServerOpts[] = {
+        "i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList"
+        };
+    protected static final Set _noShowSet = new HashSet();
+    static {
+        _noShowSet.addAll(Arrays.asList(_noShowOpts));
+        _noShowSet.addAll(Arrays.asList(_booleanClientOpts));
+        _noShowSet.addAll(Arrays.asList(_booleanServerOpts));
+        _noShowSet.addAll(Arrays.asList(_otherClientOpts));
+        _noShowSet.addAll(Arrays.asList(_otherServerOpts));
+    }
+
     private void updateConfigGeneric(Properties config) {
         config.setProperty("type", _type);
         if (_name != null)
@@ -639,19 +723,9 @@ public class IndexBean {
                 if ( (eq <= 0) || (eq >= pair.length()) )
                     continue;
                 String key = pair.substring(0, eq);
+                if (_noShowSet.contains(key))
+                    continue;
                 String val = pair.substring(eq+1);
-                if ("inbound.length".equals(key)) continue;
-                if ("outbound.length".equals(key)) continue;
-                if ("inbound.quantity".equals(key)) continue;
-                if ("outbound.quantity".equals(key)) continue;
-                if ("inbound.lengthVariance".equals(key)) continue;
-                if ("outbound.lengthVariance".equals(key)) continue;
-                if ("inbound.backupQuantity".equals(key)) continue;
-                if ("outbound.backupQuantity".equals(key)) continue;
-                if ("inbound.nickname".equals(key)) continue;
-                if ("outbound.nickname".equals(key)) continue;
-                if ("i2p.streaming.connectDelay".equals(key)) continue;
-                if ("i2p.streaming.maxWindowSize".equals(key)) continue;
                 config.setProperty("option." + key, val);
             }
         }
@@ -679,14 +753,14 @@ public class IndexBean {
         else
             config.setProperty("option.i2p.streaming.connectDelay", "0");
         if (_name != null) {
-            if ( ((!"client".equals(_type)) && (!"httpclient".equals(_type))&& (!"ircclient".equals(_type))) || (!_sharedClient) ) {
+            if ( (!isClient(_type)) || (!_sharedClient) ) {
                 config.setProperty("option.inbound.nickname", _name);
                 config.setProperty("option.outbound.nickname", _name);
             } else {
                 config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
                 config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
             }
-        } 
+        }
         if ("interactive".equals(_profile))
             // This was 1 which doesn't make much sense
             // The real way to make it interactive is to make the streaming lib
diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp
index f5e1fac7f82d6e8451d816c8c6ce699e01a97d1d..3e4c3ecd80f88a991073b2c550541ec7675bca14 100644
--- a/apps/i2ptunnel/jsp/editClient.jsp
+++ b/apps/i2ptunnel/jsp/editClient.jsp
@@ -116,7 +116,7 @@
                 <hr />
             </div>
            
-            <% if ("httpclient".equals(tunnelType)) {
+            <% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType)) {
           %><div id="destinationField" class="rowItem">
                 <label for="proxyList" accesskey="x">
                     Outpro<span class="accessKey">x</span>ies:
@@ -344,6 +344,7 @@
                     <input type="hidden" value="true" name="removeConfirm" />
                     <button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
                     <button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
+                    <button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel">Cancel</button>
                 </div>
             </div> 
         </div>
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp
index e6cc0497d7d3219331a443260e4c12d301cf29b1..5968486178375b1288ef449837ce3f41d5141ffb 100644
--- a/apps/i2ptunnel/jsp/editServer.jsp
+++ b/apps/i2ptunnel/jsp/editServer.jsp
@@ -281,7 +281,7 @@
                 <label for="accessList" accesskey="s">
                     Access List:
                 </label>
-                <textarea rows="2" cols="60" id="hostField" title="Access List" wrap="off"><%=editBean.getAccessList(curTunnel)%></textarea>               
+                <textarea rows="2" cols="60" id="hostField" name="accessList" title="Access List" wrap="off"><%=editBean.getAccessList(curTunnel)%></textarea>               
                 <span class="comment">(Restrict to these clients only)</span>
             </div>
                  
@@ -385,6 +385,7 @@
                     <input type="hidden" value="true" name="removeConfirm" />
                     <button id="controlSave" accesskey="S" class="control" type="submit" name="action" value="Save changes" title="Save Changes"><span class="accessKey">S</span>ave</button>
                     <button id="controlDelete" <%=(editBean.allowJS() ? "onclick=\"if (!confirm('Are you sure you want to delete?')) { return false; }\" " : "")%>accesskey="D" class="control" type="submit" name="action" value="Delete this proxy" title="Delete this Proxy"><span class="accessKey">D</span>elete</button>
+                    <button id="controlCancel" class="control" type="submit" name="action" value="" title="Cancel">Cancel</button>
                 </div>
             </div> 
         </div>
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 0825493073c731d37d6b568fc6609e9258f21986..a06177dd470d0fe18b340ea24871144d93fcd61f 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -114,7 +114,13 @@
 
       <% if (!"sockstunnel".equals(indexBean.getInternalType(curClient))) { %>
         <div class="destinationField rowItem">
-            <label>Destination:</label>
+            <label>
+            <% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient))) { %>
+                Outproxy:
+            <% } else { %>
+                Destination:
+            <% } %>
+            </label>
             <input class="freetext" size="40" readonly="readonly" value="<%=indexBean.getClientDestination(curClient)%>" />
         </div>
       <% } %>
@@ -143,6 +149,7 @@
                         <option value="httpclient">HTTP</option>
                         <option value="ircclient">IRC</option>
                         <option value="sockstunnel">SOCKS</option>
+                        <option value="connectclient">CONNECT</option>
                     </select>
                     <input class="control" type="submit" value="Create" />
                 </div>
@@ -162,10 +169,10 @@
         <div class="nameHeaderField rowItem">
             <label>Name:</label>
         </div>
-        <div class="targetHeaderField rowItem">
+        <div class="previewHeaderField rowItem">
             <label>Points at:</label>
         </div>
-        <div class="previewHeaderField rowItem">
+        <div class="targetHeaderField rowItem">
             <label>Preview:</label>
         </div>
         <div class="statusHeaderField rowItem">
@@ -181,7 +188,7 @@
             <label>Name:</label>
             <span class="text"><a href="edit.jsp?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
         </div>
-        <div class="targetField rowItem">
+        <div class="previewField rowItem">
             <label>Points at:</label>
             <span class="text">
         <%
@@ -195,11 +202,14 @@
             }
           %></span>
         </div>
-        <div class="previewField rowItem">
+        <div class="targetField rowItem">
             <%
             if ("httpserver".equals(indexBean.getInternalType(curServer)) && indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
           %><label>Preview:</label>    
             <a class="control" title="Test HTTP server through I2P" href="http://<%=indexBean.getDestHashBase32(curServer)%>.b32.i2p">Preview</a>     
+            <%
+            } else if (indexBean.getTunnelStatus(curServer) == IndexBean.RUNNING) {
+          %><span class="text">Base32 Address:<br><%=indexBean.getDestHashBase32(curServer)%>.b32.i2p</span>
         <%
             } else {
           %><span class="comment">No Preview</span>
diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java
index 2c8582a4f8272106a9dbf1294ba4d1619050d55e..b5f4e8ab3bf30af02355969fd08e7e35860eb48a 100644
--- a/core/java/src/net/i2p/client/I2PSessionImpl.java
+++ b/core/java/src/net/i2p/client/I2PSessionImpl.java
@@ -442,8 +442,8 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
                             long before = System.currentTimeMillis();
                             _sessionListener.messageAvailable(I2PSessionImpl.this, msgId.intValue(), size.intValue());
                             long duration = System.currentTimeMillis() - before;
-                            if ((duration > 100) && _log.shouldLog(Log.WARN)) 
-                                _log.warn("Message availability notification for " + msgId.intValue() + " took " 
+                            if ((duration > 100) && _log.shouldLog(Log.INFO)) 
+                                _log.info("Message availability notification for " + msgId.intValue() + " took " 
                                            + duration + " to " + _sessionListener);
                         } catch (Exception e) {
                             _log.log(Log.CRIT, "Error notifying app of message availability", e);
@@ -678,6 +678,8 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
         _lastActivity = _context.clock().now();
         if (_isReduced) {
             _isReduced = false;
+            if (_log.shouldLog(Log.WARN)) 
+                _log.warn(getPrefix() + "Restoring original tunnel quantity");
             try {
                 _producer.updateTunnels(this, 0);
             } catch (I2PSessionException ise) {
diff --git a/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java b/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
index 6163771e366c90d6cd68b45fe838f15707485202..7a8bd200e1009df5c638fc7e4baa03f911052711 100644
--- a/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
+++ b/core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java
@@ -79,15 +79,16 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
 
         leaseSet.setEncryptionKey(li.getPublicKey());
         leaseSet.setSigningKey(li.getSigningPublicKey());
-        String sk = session.getOptions().getProperty("i2cp.sessionKey");
-        if (sk != null) {
+        boolean encrypt = Boolean.valueOf(session.getOptions().getProperty("i2cp.encryptLeaseset")).booleanValue();
+        String sk = session.getOptions().getProperty("i2cp.leaseSetKey");
+        if (encrypt && sk != null) {
             SessionKey key = new SessionKey();
             try {
                 key.fromBase64(sk);
                 leaseSet.encrypt(key);
                 _context.keyRing().put(session.getMyDestination().calculateHash(), key);
             } catch (DataFormatException dfe) {
-                _log.error("Bad session key: " + sk);
+                _log.error("Bad leaseset key: " + sk);
             }
         }
         try {
diff --git a/core/java/src/net/i2p/client/SessionIdleTimer.java b/core/java/src/net/i2p/client/SessionIdleTimer.java
index 1babd9551c5a179eac030b8dabedd4e836b608e3..354a2b6334f36e823c876db460be4fb5770a6e94 100644
--- a/core/java/src/net/i2p/client/SessionIdleTimer.java
+++ b/core/java/src/net/i2p/client/SessionIdleTimer.java
@@ -31,6 +31,7 @@ public class SessionIdleTimer implements SimpleTimer.TimedEvent {
     private boolean _shutdownEnabled;
     private long _shutdownTime;
     private long _minimumTime;
+    private long _lastActive;
 
     /**
      *  reduce, shutdown, or both must be true
@@ -44,6 +45,7 @@ public class SessionIdleTimer implements SimpleTimer.TimedEvent {
             throw new IllegalArgumentException("At least one must be enabled");
         Properties props = session.getOptions();
         _minimumTime = Long.MAX_VALUE;
+        _lastActive = 0;
         if (reduce) {
             _reduceQuantity = 1;
             String p = props.getProperty("i2cp.reduceQuantity");
@@ -83,10 +85,16 @@ public class SessionIdleTimer implements SimpleTimer.TimedEvent {
         long lastActivity = _session.lastActivity();
         if (_log.shouldLog(Log.INFO))
             _log.info("Fire idle timer, last activity: " + DataHelper.formatDuration(now - lastActivity) + " ago ");
+        long nextDelay = 0;
         if (_shutdownEnabled && now - lastActivity >= _shutdownTime) {
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Closing on idle " + _session);
             _session.destroySession();
+            return;
+        } else if (lastActivity <= _lastActive && !_shutdownEnabled) {
+            if (_log.shouldLog(Log.WARN))
+                _log.warn("Still idle, sleeping again " + _session);
+            nextDelay = _reduceTime;
         } else if (_reduceEnabled && now - lastActivity >= _reduceTime) {
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Reducing quantity on idle " + _session);
@@ -96,11 +104,14 @@ public class SessionIdleTimer implements SimpleTimer.TimedEvent {
                 _log.error("bork idle reduction " + ise);
             }
             _session.setReduced();
+            _lastActive = lastActivity;
             if (_shutdownEnabled)
-                SimpleScheduler.getInstance().addEvent(this, _shutdownTime - (now - lastActivity));
-            // else sessionimpl must reschedule??
+                nextDelay =  _shutdownTime - (now - lastActivity);
+            else
+                nextDelay =  _reduceTime;
         } else {
-            SimpleScheduler.getInstance().addEvent(this, _minimumTime - (now - lastActivity));
+            nextDelay = _minimumTime - (now - lastActivity);
         }
+        SimpleScheduler.getInstance().addEvent(this, nextDelay);
     }
 }
diff --git a/core/java/src/net/i2p/data/i2cp/I2CPMessageHandler.java b/core/java/src/net/i2p/data/i2cp/I2CPMessageHandler.java
index 294059bdbedab7c164f18b79c02f105900e02fa2..61d86505344d1c201d24597edb35e98d09c07c8c 100644
--- a/core/java/src/net/i2p/data/i2cp/I2CPMessageHandler.java
+++ b/core/java/src/net/i2p/data/i2cp/I2CPMessageHandler.java
@@ -34,8 +34,13 @@ public class I2CPMessageHandler {
      *          message - if it is an unknown type or has improper formatting, etc.
      */
     public static I2CPMessage readMessage(InputStream in) throws IOException, I2CPMessageException {
+        int length = -1;
+        try {
+            length = (int) DataHelper.readLong(in, 4);
+        } catch (DataFormatException dfe) {
+            throw new IOException("Connection closed");
+        }
         try {
-            int length = (int) DataHelper.readLong(in, 4);
             if (length < 0) throw new I2CPMessageException("Invalid message length specified");
             int type = (int) DataHelper.readLong(in, 1);
             I2CPMessage msg = createMessage(in, length, type);
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
index c6b1f5b9a9925e356e0ac713e6e3bea14780d7d5..58637ce63a1c50d981f1b9862548e1572cf47c01 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
@@ -237,22 +237,20 @@ public class TunnelPoolManager implements TunnelManagerFacade {
             return null;
     }
     public void setInboundSettings(Hash client, TunnelPoolSettings settings) {
-        
-        TunnelPool pool = null;
-        synchronized (_clientInboundPools) { 
-            pool = (TunnelPool)_clientInboundPools.get(client); 
-        }
-        if (pool != null)
-            pool.setSettings(settings);
+        setSettings(_clientInboundPools, client, settings);
     }
     public void setOutboundSettings(Hash client, TunnelPoolSettings settings) {
-        
+        setSettings(_clientOutboundPools, client, settings);
+    }
+    private void setSettings(Map pools, Hash client, TunnelPoolSettings settings) {
         TunnelPool pool = null;
-        synchronized (_clientOutboundPools) { 
-            pool = (TunnelPool)_clientOutboundPools.get(client); 
+        synchronized (pools) { 
+            pool = (TunnelPool)pools.get(client); 
         }
-        if (pool != null)
+        if (pool != null) {
+            settings.setDestination(client); // prevent spoofing or unset dest
             pool.setSettings(settings);
+        }
     }
     
     public void restart() {