Compare commits

...

20 Commits

Author SHA1 Message Date
zzz
2f7fe96d67 bump -2 2024-08-16 07:43:29 -04:00
zzz
73a9bf87f2 Merge branch '487-ls2' into 'master'
NetDB, I2CP: Fix tunnels going yellow for several minutes (Gitlab #487)

Closes #487

See merge request i2p-hackers/i2p.i2p!211
2024-08-16 11:15:15 +00:00
zzz
fc728c468e NetDB, I2CP: Fix tunnels going yellow for several minutes (Gitlab #487) 2024-08-16 11:15:15 +00:00
zzz
5692890239 Remove old plugin cert 2024-08-12 17:29:40 -04:00
zzz
32d21e5e88 Merge branch 'temp-scanner' into 'master'
Util: New temp dir timestamper

See merge request i2p-hackers/i2p.i2p!210
2024-08-12 11:46:06 +00:00
zzz
f2908b8bc4 Util: New temp dir timestamper 2024-08-12 11:46:06 +00:00
zzz
8d4ddd0f17 NetDB: Don't expire entries in test mode
Don't immediately expire entries for Android
2024-08-11 10:42:57 -04:00
zzz
2285e7ce2f Tunnels: Minor cleanup 2024-08-10 08:16:41 -04:00
zzz
2d516512a9 bump -1 2024-08-09 10:01:42 -04:00
zzz
eec09d4c9c i2psnark: Reduce minimum bandwidth, reduce max connections if low bandwidth
per user request
2024-08-09 09:59:57 -04:00
zzz
41f678b926 Util: Reduce number of PRNG output buffers
Random is either fast enough or it isn't.
2024-08-09 09:54:40 -04:00
zzz
934e4e9cdb javadoc notes 2024-08-09 09:47:57 -04:00
zzz
d35faf032b Data: Consolidate toBase32() code 2024-08-09 09:45:55 -04:00
zzz
a8dbc29dcf Tunnels: Do not select ElG routers for tunnels 2024-08-09 09:42:18 -04:00
zzz
46e429cd49 susimail: Fix searches for multiple terms
by decoding and trimming search param,
and stripping empty fields after split()
2024-08-09 09:40:15 -04:00
zzz
5a3a7b24af i2psnark, susimail: Normailze strings when searching (Gitlab #488)
to improve search for non-ASCII strings.
Normalize both search and searched strings to NFKD when searching.
NFKD is best because it is more efficient than NFKC and it removes
formatting distinctions. This results in the best fuzzy matching.
2024-08-09 09:37:50 -04:00
zzz
181d5da2e2 checklist update 2024-08-08 16:21:34 -04:00
c969274866 check in and update Debian changelogs 2024-08-08 13:30:38 -04:00
903d69eb01 Debian: re-align 0002-jetty-old-api.patch 2024-08-06 21:59:31 -04:00
20df8779bd Router: version 2.6.1 2024-08-06 21:43:27 -04:00
38 changed files with 349 additions and 116 deletions

View File

@ -614,20 +614,18 @@ class PeerCoordinator implements PeerListener, BandwidthListener
if (metainfo == null)
return 6;
int pieces = metainfo.getPieces();
if (pieces <= 10)
return 4;
if (pieces <= 25)
return 10;
if (pieces <= 80)
return 16;
//int size = metainfo.getPieceLength(0);
int max = _util.getMaxConnections();
// Now that we use temp files, no memory concern
//if (size <= 512*1024 || completed())
return max;
//if (size <= 1024*1024)
// return (max + max + 2) / 3;
//return (max + 2) / 3;
if (pieces <= 10) {
if (max > 4) max = 4;
} else if (pieces <= 25) {
if (max > 10) max = 10;
} else if (pieces <= 80) {
if (max > 16) max = 16;
}
long bwl = getDownBWLimit();
if (bwl < 32*1024)
max = Math.min(max, Math.max(6, (int) (I2PSnarkUtil.MAX_CONNECTIONS * bwl / (32*1024))));
return max;
}
public boolean halted() { return halted; }

View File

@ -170,7 +170,7 @@ public class SnarkManager implements CompleteListener, ClientApp, DisconnectList
/** @since 0.9.58 */
public static final String PROP_MAX_FILES_PER_TORRENT = "i2psnark.maxFilesPerTorrent";
public static final int MIN_UP_BW = 10;
public static final int MIN_UP_BW = 5;
public static final int MIN_DOWN_BW = 2 * MIN_UP_BW;
public static final int DEFAULT_MAX_UP_BW = 25;
private static final int DEFAULT_MAX_DOWN_BW = 200;

View File

@ -13,6 +13,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.text.Collator;
import java.text.DecimalFormat;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -875,14 +876,14 @@ public class I2PSnarkServlet extends BasicServlet {
if (term.length() > 0) {
if (searchList == null)
searchList = new ArrayList<String>(4);
searchList.add(term.toLowerCase(Locale.US));
searchList.add(Normalizer.normalize(term.toLowerCase(Locale.US), Normalizer.Form.NFKD));
}
}
if (searchList == null)
return null;
List<Snark> matches = new ArrayList<Snark>(32);
for (Snark snark : snarks) {
String lcname = snark.getBaseName().toLowerCase(Locale.US);
String lcname = Normalizer.normalize(snark.getBaseName().toLowerCase(Locale.US), Normalizer.Form.NFKD);
// search for any term (OR)
for (int j = 0; j < searchList.size(); j++) {
String term = searchList.get(j);

View File

@ -260,6 +260,8 @@ class Packet {
* List of packet sequence numbers below the getAckThrough() value
* have not been received. this may be null.
*
* Warning: This is different than getNACKs() in PacketLocal
*
* @return List of packet sequence numbers not ACKed, or null if there are none.
*/
public long[] getNacks() { return _nacks; }

View File

@ -209,6 +209,11 @@ class PacketLocal extends Packet implements MessageOutputStream.WriteStatus {
}
}
/**
* Warning: This is different than getNacks() in super
*
* @return Number of times this packet has been nacked
*/
public int getNACKs() { return _nackCount.get(); }
/**

View File

@ -62,6 +62,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.Collator;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@ -2571,6 +2572,8 @@ public class WebMail extends HttpServlet
}
response.setContentType("text/html");
String search = httpRequest.getParameter(SEARCH);
if (search != null && search.length() > 0)
search = decodePath(search).trim();
if (_log.shouldDebug()) _log.debug("XHR1 search=" + search);
if (search != null && search.length() > 0) {
Folder.Selector olds = folder.getCurrentSelector();
@ -2587,6 +2590,8 @@ public class WebMail extends HttpServlet
return;
}
String search = httpRequest.getParameter(SEARCH);
if (search != null && search.length() > 0)
search = decodePath(search).trim();
if (_log.shouldDebug()) _log.debug("XHR2 search=" + search);
if (search != null && search.length() > 0) {
Folder.Selector olds = folder.getCurrentSelector();
@ -2829,6 +2834,21 @@ public class WebMail extends HttpServlet
} // synch sessionObject
}
/**
* Simple version of URIUtil.decodePath()
* Adapted from I2PSnark BasicServlet
* @since 0.9.63
*/
private static String decodePath(String path) {
if (path.indexOf('%') >= 0) {
try {
URI uri = new URI(path);
return uri.getPath();
} catch (URISyntaxException use) {}
}
return path;
}
/**
* Redirect a POST to a GET (P-R-G), replacing the query string
* @param q starting with '?' or null
@ -3838,7 +3858,7 @@ public class WebMail extends HttpServlet
private static class SearchSelector implements Folder.Selector<String> {
private final String key;
private final MailCache mc;
private final String[] terms;
private final List<String> terms;
private final boolean isDrafts;
/**
@ -3848,10 +3868,11 @@ public class WebMail extends HttpServlet
mc = cache;
isDrafts = mc.getFolderName().equals(DIR_DRAFTS);
key = search;
terms = DataHelper.split(search, " ");
// decode
for (int i = 0; i < terms.length; i++) {
terms[i] = terms[i].toLowerCase(Locale.US);
String[] tms = DataHelper.split(search, " ");
terms = new ArrayList<String>(4);
for (int i = 0; i < tms.length; i++) {
if (tms[i].length() > 0)
terms.add(Normalizer.normalize(tms[i].toLowerCase(Locale.US), Normalizer.Form.NFKD));
}
}
@ -3863,10 +3884,10 @@ public class WebMail extends HttpServlet
Mail mail = mc.getMail(uidl, MailCache.FetchMode.HEADER_CACHE_ONLY);
if (mail == null)
return false;
String subj = mail.subject.toLowerCase(Locale.US);
String subj = Normalizer.normalize(mail.subject.toLowerCase(Locale.US), Normalizer.Form.NFKD);
String sender = isDrafts ? null : mail.sender;
if (sender != null)
sender = sender.toLowerCase(Locale.US);
sender = Normalizer.normalize(sender.toLowerCase(Locale.US), Normalizer.Form.NFKD);
String[] to = isDrafts ? mail.to : null;
for (String term : terms) {
if (subj.contains(term))
@ -3875,7 +3896,7 @@ public class WebMail extends HttpServlet
return true;
if (to != null) {
for (int i = 0; i < to.length; i++) {
if (to[i].toLowerCase(Locale.US).contains(term))
if (Normalizer.normalize(to[i].toLowerCase(Locale.US), Normalizer.Form.NFKD).contains(term))
return true;
}
}

View File

@ -31,7 +31,7 @@ public class CoreVersion {
* Otherwise, the same as PUBLISHED_VERSION.
* RouterVersion.FULL_VERSION is suggested for display to the user.
*/
public final static String VERSION = "2.6.0";
public final static String VERSION = "2.6.1";
/**
* The version published in the netdb via StatisticsManager.

View File

@ -36,6 +36,7 @@ import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.SystemVersion;
import net.i2p.util.TempDirScanner;
import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
@ -436,6 +437,8 @@ public class I2PAppContext {
// good or bad ? loop and try again?
} else if (_tmpDir.mkdir()) {
_tmpDir.deleteOnExit();
if (!SystemVersion.isWindows() && !SystemVersion.isMac() && !SystemVersion.isAndroid())
new TempDirScanner(this);
} else {
System.err.println("WARNING: Could not create temp dir " + _tmpDir.getAbsolutePath());
_tmpDir = new SecureDirectory(_routerDir, "tmp");

View File

@ -105,6 +105,7 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
private long _offlineExpiration;
private Signature _offlineSignature;
protected SigningPublicKey _transientSigningPublicKey;
private long _lastLS2SignTime;
// subsession stuff
// registered subsessions
@ -1185,6 +1186,21 @@ public abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2
SessionId getSessionId() { return _sessionId; }
void setSessionId(SessionId id) { _sessionId = id; }
/**
* The published timestamp of the last LS2 we signed
*
* @return 0 if never
* @since 0.9.64
*/
long getLastLS2SignTime() { return _lastLS2SignTime; };
/**
* The published timestamp of the last LS2 we signed
*
* @since 0.9.64
*/
void setLastLS2SignTime(long now) { _lastLS2SignTime = now; };
/** configure the listener */
public void setSessionListener(I2PSessionListener lsnr) { _sessionListener = lsnr; }

View File

@ -130,19 +130,25 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
boolean isLS2 = requiresLS2(session);
LeaseSet leaseSet;
if (isLS2) {
LeaseSet2 ls2;
if (_ls2Type == DatabaseEntry.KEY_TYPE_LS2) {
leaseSet = new LeaseSet2();
ls2 = new LeaseSet2();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
leaseSet = new EncryptedLeaseSet();
ls2 = new EncryptedLeaseSet();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_META_LS2) {
leaseSet = new MetaLeaseSet();
ls2= new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
if (Boolean.parseBoolean(session.getOptions().getProperty("i2cp.dontPublishLeaseSet")))
((LeaseSet2)leaseSet).setUnpublished();
ls2.setUnpublished();
// ensure 1-second resolution timestamp is higher than last one
long now = Math.max(_context.clock().now(), session.getLastLS2SignTime() + 1000);
ls2.setPublished(now);
session.setLastLS2SignTime(now);
leaseSet = ls2;
} else {
leaseSet = new LeaseSet();
}

View File

@ -42,19 +42,25 @@ class RequestVariableLeaseSetMessageHandler extends RequestLeaseSetMessageHandle
boolean isLS2 = requiresLS2(session);
LeaseSet leaseSet;
if (isLS2) {
LeaseSet2 ls2;
if (_ls2Type == DatabaseEntry.KEY_TYPE_LS2) {
leaseSet = new LeaseSet2();
ls2 = new LeaseSet2();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
leaseSet = new EncryptedLeaseSet();
ls2 = new EncryptedLeaseSet();
} else if (_ls2Type == DatabaseEntry.KEY_TYPE_META_LS2) {
leaseSet = new MetaLeaseSet();
ls2 = new MetaLeaseSet();
} else {
session.propogateError("Unsupported LS2 type", new Exception());
session.destroySession();
return;
}
if (Boolean.parseBoolean(session.getOptions().getProperty("i2cp.dontPublishLeaseSet")))
((LeaseSet2)leaseSet).setUnpublished();
ls2.setUnpublished();
// ensure 1-second resolution timestamp is higher than last one
long now = Math.max(_context.clock().now(), session.getLastLS2SignTime() + 1000);
ls2.setPublished(now);
session.setLastLS2SignTime(now);
leaseSet = ls2;
} else {
leaseSet = new LeaseSet();
}

View File

@ -195,7 +195,7 @@ public class Destination extends KeysAndCert {
*/
public String toBase32() {
try {
return Base32.encode(getHash().getData()) + ".b32.i2p";
return getHash().toBase32();
} catch (IllegalStateException ise) {
return null;
}

View File

@ -310,7 +310,7 @@ public class EncryptedLeaseSet extends LeaseSet2 {
DataHelper.writeLong(out, 2, _signingKey.getType().getCode());
_signingKey.writeBytes(out);
if (_published <= 0)
_published = Clock.getInstance().now();
setPublished(Clock.getInstance().now());
DataHelper.writeLong(out, 4, _published / 1000);
DataHelper.writeLong(out, 2, (_expires - _published) / 1000);
DataHelper.writeLong(out, 2, _flags);

View File

@ -238,6 +238,9 @@ public class LeaseSet extends DatabaseEntry {
* determine which LeaseSet was published more recently (later earliestLeaseSetDate
* means it was published later)
*
* Warning - do not use this for version comparison for LeaseSet2.
* Use LeaseSet2.getPublished() instead.
*
* @return earliest end date of any lease in the set, or -1 if there are no leases
*/
public long getEarliestLeaseDate() {

View File

@ -66,6 +66,9 @@ public class LeaseSet2 extends LeaseSet {
* Published timestamp, as received.
* Different than getDate() or getEarliestLeaseDate(), which are the earliest lease expiration.
*
* Use this for LS2 version comparison, NOT getEarliestLeaseDate(), because
* that will return -1 for EncryptedLS and MetaLS.
*
* @return in ms, with 1 second resolution
* @since 0.9.39
*/
@ -73,6 +76,18 @@ public class LeaseSet2 extends LeaseSet {
return _published;
}
/**
* Set published timestamp.
* Will be rounded to nearest second.
* If not called, will be set on write.
*
* @since 0.9.64
*/
public void setPublished(long now) {
// we round it here, so comparisons during verifies aren't wrong
_published = ((now + 500) / 1000) * 1000;
}
/**
* Published expiration, as received.
* May be different than getLatestLeaseDate(), which is the latest lease expiration.
@ -524,8 +539,7 @@ public class LeaseSet2 extends LeaseSet {
protected void writeHeader(OutputStream out) throws DataFormatException, IOException {
_destination.writeBytes(out);
if (_published <= 0) {
// we round it here, so comparisons during verifies aren't wrong
_published = ((Clock.getInstance().now() + 500) / 1000) * 1000;
setPublished(Clock.getInstance().now());
}
long pub1k = _published / 1000;
DataHelper.writeLong(out, 4, pub1k);

View File

@ -0,0 +1,66 @@
package net.i2p.util;
import java.io.File;
import net.i2p.I2PAppContext;
/**
* Prevent systemd from deleting our temp dir or any dirs or files in it.
* Scheduled by I2PAppContext when the temp dir is created.
*
* To configure/test systemd: Edit file /usr/lib/tmpfiles.d/tmp.conf,
* change line
* D /tmp 1777 root root -
* to
* D /tmp 1777 root root 24h
*
* Ref: https://lwn.net/Articles/975565/
* Ref: https://systemd.io/TEMPORARY_DIRECTORIES/
* Ref: man systemd-tmpfiles; man tmpfiles.d
*
* @since 0.9.64
*/
public class TempDirScanner extends SimpleTimer2.TimedEvent {
private final I2PAppContext ctx;
// systemd default is 10 days for /tmp? distro dependent.
// go a little faster than 1 day just in case
private static final long DELAY = 23*60*60*1000L;
/**
* Schedules itself
*/
public TempDirScanner(I2PAppContext context) {
super(context.simpleTimer2());
ctx = context;
schedule(DELAY);
}
public void timeReached() {
scan(ctx.getTempDir());
schedule(DELAY);
}
/**
* Recursively timestamp all files and empty dirs
* We can't count on the filesystem updating access time.
* This should not affect any known usage of our temp dir.
*/
private static void scan(File f) {
if (f.isDirectory()) {
File[] files = f.listFiles();
if (files != null) {
if (files.length > 0) {
for (File ff : files) {
scan(ff);
}
} else {
// Update last mod time on empty directories
f.setLastModified(System.currentTimeMillis());
}
}
} else if (f.isFile()) {
f.setLastModified(System.currentTimeMillis());
}
}
}

View File

@ -1,3 +1,9 @@
i2p (2.6.1-1~bionic+1) bionic; urgency=medium
* New upstream version 2.6.1
-- idk <hankhill19580@gmail.com> Wed, 7 August 2024 12:00:00 +0000
i2p (2.6.0-1~bionic+1) bionic; urgency=medium
* New upstream version 2.6.0

View File

@ -1,3 +1,9 @@
i2p (2.6.1-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.1
-- idk <hankhill19580@gmail.com> Wed, 7 August 2024 12:00:00 +0000
i2p (2.6.0-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.0

View File

@ -1,8 +1,8 @@
Index: b/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
===================================================================
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
index aad652084..b354792df 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
@@ -15,7 +15,7 @@ import org.eclipse.jetty.server.Request;
@@ -15,7 +15,7 @@ import net.i2p.util.Log;
import net.i2p.util.PortMapper;
import org.eclipse.jetty.server.Request;
@ -11,16 +11,14 @@ Index: b/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
/**
* Block certain Host headers to prevent DNS rebinding attacks.
@@ -44,19 +44,12 @@ public class HostCheckHandler extends Gz
@@ -44,17 +44,12 @@ public class HostCheckHandler extends GzipHandler
_listenHosts = new HashSet<String>(8);
setMinGzipSize(64*1024);
setMinGzipSize(32*1024);
if (_context.getBooleanPropertyDefaultTrue(PROP_GZIP)) {
- addIncludedMimeTypes(
- // our js is very small
- //"application/javascript", "application/x-javascript",
- "application/javascript", "application/x-javascript",
- "application/xhtml+xml", "application/xml",
- // ditto svg
- //"image/svg+xml",
- "image/svg+xml",
- "text/css", "text/html", "text/plain"
- );
+ setMimeTypes("application/xhtml+xml,application/xml,text/css,text/html,text/plain");
@ -33,11 +31,11 @@ Index: b/apps/routerconsole/java/src/net/i2p/router/web/HostCheckHandler.java
}
}
Index: b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
============================================================
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
index 31261e3de..374df3bd2 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
@@ -1100,8 +1100,8 @@ public class RouterConsoleRunner impleme
@@ -1100,8 +1100,8 @@ public class RouterConsoleRunner implements RouterApp {
}
@Override

8
debian/changelog vendored
View File

@ -1,8 +1,14 @@
i2p (2.6.1-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.1
-- idk <hankhill19580@gmail.com> Wed, 7 August 2024 12:00:00 +0000
i2p (2.6.0-1~ubuntu1) focal; urgency=medium
* New upstream version 2.6.0
-- idk <hankhill19580@gmail.com> Wed, 20 July 2024 12:12:12 +0000
-- idk <hankhill19580@gmail.com> Wed, 20 July 2024 12:40:12 +0000
i2p (2.5.2-1~ubuntu1) focal; urgency=medium

View File

@ -1,3 +1,26 @@
2024-08-16 zzz
* NetDB, I2CP: Fix tunnels going yellow for several minutes (Gitlab #487)
2024-08-12 zzz
* Util: Add temp dir timestamper to prevent deletion by systemd
2024-08-11 zzz
* NetDB:
- Don't expire entries in test mode
- Don't immediately expire entries for Android
2024-08-09 zzz
* i2psnark: Reduce minimum banwdith, reduce max connections if low bandwidth
* i2psnark, susimail: Normailze strings when searching (Gitlab #488)
* susimail: Fix searches for multiple terms
* Tunnels: Do not select ElG routers for tunnels
* Util: Reduce number of PRNG output buffers
2024-08-07 2.6.1 (API 0.9.63) released
2024-08-07 idk
* update geoip database
2024-07-25 zzz
* Console:
- Add translation status report (Gitlab MR !207)

View File

@ -4,7 +4,7 @@
<info>
<appname>i2p</appname>
<appversion>2.6.0</appversion>
<appversion>2.6.1</appversion>
<authors>
<author name="I2P" email="https://geti2p.net/"/>
</authors>

View File

@ -10,7 +10,7 @@
<info>
<appname>i2p</appname>
<appversion>2.6.0</appversion>
<appversion>2.6.1</appversion>
<authors>
<author name="I2P" email="https://geti2p.net/"/>
</authors>

View File

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFfTCCA2WgAwIBAgIEUTjHEzANBgkqhkiG9w0BAQ0FADBvMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEYMBYGA1UEAwwPY2FjYXBvQG1haWwu
aTJwMB4XDTE1MDIwOTEyNTQxOFoXDTI1MDIwODEyNTQxOFowbzELMAkGA1UEBhMC
WFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255
bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGDAWBgNVBAMMD2NhY2Fwb0BtYWls
LmkycDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJjVqyjEJqCCufjO
E80hXMPZiQZCiBjSKiA27dTX5rKABI26eLzcKl7e80Ooe9wEGBXEHZCxGIXAFt8x
EHBP4W2u1dmBLpnz6cGxZRMvlTuCKHAbzdJwsWblruXgRg6EQCrtewJ9yuY5SypM
WyJEkL68XMiTeg6fsU367ifWeuPnaO9wqL45pjt9raJMYzXZb3dc6WNUIhg0u7w0
GA4z7X3CZc3f58/4F5ivKOmDd3FqM/suIH6qZJHvQQJZqLtfReLquD5TlqQjcZ1I
vtfYJWsx3Mx3tyXU4x7CHlXyxM4hEGOgMb041GR8td7AvqM0PLuexvNUHO1wDyWF
C6lydNlBwOOUXqPZCG5afgjliwAIIt0WoASEUqSFDiRmhaQZyShQ9P7NUg7jo8x1
SK/YL6agSRfyARvKG+lVoSPlVMdwuP4SGYHW9OA0wlI1fO3aY+q71iP3DFfWsLCh
hE/KXKzruDdGe0tIQdWaz5Xrv4bLN8Ot5a79TYRFUeY7lCyFP7vqert+l31hiyZS
gVugjF6zz91F/gtLsjG+y2HdbdlD3TR/+I/dZFuoiZoVPtXGla36CHLrzyTmKPg9
nZLtrVmOKAfUW1ejYjSeO9Rv05hOsGtPtdi70jw1b7WkUC7Ic8L4HzJE0zDzKwEk
ESVZiLX9G9b0O9CDQnKxRluuZDmVAgMBAAGjITAfMB0GA1UdDgQWBBT9cbSyt2cH
nN9RnC6o9TOoPH5QWTANBgkqhkiG9w0BAQ0FAAOCAgEAVMpgq3aTTv4v3ZmSJ1P6
jZBXX85IdnRUvadXX0HDgqpqs8k3Sm67C0UwpLQHeYw5t6ilSJocCw62pMCgfxwf
dmJ9VEcFoQSd30BdCMXNmPxAnQ+/INUBPzmcZwe+KlI07IQUsjoEPtRG9LBxwric
PifjxKzzVgOlPPb5XGNmVLdlncY9Z4v5McZPQx6+hG4CqNULEOrx/xRpQDTsGUem
AXR/ocHm7dDwUIQrkRPkbPK+urEtqKS+RL5ttQ4myzJWasCiDoAdlDv15X7u2G+i
E8rTSohtr4Crd4DbNpT11aQHtnympNJCAc7PyRLcQRV3FASXvDUsvwT4dMcPN+M1
ZR5oatbo9hxy/MPyhQun4awMRvaF7HSKrPI8XJRdJzzufusv662N6A7UX31i5W82
rnSxfP/haklNfwcBAQ0R3R/MkoURYanJYoHnr2WuAx0yfxNIYlJMX7hfPdWOW6a4
7nQQAkrgW3knQGlKwCEypjm0tdK0bsUrQ0F91wUUYSUSFuPDPb19ifKXklBoCVlB
6u3ckHu7LG/YZcHmtsxMRMuT+6LtIs/huFnfs4YhJYggswFJHjEX5PcBfsiQklz+
ahs+UsJAb+lbMOlWj+LYDdyC4T7ZHT+Ii/JZdBN3WNXiBzNuXGC7bd0KWBgCaFuU
ZAPV0YlmPjsGRaSl7vfh+cI=
-----END CERTIFICATE-----

View File

@ -259,6 +259,7 @@
- `i2p2www/pages/downloads/macros` (checksums)
- `i2p2www/pages/site/get-involved/roadmap.html` (release date, actual release contents)
- `i2p2www/static/news/news.xml` (no longer necessary)
- Rename (undraft) the blog post
- Sync with git.idk.i2p
4. Announce on:

View File

@ -123,6 +123,7 @@ certificates/reseed/bugme_at_mail.i2p.crt
certificates/ssl/i2p.mooo.com.crt
certificates/plugin/zab_at_mail.i2p.crt
certificates/plugin/str4d_at_mail.i2p.crt
certificates/plugin/cacapo_at_mail.i2p.crt
certificates/reseed/null_at_i2pmail.org.crt
certificates/reseed/reheatedburger_at_protonmail.com.crt
# moved css

View File

@ -170,7 +170,7 @@ public class RouterContext extends I2PAppContext {
// or about 2 seconds per buffer - so about 200x faster
// to fill than to drain - so we don't need too many
long maxMemory = SystemVersion.getMaxMemory();
long maxBuffs = (SystemVersion.isAndroid() || SystemVersion.isARM()) ? 4 : 8;
long maxBuffs = (SystemVersion.isAndroid() || SystemVersion.isARM()) ? 3 : 5;
long buffs = Math.min(maxBuffs, Math.max(2, maxMemory / (21 * 1024 * 1024)));
envProps.setProperty("prng.buffers", Long.toString(buffs));
}

View File

@ -22,7 +22,7 @@ public class RouterVersion {
public final static String QUALIFIER = "";
public final static long BUILD = 2;
/** for example "-test" */
public final static String EXTRA = "-rc";
public final static String EXTRA = "";
public final static String FULL_VERSION = VERSION + "-" + BUILD + QUALIFIER + EXTRA;
public static void main(String args[]) {

View File

@ -22,6 +22,17 @@ public interface DataStore {
public DatabaseEntry get(Hash key, boolean persist);
public boolean put(Hash key, DatabaseEntry data);
public boolean put(Hash key, DatabaseEntry data, boolean persist);
/*
* Unconditionally store, bypass all newer/older checks
*
* @return success
* @param key non-null
* @param data non-null
* @since 0.9.64
*/
public boolean forcePut(Hash key, DatabaseEntry data);
public DatabaseEntry remove(Hash key);
public DatabaseEntry remove(Hash key, boolean persist);
public Set<Hash> getKeys();

View File

@ -61,15 +61,18 @@ class ExpireLeasesJob extends JobImpl {
*
*/
private List<Hash> selectKeysToExpire() {
RouterContext ctx = getContext();
List<Hash> toExpire = new ArrayList<Hash>(128);
for (Map.Entry<Hash, DatabaseEntry> entry : _facade.getDataStore().getMapEntries()) {
DatabaseEntry obj = entry.getValue();
if (obj.isLeaseSet()) {
LeaseSet ls = (LeaseSet)obj;
if (!ls.isCurrent(Router.CLOCK_FUDGE_FACTOR))
toExpire.add(entry.getKey());
else if (_log.shouldLog(Log.DEBUG))
_log.debug("Lease " + ls.getDestination().calculateHash() + " is current, no need to expire");
if (!ls.isCurrent(Router.CLOCK_FUDGE_FACTOR)) {
Hash h = entry.getKey();
toExpire.add(h);
if (ctx.clientManager().isLocal(h))
_log.logAlways(Log.WARN, "Expired local leaseset " + h.toBase32());
}
}
}
return toExpire;

View File

@ -146,22 +146,11 @@ class HandleFloodfillDatabaseStoreMessageJob extends JobImpl {
LeaseSet match = _facade.store(key, ls);
if (match == null) {
wasNew = true;
} else if (match.getEarliestLeaseDate() < ls.getEarliestLeaseDate()) {
} else if (KademliaNetworkDatabaseFacade.isNewer(ls, match)) {
wasNew = true;
// If it is in our keyspace and we are talking to it
//if (match.getReceivedAsPublished())
// ls.setReceivedAsPublished(true);
} else if (type != DatabaseEntry.KEY_TYPE_LEASESET &&
match.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
LeaseSet2 ls2 = (LeaseSet2) ls;
LeaseSet2 match2 = (LeaseSet2) match;
if (match2.getPublished() < ls2.getPublished()) {
wasNew = true;
//if (match.getReceivedAsPublished())
// ls.setReceivedAsPublished(true);
} else {
wasNew = false;
}
} else {
wasNew = false;
// The FloodOnlyLookupSelector goes away after the first good reply

View File

@ -53,6 +53,7 @@ import net.i2p.router.networkdb.reseed.ReseedChecker;
import net.i2p.router.peermanager.PeerProfile;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
/**
* Kademlia based version of the network database.
@ -880,6 +881,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
private static final long PUBLISH_DELAY = 3*1000;
/**
* Stores in local netdb, and publishes to floodfill if client manager says to
*
* @throws IllegalArgumentException if the leaseSet is not valid
*/
public void publish(LeaseSet localLeaseSet) throws IllegalArgumentException {
@ -890,7 +893,8 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
}
Hash h = localLeaseSet.getHash();
try {
store(h, localLeaseSet);
// force overwrite of previous entry
store(h, localLeaseSet, true);
} catch (IllegalArgumentException iae) {
_log.error("locally published leaseSet is not valid?", iae);
throw iae;
@ -1077,7 +1081,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
}
return null;
}
/**
* Store the leaseSet.
*
@ -1089,12 +1093,28 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
* @return previous entry or null
*/
public LeaseSet store(Hash key, LeaseSet leaseSet) throws IllegalArgumentException {
return store(key, leaseSet, false);
}
/**
* Store the leaseSet.
*
* If the store fails due to unsupported crypto, it will negative cache
* the hash until restart.
*
* @param force always store even if not newer
* @throws IllegalArgumentException if the leaseSet is not valid
* @throws UnsupportedCryptoException if that's why it failed.
* @return previous entry or null
* @since 0.9.64
*/
public LeaseSet store(Hash key, LeaseSet leaseSet, boolean force) throws IllegalArgumentException {
if (!_initialized) return null;
LeaseSet rv;
try {
rv = (LeaseSet)_ds.get(key);
if (rv != null && rv.getEarliestLeaseDate() >= leaseSet.getEarliestLeaseDate()) {
if (rv != null && !force && !isNewer(leaseSet, rv)) {
if (_log.shouldDebug())
_log.debug("Not storing older " + key);
// if it hasn't changed, no need to do anything
@ -1116,7 +1136,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
// spoof / hash collision detection
// todo allow non-exp to overwrite exp
if (rv != null) {
if (rv != null && !force) {
Destination d1 = leaseSet.getDestination();
Destination d2 = rv.getDestination();
if (d1 != null && d2 != null && !d1.equals(d2))
@ -1158,9 +1178,10 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
if (err != null)
throw new IllegalArgumentException("Invalid store attempt - " + err);
if (_log.shouldDebug())
_log.debug("Storing LS to the data store...");
_ds.put(key, leaseSet);
if (force)
_ds.forcePut(key, leaseSet);
else
_ds.put(key, leaseSet);
if (encls != null) {
// we now have decrypted it, store it as well
@ -1204,6 +1225,24 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
return rv;
}
/**
* Utility to determine if a is newer than b.
* Uses publish date if a and b are both LS2, else earliest lease date.
*
* @param a non-null
* @param b non-null
* @return if a is newer than b
* @since 0.9.64
*/
public static boolean isNewer(LeaseSet a, LeaseSet b) {
if (a.getType() != DatabaseEntry.KEY_TYPE_LEASESET &&
b.getType() != DatabaseEntry.KEY_TYPE_LEASESET) {
return ((LeaseSet2) a).getPublished() > ((LeaseSet2) b).getPublished();
} else {
return a.getEarliestLeaseDate() > b.getEarliestLeaseDate();
}
}
private static final int MIN_ROUTERS = 90;
@ -1279,9 +1318,11 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad
* @since 0.9.7
*/
String validate(RouterInfo routerInfo) throws IllegalArgumentException {
if (_context.commSystem().isDummy())
return null;
long now = _context.clock().now();
boolean upLongEnough = _context.router().getUptime() > 60*60*1000;
if (!upLongEnough) {
if (!upLongEnough && !SystemVersion.isAndroid()) {
long down = _context.router().getEstimatedDowntime();
upLongEnough = down > 0 && down < 10*60*60*1000L;
}

View File

@ -164,6 +164,24 @@ public class PersistentDataStore extends TransientDataStore {
_writer.queue(key, data);
return rv;
}
/*
* Unconditionally store, bypass all newer/older checks.
* Persists for RI only.
*
* @param persist if false, call super only, don't access disk
* @return success
* @param key non-null
* @param data non-null
* @since 0.9.64
*/
@Override
public boolean forcePut(Hash key, DatabaseEntry data) {
boolean rv = super.forcePut(key, data);
if (rv && data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO)
_writer.queue(key, data);
return rv;
}
/** How many files to write every 10 minutes. Doesn't make sense to limit it,
* they just back up in the queue hogging memory.
@ -329,10 +347,11 @@ public class PersistentDataStore extends TransientDataStore {
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
}
}
private long getPublishDate(DatabaseEntry data) {
private static long getPublishDate(DatabaseEntry data) {
return data.getDate();
}
/**
* This was mostly for manual reseeding, i.e. the user manually
* copies RI files to the directory. Nobody does this,

View File

@ -190,6 +190,20 @@ class TransientDataStore implements DataStore {
}
return rv;
}
/*
* Unconditionally store, bypass all newer/older checks
*
* @return success
* @param key non-null
* @param data non-null
* @since 0.9.64
*/
@Override
public boolean forcePut(Hash key, DatabaseEntry data) {
_data.put(key, data);
return true;
}
@Override
public String toString() {

View File

@ -380,8 +380,11 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
RouterIdentity ident = peer.getIdentity();
if (ident.getSigningPublicKey().getType() == SigType.DSA_SHA1)
return true;
// Shouldn't be any ElG routers MIN_VERSION or higher, but just to make sure,
// and prevent large build messages.
// Restricting to 25519 may also allow us to remove some of the ElG tunnel build code.
EncType type = ident.getPublicKey().getType();
if (!LeaseSetKeys.SET_BOTH.contains(type))
if (type != EncType.ECIES_X25519)
return true;
// otherwise, it contains flags we aren't trying to focus on,

View File

@ -104,7 +104,7 @@ public class TunnelPool {
_started = System.currentTimeMillis();
_lastRateUpdate = _started;
_lastLifetimeProcessed = 0;
_manager.getExecutor().repoll();
_manager.tunnelFailed();
if (_settings.isInbound() && !_settings.isExploratory()) {
// we just reconnected and didn't require any new tunnel builders.
// however, we /do/ want a leaseSet, so build one
@ -452,7 +452,7 @@ public class TunnelPool {
if (_settings != null) {
if (_log.shouldLog(Log.INFO))
_log.info(toString() + ": Settings updated on the pool: " + settings);
_manager.getExecutor().repoll(); // in case we need more
_manager.tunnelFailed(); // in case we need more
}
}
@ -508,7 +508,7 @@ public class TunnelPool {
remaining = _tunnels.size();
}
_manager.getExecutor().repoll();
_manager.tunnelFailed();
_lifetimeProcessed += info.getProcessedMessagesCount();
updateRate();

View File

@ -631,6 +631,9 @@ public class TunnelPoolManager implements TunnelManagerFacade {
out.add(_outboundExploratory);
}
/**
* Poke the build executor to build more tunnels.
*/
void tunnelFailed() { _executor.repoll(); }
BuildExecutor getExecutor() { return _executor; }