Compare commits

...

10 Commits

8 changed files with 830 additions and 366 deletions

View File

@ -9,6 +9,7 @@ import java.util.Properties;
import net.i2p.router.RouterContext;
import net.i2p.router.web.PluginStarter;
import net.i2p.update.*;
import net.i2p.util.SystemVersion;
/**
* Check for or download an updated version of a plugin.
@ -32,7 +33,7 @@ class PluginUpdateHandler implements Checker, Updater {
_context = ctx;
_mgr = mgr;
}
/** check a single plugin */
@Override
public UpdateTask check(UpdateType type, UpdateMethod method,
@ -48,6 +49,8 @@ class PluginUpdateHandler implements Checker, Updater {
xpi2pURL = props.getProperty("updateURL");
List<URI> updateSources = null;
if (xpi2pURL != null) {
xpi2pURL = xpi2pURL.replace("$OS", SystemVersion.getOS());
xpi2pURL = xpi2pURL.replace("$ARCH", SystemVersion.getArch());
try {
updateSources = Collections.singletonList(new URI(xpi2pURL));
} catch (URISyntaxException use) {}
@ -61,7 +64,7 @@ class PluginUpdateHandler implements Checker, Updater {
UpdateRunner update = new PluginUpdateChecker(_context, _mgr, updateSources, appName, oldVersion);
return update;
}
/** download a single plugin */
@Override
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
@ -83,4 +86,4 @@ class PluginUpdateHandler implements Checker, Updater {
return update;
}
}

View File

@ -838,6 +838,8 @@ public class PluginStarter implements Runnable {
argVal[i] = argVal[i].replace("$I2P", ctx.getBaseDir().getAbsolutePath());
argVal[i] = argVal[i].replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
argVal[i] = argVal[i].replace("$OS", SystemVersion.getOS());
argVal[i] = argVal[i].replace("$ARCH", SystemVersion.getArch());
}
}
ClientApp ca = ctx.routerAppManager().getClientApp(app.className, argVal);
@ -877,6 +879,8 @@ public class PluginStarter implements Runnable {
argVal[i] = argVal[i].replace("$I2P", ctx.getBaseDir().getAbsolutePath());
argVal[i] = argVal[i].replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
argVal[i] = argVal[i].replace("$OS", SystemVersion.getOS());
argVal[i] = argVal[i].replace("$ARCH", SystemVersion.getArch());
}
}
@ -887,6 +891,8 @@ public class PluginStarter implements Runnable {
cp = cp.replace("$I2P", ctx.getBaseDir().getAbsolutePath());
cp = cp.replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
cp = cp.replace("$PLUGIN", pluginDir.getAbsolutePath());
cp = cp.replace("$OS", SystemVersion.getOS());
cp = cp.replace("$ARCH", SystemVersion.getArch());
}
// Old way - add for the whole JVM

View File

