merge of '639a99d15ec0e7cbf0b44fd44564a6ae304b8673'

and '6b24962b7b3513e22153068b62922cabebb2dee4'
This commit is contained in:
meeh
2018-07-13 10:10:14 +00:00
24 changed files with 757 additions and 217 deletions

View File

@ -105,6 +105,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
private static final String PROP_META_UPLOADED = "uploaded";
private static final String PROP_META_ADDED = "added";
private static final String PROP_META_COMPLETED = "completed";
private static final String PROP_META_INORDER = "inOrder";
private static final String PROP_META_MAGNET = "magnet";
private static final String PROP_META_MAGNET_DN = "magnet_dn";
private static final String PROP_META_MAGNET_TR = "magnet_tr";
@ -1759,7 +1760,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
addMessage(_t("Torrent with this info hash is already running: {0}", snark.getBaseName()));
return false;
} else if (bitfield != null) {
saveTorrentStatus(metainfo, bitfield, null, baseFile, true, 0, true); // no file priorities
saveTorrentStatus(metainfo, bitfield, null, false, baseFile, true, 0, true); // no file priorities
}
// so addTorrent won't recheck
if (filename == null) {
@ -1898,19 +1899,21 @@ public class SnarkManager implements CompleteListener, ClientApp {
return;
Properties config = getConfig(snark);
String pri = config.getProperty(PROP_META_PRIORITY);
if (pri == null)
return;
int filecount = metainfo.getFiles().size();
int[] rv = new int[filecount];
String[] arr = DataHelper.split(pri, ",");
for (int i = 0; i < filecount && i < arr.length; i++) {
if (arr[i].length() > 0) {
try {
rv[i] = Integer.parseInt(arr[i]);
} catch (Throwable t) {}
if (pri != null) {
int filecount = metainfo.getFiles().size();
int[] rv = new int[filecount];
String[] arr = DataHelper.split(pri, ",");
for (int i = 0; i < filecount && i < arr.length; i++) {
if (arr[i].length() > 0) {
try {
rv[i] = Integer.parseInt(arr[i]);
} catch (Throwable t) {}
}
}
storage.setFilePriorities(rv);
}
storage.setFilePriorities(rv);
boolean inOrder = Boolean.parseBoolean(config.getProperty(PROP_META_INORDER));
storage.setInOrder(inOrder);
}
/**
@ -2017,7 +2020,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
Storage storage = snark.getStorage();
if (meta == null || storage == null)
return;
saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(),
saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), storage.getInOrder(),
storage.getBase(), storage.getPreserveFileNames(),
snark.getUploaded(), snark.isStopped(), comments);
}
@ -2034,24 +2037,24 @@ public class SnarkManager implements CompleteListener, ClientApp {
* @param priorities may be null
* @param base may be null
*/
private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities,
private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, boolean inOrder,
File base, boolean preserveNames, long uploaded, boolean stopped) {
saveTorrentStatus(metainfo, bitfield, priorities, base, preserveNames, uploaded, stopped, null);
saveTorrentStatus(metainfo, bitfield, priorities, inOrder, base, preserveNames, uploaded, stopped, null);
}
/*
* @param comments null for no change
* @since 0.9.31
*/
private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities,
private void saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, boolean inOrder,
File base, boolean preserveNames, long uploaded, boolean stopped,
Boolean comments) {
synchronized (_configLock) {
locked_saveTorrentStatus(metainfo, bitfield, priorities, base, preserveNames, uploaded, stopped, comments);
locked_saveTorrentStatus(metainfo, bitfield, priorities, inOrder, base, preserveNames, uploaded, stopped, comments);
}
}
private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities,
private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities, boolean inOrder,
File base, boolean preserveNames, long uploaded, boolean stopped,
Boolean comments) {
byte[] ih = metainfo.getInfoHash();
@ -2077,6 +2080,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
config.setProperty(PROP_META_UPLOADED, Long.toString(uploaded));
boolean running = !stopped;
config.setProperty(PROP_META_RUNNING, Boolean.toString(running));
config.setProperty(PROP_META_INORDER, Boolean.toString(inOrder));
if (base != null)
config.setProperty(PROP_META_BASE, base.getAbsolutePath());
if (comments != null)
@ -2095,7 +2099,9 @@ public class SnarkManager implements CompleteListener, ClientApp {
// generate string like -5,,4,3,,,,,,-2 where no number is zero.
StringBuilder buf = new StringBuilder(2 * priorities.length);
for (int i = 0; i < priorities.length; i++) {
if (priorities[i] != 0)
// only output if !inOrder || !skipped so the string isn't too long
if (priorities[i] != 0 &&
(!inOrder || priorities[i] < 0))
buf.append(Integer.toString(priorities[i]));
if (i != priorities.length - 1)
buf.append(',');
@ -2443,7 +2449,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
MetaInfo meta = snark.getMetaInfo();
Storage storage = snark.getStorage();
if (meta != null && storage != null)
saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(),
saveTorrentStatus(meta, storage.getBitField(), storage.getFilePriorities(), storage.getInOrder(),
storage.getBase(), storage.getPreserveFileNames(), snark.getUploaded(),
snark.isStopped());
}
@ -2467,7 +2473,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
snark.stopTorrent();
return null;
}
saveTorrentStatus(meta, storage.getBitField(), null,
saveTorrentStatus(meta, storage.getBitField(), null, false,
storage.getBase(), storage.getPreserveFileNames(), 0,
snark.isStopped());
// temp for addMessage() in case canonical throws

View File

@ -25,11 +25,14 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.security.MessageDigest;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -72,6 +75,7 @@ public class Storage implements Closeable
private final boolean _preserveFileNames;
private boolean changed;
private volatile boolean _isChecking;
private boolean _inOrder;
private final AtomicInteger _allocateCount = new AtomicInteger();
private final AtomicInteger _checkProgress = new AtomicInteger();
@ -82,6 +86,8 @@ public class Storage implements Closeable
/** The maximum number of pieces in a torrent. */
public static final int MAX_PIECES = 32*1024;
public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES;
public static final int PRIORITY_SKIP = -9;
public static final int PRIORITY_NORMAL = 0;
private static final Map<String, String> _filterNameCache = new ConcurrentHashMap<String, String>();
@ -145,7 +151,7 @@ public class Storage implements Closeable
_torrentFiles = getFiles(baseFile);
long total = 0;
ArrayList<Long> lengthsList = new ArrayList<Long>();
ArrayList<Long> lengthsList = new ArrayList<Long>(_torrentFiles.size());
for (TorrentFile tf : _torrentFiles)
{
long length = tf.length;
@ -178,7 +184,7 @@ public class Storage implements Closeable
bitfield = new BitField(pieces);
needed = 0;
List<List<String>> files = new ArrayList<List<String>>();
List<List<String>> files = new ArrayList<List<String>>(_torrentFiles.size());
for (TorrentFile tf : _torrentFiles)
{
List<String> file = new ArrayList<String>();
@ -494,6 +500,60 @@ public class Storage implements Closeable
}
}
/**
* @return as last set, default false
* @since 0.9.36
*/
public boolean getInOrder() {
return _inOrder;
}
/**
* Call AFTER setFilePriorites() so we know what's skipped
* @param yes enable or not
* @since 0.9.36
*/
public void setInOrder(boolean yes) {
if (yes == _inOrder)
return;
_inOrder = yes;
if (complete() || metainfo.getFiles() == null)
return;
if (yes) {
List<TorrentFile> sorted = _torrentFiles;
int sz = sorted.size();
if (sz > 1) {
sorted = new ArrayList<TorrentFile>(sorted);
Collections.sort(sorted, new FileNameComparator());
}
for (int i = 0; i < sz; i++) {
TorrentFile tf = sorted.get(i);
// higher number is higher priority
if (tf.priority >= PRIORITY_NORMAL)
tf.priority = sz - i;
}
} else {
for (TorrentFile tf : _torrentFiles) {
if (tf.priority > PRIORITY_NORMAL)
tf.priority = PRIORITY_NORMAL;
}
}
}
/**
* Sort with locale comparator.
* (not using TorrentFile.compareTo())
* @since 0.9.36
*/
private static class FileNameComparator implements Comparator<TorrentFile>, Serializable {
private final Collator c = Collator.getInstance();
public int compare(TorrentFile l, TorrentFile r) {
return c.compare(l.toString(), r.toString());
}
}
/**
* Call setPriority() for all changed files first,
* then call this.
@ -523,6 +583,25 @@ public class Storage implements Closeable
}
rv[i] = pri;
}
if (_inOrder) {
// Do a second pass to set the priority of the pieces within each file
// this only works because MAX_PIECES * MAX_FILES_PER_TORRENT < Integer.MAX_VALUE
// the base file priority
int pri = PRIORITY_SKIP;
for (int i = 0; i < rv.length; i++) {
int val = rv[i];
if (val <= PRIORITY_NORMAL)
continue;
if (val != pri) {
pri = val;
// new file
rv[i] *= MAX_PIECES;
} else {
// same file, decrement priority from previous piece
rv[i] = rv[i-1] - 1;
}
}
}
return rv;
}
@ -544,7 +623,7 @@ public class Storage implements Closeable
long rv = 0;
final int end = pri.length - 1;
for (int i = 0; i <= end; i++) {
if (pri[i] <= -9 && !bitfield.get(i)) {
if (pri[i] <= PRIORITY_SKIP && !bitfield.get(i)) {
rv += (i != end) ? piece_size : metainfo.getPieceLength(i);
}
}

View File

@ -2931,7 +2931,8 @@ public class I2PSnarkServlet extends BasicServlet {
if (val != null) {
String nonce = val[0];
if (String.valueOf(_nonce).equals(nonce)) {
if (postParams.get("savepri") != null) {
if (postParams.get("savepri") != null ||
postParams.get("setInOrderEnabled") != null) {
savePriorities(snark, postParams);
} else if (postParams.get("addComment") != null) {
saveComments(snark, postParams);
@ -2974,7 +2975,8 @@ public class I2PSnarkServlet extends BasicServlet {
}
boolean showStopStart = snark != null;
boolean showPriority = snark != null && snark.getStorage() != null && !snark.getStorage().complete() &&
Storage storage = snark != null ? snark.getStorage() : null;
boolean showPriority = storage != null && !storage.complete() &&
r.isDirectory();
StringBuilder buf=new StringBuilder(4096);
@ -3036,13 +3038,13 @@ public class I2PSnarkServlet extends BasicServlet {
.append(":</b> <a href=\"").append(_contextPath).append('/').append(baseName).append("\">")
.append(DataHelper.escapeHTML(fullPath))
.append("</a></td></tr>\n");
if (snark.getStorage() != null) {
if (storage != null) {
buf.append("<tr><td>");
toThemeImg(buf, "file");
buf.append("</td><td><b>")
.append(_t("Data location"))
.append(":</b> ")
.append(DataHelper.escapeHTML(snark.getStorage().getBase().getPath()))
.append(DataHelper.escapeHTML(storage.getBase().getPath()))
.append("</td></tr>\n");
}
String hex = I2PSnarkUtil.toHex(snark.getInfoHash());
@ -3285,6 +3287,23 @@ public class I2PSnarkServlet extends BasicServlet {
}
buf.append("</td></tr>\n");
}
boolean showInOrder = storage != null && !storage.complete() &&
meta != null && meta.getFiles() != null && meta.getFiles().size() > 1;
if (showInOrder) {
buf.append("<tr id=\"torrentOrderControl\"><td colspan=\"2\">");
buf.append(_t("Download files in order"));
buf.append(":<label><input type=\"checkbox\" class=\"optbox\" name=\"enableInOrder\" id=\"enableInOrder\" ");
if (storage.getInOrder())
buf.append("checked=\"checked\"");
buf.append(">&nbsp;");
buf.append(_t("Enable for this torrent"));
buf.append("</label>" +
"<input type=\"submit\" name=\"setInOrderEnabled\" value=\"");
buf.append(_t("Save Preference"));
buf.append("\" class=\"accept\">" +
"</td></tr>\n");
}
} else {
// snark == null
// shouldn't happen
@ -3323,7 +3342,6 @@ public class I2PSnarkServlet extends BasicServlet {
return buf.toString();
}
Storage storage = snark != null ? snark.getStorage() : null;
List<Sorters.FileAndIndex> fileList = new ArrayList<Sorters.FileAndIndex>(ls.length);
// precompute remaining for all files for efficiency
long[] remainingArray = (storage != null) ? storage.remaining() : null;
@ -3424,6 +3442,7 @@ public class I2PSnarkServlet extends BasicServlet {
// DateFormat.MEDIUM);
boolean showSaveButton = false;
boolean rowEven = true;
boolean inOrder = storage != null && storage.getInOrder();
for (Sorters.FileAndIndex fai : fileList)
{
//String encoded = encodePath(ls[i].getName());
@ -3447,7 +3466,7 @@ public class I2PSnarkServlet extends BasicServlet {
complete = true;
//status = toImg("tick") + ' ' + _t("Directory");
} else {
if (snark == null || snark.getStorage() == null) {
if (storage == null) {
// Assume complete, perhaps he removed a completed torrent but kept a bookmark
complete = true;
status = toImg("cancel") + ' ' + _t("Torrent not found?");
@ -3527,16 +3546,18 @@ public class I2PSnarkServlet extends BasicServlet {
if (showPriority) {
buf.append("<td class=\"priority\">");
if ((!complete) && (!item.isDirectory())) {
buf.append("<label class=\"priorityHigh\" title=\"").append(_t("Download file at high priority")).append("\">" +
"\n<input type=\"radio\" onclick=\"priorityclicked();\" class=\"prihigh\" value=\"5\" name=\"pri.").append(fileIndex).append("\" ");
if (priority > 0)
buf.append("checked=\"checked\"");
buf.append('>')
.append(_t("High")).append("</label>");
if (!inOrder) {
buf.append("<label class=\"priorityHigh\" title=\"").append(_t("Download file at high priority")).append("\">" +
"\n<input type=\"radio\" onclick=\"priorityclicked();\" class=\"prihigh\" value=\"5\" name=\"pri.").append(fileIndex).append("\" ");
if (priority > 0)
buf.append("checked=\"checked\"");
buf.append('>')
.append(_t("High")).append("</label>");
}
buf.append("<label class=\"priorityNormal\" title=\"").append(_t("Download file at normal priority")).append("\">" +
"\n<input type=\"radio\" onclick=\"priorityclicked();\" class=\"prinorm\" value=\"0\" name=\"pri.").append(fileIndex).append("\" ");
if (priority == 0)
if (priority == 0 || (inOrder && priority >= 0))
buf.append("checked=\"checked\"");
buf.append('>')
.append(_t("Normal")).append("</label>");
@ -3555,9 +3576,12 @@ public class I2PSnarkServlet extends BasicServlet {
}
if (showSaveButton) {
buf.append("<thead><tr id=\"setPriority\"><th class=\"headerpriority\" colspan=\"5\">" +
"<span class=\"script\"><a class=\"control\" id=\"setallhigh\" href=\"javascript:void(null);\" onclick=\"setallhigh();\">")
.append(toImg("clock_red")).append(_t("Set all high")).append("</a>\n" +
"<a class=\"control\" id=\"setallnorm\" href=\"javascript:void(null);\" onclick=\"setallnorm();\">")
"<span class=\"script\">");
if (!inOrder) {
buf.append("<a class=\"control\" id=\"setallhigh\" href=\"javascript:void(null);\" onclick=\"setallhigh();\">")
.append(toImg("clock_red")).append(_t("Set all high")).append("</a>\n");
}
buf.append("<a class=\"control\" id=\"setallnorm\" href=\"javascript:void(null);\" onclick=\"setallnorm();\">")
.append(toImg("clock")).append(_t("Set all normal")).append("</a>\n" +
"<a class=\"control\" id=\"setallskip\" href=\"javascript:void(null);\" onclick=\"setallskip();\">")
.append(toImg("cancel")).append(_t("Skip all")).append("</a></span>\n" +
@ -3926,6 +3950,8 @@ public class I2PSnarkServlet extends BasicServlet {
} catch (Throwable t) { t.printStackTrace(); }
}
}
if (postParams.get("setInOrderEnabled") != null)
storage.setInOrder(postParams.get("enableInOrder") != null);
snark.updatePiecePriorities();
_manager.saveTorrentStatus(snark);
}

View File

@ -97,11 +97,10 @@ class ConnectionManager {
_connectionHandler = new ConnectionHandler(_context, this, _timer);
_tcbShare = new TCBShare(_context, _timer);
// PROTO_ANY is for backward compatibility (pre-0.7.1)
// TODO change proto to PROTO_STREAMING someday.
// Right now we get everything, and rely on Datagram to specify PROTO_UDP.
// PacketQueue has sent PROTO_STREAMING since the beginning of mux support (0.7.1)
// As of 0.9.1, new option to enforce streaming protocol, off by default
// As of 0.9.1, listen on configured port (default 0 = all)
// enforce protocol default changed to true in 0.9.36
int protocol = defaultOptions.getEnforceProtocol() ? I2PSession.PROTO_STREAMING : I2PSession.PROTO_ANY;
_session.addMuxedSessionListener(_messageHandler, protocol, defaultOptions.getLocalPort());
_outboundQueue = new PacketQueue(_context, _timer);

View File

@ -155,9 +155,10 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
/**
* If PROTO is enforced, we cannot communicate with destinations earlier than version 0.7.1.
* Default true as of 0.9.36.
* @since 0.9.1
*/
private static final boolean DEFAULT_ENFORCE_PROTO = false;
private static final boolean DEFAULT_ENFORCE_PROTO = true;
private final int _trend[] = new int[TREND_COUNT];
@ -523,7 +524,7 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
/**
* Do we receive all traffic, or only traffic marked with I2PSession.PROTO_STREAMING (6) ?
* Default false.
* Default true.
* If PROTO is enforced, we cannot communicate with destinations earlier than version 0.7.1
* (released March 2009), which is when streaming started sending the PROTO_STREAMING indication.
* Set to true if you are running multiple protocols on a single Destination.

View File

@ -30,10 +30,12 @@ sloccount.report.file=sloccount.sc
# Building EXEs in x64 Linux requires that 32bit libraries are installed. In Debian,
# for example, installing the libc6-i386 package will satisfy this requirement.
# Uncomment the next line to prevent building EXEs (changing it to false will have no impact)
#noExe=true
# IzPack 5.1.x install dir
#izpack5.home=/PATH/TO/IzPack
# Change this to false if you don't have gettext or you want to prevent it from running during the build
require.gettext=true

View File

@ -24,6 +24,7 @@
<echo message=" installer-osx: build the GUI installer (OSX only)" />
<echo message=" installer-windows: build the GUI installer (Windows only)" />
<echo message=" installer-nowindows: build the GUI installer (all but Windows)" />
<echo message=" installer5, installer5-linux, installer5-nowindows, installer5-windows: use IzPack 5" />
<echo message=" osxLauncher: build the Mac OS X router/GUI launcher (OSX only)" />
<echo message=" bbLauncher: build the Browser Bundle router launcher" />
<echo message=" tarball: tar the full install into i2p.tar.bz2 (extracts to build a new clean install)" />
@ -79,7 +80,7 @@
<echo message=" devscripts libjetty9-java libtomcat8-java libtaglibs-standard-jstlel-java libgetopt-java" />
<echo message=" " />
<echo message="The following command will install the additional runtime dependencies:" />
<echo message="sudo apt-get install libecj-java geoip-database" />
<echo message="sudo apt-get install geoip-database famfamfam-flag-png" />
<echo message=" " />
<echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
<echo message="to patch the source and build the packages." />
@ -1762,18 +1763,36 @@
<ant dir="installer/java" target="build" />
</target>
<!-- IzPack 4 -->
<target name="installer" depends="preppkg, buildProperties, util-list-changes, izpack-patches, buildUtilityJar" >
<!--
Force 1.5 pack200 output
Doesnt work!
http://jira.codehaus.org/browse/IZPACK-404
http://forums.sun.com/thread.jspa?threadID=773439
http://bfo.co.uk/blog/2010/05/13/combining_ant_jar_signatures_and_pack200.html
<property name="com.sun.java.util.jar.pack.package.majver" value="150" />
<property name="com.sun.java.util.jar.pack.package.minver" value="7" />
-->
<izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
<ant target="installerexe" />
</target>
<!-- IzPack 5 -->
<target name="ensureIzpack5" >
<!-- set if unset -->
<property name="izpack5.home" value="${user.home}/IzPack" />
<condition property="izpack5.available" >
<available file="${izpack5.home}" type="dir" />
</condition>
<fail message="Error - IzPack 5.1.x must be installed at ${izpack5.home}, or set izpack5.home=/PATH/TO/IzPack in override.properties, or download from http://izpack.org/downloads/ and install" >
<condition>
<not>
<isset property="izpack5.available" />
</not>
</condition>
</fail>
<path id="izpack5.lib.path">
<fileset dir="${izpack5.home}/lib" includes="*.jar"/>
</path>
<taskdef name="izpack5"
classpathref="izpack5.lib.path"
classname="com.izforge.izpack.ant.IzPackTask" />
</target>
<target name="installer5" depends="ensureIzpack5, preppkg, buildProperties, util-list-changes, buildUtilityJar" >
<izpack5 input="${basedir}/installer/install5.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
<ant target="installerexe" />
</target>
@ -1786,22 +1805,36 @@
</target>
<!-- Custom installers -->
<!-- IzPack 4 -->
<target name="installer-nowindows" depends="clean, preppkg-nowindows, izpack-patches" >
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}.jar" installerType="standard" basedir="${basedir}" />
</target>
<!-- IzPack 5 -->
<target name="installer5-nowindows" depends="ensureIzpack5, clean, preppkg-nowindows" >
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
<izpack5 input="${basedir}/installer/install5.xml" output="${basedir}/i2pinstall_${full.version}.jar" installerType="standard" basedir="${basedir}" />
</target>
<target name="installer-freebsd" depends="clean, preppkg-freebsd-only, izpack-patches" >
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
</target>
<!-- IzPack 4 -->
<target name="installer-linux" depends="clean, preppkg-linux-only, izpack-patches" >
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_linux-only.jar" installerType="standard" basedir="${basedir}" />
</target>
<!-- IzPack 5 -->
<target name="installer5-linux" depends="ensureIzpack5, clean, preppkg-linux-only" >
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
<izpack5 input="${basedir}/installer/install5.xml" output="${basedir}/i2pinstall_${full.version}_linux-only.jar" installerType="standard" basedir="${basedir}" />
</target>
<target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, izpack-patches">
<fixcrlf srcdir="pkg-temp" includes="*.config **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="lf" />
@ -1845,6 +1878,7 @@
<delete dir="pkg-temp" includes="eepget i2prouter INSTALL-headless.txt osid postinstall.sh runplain.sh" />
</target>
<!-- IzPack 4 -->
<target name="installer-windows" depends="clean, preppkg-windows-only, util-list-changes, izpack-patches, buildUtilityJar" >
<fixcrlf srcdir="pkg-temp" includes="*.config *.bat *.cmd **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="crlf"/>
<izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
@ -1853,6 +1887,15 @@
<move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows.exe" />
</target>
<!-- IzPack 5 -->
<target name="installer5-windows" depends="ensureIzpack5, clean, preppkg-windows-only, util-list-changes, buildUtilityJar" >
<fixcrlf srcdir="pkg-temp" includes="*.config *.bat *.cmd **/*.xml **/*.properties **/*.txt scripts/*" encoding="utf8" eol="crlf"/>
<izpack5 input="${basedir}/installer/install5.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
<ant target="installerexe" />
<delete file="${basedir}/install.jar" />
<move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows.exe" />
</target>
<!-- this is broken as installer-xxx targets may delete (or not delete) things in pkg-temp -->
<target name="installer-all" depends="installer-freebsd, installer-linux, installer-osx, installer-windows, installer-nowindows, installer" >
</target>

View File

@ -477,6 +477,23 @@ class AMDInfoImpl extends CPUIDCPUInfo implements AMDCPUInfo
modelString = "Ryzen model " + model;
}
break;
// http://lkml.iu.edu/hypermail/linux/kernel/1806.1/00730.html
// untested
case 24: {
isK6Compatible = true;
isK6_2_Compatible = true;
isK6_3_Compatible = true;
isAthlonCompatible = true;
isAthlon64Compatible = true;
// Pending testing of the bulldozer jbigi
//isPiledriverCompatible = true;
//isSteamrollerCompatible = true;
//isExcavatorCompatible = true;
//isBulldozerCompatible = true;
modelString = "Hygon Dhyana model " + model;
}
break;
}
return modelString;
}

View File

@ -310,7 +310,8 @@ public class CPUID {
return new VIAInfoImpl();
if(!isX86)
throw new UnknownCPUException("Failed to read CPU information from the system. The CPUID instruction exists on x86 CPUs only.");
if(id.equals("AuthenticAMD"))
// http://lkml.iu.edu/hypermail/linux/kernel/1806.1/00730.html
if(id.equals("AuthenticAMD") || id.equals("HygonGenuine"))
return new AMDInfoImpl();
if(id.equals("GenuineIntel"))
return new IntelInfoImpl();

View File

@ -2,9 +2,7 @@ package net.i2p.util;
import java.util.Arrays;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
@ -22,13 +20,14 @@ import net.i2p.data.ByteArray;
Size Max MaxMem From
1K 32 32K tunnel TrivialPreprocessor
*changed to 512 since we disabled resize()
1K 512 512K tunnel FragmentHandler
1K 512 512K I2NP TunnelDataMessage
1K 512 512K tunnel FragmentedMessage
1730 128 216K streaming MessageOutputStream
1572 64 100K UDP InboundMessageState
2K 64 128K UDP IMS
1730 128 216K streaming MessageOutputStream
4K 32 128K I2PTunnelRunner
@ -49,7 +48,7 @@ import net.i2p.data.ByteArray;
* </pre>
*
*/
public final class ByteCache {
public final class ByteCache extends TryCache<ByteArray> {
//private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
private static final Map<Integer, ByteCache> _caches = new ConcurrentHashMap<Integer, ByteCache>(16);
@ -83,10 +82,13 @@ public final class ByteCache {
if (cacheSize * size > MAX_CACHE)
cacheSize = MAX_CACHE / size;
Integer sz = Integer.valueOf(size);
ByteCache cache = _caches.get(sz);
if (cache == null) {
cache = new ByteCache(cacheSize, size);
_caches.put(sz, cache);
ByteCache cache;
synchronized(_caches) {
cache = _caches.get(sz);
if (cache == null) {
cache = new ByteCache(cacheSize, size);
_caches.put(sz, cache);
}
}
cache.resize(cacheSize);
//I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class).error("ByteCache size: " + size + " max: " + cacheSize, new Exception("from"));
@ -103,109 +105,85 @@ public final class ByteCache {
//_log.warn("WARNING: Low memory, clearing byte caches");
}
/** list of available and available entries */
private volatile Queue<ByteArray> _available;
private int _maxCached;
private final int _entrySize;
private volatile long _lastOverflow;
/** do we actually want to cache? Warning - setting to false may NPE, this should be fixed or removed */
private static final boolean _cache = true;
/** how often do we cleanup the cache */
private static final int CLEANUP_FREQUENCY = 33*1000;
/** if we haven't exceeded the cache size in 2 minutes, cut our cache in half */
private static final long EXPIRE_PERIOD = 2*60*1000;
/** @since 0.9.36 */
private static class ByteArrayFactory implements TryCache.ObjectFactory<ByteArray> {
private final int sz;
ByteArrayFactory(int entrySize) {
sz = entrySize;
}
public ByteArray newInstance() {
byte data[] = new byte[sz];
ByteArray rv = new ByteArray(data);
rv.setValid(0);
return rv;
}
}
private ByteCache(int maxCachedEntries, int entrySize) {
if (_cache)
_available = new LinkedBlockingQueue<ByteArray>(maxCachedEntries);
_maxCached = maxCachedEntries;
super(new ByteArrayFactory(entrySize), maxCachedEntries);
_entrySize = entrySize;
_lastOverflow = -1;
SimpleTimer2.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY + (entrySize % 777)); //stagger
int stagger = SystemVersion.isAndroid() ? 0 : (entrySize % 777);
SimpleTimer2.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY + stagger);
I2PAppContext.getGlobalContext().statManager().createRateStat("byteCache.memory." + entrySize, "Memory usage (B)", "Router", new long[] { 10*60*1000 });
}
private void resize(int maxCachedEntries) {
if (_maxCached >= maxCachedEntries) return;
_maxCached = maxCachedEntries;
// make a bigger one, move the cached items over
Queue<ByteArray> newLBQ = new LinkedBlockingQueue<ByteArray>(maxCachedEntries);
ByteArray ba;
while ((ba = _available.poll()) != null)
newLBQ.offer(ba);
_available = newLBQ;
}
/**
* Get the next available structure, either from the cache or a brand new one.
* Returned ByteArray will have valid = 0 and offset = 0.
* Returned ByteArray may or may not be zero, depends on whether
* release(ba) or release(ba, false) was called.
* Which is a problem, you should really specify shouldZero on acquire, not release.
*/
public final ByteArray acquire() {
if (_cache) {
ByteArray rv = _available.poll();
if (rv != null)
return rv;
}
_lastOverflow = System.currentTimeMillis();
byte data[] = new byte[_entrySize];
ByteArray rv = new ByteArray(data);
rv.setValid(0);
//rv.setOffset(0);
return rv;
// disabled since we're now extending TryCache
}
/**
* Put this structure back onto the available cache for reuse
*
*/
@Override
public final void release(ByteArray entry) {
release(entry, true);
}
public final void release(ByteArray entry, boolean shouldZero) {
if (_cache) {
if (entry == null || entry.getData() == null)
return;
if (entry.getData().length != _entrySize) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
if (log.shouldLog(Log.WARN))
log.warn("Bad size", new Exception("I did it"));
return;
}
entry.setValid(0);
entry.setOffset(0);
if (shouldZero)
Arrays.fill(entry.getData(), (byte)0x0);
_available.offer(entry);
if (entry == null || entry.getData() == null)
return;
if (entry.getData().length != _entrySize) {
Log log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
if (log.shouldLog(Log.WARN))
log.warn("Bad size", new Exception("I did it"));
return;
}
}
/**
* Clear everything (memory pressure)
* @since 0.7.14
*/
private void clear() {
_available.clear();
entry.setValid(0);
entry.setOffset(0);
if (shouldZero)
Arrays.fill(entry.getData(), (byte)0x0);
super.release(entry);
}
private class Cleanup implements SimpleTimer.TimedEvent {
public void timeReached() {
I2PAppContext.getGlobalContext().statManager().addRateData("byteCache.memory." + _entrySize, _entrySize * _available.size(), 0);
if (System.currentTimeMillis() - _lastOverflow > EXPIRE_PERIOD) {
// we haven't exceeded the cache size in a few minutes, so lets
// shrink the cache
int toRemove = _available.size() / 2;
for (int i = 0; i < toRemove; i++)
_available.poll();
//if ( (toRemove > 0) && (_log.shouldLog(Log.DEBUG)) )
// _log.debug("Removing " + toRemove + " cached entries of size " + _entrySize);
int origsz;
lock.lock();
try {
origsz = items.size();
if (origsz > 1 && System.currentTimeMillis() - _lastUnderflow > EXPIRE_PERIOD) {
// we haven't exceeded the cache size in a few minutes, so lets
// shrink the cache
int toRemove = origsz / 2;
for (int i = 0; i < toRemove; i++) {
items.remove(items.size() - 1);
}
}
} finally {
lock.unlock();
}
I2PAppContext.getGlobalContext().statManager().addRateData("byteCache.memory." + _entrySize, _entrySize * origsz);
}
@Override

View File

@ -1,9 +1,6 @@
package net.i2p.util;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Like ByteCache but works directly with byte arrays, not ByteArrays.
@ -19,9 +16,6 @@ public final class SimpleByteCache {
private static final int DEFAULT_SIZE = 64;
/** up to this, use ABQ to minimize object churn and for performance; above this, use LBQ for two locks */
private static final int MAX_FOR_ABQ = 64;
/**
* Get a cache responsible for arrays of the given size
*
@ -60,38 +54,32 @@ public final class SimpleByteCache {
bc.clear();
}
/** list of available and available entries */
private Queue<byte[]> _available;
private int _maxCached;
private final TryCache<byte[]> _available;
private final int _entrySize;
/** @since 0.9.36 */
private static class ByteArrayFactory implements TryCache.ObjectFactory<byte[]> {
private final int sz;
ByteArrayFactory(int entrySize) {
sz = entrySize;
}
public byte[] newInstance() {
return new byte[sz];
}
}
private SimpleByteCache(int maxCachedEntries, int entrySize) {
_maxCached = maxCachedEntries;
_available = createQueue();
_available = new TryCache(new ByteArrayFactory(entrySize), maxCachedEntries);
_entrySize = entrySize;
}
private void resize(int maxCachedEntries) {
if (_maxCached >= maxCachedEntries) return;
_maxCached = maxCachedEntries;
// make a bigger one, move the cached items over
Queue<byte[]> newLBQ = createQueue();
byte[] ba;
while ((ba = _available.poll()) != null)
newLBQ.offer(ba);
_available = newLBQ;
// _available is now final, and getInstance() is not used anywhere,
// all call sites just use static acquire()
}
/**
* @return LBQ or ABQ
* @since 0.9.2
*/
private Queue<byte[]> createQueue() {
if (_entrySize <= MAX_FOR_ABQ)
return new ArrayBlockingQueue<byte[]>(_maxCached);
return new LinkedBlockingQueue<byte[]>(_maxCached);
}
/**
* Get the next available array, either from the cache or a brand new one
*/
@ -99,14 +87,11 @@ public final class SimpleByteCache {
return getInstance(size).acquire();
}
/**
/**
* Get the next available array, either from the cache or a brand new one
*/
private byte[] acquire() {
byte[] rv = _available.poll();
if (rv == null)
rv = new byte[_entrySize];
return rv;
return _available.acquire();
}
/**
@ -126,7 +111,7 @@ public final class SimpleByteCache {
return;
// should be safe without this
//Arrays.fill(entry, (byte) 0);
_available.offer(entry);
_available.release(entry);
}
/**

View File

@ -11,6 +11,7 @@ import java.util.concurrent.locks.ReentrantLock;
* @author zab
*
* @param <T>
* @since 0.9.36
*/
public class TryCache<T> {
@ -24,9 +25,10 @@ public class TryCache<T> {
}
private final ObjectFactory<T> factory;
private final int capacity;
private final List<T> items;
private final Lock lock = new ReentrantLock();
protected final int capacity;
protected final List<T> items;
protected final Lock lock = new ReentrantLock();
protected long _lastUnderflow;
/**
* @param factory to be used for creating new instances
@ -47,6 +49,8 @@ public class TryCache<T> {
try {
if (!items.isEmpty()) {
rv = items.remove(items.size() - 1);
} else {
_lastUnderflow = System.currentTimeMillis();
}
} finally {
lock.unlock();

View File

@ -1,3 +1,10 @@
2018-07-10 zzz
* Installer (ticket #1864):
- Fix wrapper selection on Windows 10
- Add support for IzPack 5
* SSU: Sync/notify improvements (ticket #2260)
* Util: Convert more caches to TryCache (ticket #2263)
2018-07-08 zzz
* i2psnark: Add comment icon (ticket #2278)
* NTCP2: Avoid possible NPEs (ticket #2286)

View File

@ -102,6 +102,17 @@
<res id="XInfoPanel.info" src="installer/resources/start-i2p.txt" />
</resources>
<dynamicvariables>
<variable name="datamodel" value="${SYSTEM_sun_arch_data_model}"/>
</dynamicvariables>
<conditions>
<condition type="variable" id="is64bit">
<name>datamodel</name>
<value>64</value>
</condition>
</conditions>
<panels>
<panel classname="HelloPanel"/>
<panel classname="InfoPanel"/>
@ -115,9 +126,9 @@
<!--
Using the condition this way, the panel is shown on everything *but* Windows.
-->
<panel classname="XInfoPanel" condition="!izpack.windowsinstall" />
<panel classname="SimpleFinishPanel"/>
</panels>
<panel classname="XInfoPanel" condition="!izpack.windowsinstall" />
<panel classname="SimpleFinishPanel"/>
</panels>
<packs>
<pack name="Base" required="yes">
@ -136,13 +147,6 @@
<parsable targetfile="$INSTALL_PATH/runplain.sh" type="shell"> <os family="unix" /> </parsable>
<parsable targetfile="$INSTALL_PATH/Start I2P Router.app/Contents/MacOS/i2prouter" type="shell" os="mac" />
<conditions>
<condition type="variable" id="is64bit">
<name>SYSTEM_sun_arch_data_model</name>
<value>64</value>
</condition>
</conditions>
<!-- postinstall stuff for windows -->
<!-- Wrapper for 32bit Windows JVM -->
<executable targetfile="$INSTALL_PATH/utility.jar"

399
installer/install5.xml Normal file
View File

@ -0,0 +1,399 @@
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
<!--
This is for izpack 5.
See install.xml for izpack 4.
-->
<izpack:installation version="5.0"
xmlns:izpack="http://izpack.org/schema/installation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://izpack.org/schema/installation http://izpack.org/schema/5.0/izpack-installation-5.0.xsd">
<info>
<appname>i2p</appname>
<appversion>0.9.35</appversion>
<authors>
<author name="I2P" email="https://geti2p.net/"/>
</authors>
<url>https://geti2p.net/</url>
<javaversion>1.7</javaversion>
<!-- adding this element will make the installer attempt to launch itself with administrator permissions,
but see http://www.nabble.com/Classpath-security-issues-on-Vista-td22456230.html
which says it isn't sufficient:
Just to let you know that I managed to identify and resolve the problem (in
case anyone else has it). The default installation directory for Vista is
under "Program Files" which is a "special" directory which can only be
written to (create sub-directories) by administrators. However, stupid
Vista downgrades an administrator to a normal user when the program is run
via the application shortcut menu. As you suggested, I added a script which
runs ICACLS which resolved the problem, i.e.
icacls %1 /grant Users:F /T > priv.log
The command needs to be run as a Process rather than as an executable tag in
order to pass $INSTALL_PATH as a parameter.
-->
<run-privileged condition="izpack.windowsinstall.vista|izpack.windowsinstall.7"/>
</info>
<guiprefs width="590" height="356" resizable="yes">
<!--
Not in 5.1.2, pick another one
https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491730/GUI+Preferences
<laf name="liquid">
<os family="unix"/>
</laf>
-->
<!-- full names, not iso3 codes -->
<modifier key="langDisplayType" value="native" />
</guiprefs>
<locale>
<langpack iso3="eng"/>
<langpack iso3="bra"/>
<langpack iso3="cat"/>
<langpack iso3="ces"/>
<langpack iso3="chn"/>
<langpack iso3="dan"/>
<langpack iso3="deu"/>
<langpack iso3="ell"/>
<langpack iso3="fin"/>
<langpack iso3="fra"/>
<langpack iso3="hun"/>
<langpack iso3="idn"/>
<langpack iso3="ita"/>
<langpack iso3="jpn"/>
<langpack iso3="kor"/>
<langpack iso3="msa"/>
<langpack iso3="nld"/>
<langpack iso3="nor"/>
<langpack iso3="pol"/>
<langpack iso3="prt"/>
<langpack iso3="ron"/>
<langpack iso3="rus"/>
<langpack iso3="slk"/>
<langpack iso3="spa"/>
<langpack iso3="srp"/>
<langpack iso3="swe"/>
<langpack iso3="tur"/>
<langpack iso3="twn"/>
<langpack iso3="ukr"/>
<!--
"WARNING: No locale for:"
<langpack iso3="eus"/>
<langpack iso3="fa"/>
<langpack iso3="glg"/>
-->
</locale>
<!--
The <os> tag can be used to restrict the inclusion into the uninstaller
to a specific operating system family, architecture or version.
The inclusion into the installer will be always done.
Here's a sample :
<native type="izpack" name="ShellLink.dll">
<os family="windows"/>
</native>
This doesn't appear to be necessary, the dlls don't get put in Uninstaller/uninstaller.jar on linux
-->
<natives>
<native type="izpack" name="ShellLink.dll" />
<native type="izpack" name="ShellLink_x64.dll" />
<!--
https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491532/Advanced+Features
<native type="izpack" name="WinSetupAPI.dll" />
<native type="izpack" name="WinSetupAPI_x64.dll" />
https://izpack.atlassian.net/wiki/spaces/IZPACK/pages/491676/RegistryInstallerListener+RegistryUninstallerListener
<native type="3rdparty" name="COIOSHelper.dll" />
<native type="3rdparty" name="COIOSHelper_x64.dll" />
-->
</natives>
<resources>
<res id="Installer.image" src="installer/resources/i2plogo.png" />
<res id="InfoPanel.info" src="installer/resources/readme.license.txt"/>
<!-- <res id="ProcessPanel.Spec.xml" src="installer/resources/ProcessPanel.Spec.xml"/> -->
<res id="shortcutSpec.xml" src="installer/resources/shortcutSpec.xml" />
<res id="XInfoPanel.info" src="installer/resources/start-i2p.txt" />
</resources>
<variables>
<!-- desktop shortcuts enabled by default in ShortcutPanel -->
<variable name="DesktopShortcutCheckboxEnabled" value="true" />
</variables>
<dynamicvariables>
<variable name="datamodel" value="${SYSTEM[sun.arch.data.model]}"/>
</dynamicvariables>
<conditions>
<condition type="variable" id="is64bit">
<name>datamodel</name>
<value>64</value>
</condition>
</conditions>
<panels>
<panel classname="HelloPanel"/>
<panel classname="InfoPanel"/>
<panel classname="TargetPanel"/>
<!-- In 5.1.2, PacksPanel will NPE at install time if before TargetPanel -->
<panel classname="PacksPanel"><os family="windows" /></panel>
<panel classname="InstallPanel"/>
<!-- In 5.1.2, ShortcutPanel must be after InstallPanel, so the .ico files will be there,
unless <lateShortcutInstall/> is set in shorcutSpec.xml.
If you don't do this right, the shortcuts won't have our icons.
-->
<panel classname="ShortcutPanel"><os family="windows" /></panel>
<!--
Using the condition this way, the panel is shown on everything *but* Windows.
Fails in console mode: Installer says:
No console mode helper found for class com.izforge.izpack.panels.xinfo.XInfoPanel, panel type will be skipped in console mode installation
No automation helper found for class com.izforge.izpack.panels.xinfo.XInfoPanel, panel type will be skipped in automated installation
But isn't actually skipped when installing with -console:
SEVERE: com.izforge.izpack.api.exception.IzPackException: Console implementation not found for panel: com.izforge.izpack.panels.xinfo.XInfoPanel
-->
<panel classname="XInfoPanel" condition="!izpack.windowsinstall" />
<panel classname="SimpleFinishPanel"/>
</panels>
<packs>
<pack name="Base" required="yes">
<description>Base installation files</description>
<!-- non-jars -->
<fileset dir="pkg-temp" excludes="**/*.jar" targetdir="$INSTALL_PATH"/>
<!-- pack200 jars -->
<fileset dir="pkg-temp" includes="**/*.jar"
excludes="lib/commons-logging.jar lib/jasper-compiler.jar lib/jetty-java5-threadpool.jar lib/jetty-sslengine.jar lib/jbigi.jar"
targetdir="$INSTALL_PATH">
<pack200/>
</fileset>
<!-- non-pack200 jars -->
<fileset dir="pkg-temp"
includes="lib/commons-logging.jar lib/jasper-compiler.jar lib/jetty-java5-threadpool.jar lib/jetty-sslengine.jar lib/jbigi.jar"
targetdir="$INSTALL_PATH">
</fileset>
<!--
Do variable substitution in these files. See:
http://www.javalobby.org/forums/thread.jspa?threadID=15967&tstart=0
and the izpack docs for some guidance.
-->
<parsable targetfile="$INSTALL_PATH/wrapper.config" type="plain" />
<parsable targetfile="$INSTALL_PATH/scripts/home.i2p.i2prouter" type="plain"> <os family="unix" /> </parsable>
<parsable targetfile="$INSTALL_PATH/i2prouter" type="shell"> <os family="unix" /> </parsable>
<parsable targetfile="$INSTALL_PATH/eepget" type="shell"> <os family="unix" /> </parsable>
<parsable targetfile="$INSTALL_PATH/eepget.bat" type="shell"><os family="windows" /></parsable>
<parsable targetfile="$INSTALL_PATH/runplain.sh" type="shell"> <os family="unix" /> </parsable>
<parsable targetfile="$INSTALL_PATH/Start I2P Router.app/Contents/MacOS/i2prouter" type="shell"><os family="mac" /></parsable>
<!-- postinstall stuff for windows -->
<!-- Wrapper for 32bit Windows JVM -->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall"
keep="true"
failure="warn"
condition="!is64bit">
<os family="windows" />
<args>
<arg value="copy" />
<arg value="$INSTALL_PATH\lib\wrapper\win32\I2Psvc.exe" />
<arg value="$INSTALL_PATH" />
</args>
</executable>
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall"
keep="true"
failure="warn"
condition="!is64bit">
<os family="windows" />
<args>
<arg value="copy" />
<arg value="$INSTALL_PATH\lib\wrapper\win32\wrapper.dll" />
<arg value="$INSTALL_PATH\lib" />
</args>
</executable>
<!-- wrapper for 64bit Windows JVM -->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall"
keep="true"
failure="warn"
condition="is64bit">
<os family="windows" />
<args>
<arg value="copy" />
<arg value="$INSTALL_PATH\lib\wrapper\win64\I2Psvc.exe" />
<arg value="$INSTALL_PATH" />
</args>
</executable>
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall"
keep="true"
failure="warn"
condition="is64bit">
<os family="windows" />
<args>
<arg value="copy" />
<arg value="$INSTALL_PATH\lib\wrapper\win64\wrapper.dll" />
<arg value="$INSTALL_PATH\lib" />
</args>
</executable>
<!--
We still copy the 32 bit version of wrapper.dll (even with a
64bit jvm) so that if a 32 bit jvm is installed in the future,
nothing breaks.
-->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall"
keep="true"
failure="warn"
condition="is64bit">
<os family="windows" />
<args>
<arg value="copy" />
<arg value="$INSTALL_PATH\lib\wrapper\win32\wrapper.dll" />
<arg value="$INSTALL_PATH\lib\wrapper-windows-x86-32.dll" />
</args>
</executable>
<!-- workaround for bad default path for wrapper.log in Windows. -->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall" keep="true">
<os family="windows" />
<args>
<arg value="fixwinpaths" />
<arg value="$INSTALL_PATH\wrapper.config" />
</args>
</executable>
<!-- Now we'll get rid of the UNIX-only stuff -->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall" keep="true" failure="warn">
<os family="windows" />
<args>
<arg value="delete" />
<arg value="$INSTALL_PATH\i2prouter" />
<arg value="$INSTALL_PATH\install_i2p_service_unix" />
<arg value="$INSTALL_PATH\install-headless.txt" />
<arg value="$INSTALL_PATH\runplain.sh" />
<arg value="$INSTALL_PATH\osid" />
<arg value="$INSTALL_PATH\postinstall.sh" />
<arg value="$INSTALL_PATH\uninstall_i2p_service_unix" />
<arg value="$INSTALL_PATH\lib\wrapper" />
<arg value="$INSTALL_PATH\eepget" />
<arg value="$INSTALL_PATH/Start I2P Router.app" />
<arg value="$INSTALL_PATH/net.i2p.router.plist.template" />
<arg value="$INSTALL_PATH/install_i2p_service_osx.command" />
<arg value="$INSTALL_PATH/uninstall_i2p_service_osx.command" />
<arg value="$INSTALL_PATH/man" />
<arg value="$INSTALL_PATH/locale" />
<!-- Placeholder for an OSX 'shortcut' to the router console
<arg value="$INSTALL_PATH/I2P Router Console.webloc" />
-->
</args>
</executable>
<!-- workaround for vista permission problems - see comments above -->
<executable targetfile="$INSTALL_PATH/fixperms.bat" type="bin" stage="postinstall" keep="true" failure="warn"
condition="!izpack.windowsinstall.xp+!izpack.windowsinstall.2003" >
<os family="windows" />
<args>
<arg value="$INSTALL_PATH" />
</args>
</executable>
<!-- else delete it -->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall" keep="true" failure="warn" condition="izpack.windowsinstall.xp|izpack.windowsinstall.2003">
<os family="windows" />
<args>
<arg value="delete" />
<arg value="$INSTALL_PATH\fixperms.bat" />
</args>
</executable>
<!--
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall" keep="true" failure="warn">
<os family="windows" />
<args>
<arg value="exec" />
<arg value="$INSTALL_PATH" />
<arg value="$INSTALL_PATH\I2Psvc.exe" />
<arg value="-c" />
<arg value="$INSTALL_PATH\wrapper.config" />
</args>
</executable>
-->
<!--
and now we delete the installer utility jar.
I moved this out of installer/ because the directory
couldn't be deleted while the jar was active and would
remain on the system.
This, however, works fine.
-->
<executable targetfile="$INSTALL_PATH/utility.jar"
type="jar"
class="net.i2p.installer.Main"
stage="postinstall" keep="false" failure="warn">
<os family="windows" />
<args>
<arg value="delete" />
<arg value="$INSTALL_PATH/utility.jar" />
</args>
</executable>
<!-- postinstall stuff for *nix -->
<!-- stage=never means chmod a+x -->
<executable targetfile="$INSTALL_PATH/postinstall.sh" type="bin" stage="never" keep="true" failure="warn"><os family="unix" /></executable>
<executable targetfile="$INSTALL_PATH/postinstall.sh" type="bin" stage="postinstall" keep="true" failure="warn"><os family="unix" />
<args><arg value="$INSTALL_PATH" /></args></executable>
<!--
Removal of the I2P service in Windows should be done in the base pack
so that even if a user installed the service manually it will still be
removed when uninstalling.
-->
<executable targetfile="$INSTALL_PATH/uninstall_i2p_service_winnt.bat" stage="uninstall"><os family="windows" /></executable>
</pack>
<!-- to disable by default, add preselected="no" -->
<pack name="Windows Service" required="no" preselected="no">
<description>Automatically start I2P in the background</description>
<os family="windows" />
<executable targetfile="$INSTALL_PATH/set_config_dir_for_nt_service.bat" stage="postinstall" failure="warn" keep="true" />
<executable targetfile="$INSTALL_PATH/install_i2p_service_winnt.bat" stage="postinstall" failure="warn" keep="true" />
<executable targetfile="$INSTALL_PATH/I2Psvc.exe" stage="postinstall" failure="warn" keep="true">
<args>
<arg value="-t" />
<arg value="$INSTALL_PATH\wrapper.config" />
</args>
</executable>
</pack>
</packs>
</izpack:installation>

View File

@ -106,6 +106,7 @@
6. Change revision in:
- `history.txt`
- `installer/install.xml`
- `installer/install5.xml`
- `core/java/src/net/i2p/CoreVersion.java`
- `router/java/src/net/i2p/router/RouterVersion.java`
- (change to BUILD = 0 and EXTRA = "")

View File

@ -104,7 +104,7 @@ fi
chmod 755 ./eepget
rm -rf ./icons ./lib/wrapper
rm -f ./lib/*.dll /*.bat ./*.cmd ./*.exe ./utility.jar
rm -f ./lib/*.dll ./*.bat ./*.cmd ./*.exe ./utility.jar
if [ ! `echo $HOST_OS |grep osx` ]; then
rm -rf ./Start\ I2P\ Router.app

View File

@ -882,14 +882,6 @@ public class HandshakeState implements Destroyable {
return symmetric.getChainingKey();
}
/**
* I2P for getting current hash for siphash calculation
* @return NOT a copy, do not modify
*/
public byte[] getHash() {
return symmetric.getHandshakeHash();
}
/**
* I2P debug
*/

View File

@ -18,7 +18,7 @@ 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 = "";

View File

@ -343,8 +343,6 @@ class NTCP2Payload {
* Big endian.
* Same as DataHelper.fromLong(src, offset, 8) but allows negative result
*
* Package private for NTCP2Payload.
*
* @throws ArrayIndexOutOfBoundsException
* @since 0.9.36
*/

View File

@ -442,7 +442,7 @@ class OutboundNTCP2State implements EstablishState {
tk = new SessionKey(temp_key);
byte[] ask_master = doHMAC(ctx, tk, ASK);
byte[] tmp = new byte[32 + SIPHASH.length];
byte[] hash = state.getHash();
byte[] hash = state.getHandshakeHash();
System.arraycopy(hash, 0, tmp, 0, 32);
System.arraycopy(SIPHASH, 0, tmp, 32, SIPHASH.length);
tk = new SessionKey(ask_master);

View File

@ -260,7 +260,7 @@ class InboundMessageFragments /*implements UDPTransport.PartialACKSource */{
// By calling add(), this also is a failsafe against possible
// races in OutboundMessageFragments.
if (newAck && from.getOutboundMessageCount() > 0)
_outbound.add(from);
_outbound.add(from, 0);
return rv;
}

View File

@ -51,11 +51,6 @@ class OutboundMessageFragments {
*/
private Iterator<PeerState> _iterator;
/**
* Avoid sync in add() if possible (not 100% reliable)
*/
private volatile boolean _isWaiting;
private volatile boolean _alive;
private final PacketBuilder _builder;
@ -104,7 +99,7 @@ class OutboundMessageFragments {
_alive = false;
_activePeers.clear();
synchronized (_activePeers) {
_activePeers.notifyAll();
_activePeers.notify();
}
}
@ -165,7 +160,7 @@ class OutboundMessageFragments {
// will throw IAE if peer == null
OutboundMessageState state = new OutboundMessageState(_context, msg, peer);
peer.add(state);
add(peer);
add(peer, state.fragmentSize(0));
} catch (IllegalArgumentException iae) {
_transport.failed(msg, "Peer disconnected quickly");
return;
@ -182,7 +177,7 @@ class OutboundMessageFragments {
if (peer == null)
throw new RuntimeException("null peer for " + state);
peer.add(state);
add(peer);
add(peer, state.fragmentSize(0));
//_context.statManager().addRateData("udp.outboundActiveCount", active, 0);
}
@ -195,10 +190,15 @@ class OutboundMessageFragments {
if (peer == null)
throw new RuntimeException("null peer");
int sz = states.size();
int min = peer.fragmentSize();
for (int i = 0; i < sz; i++) {
peer.add(states.get(i));
OutboundMessageState state = states.get(i);
peer.add(state);
int fsz = state.fragmentSize(0);
if (fsz < min)
min = fsz;
}
add(peer);
add(peer, min);
//_context.statManager().addRateData("udp.outboundActiveCount", active, 0);
}
@ -211,10 +211,10 @@ class OutboundMessageFragments {
* There are larger chances of adding the PeerState "behind" where
* the iterator is now... but these issues are the same as before concurrentification.
*
* @param the minimum size we can send, or 0 to always notify
* @since 0.8.9
*/
public void add(PeerState peer) {
boolean wasEmpty = _activePeers.isEmpty();
public void add(PeerState peer, int size) {
boolean added = _activePeers.add(peer);
if (added) {
if (_log.shouldLog(Log.DEBUG))
@ -229,9 +229,9 @@ class OutboundMessageFragments {
// no, this doesn't always work.
// Also note that the iterator in getNextVolley may have alreay passed us,
// or not reflect the addition.
if (_isWaiting || wasEmpty) {
if (added || size <= 0 || peer.getSendWindowBytesRemaining() >= size) {
synchronized (_activePeers) {
_activePeers.notifyAll();
_activePeers.notify();
}
}
}
@ -321,7 +321,6 @@ class OutboundMessageFragments {
// if we've gone all the way through the loop, wait
// ... unless nextSendDelay says we have more ready now
if (states == null && peersProcessed >= _activePeers.size() && nextSendDelay > 0) {
_isWaiting = true;
peersProcessed = 0;
// why? we do this in the loop one at a time
//finishMessages();
@ -341,7 +340,6 @@ class OutboundMessageFragments {
_log.debug("Woken up while waiting");
}
}
_isWaiting = false;
//} else {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("dont wait: alive=" + _alive + " state = " + state);

View File

@ -34,7 +34,7 @@ class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
* (since ByteCache only maintains once instance for each size)
* Used in BatchedPreprocessor; see add'l comments there
*/
protected static final ByteCache _dataCache = ByteCache.getInstance(32, PREPROCESSED_SIZE);
protected static final ByteCache _dataCache = ByteCache.getInstance(512, PREPROCESSED_SIZE);
public TrivialPreprocessor(RouterContext ctx) {
_context = ctx;