forked from I2P_Developers/i2p.i2p
merge of '44418e8f7048de3ac06833176b607d55afc94bdd'
and '6cd2f8bb60720e3aeeb500d67b3f162f2831c3fa'
This commit is contained in:
@@ -39,6 +39,7 @@ import net.i2p.I2PAppContext;
|
||||
public class Daemon {
|
||||
public static final String VERSION = "2.0.3";
|
||||
private static final Daemon _instance = new Daemon();
|
||||
private boolean _running;
|
||||
|
||||
/**
|
||||
* Update the router and published address books using remote data from the
|
||||
@@ -126,6 +127,7 @@ public class Daemon {
|
||||
}
|
||||
|
||||
public void run(String[] args) {
|
||||
_running = true;
|
||||
String settingsLocation = "config.txt";
|
||||
File homeFile;
|
||||
if (args.length > 0) {
|
||||
@@ -166,7 +168,7 @@ public class Daemon {
|
||||
// Static method, and redundent Thread.currentThread().sleep(5*60*1000);
|
||||
} catch (InterruptedException ie) {}
|
||||
|
||||
while (true) {
|
||||
while (_running) {
|
||||
long delay = Long.parseLong((String) settings.get("update_delay"));
|
||||
if (delay < 1) {
|
||||
delay = 1;
|
||||
@@ -179,6 +181,8 @@ public class Daemon {
|
||||
}
|
||||
} catch (InterruptedException exp) {
|
||||
}
|
||||
if (!_running)
|
||||
break;
|
||||
settings = ConfigParser.parse(settingsFile, defaultSettings);
|
||||
}
|
||||
}
|
||||
@@ -192,4 +196,9 @@ public class Daemon {
|
||||
_instance.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
_instance._running = false;
|
||||
wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,4 +51,9 @@ public class DaemonThread extends Thread {
|
||||
//}
|
||||
Daemon.main(this.args);
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
Daemon.stop();
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*
|
||||
*/
|
||||
public class Servlet extends HttpServlet {
|
||||
private Thread thread;
|
||||
private DaemonThread thread;
|
||||
private String nonce;
|
||||
private static final String PROP_NONCE = "addressbook.nonce";
|
||||
|
||||
@@ -88,4 +88,9 @@ public class Servlet extends HttpServlet {
|
||||
//System.out.println("INFO: config root under " + args[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.thread.halt();
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
private I2PSnarkUtil _util;
|
||||
private PeerCoordinatorSet _peerCoordinatorSet;
|
||||
private ConnectionAcceptor _connectionAcceptor;
|
||||
private Thread _monitor;
|
||||
private boolean _running;
|
||||
|
||||
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
||||
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
|
||||
@@ -78,15 +80,22 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
* for i2cp host/port or i2psnark.dir
|
||||
*/
|
||||
public void start() {
|
||||
_running = true;
|
||||
_peerCoordinatorSet = new PeerCoordinatorSet();
|
||||
_connectionAcceptor = new ConnectionAcceptor(_util);
|
||||
int minutes = getStartupDelayMinutes();
|
||||
_messages.add(_("Adding torrents in {0} minutes", minutes));
|
||||
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
|
||||
monitor.setDaemon(true);
|
||||
monitor.start();
|
||||
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
|
||||
_monitor.start();
|
||||
_context.addShutdownTask(new SnarkManagerShutdown());
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
_running = false;
|
||||
_monitor.interrupt();
|
||||
_connectionAcceptor.halt();
|
||||
(new SnarkManagerShutdown()).run();
|
||||
}
|
||||
|
||||
/** hook to I2PSnarkUtil for the servlet */
|
||||
public I2PSnarkUtil util() { return _util; }
|
||||
|
||||
@@ -150,7 +150,7 @@ public class TrackerClient extends I2PAppThread
|
||||
continue;
|
||||
String dest = _util.lookup(url.substring(7, slash));
|
||||
if (dest == null) {
|
||||
_log.error("Announce host unknown: [" + url + "]");
|
||||
_log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
|
||||
continue;
|
||||
}
|
||||
if (primary.startsWith("http://" + dest))
|
||||
@@ -258,7 +258,7 @@ public class TrackerClient extends I2PAppThread
|
||||
tr.started = true;
|
||||
|
||||
Set peers = info.getPeers();
|
||||
tr.seenPeers = peers.size();
|
||||
tr.seenPeers = info.getPeerCount();
|
||||
if (coordinator.trackerSeenPeers < tr.seenPeers) // update rising number quickly
|
||||
coordinator.trackerSeenPeers = tr.seenPeers;
|
||||
if ( (left > 0) && (!completed) ) {
|
||||
@@ -269,6 +269,7 @@ public class TrackerClient extends I2PAppThread
|
||||
Iterator it = ordered.iterator();
|
||||
while (it.hasNext()) {
|
||||
Peer cur = (Peer)it.next();
|
||||
// FIXME if id == us || dest == us continue;
|
||||
// only delay if we actually make an attempt to add peer
|
||||
if(coordinator.addPeer(cur)) {
|
||||
int delay = DELAY_MUL;
|
||||
@@ -356,6 +357,10 @@ public class TrackerClient extends I2PAppThread
|
||||
+ "&downloaded=" + downloaded
|
||||
+ "&left=" + left
|
||||
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
|
||||
if (left <= 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
||||
s += "&numwant=0";
|
||||
else
|
||||
s += "&numwant=" + _util.getMaxConnections();
|
||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
|
||||
tr.lastRequestTime = System.currentTimeMillis();
|
||||
@@ -430,7 +435,7 @@ public class TrackerClient extends I2PAppThread
|
||||
url.getPort() < 0;
|
||||
}
|
||||
|
||||
private class Tracker
|
||||
private static class Tracker
|
||||
{
|
||||
String announce;
|
||||
boolean isPrimary;
|
||||
|
||||
@@ -23,6 +23,7 @@ package org.klomp.snark;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +38,8 @@ public class TrackerInfo
|
||||
private final String failure_reason;
|
||||
private final int interval;
|
||||
private final Set peers;
|
||||
private int complete;
|
||||
private int incomplete;
|
||||
|
||||
public TrackerInfo(InputStream in, byte[] my_id, MetaInfo metainfo)
|
||||
throws IOException
|
||||
@@ -68,11 +71,26 @@ public class TrackerInfo
|
||||
throw new InvalidBEncodingException("No interval given");
|
||||
else
|
||||
interval = beInterval.getInt();
|
||||
|
||||
BEValue bePeers = (BEValue)m.get("peers");
|
||||
if (bePeers == null)
|
||||
throw new InvalidBEncodingException("No peer list");
|
||||
peers = Collections.EMPTY_SET;
|
||||
else
|
||||
peers = getPeers(bePeers.getList(), my_id, metainfo);
|
||||
|
||||
BEValue bev = (BEValue)m.get("complete");
|
||||
if (bev != null) try {
|
||||
complete = bev.getInt();
|
||||
if (complete < 0)
|
||||
complete = 0;
|
||||
} catch (InvalidBEncodingException ibe) {}
|
||||
|
||||
bev = (BEValue)m.get("incomplete");
|
||||
if (bev != null) try {
|
||||
incomplete = bev.getInt();
|
||||
if (incomplete < 0)
|
||||
incomplete = 0;
|
||||
} catch (InvalidBEncodingException ibe) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +133,12 @@ public class TrackerInfo
|
||||
return peers;
|
||||
}
|
||||
|
||||
public int getPeerCount()
|
||||
{
|
||||
int pc = peers == null ? 0 : peers.size();
|
||||
return Math.max(pc, complete + incomplete - 1);
|
||||
}
|
||||
|
||||
public String getFailureReason()
|
||||
{
|
||||
return failure_reason;
|
||||
@@ -132,6 +156,8 @@ public class TrackerInfo
|
||||
return "TrackerInfo[FAILED: " + failure_reason + "]";
|
||||
else
|
||||
return "TrackerInfo[interval=" + interval
|
||||
+ (complete > 0 ? (", complete=" + complete) : "" )
|
||||
+ (incomplete > 0 ? (", incomplete=" + incomplete) : "" )
|
||||
+ ", peers=" + peers + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,12 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
_manager.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
_manager.stop();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
req.setCharacterEncoding("UTF-8");
|
||||
|
||||
@@ -124,13 +124,13 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
* Tweak that first HTTP response line (HTTP 200 OK, etc)
|
||||
*
|
||||
*/
|
||||
protected String filterResponseLine(String line) {
|
||||
protected static String filterResponseLine(String line) {
|
||||
return line;
|
||||
}
|
||||
|
||||
/** we ignore any potential \r, since we trim it on write anyway */
|
||||
private static final byte NL = '\n';
|
||||
private boolean isNL(byte b) { return (b == NL); }
|
||||
private static boolean isNL(byte b) { return (b == NL); }
|
||||
|
||||
/** ok, received, now munge & write it */
|
||||
private void writeHeader() throws IOException {
|
||||
@@ -275,7 +275,8 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
_context.statManager().addRateData("i2ptunnel.httpExpanded", (long)expanded, end-start);
|
||||
}
|
||||
}
|
||||
private class InternalGZIPInputStream extends GZIPInputStream {
|
||||
|
||||
private static class InternalGZIPInputStream extends GZIPInputStream {
|
||||
public InternalGZIPInputStream(InputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
@@ -318,6 +319,7 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
return super.toString() + ": " + _in;
|
||||
}
|
||||
|
||||
/*******
|
||||
public static void main(String args[]) {
|
||||
String simple = "HTTP/1.1 200 OK\n" +
|
||||
"foo: bar\n" +
|
||||
@@ -367,7 +369,6 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
"A:\n" +
|
||||
"\n";
|
||||
|
||||
/* */
|
||||
test("Simple", simple, true);
|
||||
test("Filtered", filtered, true);
|
||||
test("Filtered windows", winfilter, true);
|
||||
@@ -382,7 +383,6 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
test("Invalid (bad headers)", invalid5, true);
|
||||
test("Invalid (bad headers2)", invalid6, false);
|
||||
test("Invalid (bad headers3)", invalid7, false);
|
||||
/* */
|
||||
}
|
||||
|
||||
private static void test(String name, String orig, boolean shouldPass) {
|
||||
@@ -401,4 +401,5 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
System.out.println("Properly fails with " + e.getMessage());
|
||||
}
|
||||
}
|
||||
******/
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
sockMgr.getSession().destroySession();
|
||||
} catch (I2PException ex) {
|
||||
_log.error("Error destroying the session", ex);
|
||||
System.exit(1);
|
||||
//System.exit(1);
|
||||
}
|
||||
l.log("Server shut down.");
|
||||
open = false;
|
||||
|
||||
@@ -11,7 +11,6 @@ import java.util.Set;
|
||||
|
||||
import net.i2p.router.startup.ClientAppConfig;
|
||||
import net.i2p.router.startup.LoadClientAppsJob;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
|
||||
@@ -19,15 +18,19 @@ import org.mortbay.jetty.Server;
|
||||
* Saves changes to clients.config or webapps.config
|
||||
*/
|
||||
public class ConfigClientsHandler extends FormHandler {
|
||||
private Log configClient_log;
|
||||
private Map _settings;
|
||||
|
||||
public ConfigClientsHandler() {
|
||||
configClient_log = ContextHelper.getContext(null).logManager().getLog(ConfigClientsHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processForm() {
|
||||
// set action for when CR is hit in a text input box
|
||||
if (_action.length() <= 0) {
|
||||
String url = getJettyString("pluginURL");
|
||||
if (url != null && url.length() > 0)
|
||||
_action = "Install Plugin";
|
||||
else
|
||||
_action = "Save Client Configuration";
|
||||
}
|
||||
|
||||
if (_action.equals(_("Save Client Configuration"))) {
|
||||
saveClientChanges();
|
||||
return;
|
||||
@@ -200,7 +203,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
return;
|
||||
}
|
||||
ClientAppConfig ca = clients.get(i);
|
||||
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), configClient_log);
|
||||
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), _log);
|
||||
addFormNotice(_("Client") + ' ' + _(ca.clientName) + ' ' + _("started") + '.');
|
||||
}
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled,
|
||||
"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
|
||||
ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit),
|
||||
true, false, false, true);
|
||||
true, false, false, true, !ca.disabled);
|
||||
}
|
||||
|
||||
if ("new".equals(_edit))
|
||||
renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false, false, false, false);
|
||||
renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false, false, false, false, false);
|
||||
buf.append("</table>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
String val = props.getProperty(name);
|
||||
renderForm(buf, app, app, !"addressbook".equals(app),
|
||||
"true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war",
|
||||
false, false, false, false, false);
|
||||
false, false, false, false, false, true);
|
||||
}
|
||||
}
|
||||
buf.append("</table>\n");
|
||||
@@ -149,7 +149,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
boolean enableStop = !Boolean.valueOf(appProps.getProperty("disableStop")).booleanValue();
|
||||
renderForm(buf, app, app, false,
|
||||
"true".equals(val), false, desc.toString(), false, false,
|
||||
updateURL != null, enableStop, true);
|
||||
updateURL != null, enableStop, true, true);
|
||||
}
|
||||
}
|
||||
buf.append("</table>\n");
|
||||
@@ -160,7 +160,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
private void renderForm(StringBuilder buf, String index, String name, boolean urlify,
|
||||
boolean enabled, boolean ro, String desc, boolean edit,
|
||||
boolean showEditButton, boolean showUpdateButton, boolean showStopButton,
|
||||
boolean showDeleteButton) {
|
||||
boolean showDeleteButton, boolean showStartButton) {
|
||||
buf.append("<tr><td class=\"mediumtags\" align=\"right\" width=\"25%\">");
|
||||
if (urlify && enabled) {
|
||||
String link = "/";
|
||||
@@ -183,7 +183,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
buf.append("disabled=\"true\" ");
|
||||
}
|
||||
buf.append("></td><td align=\"center\" width=\"15%\">");
|
||||
if ((!enabled) && !edit) {
|
||||
if (showStartButton && (!ro) && !edit) {
|
||||
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" >" + _("Start") + "<span class=hide> ").append(index).append("</span></button>");
|
||||
}
|
||||
if (showEditButton && (!edit) && !ro)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -31,9 +33,12 @@ public class NavHelper {
|
||||
if (_apps.isEmpty())
|
||||
return "";
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
for (Iterator<String> iter = _apps.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = iter.next();
|
||||
List<String> l = new ArrayList(_apps.keySet());
|
||||
Collections.sort(l);
|
||||
for (String name : l) {
|
||||
String path = _apps.get(name);
|
||||
if (path == null)
|
||||
continue;
|
||||
buf.append(" <a target=\"_top\" href=\"").append(path).append("\">");
|
||||
buf.append(name).append("</a>");
|
||||
}
|
||||
|
||||
@@ -286,11 +286,11 @@ public class NetDbRenderer {
|
||||
buf.append("<b>").append(DataHelper.stripHTML(style)).append(":</b> ");
|
||||
int cost = addr.getCost();
|
||||
if (!((style.equals("SSU") && cost == 5) || (style.equals("NTCP") && cost == 10)))
|
||||
buf.append('[').append("cost").append('=').append("" + cost).append("] ");
|
||||
buf.append('[').append(_("cost")).append('=').append("" + cost).append("] ");
|
||||
for (Iterator optIter = addr.getOptions().keySet().iterator(); optIter.hasNext(); ) {
|
||||
String name = (String)optIter.next();
|
||||
String val = addr.getOptions().getProperty(name);
|
||||
buf.append('[').append(DataHelper.stripHTML(name)).append('=').append(DataHelper.stripHTML(val)).append("] ");
|
||||
buf.append('[').append(_(DataHelper.stripHTML(name))).append('=').append(DataHelper.stripHTML(val)).append("] ");
|
||||
}
|
||||
}
|
||||
buf.append("</td></tr>\n");
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.mortbay.jetty.Server;
|
||||
* @author zzz
|
||||
*/
|
||||
public class PluginStarter implements Runnable {
|
||||
private RouterContext _context;
|
||||
protected RouterContext _context;
|
||||
static final String PREFIX = "plugin.";
|
||||
static final String ENABLED = ".startOnLoad";
|
||||
private static final String[] STANDARD_WEBAPPS = { "i2psnark", "i2ptunnel", "susidns",
|
||||
@@ -223,7 +223,8 @@ public class PluginStarter implements Runnable {
|
||||
if (name != null && name.length() > 0)
|
||||
NavHelper.unregisterApp(name);
|
||||
|
||||
log.error("Stopping plugin: " + appName);
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn("Stopping plugin: " + appName);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -426,7 +427,8 @@ public class PluginStarter implements Runnable {
|
||||
}
|
||||
try {
|
||||
addPath(f.toURI().toURL());
|
||||
log.error("INFO: Adding plugin to classpath: " + f);
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn("INFO: Adding plugin to classpath: " + f);
|
||||
} catch (Exception e) {
|
||||
log.error("Plugin client " + clientName + " bad classpath element: " + f, e);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Stop all plugins that are installed
|
||||
*
|
||||
* @since 0.7.13
|
||||
* @author zzz
|
||||
*/
|
||||
public class PluginStopper extends PluginStarter {
|
||||
|
||||
public PluginStopper(RouterContext ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
stopPlugins(_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all plugins
|
||||
* (whether or not they were ever started)
|
||||
*
|
||||
* this shouldn't throw anything
|
||||
*/
|
||||
static void stopPlugins(RouterContext ctx) {
|
||||
Log log = ctx.logManager().getLog(PluginStopper.class);
|
||||
for (String app : getPlugins()) {
|
||||
try {
|
||||
stopPlugin(ctx, app);
|
||||
} catch (Throwable e) {
|
||||
if (log.shouldLog(Log.WARN))
|
||||
log.warn("Failed to stop plugin: " + app, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
@@ -14,6 +15,8 @@ import net.i2p.util.EepGet;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.PartialEepGet;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
/**
|
||||
@@ -46,6 +49,20 @@ public class PluginUpdateChecker extends UpdateHandler {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
/** check all plugins */
|
||||
public void update() {
|
||||
Thread t = new I2PAppThread(new AllCheckerRunner(), "AllAppChecker", true);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public class AllCheckerRunner implements Runnable {
|
||||
public void run() {
|
||||
List<String> plugins = PluginStarter.getPlugins();
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
/** check a single plugin */
|
||||
public void update(String appName) {
|
||||
// don't block waiting for the other one to finish
|
||||
if ("true".equals(System.getProperty(PROP_UPDATE_IN_PROGRESS))) {
|
||||
@@ -84,6 +101,21 @@ public class PluginUpdateChecker extends UpdateHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void scheduleStatusClean(String msg) {
|
||||
SimpleScheduler.getInstance().addEvent(new Cleaner(msg), 60*60*1000);
|
||||
}
|
||||
|
||||
private class Cleaner implements SimpleTimer.TimedEvent {
|
||||
private String _msg;
|
||||
public Cleaner(String msg) {
|
||||
_msg = msg;
|
||||
}
|
||||
public void timeReached() {
|
||||
if (_msg.equals(getStatus()))
|
||||
updateStatus("");
|
||||
}
|
||||
}
|
||||
|
||||
public class PluginUpdateCheckerRunner extends UpdateRunner implements Runnable, EepGet.StatusListener {
|
||||
ByteArrayOutputStream _baos;
|
||||
|
||||
@@ -116,17 +148,22 @@ public class PluginUpdateChecker extends UpdateHandler {
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
|
||||
String newVersion = TrustedUpdate.getVersionString(new ByteArrayInputStream(_baos.toByteArray()));
|
||||
boolean newer = (new VersionComparator()).compare(newVersion, _oldVersion) > 0;
|
||||
String msg;
|
||||
if (newer)
|
||||
updateStatus("<b>" + _("New plugin version {0} is available", newVersion) + "</b>");
|
||||
msg = "<b>" + _("New plugin version {0} is available", newVersion) + "</b>";
|
||||
else
|
||||
updateStatus("<b>" + _("No new version is available for plugin {0}", _appName) + "</b>");
|
||||
msg = "<b>" + _("No new version is available for plugin {0}", _appName) + "</b>";
|
||||
updateStatus(msg);
|
||||
scheduleStatusClean(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
||||
File f = new File(_updateFile);
|
||||
f.delete();
|
||||
updateStatus("<b>" + _("Update check failed for plugin {0}", _appName) + "</b>");
|
||||
String msg = "<b>" + _("Update check failed for plugin {0}", _appName) + "</b>";
|
||||
updateStatus(msg);
|
||||
scheduleStatusClean(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
/**
|
||||
@@ -89,6 +91,21 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void scheduleStatusClean(String msg) {
|
||||
SimpleScheduler.getInstance().addEvent(new Cleaner(msg), 60*60*1000);
|
||||
}
|
||||
|
||||
private class Cleaner implements SimpleTimer.TimedEvent {
|
||||
private String _msg;
|
||||
public Cleaner(String msg) {
|
||||
_msg = msg;
|
||||
}
|
||||
public void timeReached() {
|
||||
if (_msg.equals(getStatus()))
|
||||
updateStatus("");
|
||||
}
|
||||
}
|
||||
|
||||
public class PluginUpdateRunner extends UpdateRunner implements Runnable, EepGet.StatusListener {
|
||||
|
||||
public PluginUpdateRunner(String url) {
|
||||
@@ -136,7 +153,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
File appDir = new File(_context.getAppDir(), PLUGIN_DIR);
|
||||
if ((!appDir.exists()) && (!appDir.mkdir())) {
|
||||
f.delete();
|
||||
updateStatus("<b>" + _("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>");
|
||||
statusDone("<b>" + _("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,7 +162,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
// extract to a zip file whether the sig is good or not, so we can get the properties file
|
||||
String err = up.migrateFile(f, to);
|
||||
if (err != null) {
|
||||
updateStatus("<b>" + err + ' ' + _("from {0}", url) + " </b>");
|
||||
statusDone("<b>" + err + ' ' + _("from {0}", url) + " </b>");
|
||||
f.delete();
|
||||
to.delete();
|
||||
return;
|
||||
@@ -155,7 +172,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
f.delete();
|
||||
to.delete();
|
||||
FileUtil.rmdir(tempDir, false);
|
||||
updateStatus("<b>" + _("Plugin from {0} is corrupt", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin from {0} is corrupt", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
File installProps = new File(tempDir, "plugin.config");
|
||||
@@ -166,7 +183,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
f.delete();
|
||||
to.delete();
|
||||
FileUtil.rmdir(tempDir, false);
|
||||
updateStatus("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin from {0} does not contain the required configuration file", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
// we don't need this anymore, we will unzip again
|
||||
@@ -179,7 +196,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
f.delete();
|
||||
to.delete();
|
||||
//updateStatus("<b>" + "Plugin contains an invalid key" + ' ' + pubkey + ' ' + signer + "</b>");
|
||||
updateStatus("<b>" + _("Plugin from {0} contains an invalid key", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin from {0} contains an invalid key", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,7 +215,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
if (!signer.equals(signingKeyName)) {
|
||||
f.delete();
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -207,7 +224,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
// bad or duplicate key
|
||||
f.delete();
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
// ...and try the verify again
|
||||
@@ -216,7 +233,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
if (!signer.equals(signingKeyName)) {
|
||||
f.delete();
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin signature verification of {0} failed", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -231,12 +248,12 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
version.indexOf("<") >= 0 || version.indexOf(">") >= 0 ||
|
||||
appName.startsWith(".") || appName.indexOf("/") >= 0 || appName.indexOf("\\") >= 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin from {0} has invalid name or version", url) + "</b>");
|
||||
statusDone("<b>" + _("Plugin from {0} has invalid name or version", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
if (!version.equals(sudVersion)) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin {0} has mismatched versions", appName) + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} has mismatched versions", appName) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -244,7 +261,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
if (minVersion != null &&
|
||||
(new VersionComparator()).compare(CoreVersion.VERSION, minVersion) < 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
|
||||
statusDone("<b>" + _("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,7 +269,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
if (minVersion != null &&
|
||||
(new VersionComparator()).compare(System.getProperty("java.version"), minVersion) < 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("This plugin requires Java version {0} or higher", minVersion) + "</b>");
|
||||
statusDone("<b>" + _("This plugin requires Java version {0} or higher", minVersion) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -260,7 +277,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
if (destDir.exists()) {
|
||||
if (Boolean.valueOf(props.getProperty("install-only")).booleanValue()) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Downloaded plugin is for new installs only, but the plugin is already installed", url) + "</b>");
|
||||
statusDone("<b>" + _("Downloaded plugin is for new installs only, but the plugin is already installed", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -272,7 +289,7 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
} catch (IOException ioe) {
|
||||
to.delete();
|
||||
FileUtil.rmdir(tempDir, false);
|
||||
updateStatus("<b>" + _("Installed plugin does not contain the required configuration file", url) + "</b>");
|
||||
statusDone("<b>" + _("Installed plugin does not contain the required configuration file", url) + "</b>");
|
||||
return;
|
||||
}
|
||||
String oldPubkey = oldProps.getProperty("key");
|
||||
@@ -280,28 +297,28 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
String oldAppName = props.getProperty("name");
|
||||
if ((!pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Signature of downloaded plugin does not match installed plugin") + "</b>");
|
||||
statusDone("<b>" + _("Signature of downloaded plugin does not match installed plugin") + "</b>");
|
||||
return;
|
||||
}
|
||||
String oldVersion = oldProps.getProperty("version");
|
||||
if (oldVersion == null ||
|
||||
(new VersionComparator()).compare(oldVersion, version) >= 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
|
||||
statusDone("<b>" + _("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
|
||||
return;
|
||||
}
|
||||
minVersion = ConfigClientsHelper.stripHTML(props, "min-installed-version");
|
||||
if (minVersion != null &&
|
||||
(new VersionComparator()).compare(minVersion, oldVersion) > 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
|
||||
statusDone("<b>" + _("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
|
||||
return;
|
||||
}
|
||||
String maxVersion = ConfigClientsHelper.stripHTML(props, "max-installed-version");
|
||||
if (maxVersion != null &&
|
||||
(new VersionComparator()).compare(maxVersion, oldVersion) < 0) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
|
||||
statusDone("<b>" + _("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -318,12 +335,12 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
} else {
|
||||
if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Plugin is for upgrades only, but the plugin is not installed") + "</b>");
|
||||
statusDone("<b>" + _("Plugin is for upgrades only, but the plugin is not installed") + "</b>");
|
||||
return;
|
||||
}
|
||||
if (!destDir.mkdir()) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Cannot create plugin directory {0}", destDir.getAbsolutePath()) + "</b>");
|
||||
statusDone("<b>" + _("Cannot create plugin directory {0}", destDir.getAbsolutePath()) + "</b>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -331,16 +348,16 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
// Finally, extract the zip to the plugin directory
|
||||
if (!FileUtil.extractZip(to, destDir)) {
|
||||
to.delete();
|
||||
updateStatus("<b>" + _("Failed to install plugin in {0}", destDir.getAbsolutePath()) + "</b>");
|
||||
statusDone("<b>" + _("Failed to install plugin in {0}", destDir.getAbsolutePath()) + "</b>");
|
||||
return;
|
||||
}
|
||||
|
||||
to.delete();
|
||||
if (Boolean.valueOf(props.getProperty("dont-start-at-install")).booleanValue()) {
|
||||
if (Boolean.valueOf(props.getProperty("router-restart-required")).booleanValue())
|
||||
updateStatus("<b>" + _("Plugin {0} installed, router restart required", appName) + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} installed, router restart required", appName) + "</b>");
|
||||
else {
|
||||
updateStatus("<b>" + _("Plugin {0} installed", appName) + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} installed", appName) + "</b>");
|
||||
Properties pluginProps = PluginStarter.pluginProperties();
|
||||
pluginProps.setProperty(PluginStarter.PREFIX + appName + PluginStarter.ENABLED, "false");
|
||||
PluginStarter.storePluginProperties(pluginProps);
|
||||
@@ -349,11 +366,11 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
// start everything
|
||||
try {
|
||||
if (PluginStarter.startPlugin(_context, appName))
|
||||
updateStatus("<b>" + _("Plugin {0} installed and started", appName) + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} installed and started", appName) + "</b>");
|
||||
else
|
||||
updateStatus("<b>" + _("Plugin {0} installed but failed to start, check logs", appName) + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} installed but failed to start, check logs", appName) + "</b>");
|
||||
} catch (Throwable e) {
|
||||
updateStatus("<b>" + _("Plugin {0} installed but failed to start", appName) + ": " + e + "</b>");
|
||||
statusDone("<b>" + _("Plugin {0} installed but failed to start", appName) + ": " + e + "</b>");
|
||||
_log.error("Error starting plugin " + appName, e);
|
||||
}
|
||||
}
|
||||
@@ -363,8 +380,14 @@ public class PluginUpdateHandler extends UpdateHandler {
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
||||
File f = new File(_updateFile);
|
||||
f.delete();
|
||||
updateStatus("<b>" + _("Failed to download plugin from {0}", url) + "</b>");
|
||||
statusDone("<b>" + _("Failed to download plugin from {0}", url) + "</b>");
|
||||
}
|
||||
|
||||
private void statusDone(String msg) {
|
||||
updateStatus(msg);
|
||||
scheduleStatusClean(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -190,9 +190,11 @@ public class RouterConsoleRunner {
|
||||
|
||||
List<RouterContext> contexts = RouterContext.listContexts();
|
||||
if (contexts != null) {
|
||||
if (PluginStarter.pluginsEnabled(contexts.get(0))) {
|
||||
t = new I2PAppThread(new PluginStarter(contexts.get(0)), "PluginStarter", true);
|
||||
RouterContext ctx = contexts.get(0);
|
||||
if (PluginStarter.pluginsEnabled(ctx)) {
|
||||
t = new I2PAppThread(new PluginStarter(ctx), "PluginStarter", true);
|
||||
t.start();
|
||||
ctx.addShutdownTask(new PluginStopper(ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,9 +43,17 @@ public class WebAppStarter {
|
||||
|
||||
/**
|
||||
* add but don't start
|
||||
* This is used only by RouterConsoleRunner, which adds all the webapps first
|
||||
* and then starts all at once.
|
||||
*/
|
||||
static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException {
|
||||
|
||||
// Jetty will happily load one context on top of another without stopping
|
||||
// the first one, so we remove any previous one here
|
||||
try {
|
||||
stopWebApp(server, appName);
|
||||
} catch (Throwable t) {}
|
||||
|
||||
WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath);
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
@@ -64,7 +72,7 @@ public class WebAppStarter {
|
||||
}
|
||||
|
||||
/**
|
||||
* stop it
|
||||
* stop it and remove the context
|
||||
* @throws just about anything, caller would be wise to catch Throwable
|
||||
*/
|
||||
static void stopWebApp(Server server, String appName) {
|
||||
@@ -74,6 +82,9 @@ public class WebAppStarter {
|
||||
// false -> not graceful
|
||||
wac.stop(false);
|
||||
} catch (InterruptedException ie) {}
|
||||
try {
|
||||
server.removeContext(wac);
|
||||
} catch (IllegalStateException ise) {}
|
||||
}
|
||||
|
||||
/** see comments in ConfigClientsHandler */
|
||||
|
||||
@@ -71,5 +71,30 @@ class Dummy {
|
||||
_("Transport");
|
||||
_("Tunnels");
|
||||
_("udp");
|
||||
|
||||
// parameters in transport addresses (netdb.jsp)
|
||||
// may or may not be worth translating
|
||||
_("host");
|
||||
_("key");
|
||||
_("port");
|
||||
// capabilities
|
||||
_("caps");
|
||||
// introducer host
|
||||
_("ihost0");
|
||||
_("ihost1");
|
||||
_("ihost2");
|
||||
// introducer port
|
||||
_("iport0");
|
||||
_("iport1");
|
||||
_("iport2");
|
||||
// introducer key
|
||||
_("ikey0");
|
||||
_("ikey1");
|
||||
_("ikey2");
|
||||
// introducer tag
|
||||
_("itag0");
|
||||
_("itag1");
|
||||
_("itag2");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ button span.hide{
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigClientsHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigClientsHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce")%>" />
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce")%>" >
|
||||
<% /* set hidden default */ %>
|
||||
<button type="submit" name="action" value="" style="display:none" >Cancel</button>
|
||||
<h3><%=intl._("Client Configuration")%></h3><p>
|
||||
<%=intl._("The Java clients listed below are started by the router and run in the same JVM.")%>
|
||||
</p><div class="wideload">
|
||||
@@ -56,7 +58,7 @@ button span.hide{
|
||||
<input type="submit" name="action" value="<%=intl._("Save WebApp Configuration")%>" />
|
||||
</div></div>
|
||||
<% if (clientshelper.showPlugins()) { %>
|
||||
<h3><a name="webapp"></a><%=intl._("Plugin Configuration")%></h3><p>
|
||||
<h3><a name="pconfig"></a><%=intl._("Plugin Configuration")%></h3><p>
|
||||
<%=intl._("The plugins listed below are started by the webConsole client.")%>
|
||||
</p><div class="wideload"><p>
|
||||
<jsp:getProperty name="clientshelper" property="form3" />
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
<% String prev = System.getProperty("net.i2p.router.web.ConfigUpdateHandler.nonce");
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigUpdateHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigUpdateHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigUpdateHandler.nonce")%>" />
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigUpdateHandler.nonce")%>" >
|
||||
<% /* set hidden default */ %>
|
||||
<input type="submit" name="action" value="" style="display:none" >
|
||||
<h3><%=intl._("Check for I2P and news updates")%></h3>
|
||||
<div class="wideload"><table border="0" cellspacing="5">
|
||||
<tr><td colspan="2"></tr>
|
||||
@@ -59,6 +61,6 @@
|
||||
<% } // if canInstall %>
|
||||
<tr class="tablefooter"><td colspan="2">
|
||||
<div class="formaction">
|
||||
<input type="submit" name="action" value="<%=intl._("Save")%>" />
|
||||
<input type="reset" value="<%=intl._("Cancel")%>" />
|
||||
<input type="reset" value="<%=intl._("Cancel")%>" >
|
||||
<input type="submit" name="action" value="<%=intl._("Save")%>" >
|
||||
</div></td></tr></table></div></form></div></div></body></html>
|
||||
|
||||
62
build.xml
62
build.xml
@@ -264,8 +264,30 @@
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
<target name="preppkg" depends="preppkg-linux, buildexe">
|
||||
<target name="preppkg" depends="preppkg-linux, preppkg-windows">
|
||||
<copy file="build/jbigi.jar" todir="pkg-temp/lib" />
|
||||
<copy todir="pkg-temp/lib/wrapper/freebsd/">
|
||||
<fileset dir="installer/lib/wrapper/freebsd/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/macosx/">
|
||||
<fileset dir="installer/lib/wrapper/macosx/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/solaris/">
|
||||
<fileset dir="installer/lib/wrapper/solaris/" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="preppkg-windows-only" depends="preppkg-windows">
|
||||
<!-- rip the non-windows stuff out of jbigi.jar -->
|
||||
<mkdir dir="tmpextract" />
|
||||
<unjar src="build/jbigi.jar" dest="tmpextract/" />
|
||||
<jar destfile="pkg-temp/lib/jbigi.jar" >
|
||||
<fileset dir="tmpextract/" includes="*windows*" />
|
||||
</jar>
|
||||
<delete dir="tmpextract/" />
|
||||
</target>
|
||||
|
||||
<target name="preppkg-windows" depends="preppkg-base, buildexe">
|
||||
<copy file="i2p.exe" todir="pkg-temp/" failonerror="false" />
|
||||
<copy file="apps/systray/java/lib/systray4j.dll" todir="pkg-temp/lib" />
|
||||
<copy file="apps/systray/java/resources/iggy.ico" todir="pkg-temp/icons" />
|
||||
@@ -276,15 +298,6 @@
|
||||
<copy file="installer/resources/install_i2p_service_winnt.bat" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/postinstall.bat" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/uninstall_i2p_service_winnt.bat" todir="pkg-temp/" />
|
||||
<copy todir="pkg-temp/lib/wrapper/freebsd/">
|
||||
<fileset dir="installer/lib/wrapper/freebsd/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/macosx/">
|
||||
<fileset dir="installer/lib/wrapper/macosx/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/solaris/">
|
||||
<fileset dir="installer/lib/wrapper/solaris/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/win32/">
|
||||
<fileset dir="installer/lib/wrapper/win32/" />
|
||||
</copy>
|
||||
@@ -301,7 +314,22 @@
|
||||
<delete dir="tmpextract/" />
|
||||
</target>
|
||||
|
||||
<target name="preppkg-linux" depends="build, preplicenses, prepconsoleDocs">
|
||||
<target name="preppkg-linux" depends="preppkg-base">
|
||||
<copy file="installer/resources/runplain.sh" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/launch-i2psnark" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/eepget" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/i2prouter" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/osid" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/postinstall.sh" todir="pkg-temp/" />
|
||||
<copy todir="pkg-temp/lib/wrapper/linux/">
|
||||
<fileset dir="installer/lib/wrapper/linux/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/linux64/">
|
||||
<fileset dir="installer/lib/wrapper/linux64/" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="preppkg-base" depends="build, preplicenses, prepconsoleDocs">
|
||||
<copy file="build/i2p.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
|
||||
@@ -320,7 +348,6 @@
|
||||
<copy file="build/BOB.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/systray.jar" todir="pkg-temp/lib" />
|
||||
<copy file="build/i2psnark.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="installer/resources/runplain.sh" todir="pkg-temp/" />
|
||||
<copy file="apps/systray/java/lib/systray4j.jar" todir="pkg-temp/lib" />
|
||||
<copy file="build/i2ptunnel.war" todir="pkg-temp/webapps/" />
|
||||
<copy file="build/routerconsole.war" todir="pkg-temp/webapps/" />
|
||||
@@ -330,24 +357,13 @@
|
||||
<copy file="apps/susidns/src/WEB-INF/lib/jstl.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="apps/susidns/src/WEB-INF/lib/standard.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/i2psnark.war" todir="pkg-temp/webapps/" />
|
||||
<copy file="apps/i2psnark/launch-i2psnark" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/jetty-i2psnark.xml" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/i2psnark.config" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/blocklist.txt" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/clients.config" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/eepget" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/i2prouter" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/i2ptunnel.config" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/osid" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/postinstall.sh" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/systray.config" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/wrapper.config" todir="pkg-temp/" />
|
||||
<copy todir="pkg-temp/lib/wrapper/linux/">
|
||||
<fileset dir="installer/lib/wrapper/linux/" />
|
||||
</copy>
|
||||
<copy todir="pkg-temp/lib/wrapper/linux64/">
|
||||
<fileset dir="installer/lib/wrapper/linux64/" />
|
||||
</copy>
|
||||
<copy file="installer/resources/hosts.txt" todir="pkg-temp/" />
|
||||
<copy file="INSTALL-headless.txt" todir="pkg-temp/" />
|
||||
<!-- overwrite the truncated history put in by the updater -->
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
*/
|
||||
package net.i2p.client.naming;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -87,13 +91,10 @@ public class HostsTxtNamingService extends NamingService {
|
||||
List filenames = getFilenames();
|
||||
for (int i = 0; i < filenames.size(); i++) {
|
||||
String hostsfile = (String)filenames.get(i);
|
||||
Properties hosts = new Properties();
|
||||
try {
|
||||
File f = new File(_context.getRouterDir(), hostsfile);
|
||||
if ( (f.exists()) && (f.canRead()) ) {
|
||||
DataHelper.loadProps(hosts, f, true);
|
||||
|
||||
String key = hosts.getProperty(hostname.toLowerCase());
|
||||
String key = getKey(f, hostname.toLowerCase());
|
||||
if ( (key != null) && (key.trim().length() > 0) ) {
|
||||
d = lookupBase64(key);
|
||||
putCache(hostname, d);
|
||||
@@ -168,4 +169,30 @@ public class HostsTxtNamingService extends NamingService {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Better than DataHelper.loadProps(), doesn't load the whole file into memory,
|
||||
* and stops when it finds a match.
|
||||
*
|
||||
* @param host lower case
|
||||
* @since 0.7.13
|
||||
*/
|
||||
private static String getKey(File file, String host) throws IOException {
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"), 16*1024);
|
||||
String line = null;
|
||||
while ( (line = in.readLine()) != null) {
|
||||
if (!line.toLowerCase().startsWith(host + '='))
|
||||
continue;
|
||||
if (line.indexOf('#') > 0) // trim off any end of line comment
|
||||
line = line.substring(0, line.indexOf('#')).trim();
|
||||
int split = line.indexOf('=');
|
||||
return line.substring(split+1); //.trim() ??????????????
|
||||
}
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +267,8 @@ public class PrivateKeyFile {
|
||||
StringBuilder s = new StringBuilder(128);
|
||||
s.append("Dest: ");
|
||||
s.append(this.dest != null ? this.dest.toBase64() : "null");
|
||||
s.append("\nB32: ");
|
||||
s.append(this.dest != null ? Base32.encode(this.dest.calculateHash().getData()) + ".b32.i2p" : "null");
|
||||
s.append("\nContains: ");
|
||||
s.append(this.dest);
|
||||
s.append("\nPrivate Key: ");
|
||||
|
||||
@@ -455,6 +455,8 @@ public class EepGet {
|
||||
_listeners.get(i).attemptFailed(_url, _bytesTransferred, _bytesRemaining, _currentAttempt, _numRetries, ioe);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("ERR: doFetch failed " + ioe);
|
||||
if (ioe instanceof MalformedURLException)
|
||||
_keepFetching = false;
|
||||
} finally {
|
||||
if (_out != null) {
|
||||
try {
|
||||
|
||||
45
history.txt
45
history.txt
@@ -1,3 +1,44 @@
|
||||
2010-04-02 zzz
|
||||
* FloodfillPeerSelector: Adjust rankings again
|
||||
|
||||
2010-03-31 zzz
|
||||
* FloodfillPeerSelector: Adjust rankings to try to
|
||||
improve LeaseSet lookups
|
||||
* HostsTxtNamingService: Don't load the whole hosts.txt
|
||||
into memory for every lookup
|
||||
|
||||
2010-03-29 zzz
|
||||
* build.xml: Prep for a windows-only pkg
|
||||
* configclients.jsp:
|
||||
- Always show start button for webapps and plugins
|
||||
* configclients.jsp, configupdate.jsp:
|
||||
- Fix submission when entering CR in a text box
|
||||
* EepGet: Don't retry after a MalformedURLException
|
||||
* HTTPResponseOutputStream: More static
|
||||
* Plugins:
|
||||
- Stop all plugins at shutdown
|
||||
- Log tweaks
|
||||
* WebApps:
|
||||
- Remove the WAC after stopping it
|
||||
- Stop a WAC before starting it to prevent dups
|
||||
- Implement destroy() in addressbook to prevent dups
|
||||
- Implement destroy() in i2psnark to prevent dups
|
||||
|
||||
2010-03-25 zzz
|
||||
* configclients.jsp: Fix dup anchor
|
||||
* Console: Sort plugin links in summary bar
|
||||
* i2psnark:
|
||||
- Send numwant=0 if we don't need peers
|
||||
- Report returned complete and incomplete counts
|
||||
if higher than peer count
|
||||
- Allow missing peer list
|
||||
- Log tweaks
|
||||
* netdb.jsp: Tag transport properties
|
||||
* Plugins: Remove final check and install console
|
||||
messages after a while
|
||||
* PrivateKeyFile: Add b32 output
|
||||
* Reseed: Add another host
|
||||
|
||||
2010-03-18 zzz
|
||||
* Blocklist, CommSystem, FIFOBandwidth, TransportManager,
|
||||
OutNetMessage, InNetMessagePool:
|
||||
@@ -48,6 +89,10 @@
|
||||
not sure why taking them from the tail "reduces latency"
|
||||
- Java 5 cleanup
|
||||
|
||||
2010-03-17 zzz
|
||||
* I2PTunnel: Disable nonce checking when console password set
|
||||
* Reseed: Add another host
|
||||
|
||||
* 2010-03-15 0.7.12 released
|
||||
|
||||
2010-03-13 zzz
|
||||
|
||||
@@ -13,12 +13,12 @@ import net.i2p.CoreVersion;
|
||||
/**
|
||||
* Expose a version string
|
||||
*
|
||||
n */
|
||||
*/
|
||||
public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 1;
|
||||
public final static long BUILD = 5;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -112,7 +112,7 @@ class FloodfillPeerSelector extends PeerSelector {
|
||||
private static final int NO_FAIL_STORE_OK = 10*60*1000;
|
||||
private static final int NO_FAIL_STORE_GOOD = NO_FAIL_STORE_OK * 2;
|
||||
/** this must be longer than the max streaming timeout (60s) */
|
||||
private static final int NO_FAIL_LOOKUP_OK = 2*60*1000;
|
||||
private static final int NO_FAIL_LOOKUP_OK = 75*1000;
|
||||
private static final int NO_FAIL_LOOKUP_GOOD = NO_FAIL_LOOKUP_OK * 3;
|
||||
private static final int MAX_GOOD_RESP_TIME = 5*1000;
|
||||
|
||||
@@ -135,8 +135,11 @@ class FloodfillPeerSelector extends PeerSelector {
|
||||
maxFailRate = 100d; // disable
|
||||
}
|
||||
|
||||
// 8 == FNDF.MAX_TO_FLOOD + 1
|
||||
int limit = Math.max(8, howMany);
|
||||
limit = Math.min(limit, ffs.size());
|
||||
// split sorted list into 3 sorted lists
|
||||
for (int i = 0; found < howMany && i < ffs.size(); i++) {
|
||||
for (int i = 0; found < howMany && i < limit; i++) {
|
||||
Hash entry = sorted.first();
|
||||
sorted.remove(entry);
|
||||
if (entry == null)
|
||||
|
||||
@@ -36,7 +36,10 @@ public class Reseeder {
|
||||
// Reject unreasonably big files, because we download into a ByteArrayOutputStream.
|
||||
private static final long MAX_RESEED_RESPONSE_SIZE = 1024 * 1024;
|
||||
|
||||
private static final String DEFAULT_SEED_URL = "http://a.netdb.i2p2.de/,http://b.netdb.i2p2.de/,http://c.netdb.i2p2.de/,http://reseed.i2p-projekt.de/,http://i2pbote.net/netDb/,http://r31453.ovh.net/static_media/netDb/";
|
||||
private static final String DEFAULT_SEED_URL =
|
||||
"http://a.netdb.i2p2.de/,http://b.netdb.i2p2.de/,http://c.netdb.i2p2.de/," +
|
||||
"http://reseed.i2p-projekt.de/,http://i2pbote.net/netDb/,http://r31453.ovh.net/static_media/netDb/," +
|
||||
"http://p2i.mine.nu/netDb/";
|
||||
private static final String PROP_INPROGRESS = "net.i2p.router.web.ReseedHandler.reseedInProgress";
|
||||
private static final String PROP_ERROR = "net.i2p.router.web.ReseedHandler.errorMessage";
|
||||
private static final String PROP_STATUS = "net.i2p.router.web.ReseedHandler.statusMessage";
|
||||
|
||||
Reference in New Issue
Block a user