@ -15,19 +15,24 @@ import net.i2p.router.web.FormHandler;
import net.i2p.router.web.Messages;
/**
* @since 0.8.3
* @since 0.8.3
*/
public class ConfigReseedHandler extends FormHandler {
private final Map<String, String> changes = new HashMap<String, String>();
private final List<String> removes = new ArrayList<String>();
@Override
protected void processForm() {
ReseedChecker checker = _context.netDb().reseedChecker();
if (_action.equals(_t("Save changes and reseed now"))) {
saveChanges();
if (!checker.requestReseed()) {
if (checker.onionReseedsConfigured()) {
if (!checker.requestOnionReseed()) {
addFormError(_t("Onion reseeding is already in progress"));
addCheckerStatus(checker);
}
} else if (!checker.requestReseed()) {
addFormError(_t("Reseeding is already in progress"));
addCheckerStatus(checker);
} else {
@ -51,23 +56,48 @@ public class ConfigReseedHandler extends FormHandler {
return;
}
try {
if (!checker.requestReseed(url)) {
addFormError(_t("Reseeding is already in progress"));
addCheckerStatus(checker);
} else {
// wait a while for completion but not forever
for (int i = 0; i < 40; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {}
if (!checker.inProgress())
break;
if (url.getHost().endsWith(".onion")) {
if (!checker.requestOnionReseed(url)) {
addFormError(_t("Tor not available, unable to perform onion reseed"));
addCheckerStatus(checker);
} else {
// wait a while for completion but not forever
for (int i = 0; i < 40; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
if (!checker.inProgress())
break;
}
if (!addCheckerStatus(checker)) {
if (checker.inProgress()) {
addFormNotice(_t("Reseed in progress, check sidebar for status"));
} else {
addFormNotice(_t("Reseed complete, check sidebar for status"));
}
}
}
if (!addCheckerStatus(checker)) {
if (checker.inProgress()) {
addFormNotice(_t("Reseed in progress, check sidebar for status"));
} else {
addFormNotice(_t("Reseed complete, check sidebar for status"));
}else{
if (!checker.requestReseed(url)) {
addFormError(_t("Reseeding is already in progress"));
addCheckerStatus(checker);
} else {
// wait a while for completion but not forever
for (int i = 0; i < 40; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
if (!checker.inProgress())
break;
}
if (!addCheckerStatus(checker)) {
if (checker.inProgress()) {
addFormNotice(_t("Reseed in progress, check sidebar for status"));
} else {
addFormNotice(_t("Reseed complete, check sidebar for status"));
}
}
}
}
@ -89,8 +119,8 @@ public class ConfigReseedHandler extends FormHandler {
addCheckerStatus(checker);
} else {
addFormNotice(ngettext("Reseed successful, loaded {0} router info from file",
"Reseed successful, loaded {0} router infos from file",
count));
"Reseed successful, loaded {0} router infos from file",
count));
}
} catch (IOException ioe) {
addFormError(_t("Reseed from file failed") + " - " + ioe);
@ -98,19 +128,24 @@ public class ConfigReseedHandler extends FormHandler {
} finally {
// it's really a ByteArrayInputStream but we'll play along...
if (in != null)
try { in.close(); } catch (IOException ioe) {}
try {
in.close();
} catch (IOException ioe) {
}
}
} else if (_action.equals(_t("Save changes"))) {
saveChanges();
} else if (_action.equals(_t("Reset URL list"))) {
resetUrlList();
} else if (_action.equals(_t("Reset Onion URL list"))) {
resetOnionUrlList();
}
//addFormError(_t("Unsupported") + ' ' + _action + '.');
// addFormError(_t("Unsupported") + ' ' + _action + '.');
}
/**
* @return true if anything was output
* @since 0.9.33
* @return true if anything was output
* @since 0.9.33
*/
private boolean addCheckerStatus(ReseedChecker checker) {
String error = checker.getError();
@ -128,7 +163,14 @@ public class ConfigReseedHandler extends FormHandler {
private void resetUrlList() {
if (_context.router().saveConfig(Reseeder.PROP_RESEED_URL, null))
addFormNotice(_t("URL list reset successfully"));
addFormNotice(_t("URL list reset successfully"));
else
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
}
private void resetOnionUrlList() {
if (_context.router().saveConfig(Reseeder.PROP_ONION_RESEED_URL, null))
addFormNotice(_t("URL list reset successfully"));
else
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
}
@ -169,13 +211,23 @@ public class ConfigReseedHandler extends FormHandler {
changes.put(Reseeder.PROP_RESEED_URL, url);
}
}
String onionurl = getJettyString("onionReseedURL");
if (onionurl != null) {
onionurl = onionurl.trim().replace("\r\n", ",").replace("\n", ",");
if (onionurl.length() <= 0) {
addFormNotice("Restoring default URLs");
removes.add(Reseeder.PROP_ONION_RESEED_URL);
} else {
changes.put(Reseeder.PROP_ONION_RESEED_URL, onionurl);
}
}
String mode = getJettyString("mode");
boolean req = "1".equals(mode);
boolean disabled = "2".equals(mode);
changes.put(Reseeder.PROP_SSL_REQUIRED,
Boolean.toString(req));
Boolean.toString(req));
changes.put(Reseeder.PROP_SSL_DISABLE,
Boolean.toString(disabled));
Boolean.toString(disabled));
saveBoolean(Reseeder.PROP_PROXY_ENABLE, "enable");
String pmode = getJettyString("pmode");
boolean senable = pmode != null && pmode.length() > 0;

View File

@ -9,7 +9,7 @@ import net.i2p.router.networkdb.reseed.Reseeder;
import net.i2p.router.web.HelperBase;
/**
* @since 0.8.3
* @since 0.8.3
*/
public class ConfigReseedHelper extends HelperBase {
@ -52,24 +52,24 @@ public class ConfigReseedHelper extends HelperBase {
}
public String modeChecked(int mode) {
boolean required = _context.getBooleanPropertyDefaultTrue(Reseeder.PROP_SSL_REQUIRED);
boolean disabled = _context.getBooleanProperty(Reseeder.PROP_SSL_DISABLE);
boolean required = _context.getBooleanPropertyDefaultTrue(Reseeder.PROP_SSL_REQUIRED);
boolean disabled = _context.getBooleanProperty(Reseeder.PROP_SSL_DISABLE);
if ((mode == 0 && (!disabled) && (!required)) ||
(mode == 1 && (!disabled) && required) ||
(mode == 2 && disabled))
(mode == 1 && (!disabled) && required) ||
(mode == 2 && disabled))
return CHECKED;
return "";
}
/** @since 0.9.33 */
public String pmodeChecked(int mode) {
String c = _context.getProperty(Reseeder.PROP_SPROXY_TYPE, "HTTP");
boolean disabled = !_context.getBooleanProperty(Reseeder.PROP_SPROXY_ENABLE);
String c = _context.getProperty(Reseeder.PROP_SPROXY_TYPE, "HTTP");
boolean disabled = !_context.getBooleanProperty(Reseeder.PROP_SPROXY_ENABLE);
if ((mode == 0 && disabled) ||
(mode == 1 && !disabled && c.equals("HTTP")) ||
(mode == 2 && !disabled && c.equals("SOCKS4")) ||
(mode == 3 && !disabled && c.equals("SOCKS5")) ||
(mode == 4 && !disabled && c.equals("INTERNAL")))
(mode == 1 && !disabled && c.equals("HTTP")) ||
(mode == 2 && !disabled && c.equals("SOCKS4")) ||
(mode == 3 && !disabled && c.equals("SOCKS5")) ||
(mode == 4 && !disabled && c.equals("INTERNAL")))
return CHECKED;
return "";
}
@ -83,11 +83,11 @@ public class ConfigReseedHelper extends HelperBase {
return getChecked(Reseeder.PROP_PROXY_AUTH_ENABLE);
}
/****
public String getSenable() {
return getChecked(Reseeder.PROP_SPROXY_ENABLE);
}
****/
/****
* public String getSenable() {
* return getChecked(Reseeder.PROP_SPROXY_ENABLE);
* }
****/
/** @since 0.8.9 */
public String getSauth() {
@ -95,7 +95,22 @@ public class ConfigReseedHelper extends HelperBase {
}
private List<String> reseedList() {
String urls = _context.getProperty(Reseeder.PROP_RESEED_URL, Reseeder.DEFAULT_SEED_URL + ',' + Reseeder.DEFAULT_SSL_SEED_URL);
String urls = _context.getProperty(Reseeder.PROP_RESEED_URL,
Reseeder.DEFAULT_SEED_URL + ',' + Reseeder.DEFAULT_SSL_SEED_URL);
StringTokenizer tok = new StringTokenizer(urls, " ,\r\n");
List<String> URLList = new ArrayList<String>(16);
while (tok.hasMoreTokens()) {
String s = tok.nextToken().trim();
if (s.length() > 0)
URLList.add(s);
}
return URLList;
}
private List<String> onionReseedList() {
String urls = _context.getProperty(Reseeder.PROP_ONION_RESEED_URL);
if (urls == null)
return Collections.emptyList();
StringTokenizer tok = new StringTokenizer(urls, " ,\r\n");
List<String> URLList = new ArrayList<String>(16);
while (tok.hasMoreTokens()) {
@ -111,16 +126,28 @@ public class ConfigReseedHelper extends HelperBase {
Collections.sort(URLList);
StringBuilder buf = new StringBuilder();
for (String s : URLList) {
if (buf.length() > 0)
buf.append('\n');
buf.append(s);
if (buf.length() > 0)
buf.append('\n');
buf.append(s);
}
return buf.toString();
}
public String getOnionReseedURL() {
List<String> URLList = onionReseedList();
Collections.sort(URLList);
StringBuilder buf = new StringBuilder();
for (String s : URLList) {
if (buf.length() > 0)
buf.append('\n');
buf.append(s);
}
return buf.toString();
}
/**
* @return true only if we have both http and https URLs
* @since 0.9.33
* @return true only if we have both http and https URLs
* @since 0.9.33
*/
public boolean shouldShowSelect() {
boolean http = false;
@ -140,8 +167,8 @@ public class ConfigReseedHelper extends HelperBase {
}
/**
* @return true only if we have a http URL
* @since 0.9.33
* @return true only if we have a http URL
* @since 0.9.33
*/
public boolean shouldShowHTTPProxy() {
for (String u : reseedList()) {
@ -152,8 +179,8 @@ public class ConfigReseedHelper extends HelperBase {
}
/**
* @return true only if we have a https URL
* @since 0.9.33
* @return true only if we have a https URL
* @since 0.9.33
*/
public boolean shouldShowHTTPSProxy() {
for (String u : reseedList()) {

View File

@ -154,6 +154,11 @@
<div class="formaction" id="resetreseed"><input type="submit" name="action" class="reload" value="<%=intl._t("Reset URL list")%>" /></div>
</td></tr>
<tr><td align="right"><b><%=intl._t("Onion Reseed URLs")%>:</b></td>
<td><textarea wrap="off" name="onionReseedURL" cols="60" rows="7" spellcheck="false"><jsp:getProperty name="reseedHelper" property="onionReseedURL" /></textarea>
<div class="formaction" id="resetreseed"><input type="submit" name="action" class="reload" value="<%=intl._t("Reset Onion URL list")%>" /></div>
</td></tr>
<% if (reseedHelper.shouldShowHTTPSProxy()) { %>
<tr><td align="right"><b><%=intl._t("Proxy type for HTTPS reseed URLs")%>:</b></td>
<td><label><input type="radio" class="optbox" name="pmode" value="" <%=reseedHelper.pmodeChecked(0) %> >

View File

@ -117,6 +117,35 @@ public abstract class SystemVersion {
}
}
public static String getOS() {
if (isWindows())
return "windows";
if (isMac())
return "mac";
if (isGNU())
return "linux"; /* actually... */
if (isLinuxService())
return "linux";
if (isAndroid())
return "android";
return "unknown";
}
public static String getArch() {
if (is64Bit()){
if (isARM())
return "arm64";
if (isX86())
return "x86_64";
}
if (isARM())
return "arm";
if (isX86())
return "x86";
return "unknown";
}
public static boolean isWindows() {
return _isWin;
}

View File

@ -2,7 +2,10 @@ package net.i2p.router.networkdb.reseed;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
@ -11,39 +14,42 @@ import net.i2p.router.RouterContext;
import net.i2p.util.Addresses;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer;
import static net.i2p.socks.SOCKS5Constants.*;
/**
* Moved from RouterConsoleRunner.java
* Moved from RouterConsoleRunner.java
*
* Reseeding is not strictly a router function, it used to be
* in the routerconsole app, but this made it impossible to
* bootstrap an embedded router lacking a routerconsole,
* in iMule or android for example, without additional modifications.
* Reseeding is not strictly a router function, it used to be
* in the routerconsole app, but this made it impossible to
* bootstrap an embedded router lacking a routerconsole,
* in iMule or android for example, without additional modifications.
*
* Also, as this is now called from PersistentDataStore, not from the
* routerconsole, we can get started as soon as the netdb has read
* the netDb/ directory, not when the console starts.
* Also, as this is now called from PersistentDataStore, not from the
* routerconsole, we can get started as soon as the netdb has read
* the netDb/ directory, not when the console starts.
*/
public class ReseedChecker {
private final RouterContext _context;
private final Log _log;
private final AtomicBoolean _inProgress = new AtomicBoolean();
private volatile String _torHost = "127.0.0.1";
private volatile int _torSOCKSPort = 9050;
private volatile String _lastStatus = "";
private volatile String _lastError = "";
private volatile boolean _networkLogged;
private volatile boolean _alreadyRun;
public static final int MINIMUM = 50;
private static final long STATUS_CLEAN_TIME = 20*60*1000;
private static final long STATUS_CLEAN_TIME = 20 * 60 * 1000;
// if down this long, reseed at startup
private static final long RESEED_MIN_DOWNTIME = 60*24*60*60*1000L;
private static final long RESEED_MIN_DOWNTIME = 60 * 24 * 60 * 60 * 1000L;
/**
* All reseeding must be done through this instance.
* Access through context.netDb().reseedChecker(), others should not instantiate
* All reseeding must be done through this instance.
* Access through context.netDb().reseedChecker(), others should not instantiate
*
* @since 0.9
* @since 0.9
*/
public ReseedChecker(RouterContext context) {
_context = context;
@ -51,10 +57,10 @@ public class ReseedChecker {
}
/**
* Check if a reseed is needed, and start it
* Check if a reseed is needed, and start it
*
* @param count current number of known routers, includes us
* @return true if a reseed was started
* @param count current number of known routers, includes us
* @return true if a reseed was started
*/
public boolean checkReseed(int count) {
if (_alreadyRun) {
@ -67,8 +73,8 @@ public class ReseedChecker {
}
if (_context.getBooleanProperty(Reseeder.PROP_DISABLE) ||
_context.getBooleanProperty("i2p.vmCommSystem")) {
int x = count - 1; // us
_context.getBooleanProperty("i2p.vmCommSystem")) {
int x = count - 1; // us
// no ngettext, this is rare
String s;
if (x > 0)
@ -97,8 +103,9 @@ public class ReseedChecker {
return false;
}
// we check the i2p installation directory for a flag telling us not to reseed,
// but also check the home directory for that flag too, since new users installing i2p
// we check the i2p installation directory for a flag telling us not to reseed,
// but also check the home directory for that flag too, since new users
// installing i2p
// don't have an installation directory that they can put the flag in yet.
File noReseedFile = new File(new File(System.getProperty("user.home")), ".i2pnoreseed");
File noReseedFileAlt1 = new File(new File(System.getProperty("user.home")), "noreseed.i2p");
@ -119,7 +126,7 @@ public class ReseedChecker {
_log.logAlways(Log.WARN, "Very few known peers remaining - reseeding now");
return requestReseed();
} else {
int x = count - 1; // us
int x = count - 1; // us
// no ngettext, this is rare
String s;
if (x > 0)
@ -135,10 +142,10 @@ public class ReseedChecker {
}
/**
* Start a reseed
* Start a reseed
*
* @return true if a reseed was started, false if already in progress
* @since 0.9
* @return true if a reseed was started, false if already in progress
* @since 0.9
*/
public boolean requestReseed() {
if (_inProgress.compareAndSet(false, true)) {
@ -160,17 +167,217 @@ public class ReseedChecker {
}
/**
* Start a reseed from a zip or su3 URI.
* Start a reseed from the onion URL pool
*
* @return true if a reseed was started, false if already in progress
* @throws IllegalArgumentException if it doesn't end with zip or su3
* @since 0.9.19
* @return true if a reseed was started, false if already in progress
* @since 0.9.53
*/
public boolean requestReseed(URI url) throws IllegalArgumentException {
public boolean requestOnionReseed(){
if (!onionReseedsConfigured())
return false;
if (_inProgress.compareAndSet(false, true)) {
_alreadyRun = true;
try {
Reseeder reseeder = new Reseeder(_context, this);
reseeder.requestOnionReseed();
return true;
} catch (Throwable t) {
_log.error("Reseed failed to start", t);
done();
return false;
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Reseed already in progress");
return false;
}
}
/**
* Determine if a list of onion reseeds are configured with i2p.onionReseedURL
*
* @return true if at least one onion reseed is configured.
* @since 0.9.53
*/
public boolean onionReseedsConfigured() {
String url = _context.getProperty(Reseeder.PROP_ONION_RESEED_URL);
if (url == null)
return false;
if (url.length() < 1)
return false;
return true;
}
/**
* Start a reseed from a zip or su3 URI.
*
* @return true if a reseed was started, false if already in progress
* @throws IllegalArgumentException if it doesn't end with zip or su3
* @since 0.9.19
*/
public boolean requestReseed(String uri) {
URI newURI = URI.create(uri);
return requestReseed(newURI, null, -1);
}
/**
* Start a reseed from a zip or su3 URI.
* If Tor is available, use it, otherwise return false.
*
* @return true if a reseed was started, false if already in progress
* @throws IllegalArgumentException if it doesn't end with zip or su3
* @since 0.9.52
*/
public boolean requestOnionReseed(URI uri) {
int proxyPort = torSOCKSPort();
String proxyHost = torHost();
if (testTor(proxyHost, proxyPort)) {
return requestReseed(uri, proxyHost, proxyPort);
} else {
return false;
}
}
private boolean testTor() {
return testTor(this._torHost, this._torSOCKSPort);
}
private boolean testTor(String phost, int pport) { // throws IOException {
// test that the socks 5 proxy is there and auth, if any, works
Socket s = null;
OutputStream out = null;
InputStream in = null;
String _phost = phost;
int _pport = pport;
String _puser = ""; //"reseed";
String _ppw = "";
try {
s = new Socket();
s.connect(new InetSocketAddress(_phost, _pport), 10 * 1000);
out = s.getOutputStream();
boolean authAvail = _puser != null && _ppw != null;
// send the init
out.write(SOCKS_VERSION_5);
if (authAvail) {
out.write(2);
out.write(Method.USERNAME_PASSWORD);
} else {
out.write(1);
}
out.write(Method.NO_AUTH_REQUIRED);
out.flush();
// read init reply
in = s.getInputStream();
int hisVersion = in.read();
if (hisVersion != SOCKS_VERSION_5)
return false;
int method = in.read();
if (method == Method.NO_AUTH_REQUIRED) {
// good
} else if (method == Method.USERNAME_PASSWORD) {
if (authAvail) {
// send the auth
out.write(AUTH_VERSION);
byte[] user = _puser.getBytes("UTF-8");
byte[] pw = _ppw.getBytes("UTF-8");
out.write(user.length);
out.write(user);
out.write(pw.length);
out.write(pw);
out.flush();
// read the auth reply
if (in.read() != AUTH_VERSION)
return false;
if (in.read() != AUTH_SUCCESS)
return false;
} else {
return false;
}
} else {
return false;
}
} catch (IOException ioe) {
return false;
} finally {
if (in != null)
try {
in.close();
} catch (IOException ioe) {
return false;
}
if (out != null)
try {
out.close();
} catch (IOException ioe) {
return false;
}
if (s != null)
try {
s.close();
} catch (IOException ioe) {
return false;
}
}
return true;
}
/**
* Detect if Tor is running on the host. If it is, return the hostname.
*
* @return hostname of Tor, or null if Tor is not running
* @since 0.9.52
*/
public String torHost() {
if (testTor()) {
_torHost = "127.0.0.1";
}
return _torHost;
}
/**
* Detect if Tor is running on the host. If it is, return the SOCKSport
*
* @return SOCKSport of Tor, or -1 if Tor is not running
* @since 0.9.52
*/
public int torSOCKSPort() {
if (testTor()) {
_torSOCKSPort = 9050;
}
return _torSOCKSPort;
}
/**
* Start a reseed from a zip or su3 URI.
*
* @return true if a reseed was started, false if already in progress
* @throws IllegalArgumentException if it doesn't end with zip or su3
* @since 0.9.52
*/
public boolean requestReseed(URI uri) {
return requestReseed(uri, null, -1);
}
public boolean requestReseed(URI url, String proxyHost, int proxyPort) throws IllegalArgumentException {
if (url.getHost().endsWith(".onion")) {
if (proxyHost == null && testTor()) {
proxyHost = torHost();
} else {
throw new IllegalArgumentException("Onion reseed requires a proxy host");
}
if (proxyPort <= 0 && testTor()) {
proxyPort = torSOCKSPort();
} else {
throw new IllegalArgumentException("Onion reseed requires a proxy port");
}
}
if (_inProgress.compareAndSet(false, true)) {
Reseeder reseeder = new Reseeder(_context, this);
try {
reseeder.requestReseed(url);
reseeder.requestReseed(url, proxyHost, proxyPort);
return true;
} catch (IllegalArgumentException iae) {
if (iae.getMessage() != null)
@ -190,11 +397,11 @@ public class ReseedChecker {
}
/**
* Reseed from a zip or su3 input stream. Blocking.
* Reseed from a zip or su3 input stream. Blocking.
*
* @return true if a reseed was started, false if already in progress
* @throws IOException if already in progress or on most other errors
* @since 0.9.19
* @return true if a reseed was started, false if already in progress
* @throws IOException if already in progress or on most other errors
* @since 0.9.19
*/
public int requestReseed(InputStream in) throws IOException {
// don't really need to check for in progress here
@ -214,19 +421,20 @@ public class ReseedChecker {
}
}
/** .
* Is a reseed in progress?
/**
* .
* Is a reseed in progress?
*
* @since 0.9
* @since 0.9
*/
public boolean inProgress() {
return _inProgress.get();
}
/**
* The reseed is complete
* The reseed is complete
*
* @since 0.9
* @since 0.9
*/
void done() {
_inProgress.set(false);
@ -234,50 +442,50 @@ public class ReseedChecker {
}
/**
* Status from current reseed attempt,
* probably empty if no reseed in progress.
* May include HTML.
* Status from current reseed attempt,
* probably empty if no reseed in progress.
* May include HTML.
*
* @return non-null, may be empty
* @since 0.9
* @return non-null, may be empty
* @since 0.9
*/
public String getStatus() {
return _lastStatus;
}
/**
* Status from current reseed attempt
* Status from current reseed attempt
*
* @param s non-null, may be empty
* @since 0.9
* @param s non-null, may be empty
* @since 0.9
*/
void setStatus(String s) {
_lastStatus = s;
}
/**
* Error from last or current reseed attempt.
* May include HTML.
* Error from last or current reseed attempt.
* May include HTML.
*
* @return non-null, may be empty
* @since 0.9
* @return non-null, may be empty
* @since 0.9
*/
public String getError() {
return _lastError;
}
/**
* Status from last or current reseed attempt
* Status from last or current reseed attempt
*
* @param s non-null, may be empty
* @since 0.9
* @param s non-null, may be empty
* @since 0.9
*/
void setError(String s) {
_lastError = s;
}
/**
* @since 0.9.19
* @since 0.9.19
*/
private class StatusCleaner implements SimpleTimer.TimedEvent {
private final String _status, _error;

File diff suppressed because it is too large Load Diff