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 8deb1ac99f23a32a85c275c22478f463298d9378..a1a8490b2dc76d5b7bd71570dcb5f1d0a59a7341 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
@@ -1339,10 +1339,10 @@ public class IndexBean {
                 // as of 0.9.17, add a random key if not previously present
                 byte[] rk = new byte[32];
                 _context.random().nextBytes(rk);
-                config.setProperty(OPT + p, Base64.encode(rk));
+                config.setProperty(p, Base64.encode(rk));
                 p = OPT + "outbound.randomKey";
                 _context.random().nextBytes(rk);
-                config.setProperty(OPT + p, Base64.encode(rk));
+                config.setProperty(p, Base64.encode(rk));
             }
         }
 
diff --git a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
index 96ba51e25b54a3141262dcfa57206d9cff0c5d41..15adf5955f6ac0d5cf8f047fd4068eeb57009b71 100644
--- a/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
+++ b/apps/routerconsole/java/src/net/i2p/router/news/NewsMetadata.java
@@ -41,7 +41,7 @@ public class NewsMetadata {
 
         @Override
         public int compareTo(Update other) {
-            return Integer.compare(getTypeOrder(), other.getTypeOrder());
+            return getTypeOrder() - other.getTypeOrder();
         }
 
         protected int getTypeOrder() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
index 3a40b8283a8eeb2e6a3c9e5eaa8c236686f4d852..f10d6858ff921d369674cf5625119a892c5c452b 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java
@@ -348,8 +348,11 @@ public class SummaryBarRenderer {
            .append(_helper.getReachability())
            .append("</a></h4>\n");
         if (!SigType.ECDSA_SHA256_P256.isAvailable()) {
-            buf.append("<hr>\n<h4><a href=\"/logs\" target=\"_top\" title=\"")
-               .append(_("See more information on the logs page"))
+            buf.append("<hr>\n<h4><a href=\"http://trac.i2p2.i2p/wiki/Crypto/ECDSA");
+            if ("ru".equals(Messages.getLanguage(_context)))
+                buf.append("-ru");
+            buf.append("\" target=\"_top\" title=\"")
+               .append(_("See more information on the wiki"))
                .append("\">")
                .append(_("Warning: ECDSA is not available. Update your Java or OS"))
                .append("</a></h4>\n");
diff --git a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
index 75aedae57883fe62db58f641ff1851695a188b94..7504072714e8e44d0c351543ffe342d1a27a4378 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMStreamSession.java
@@ -82,7 +82,7 @@ class SAMStreamSession {
      * Create a new SAM STREAM session.
      *
      * @param dest Base64-encoded destination and private keys (same format as PrivateKeyFile)
-     * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH")
+     * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") or "__v3__" if extended by SAMv3StreamSession
      * @param props Properties to setup the I2P session
      * @param recv Object that will receive incoming data
      * @throws IOException
@@ -98,7 +98,7 @@ class SAMStreamSession {
      * Create a new SAM STREAM session.
      *
      * @param destStream Input stream containing the destination and private keys (same format as PrivateKeyFile)
-     * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH")
+     * @param dir Session direction ("RECEIVE", "CREATE" or "BOTH") or "__v3__" if extended by SAMv3StreamSession
      * @param props Properties to setup the I2P session
      * @param recv Object that will receive incoming data
      * @throws IOException
@@ -111,15 +111,24 @@ class SAMStreamSession {
         _log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
 
         boolean canReceive;
+        boolean startAcceptor;
         if (dir.equals("BOTH")) {
             canCreate = true;
             canReceive = true;
+            startAcceptor = true;
+        } else if (dir.equals("__v3__")) {
+            // we are super to SAMv3StreamSession, don't start thread, he handles it
+            canCreate = true;
+            canReceive = true;
+            startAcceptor = false;
         } else if (dir.equals("CREATE")) {
             canCreate = true;
             canReceive = false;
+            startAcceptor = false;
         } else if (dir.equals("RECEIVE")) {
             canCreate = false;
             canReceive = true;
+            startAcceptor = true;
         } else {
             _log.error("BUG! Wrong direction passed to SAMStreamSession: "
                        + dir);
@@ -162,7 +171,7 @@ class SAMStreamSession {
         forceFlush = Boolean.parseBoolean(allprops.getProperty(PROP_FORCE_FLUSH, DEFAULT_FORCE_FLUSH));
         
 
-        if (canReceive) {
+        if (startAcceptor) {
             server = new SAMStreamSessionServer();
             Thread t = new I2PAppThread(server, "SAMStreamSessionServer");
 
diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java
index ef732200f5c7396529dc9a270345fdcdad212c5c..99854637e78bcee448c1ae9690ad880f4fdec854 100644
--- a/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java
+++ b/apps/sam/java/src/net/i2p/sam/SAMv3StreamSession.java
@@ -61,7 +61,7 @@ class SAMv3StreamSession  extends SAMStreamSession implements SAMv3Handler.Sessi
 	    public SAMv3StreamSession(String login)
 	    		throws IOException, DataFormatException, SAMException
 	    {
-                super(getDB().get(login).getDest(), "BOTH",
+                super(getDB().get(login).getDest(), "__v3__",
                       getDB().get(login).getProps(),
                       getDB().get(login).getHandler());
 	    	this.nick = login ;
diff --git a/build.properties b/build.properties
index 7479e174e12295bae10280777e66bdadd7a3476b..195a13c6b3721b3708cc2e6004351813b318ae20 100644
--- a/build.properties
+++ b/build.properties
@@ -11,7 +11,7 @@
 # Note: Include the trailing slash! Don't surround the URL in quotes!
 javasedocs.url=http://docs.oracle.com/javase/6/docs/api/
 javaeedocs.url=http://docs.oracle.com/javaee/6/api/
-jettydocs.url=http://download.eclipse.org/jetty/stable-7/apidocs/
+jettydocs.url=http://download.eclipse.org/jetty/stable-8/apidocs/
 jrobindocs.url=http://docs.i2p-projekt.de/jrobin/javadoc/
 wrapperdocs.url=http://wrapper.tanukisoftware.com/jdoc/
 # these are only for unit test javadocs
diff --git a/core/java/src/net/i2p/data/PrivateKeyFile.java b/core/java/src/net/i2p/data/PrivateKeyFile.java
index 42a26ef367f6beb8a95e42040ea5d5a88b654272..4e1a6d74a71124000f808026e9c71ebdadcbf8dc 100644
--- a/core/java/src/net/i2p/data/PrivateKeyFile.java
+++ b/core/java/src/net/i2p/data/PrivateKeyFile.java
@@ -169,9 +169,11 @@ public class PrivateKeyFile {
                 usage();
                 return;
             }
-            System.out.println(pkf);
-            pkf.write();
-            verifySignature(pkf.getDestination());
+            if (mode != 0) {
+                System.out.println(pkf);
+                pkf.write();
+                verifySignature(pkf.getDestination());
+            }
         } catch (Exception e) {
             e.printStackTrace();
             System.exit(1);
diff --git a/core/java/src/net/i2p/data/Signature.java b/core/java/src/net/i2p/data/Signature.java
index 1338cb664140607a2bfc2ee1b55cc0a4e9a77831..05d24e51dcee7c34d83d25787a84e6f7e7763b94 100644
--- a/core/java/src/net/i2p/data/Signature.java
+++ b/core/java/src/net/i2p/data/Signature.java
@@ -9,6 +9,8 @@ package net.i2p.data;
  *
  */
 
+import java.util.Arrays;
+
 import net.i2p.crypto.SigType;
 
 /**
@@ -102,4 +104,23 @@ public class Signature extends SimpleDataStructure {
         buf.append(']');
         return buf.toString();
     }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public int hashCode() {
+        return DataHelper.hashCode(_type) ^ super.hashCode();
+    }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (obj == null || !(obj instanceof Signature)) return false;
+        Signature s = (Signature) obj;
+        return _type == s._type && Arrays.equals(_data, s._data);
+    }
 }
diff --git a/core/java/src/net/i2p/data/SigningPrivateKey.java b/core/java/src/net/i2p/data/SigningPrivateKey.java
index 07b8969e3c5499746a4318928f80ecf74db16bb0..fcc9b2dc86b207e599779b430a48761e839a8cb1 100644
--- a/core/java/src/net/i2p/data/SigningPrivateKey.java
+++ b/core/java/src/net/i2p/data/SigningPrivateKey.java
@@ -9,6 +9,8 @@ package net.i2p.data;
  *
  */
 
+import java.util.Arrays;
+
 import net.i2p.crypto.KeyGenerator;
 import net.i2p.crypto.SigType;
 
@@ -104,4 +106,23 @@ public class SigningPrivateKey extends SimpleDataStructure {
         buf.append(']');
         return buf.toString();
     }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public int hashCode() {
+        return DataHelper.hashCode(_type) ^ super.hashCode();
+    }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (obj == null || !(obj instanceof SigningPrivateKey)) return false;
+        SigningPrivateKey s = (SigningPrivateKey) obj;
+        return _type == s._type && Arrays.equals(_data, s._data);
+    }
 }
diff --git a/core/java/src/net/i2p/data/SigningPublicKey.java b/core/java/src/net/i2p/data/SigningPublicKey.java
index 386deadac340b98ed2a2dc35456cf9198d041795..860985d4b13034366deff3c269bcc93eddf0f74a 100644
--- a/core/java/src/net/i2p/data/SigningPublicKey.java
+++ b/core/java/src/net/i2p/data/SigningPublicKey.java
@@ -12,6 +12,7 @@ package net.i2p.data;
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Arrays;
 
 import net.i2p.crypto.SigType;
 
@@ -113,7 +114,8 @@ public class SigningPublicKey extends SimpleDataStructure {
     }
 
     /**
-     *  Up-convert this from an untyped (type 0) SPK to a typed SPK based on the Key Cert given
+     *  Up-convert this from an untyped (type 0) SPK to a typed SPK based on the Key Cert given.
+     *  The type of the returned key will be null if the kcert sigtype is null.
      *
      *  @throws IllegalArgumentException if this is already typed to a different type
      *  @since 0.9.12
@@ -126,6 +128,9 @@ public class SigningPublicKey extends SimpleDataStructure {
             return this;
         if (_type != SigType.DSA_SHA1)
             throw new IllegalArgumentException("Cannot convert " + _type + " to " + newType);
+        // unknown type, keep the 128 bytes of data
+        if (newType == null)
+            return new SigningPublicKey(null, _data);
         int newLen = newType.getPubkeyLen();
         if (newLen == SigType.DSA_SHA1.getPubkeyLen())
             return new SigningPublicKey(newType, _data);
@@ -145,7 +150,7 @@ public class SigningPublicKey extends SimpleDataStructure {
      *  Get the portion of this (type 0) SPK that is really padding based on the Key Cert type given,
      *  if any
      *
-     *  @return leading padding length > 0 or null
+     *  @return leading padding length > 0 or null if no padding or type is unknown
      *  @throws IllegalArgumentException if this is already typed to a different type
      *  @since 0.9.12
      */
@@ -153,7 +158,7 @@ public class SigningPublicKey extends SimpleDataStructure {
         if (_data == null)
             throw new IllegalStateException();
         SigType newType = kcert.getSigType();
-        if (_type == newType)
+        if (_type == newType || newType == null)
             return null;
         if (_type != SigType.DSA_SHA1)
             throw new IllegalStateException("Cannot convert " + _type + " to " + newType);
@@ -200,4 +205,23 @@ public class SigningPublicKey extends SimpleDataStructure {
     public static void clearCache() {
         _cache.clear();
     }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public int hashCode() {
+        return DataHelper.hashCode(_type) ^ super.hashCode();
+    }
+
+    /**
+     *  @since 0.9.17
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (obj == null || !(obj instanceof SigningPublicKey)) return false;
+        SigningPublicKey s = (SigningPublicKey) obj;
+        return _type == s._type && Arrays.equals(_data, s._data);
+    }
 }
diff --git a/history.txt b/history.txt
index 32d82bf6be305aba6ab3c9e0acc104436e54d73e..ff226665e6bab0a3f2193cc32210574054e1435b 100644
--- a/history.txt
+++ b/history.txt
@@ -1,7 +1,30 @@
-2014-11-28 kytv
- * Updated PO files from Transifex
- * Updates to geoip.txt and geoipv6.dat.gz based on Maxmind GeoLite Country
-   database from 2014-11-05.
+2014-11-26 zzz
+ * BuildRequestor: Reduce delay when client build can't find
+   a paired tunnel (ticket #1412)
+ * Data:
+   - Fix NPE on unknown sig type in destination
+   - Fix hashcode and equals for typed data
+ * Tunnels: Disallow changing allowZeroHop setting for exploratory
+
+2014-11-24 zzz
+ * i2ptunnel: Fix automatic setting of random key
+ * PrivateKeyFile: Don't rewrite file in main() if no options
+
+2014-11-23 zzz
+ * Reseed hosts update
+
+2014-11-22 zzz
+ * PeerSelector: If non-DSA, don't use incompatible peers
+   for exploratory tunnels or closest-hop in client tunnels
+ * SAM: Fix v3 bug accepting incoming connections
+
+2014-11-17 zzz
+ * NetDB: Exclude A1/A2 "countries" from auto-floodfill
+
+2014-11-15 zzz
+ * I2NP:
+   - Set lookup type flags even if no reply tunnel specified
+   - Reduce object churn when writing some messages
 
 2014-11-13 zzz
  * I2PTunnel:
diff --git a/installer/resources/certificates/ssl/i2p.feared.eu.crt b/installer/resources/certificates/ssl/i2p.feared.eu.crt
deleted file mode 100644
index 628c6290ce352146dca054edd0f541d1f410a877..0000000000000000000000000000000000000000
--- a/installer/resources/certificates/ssl/i2p.feared.eu.crt
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDhTCCAm2gAwIBAgIJAPVgXcMcr3zqMA0GCSqGSIb3DQEBBQUAMFkxCzAJBgNV
-BAYTAkVVMQ8wDQYDVQQIDAZFdXJvcGUxDDAKBgNVBAoMA0kyUDETMBEGA1UECwwK
-T3V0cHJveGllczEWMBQGA1UEAwwNaTJwLmZlYXJlZC5ldTAeFw0xMjEwMjkxNzMw
-MDZaFw0yMTAxMTUxNzMwMDZaMFkxCzAJBgNVBAYTAkVVMQ8wDQYDVQQIDAZFdXJv
-cGUxDDAKBgNVBAoMA0kyUDETMBEGA1UECwwKT3V0cHJveGllczEWMBQGA1UEAwwN
-aTJwLmZlYXJlZC5ldTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOUh
-y2+6Q4RO+b5WPXX/cZ/9fiI7aWGe/C7z0083HOEqnkgGCYgxFWUCed6/eZbYoZ7/
-PV1BAuEereNwTp+Ov7fQB2H73O9sSAEejW6O4C2PZiZWaPxpZiTJNENbLOZxJnIN
-+fSqmA5pqvGkYAJ2heZH4v4tayun7Vib58GWuizhzJ4EvhOrOrLq/YHrxMn++r4e
-kNNbq4QzWpfxNa7ocDY9OJh5qFzuc+6wKj1m1syK6euDqs5d6X+y0aDTMgRxey2b
-tkmNx9wC0flLg1oMcv9o1zN+dENy7Inkd/SqbSjLUqDTJzdq6xURVsgLoV63pb6r
-B4gbGIlriYWK/mOPTTkCAwEAAaNQME4wHQYDVR0OBBYEFOI94JZ3Rb2RVmr8QjOp
-u3KfVSrNMB8GA1UdIwQYMBaAFOI94JZ3Rb2RVmr8QjOpu3KfVSrNMAwGA1UdEwQF
-MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAD7bI05zg9nf9qanq4ZNw/rvEzYQRBmy
-MqzZjcwBMGvbcEbS+zYAdAkfxmN3l/AT4I4z138Om0ud4ZJUQTVlRsJkMlmLD4Rt
-Jbi2rl7mrY7Qupgu5hvgH+ZaEWr7LTq+tFjPycRS+zijw9NToKeAsgEex9zYIOYD
-BxDUn/trvyA41ItvegWh803IsZUBb45Via+bopid9aFFkejRrck9hhcQ6fVh2yju
-nuVwHrxNvGc0NmmJ7zI+nPESFS+TAYbWXikDhc5Vtyiuoz47WZU1cgXYYMejK4WA
-+3GLvei7qKm4GOJSg7BngF5Iyj/n7ML1rBqTlN3KA1YOgpGCwJlKzto=
------END CERTIFICATE-----
diff --git a/installer/resources/certificates/ssl/ieb9oopo.mooo.com2.crt b/installer/resources/certificates/ssl/ieb9oopo.mooo.com2.crt
new file mode 100644
index 0000000000000000000000000000000000000000..8be9eef8ab9b811601b0bc23bbe22230276762c6
--- /dev/null
+++ b/installer/resources/certificates/ssl/ieb9oopo.mooo.com2.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIESzCCAzOgAwIBAgIJAKII1waVnWddMA0GCSqGSIb3DQEBCwUAMIG7MQswCQYD
+VQQGEwJERTEaMBgGA1UECAwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWll
+Yjlvb3BvLm1vb28uY29tMRowGAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgG
+A1UECwwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28u
+Y29tMSAwHgYJKoZIhvcNAQkBFhFpZWI5b29wby5tb29vLmNvbTAeFw0xNDExMjIx
+MzQzNThaFw0yMDA1MTQxMzQzNThaMIG7MQswCQYDVQQGEwJERTEaMBgGA1UECAwR
+aWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWllYjlvb3BvLm1vb28uY29tMRow
+GAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgGA1UECwwRaWViOW9vcG8ubW9v
+by5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28uY29tMSAwHgYJKoZIhvcNAQkB
+FhFpZWI5b29wby5tb29vLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMhcnkSifOMw5bd66UlvYVsc42H22Nuy64qhtJHtggofrwBooF38kRCBVFL8
+9Xjzr0xsSshvO6p7E+CEUtA8v55l5vNbUTAvGP9WmzeZyZuCFg9Heo3orNMbIK7m
+ppwKhwh6tFEIEpUTz/+xF5NRt0+CqcS4aNHuH3JPwNugfTBuSa86GeSaqL7K4eEZ
+bZXqQ16Onvi0yyMqRJDp/ijRFxr2eKGPWb55kuRSET9PxVhlgRKULZkr39Dh9q1c
+wb9lAMLMRZIzPVnyvC9jWkIqSDl5bkAAto0n1Jkw92rRp6EVKgSLA/4vl9wTb6xf
+WfT5cs7pykAE0WXBr9TqpS3okncCAwEAAaNQME4wHQYDVR0OBBYEFGeEOHhWiKwZ
+TGbc7uuK3DD7YjYZMB8GA1UdIwQYMBaAFGeEOHhWiKwZTGbc7uuK3DD7YjYZMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAzRA/0OpJtCO4kQkTn/hux9
+dRi9T6B54Xav5jG53iAPLTeMxsaLkvweh2pZ3kvEUrQhvW0JF8QBrHTsgxzb4Wd6
+FNDHSgJbZv3uCjFtWeuUh+GTG1k9uwgNIEnx7J9Vp0JCi4ezi/HMNI7c+LjinM9f
+hrAzclkeRPLYg645DkxckLyDUbrc9v1qWFoTpezXSBPO7n3Wk4sCytdoA1FkTdXh
+RF4BWCl/3uOxcrn0TqoC9vCh8RcxnllOiOO5j4+PQ1Z6NkQ/5oRCK/jjaWc3Lr6/
+FicOZJe29BVnrPGynqe0Ky1o+kTdXFflKowfr7g8dwn8k9YavjtGbl1ZSHeuMF8=
+-----END CERTIFICATE-----
diff --git a/installer/resources/certificates/ssl/link.mx24.eu.crt b/installer/resources/certificates/ssl/link.mx24.eu.crt
new file mode 100644
index 0000000000000000000000000000000000000000..8e0d910fc90ee1f859a29e13370b97c7f9f70413
--- /dev/null
+++ b/installer/resources/certificates/ssl/link.mx24.eu.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIJAMsPNG1k0yV4MA0GCSqGSIb3DQEBCwUAMIGdMQswCQYD
+VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14
+MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0
+LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu
+bXgyNC5ldTAeFw0xNDExMTkxOTE4NTRaFw0yMDA1MTExOTE4NTRaMIGdMQswCQYD
+VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14
+MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0
+LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu
+bXgyNC5ldTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL8modDBRkyh
+SHSm92pTfguO3F6n5ocsBJ4vaVoosYq3ILCsapjqmynMHZUef6gEB7+Gn5cKXsH2
+JaKOeb8DHrOFCaxfj187x1QfZj1UNMQblx2T9q4th12tqp+k4JuLwgemr+2uAUpM
+xx/uHRJXD0hf67+fHQFYNVfa+WvT46xlKGsWDQ0LBsA/z4YGnyeaV4PrS5nj3euA
+IbdfDj7rJea3bfhSqYA1ZH1cquKlsXOOYO5cIcXsa5dxDWX51QS+i7+ocph+JN1X
+dRh6ZirE9OXZVXwXXVRnJSYjgBlP/DQBdE7YkE1R3LyCVZsgxJaaLV/ujijOIK61
+SqEhHvFNRe0CAwEAAaNQME4wHQYDVR0OBBYEFB6XRz6VZlrAE+3xL6AyKrkq+y2X
+MB8GA1UdIwQYMBaAFB6XRz6VZlrAE+3xL6AyKrkq+y2XMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggEBADhxBA5GHisDVf5a+1hIi7FBGBjJJLqzlaKh+bFB
+gTCYfk3F4wYzndr1HpdCZSSYDtY3mXFNMWQCpwvwvy1DM+9AMRY68wKNXHa/WypW
+zQSqTfEH8cdaIXUALB7pdWFVr3rx0f7/8I0Gj/ByUbJ94rzd22vduX5riY0Rag6B
+dPtW0M9bJrC1AIjexzDcStupj9v/ceGYZQYC4zb2tZ7Ek/6q+vei8TxWZjku7Dl4
+YRPXXufyB24uQ1hJVy2fSyIJ63tIRJoEFLBNaKDOB53i10xLWBcsJpXKY57AOQMn
+flqW4HG8uGJ/o1WjhiOB9eI7T9toy08zNzt+kSI/blFIoek=
+-----END CERTIFICATE-----
diff --git a/installer/resources/deletelist.txt b/installer/resources/deletelist.txt
index 513bfe167fde6d870d634a4005de396a7399df32..c72a265158f0684253379f1550196eb9dbdb26e0 100644
--- a/installer/resources/deletelist.txt
+++ b/installer/resources/deletelist.txt
@@ -4,6 +4,7 @@ certificates/r31453.ovh.net
 certificates/75.145.125.59.crt
 certificates/forum.i2p2.de.crt
 certificates/cowpuncher.drollette.com.crt
+certificates/ssl/i2p.feared.eu.crt
 certificates/ssl/reseed.pkol.de.crt
 # old translated proxy error pages
 docs/ahelper-conflict-header_ar.ht
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index fecba78d6973d87e9930d631de787e05fec2a510..895e8eb464be3ab9a6a5d0345dcc893f337f4947 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,10 +18,10 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 7;
+    public final static long BUILD = 10;
 
     /** for example "-test" */
-    public final static String EXTRA = "";
+    public final static String EXTRA = "-rc";
     public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
     public static void main(String args[]) {
         System.out.println("I2P Router version: " + FULL_VERSION);
diff --git a/router/java/src/net/i2p/router/TunnelPoolSettings.java b/router/java/src/net/i2p/router/TunnelPoolSettings.java
index 481836d17eeb348e6faac8c648541630b7a27b1b..fd718e4799166d34e94c4a7442275bfafe8181ee 100644
--- a/router/java/src/net/i2p/router/TunnelPoolSettings.java
+++ b/router/java/src/net/i2p/router/TunnelPoolSettings.java
@@ -244,9 +244,10 @@ public class TunnelPoolSettings {
             String name = (String) e.getKey();
             String value = (String) e.getValue();
             if (name.startsWith(prefix)) {
-                if (name.equalsIgnoreCase(prefix + PROP_ALLOW_ZERO_HOP))
-                    _allowZeroHop = getBoolean(value, DEFAULT_ALLOW_ZERO_HOP);
-                else if (name.equalsIgnoreCase(prefix + PROP_BACKUP_QUANTITY))
+                if (name.equalsIgnoreCase(prefix + PROP_ALLOW_ZERO_HOP)) {
+                    if (!_isExploratory)
+                        _allowZeroHop = getBoolean(value, DEFAULT_ALLOW_ZERO_HOP);
+                } else if (name.equalsIgnoreCase(prefix + PROP_BACKUP_QUANTITY))
                     _backupQuantity = getInt(value, DEFAULT_BACKUP_QUANTITY);
                 //else if (name.equalsIgnoreCase(prefix + PROP_DURATION))
                 //    _duration = getInt(value, DEFAULT_DURATION);
diff --git a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
index b494a441cf1c876e5461d3b887e5458d1749888f..79338d8f697f63f60780d050d6e7cf910d6d1d81 100644
--- a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
+++ b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
@@ -70,9 +70,7 @@ public class Reseeder {
      *         URLs are constructed, and because SSLEepGet doesn't follow redirects.
      */
     public static final String DEFAULT_SEED_URL =
-              //http://netdb.i2p2.de/" + "," +
               "http://reseed.i2p-projekt.de/" + "," +
-             //"http://euve5653.vserver.de/netDb/" +  "," +
               "http://cowpuncher.drollette.com/netdb/" + "," +
               "http://i2p.mooo.com/netDb/" + "," +
               "http://193.150.121.66/netDb/" + "," +
@@ -83,14 +81,10 @@ public class Reseeder {
               "http://jp.reseed.i2p2.no/" + "," +
               "http://i2p-netdb.innovatio.no/" + "," +
               "http://ieb9oopo.mooo.com/";
-              // Temp disabled since h2ik have been AWOL since 06-03-2013
-              //"http://i2p.feared.eu/";
 
     /** @since 0.8.2 */
     public static final String DEFAULT_SSL_SEED_URL =
-              //"https://netdb.i2p2.de/" + "," +
               "https://reseed.i2p-projekt.de/" + "," +
-              //"https://euve5653.vserver.de/netDb/" + "," +
               "https://cowpuncher.drollette.com/netdb/" + "," +
               "https://i2p.mooo.com/netDb/" + "," +
               "https://193.150.121.66/netDb/" + "," +
@@ -101,9 +95,8 @@ public class Reseeder {
               "https://jp.reseed.i2p2.no:444/" + "," +
               "https://i2p-netdb.innovatio.no/" + "," +
               "https://ssl.webpack.de/ivae2he9.sg4.e-plaza.de/" + "," + // Only HTTPS and SU3 (v2) support
+              "https://link.mx24.eu/" + "," + // Only HTTPS and SU3 (v3) support
               "https://ieb9oopo.mooo.com/";
-              // Temp disabled since h2ik have been AWOL since 06-03-2013
-              //"https://i2p.feared.eu/";
 
     private static final String SU3_FILENAME = "i2pseeds.su3";
 
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
index 31aaa86654af300d55b77b5c90ce5160715e91cf..084a62c2365f85b6c6a1e71931991077ff3e4ef6 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
@@ -166,7 +166,10 @@ abstract class BuildRequestor {
             exec.buildComplete(cfg, pool);
             // Not even an exploratory tunnel? We are in big trouble.
             // Let's not spin through here too fast.
-            try { Thread.sleep(250); } catch (InterruptedException ie) {}
+            // But don't let a client tunnel waiting for exploratories slow things down too much,
+            // as there may be other tunnel pools who can build
+            int ms = pool.getSettings().isExploratory() ? 250 : 25;
+            try { Thread.sleep(ms); } catch (InterruptedException ie) {}
             return false;
         }
         
diff --git a/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java
index 2e13c4c57f6f0be10c2119b490065a293497b32c..126004c8569bd23d23a73ecc432c039eb5d68366 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java
@@ -36,6 +36,10 @@ class ClientPeerSelector extends TunnelPeerSelector {
             Set<Hash> exclude = getExclude(settings.isInbound(), false);
             Set<Hash> matches = new HashSet<Hash>(length);
             if (length == 1) {
+                // closest-hop restrictions
+                Set<Hash> moreExclude = getClosestHopExclude(settings.isInbound());
+                if (moreExclude != null)
+                    exclude.addAll(moreExclude);
                 ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
                 matches.remove(ctx.routerHash());
                 rv = new ArrayList<Hash>(matches);
@@ -46,10 +50,22 @@ class ClientPeerSelector extends TunnelPeerSelector {
                 rv = new ArrayList<Hash>(length + 1);
                 // OBEP or IB last hop
                 // group 0 or 1 if two hops, otherwise group 0
+                Set<Hash> firstHopExclude;
                 if (!settings.isInbound()) {
-                    // exclude existing OBEPs to get some diversity
+                    // exclude existing OBEPs to get some diversity ?
+
+                    // closest-hop restrictions
+                    Set<Hash> moreExclude = getClosestHopExclude(false);
+                    if (moreExclude != null) {
+                        moreExclude.addAll(exclude);
+                        firstHopExclude = moreExclude;
+                    } else {
+                        firstHopExclude = exclude;
+                    }
+                } else {
+                    firstHopExclude = exclude;
                 }
-                ctx.profileOrganizer().selectFastPeers(1, exclude, matches, settings.getRandomKey(), length == 2 ? 2 : 4);
+                ctx.profileOrganizer().selectFastPeers(1, firstHopExclude, matches, settings.getRandomKey(), length == 2 ? 2 : 4);
                 matches.remove(ctx.routerHash());
                 exclude.addAll(matches);
                 rv.addAll(matches);
@@ -73,7 +89,12 @@ class ClientPeerSelector extends TunnelPeerSelector {
                 // IBGW or OB first hop
                 // group 2 or 3 if two hops, otherwise group 1
                 if (settings.isInbound()) {
-                    // exclude existing IBGWs to get some diversity
+                    // exclude existing IBGWs to get some diversity ?
+
+                    // closest-hop restrictions
+                    Set<Hash> moreExclude = getClosestHopExclude(true);
+                    if (moreExclude != null)
+                        exclude.addAll(moreExclude);
                 }
                 ctx.profileOrganizer().selectFastPeers(1, exclude, matches, settings.getRandomKey(), length == 2 ? 3 : 5);
                 matches.remove(ctx.routerHash());
diff --git a/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java
index e0581c884347698dde0c87a80fd355ec4c128af7..68ad4e046f7939cf837350d92ecc8ed4130b8851 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java
@@ -42,6 +42,13 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
         
         Set<Hash> exclude = getExclude(settings.isInbound(), true);
         exclude.add(ctx.routerHash());
+        // closest-hop restrictions
+        // Since we're applying orderPeers() later, we don't know
+        // which will be the closest hop, so just appply to all peers for now.
+        Set<Hash> moreExclude = getClosestHopExclude(settings.isInbound());
+        if (moreExclude != null)
+            exclude.addAll(moreExclude);
+
         // Don't use ff peers for exploratory tunnels to lessen exposure to netDb searches and stores
         // Hmm if they don't get explored they don't get a speed/capacity rating
         // so they don't get used for client tunnels either.
diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java
index 8bb657831c2b2e112bb7ef086f564908bf514d1d..fa3f5e75d80df44dab204985b64056bdcf8819b0 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java
@@ -14,6 +14,7 @@ import java.util.StringTokenizer;
 
 import net.i2p.I2PAppContext;
 import net.i2p.crypto.SHA256Generator;
+import net.i2p.crypto.SigType;
 import net.i2p.data.DataFormatException;
 import net.i2p.data.Hash;
 import net.i2p.data.router.RouterInfo;
@@ -327,6 +328,40 @@ public abstract class TunnelPeerSelector {
         return peers;
     }
     
+    /** 
+     *  Pick peers that we want to avoid for the first OB hop or last IB hop.
+     *  This is only filled in if our router sig type is not DSA.
+     *
+     *  @param isInbound unused
+     *  @return null if none
+     *  @since 0.9.17
+     */
+    protected Set<Hash> getClosestHopExclude(boolean isInbound) {
+        RouterInfo ri = ctx.router().getRouterInfo();
+        if (ri == null)
+            return null;
+        SigType type = ri.getIdentity().getSigType();
+        if (type == SigType.DSA_SHA1)
+            return null;
+        Set<Hash> rv = new HashSet<Hash>(1024);
+        FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)ctx.netDb();
+        List<RouterInfo> known = fac.getKnownRouterData();
+        if (known != null) {
+            for (int i = 0; i < known.size(); i++) {
+                RouterInfo peer = known.get(i);
+                String v = peer.getOption("router.version");
+                if (v == null)
+                    continue;
+                // RI sigtypes added in 0.9.16
+                // SSU inbound connection bug fixed in 0.9.17, but it won't bid, so NTCP only,
+                // no need to check
+                if (VersionComparator.comp(v, "0.9.16") < 0)
+                    rv.add(peer.getIdentity().calculateHash());
+            }
+        }
+        return rv;
+    }
+    
     /** warning, this is also called by ProfileOrganizer.isSelectable() */
     public static boolean shouldExclude(RouterContext ctx, RouterInfo peer) {
         Log log = ctx.logManager().getLog(TunnelPeerSelector.class);