forked from I2P_Developers/i2p.i2p
Compare commits
9 Commits
i2p.i2p.2.
...
dynamic-on
Author | SHA1 | Date | |
---|---|---|---|
0605977776 | |||
714adbdf10 | |||
fe1e245c25 | |||
b02389a0a4 | |||
171263e3ab | |||
c0bd91daec | |||
39a95e457a | |||
8414cb8eae | |||
2aa109bc2e |
@ -15,19 +15,24 @@ import net.i2p.router.web.FormHandler;
|
|||||||
import net.i2p.router.web.Messages;
|
import net.i2p.router.web.Messages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 0.8.3
|
* @since 0.8.3
|
||||||
*/
|
*/
|
||||||
public class ConfigReseedHandler extends FormHandler {
|
public class ConfigReseedHandler extends FormHandler {
|
||||||
private final Map<String, String> changes = new HashMap<String, String>();
|
private final Map<String, String> changes = new HashMap<String, String>();
|
||||||
private final List<String> removes = new ArrayList<String>();
|
private final List<String> removes = new ArrayList<String>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processForm() {
|
protected void processForm() {
|
||||||
|
|
||||||
ReseedChecker checker = _context.netDb().reseedChecker();
|
ReseedChecker checker = _context.netDb().reseedChecker();
|
||||||
if (_action.equals(_t("Save changes and reseed now"))) {
|
if (_action.equals(_t("Save changes and reseed now"))) {
|
||||||
saveChanges();
|
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"));
|
addFormError(_t("Reseeding is already in progress"));
|
||||||
addCheckerStatus(checker);
|
addCheckerStatus(checker);
|
||||||
} else {
|
} else {
|
||||||
@ -51,23 +56,48 @@ public class ConfigReseedHandler extends FormHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!checker.requestReseed(url)) {
|
if (url.getHost().endsWith(".onion")) {
|
||||||
addFormError(_t("Reseeding is already in progress"));
|
if (!checker.requestOnionReseed(url)) {
|
||||||
addCheckerStatus(checker);
|
addFormError(_t("Tor not available, unable to perform onion reseed"));
|
||||||
} else {
|
addCheckerStatus(checker);
|
||||||
// wait a while for completion but not forever
|
} else {
|
||||||
for (int i = 0; i < 40; i++) {
|
// wait a while for completion but not forever
|
||||||
try {
|
for (int i = 0; i < 40; i++) {
|
||||||
Thread.sleep(500);
|
try {
|
||||||
} catch (InterruptedException ie) {}
|
Thread.sleep(500);
|
||||||
if (!checker.inProgress())
|
} catch (InterruptedException ie) {
|
||||||
break;
|
}
|
||||||
|
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)) {
|
}else{
|
||||||
if (checker.inProgress()) {
|
if (!checker.requestReseed(url)) {
|
||||||
addFormNotice(_t("Reseed in progress, check sidebar for status"));
|
addFormError(_t("Reseeding is already in progress"));
|
||||||
} else {
|
addCheckerStatus(checker);
|
||||||
addFormNotice(_t("Reseed complete, check sidebar for status"));
|
} 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);
|
addCheckerStatus(checker);
|
||||||
} else {
|
} else {
|
||||||
addFormNotice(ngettext("Reseed successful, loaded {0} router info from file",
|
addFormNotice(ngettext("Reseed successful, loaded {0} router info from file",
|
||||||
"Reseed successful, loaded {0} router infos from file",
|
"Reseed successful, loaded {0} router infos from file",
|
||||||
count));
|
count));
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
addFormError(_t("Reseed from file failed") + " - " + ioe);
|
addFormError(_t("Reseed from file failed") + " - " + ioe);
|
||||||
@ -98,19 +128,24 @@ public class ConfigReseedHandler extends FormHandler {
|
|||||||
} finally {
|
} finally {
|
||||||
// it's really a ByteArrayInputStream but we'll play along...
|
// it's really a ByteArrayInputStream but we'll play along...
|
||||||
if (in != null)
|
if (in != null)
|
||||||
try { in.close(); } catch (IOException ioe) {}
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (_action.equals(_t("Save changes"))) {
|
} else if (_action.equals(_t("Save changes"))) {
|
||||||
saveChanges();
|
saveChanges();
|
||||||
} else if (_action.equals(_t("Reset URL list"))) {
|
} else if (_action.equals(_t("Reset URL list"))) {
|
||||||
resetUrlList();
|
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
|
* @return true if anything was output
|
||||||
* @since 0.9.33
|
* @since 0.9.33
|
||||||
*/
|
*/
|
||||||
private boolean addCheckerStatus(ReseedChecker checker) {
|
private boolean addCheckerStatus(ReseedChecker checker) {
|
||||||
String error = checker.getError();
|
String error = checker.getError();
|
||||||
@ -128,7 +163,14 @@ public class ConfigReseedHandler extends FormHandler {
|
|||||||
|
|
||||||
private void resetUrlList() {
|
private void resetUrlList() {
|
||||||
if (_context.router().saveConfig(Reseeder.PROP_RESEED_URL, null))
|
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
|
else
|
||||||
addFormError(_t("Error saving the configuration (applied but not saved) - please see the error logs"));
|
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);
|
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");
|
String mode = getJettyString("mode");
|
||||||
boolean req = "1".equals(mode);
|
boolean req = "1".equals(mode);
|
||||||
boolean disabled = "2".equals(mode);
|
boolean disabled = "2".equals(mode);
|
||||||
changes.put(Reseeder.PROP_SSL_REQUIRED,
|
changes.put(Reseeder.PROP_SSL_REQUIRED,
|
||||||
Boolean.toString(req));
|
Boolean.toString(req));
|
||||||
changes.put(Reseeder.PROP_SSL_DISABLE,
|
changes.put(Reseeder.PROP_SSL_DISABLE,
|
||||||
Boolean.toString(disabled));
|
Boolean.toString(disabled));
|
||||||
saveBoolean(Reseeder.PROP_PROXY_ENABLE, "enable");
|
saveBoolean(Reseeder.PROP_PROXY_ENABLE, "enable");
|
||||||
String pmode = getJettyString("pmode");
|
String pmode = getJettyString("pmode");
|
||||||
boolean senable = pmode != null && pmode.length() > 0;
|
boolean senable = pmode != null && pmode.length() > 0;
|
||||||
|
@ -9,7 +9,7 @@ import net.i2p.router.networkdb.reseed.Reseeder;
|
|||||||
import net.i2p.router.web.HelperBase;
|
import net.i2p.router.web.HelperBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 0.8.3
|
* @since 0.8.3
|
||||||
*/
|
*/
|
||||||
public class ConfigReseedHelper extends HelperBase {
|
public class ConfigReseedHelper extends HelperBase {
|
||||||
|
|
||||||
@ -52,24 +52,24 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String modeChecked(int mode) {
|
public String modeChecked(int mode) {
|
||||||
boolean required = _context.getBooleanPropertyDefaultTrue(Reseeder.PROP_SSL_REQUIRED);
|
boolean required = _context.getBooleanPropertyDefaultTrue(Reseeder.PROP_SSL_REQUIRED);
|
||||||
boolean disabled = _context.getBooleanProperty(Reseeder.PROP_SSL_DISABLE);
|
boolean disabled = _context.getBooleanProperty(Reseeder.PROP_SSL_DISABLE);
|
||||||
if ((mode == 0 && (!disabled) && (!required)) ||
|
if ((mode == 0 && (!disabled) && (!required)) ||
|
||||||
(mode == 1 && (!disabled) && required) ||
|
(mode == 1 && (!disabled) && required) ||
|
||||||
(mode == 2 && disabled))
|
(mode == 2 && disabled))
|
||||||
return CHECKED;
|
return CHECKED;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 0.9.33 */
|
/** @since 0.9.33 */
|
||||||
public String pmodeChecked(int mode) {
|
public String pmodeChecked(int mode) {
|
||||||
String c = _context.getProperty(Reseeder.PROP_SPROXY_TYPE, "HTTP");
|
String c = _context.getProperty(Reseeder.PROP_SPROXY_TYPE, "HTTP");
|
||||||
boolean disabled = !_context.getBooleanProperty(Reseeder.PROP_SPROXY_ENABLE);
|
boolean disabled = !_context.getBooleanProperty(Reseeder.PROP_SPROXY_ENABLE);
|
||||||
if ((mode == 0 && disabled) ||
|
if ((mode == 0 && disabled) ||
|
||||||
(mode == 1 && !disabled && c.equals("HTTP")) ||
|
(mode == 1 && !disabled && c.equals("HTTP")) ||
|
||||||
(mode == 2 && !disabled && c.equals("SOCKS4")) ||
|
(mode == 2 && !disabled && c.equals("SOCKS4")) ||
|
||||||
(mode == 3 && !disabled && c.equals("SOCKS5")) ||
|
(mode == 3 && !disabled && c.equals("SOCKS5")) ||
|
||||||
(mode == 4 && !disabled && c.equals("INTERNAL")))
|
(mode == 4 && !disabled && c.equals("INTERNAL")))
|
||||||
return CHECKED;
|
return CHECKED;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -83,11 +83,11 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
return getChecked(Reseeder.PROP_PROXY_AUTH_ENABLE);
|
return getChecked(Reseeder.PROP_PROXY_AUTH_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
public String getSenable() {
|
* public String getSenable() {
|
||||||
return getChecked(Reseeder.PROP_SPROXY_ENABLE);
|
* return getChecked(Reseeder.PROP_SPROXY_ENABLE);
|
||||||
}
|
* }
|
||||||
****/
|
****/
|
||||||
|
|
||||||
/** @since 0.8.9 */
|
/** @since 0.8.9 */
|
||||||
public String getSauth() {
|
public String getSauth() {
|
||||||
@ -95,7 +95,22 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<String> reseedList() {
|
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");
|
StringTokenizer tok = new StringTokenizer(urls, " ,\r\n");
|
||||||
List<String> URLList = new ArrayList<String>(16);
|
List<String> URLList = new ArrayList<String>(16);
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
@ -111,16 +126,28 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
Collections.sort(URLList);
|
Collections.sort(URLList);
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
for (String s : URLList) {
|
for (String s : URLList) {
|
||||||
if (buf.length() > 0)
|
if (buf.length() > 0)
|
||||||
buf.append('\n');
|
buf.append('\n');
|
||||||
buf.append(s);
|
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 buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true only if we have both http and https URLs
|
* @return true only if we have both http and https URLs
|
||||||
* @since 0.9.33
|
* @since 0.9.33
|
||||||
*/
|
*/
|
||||||
public boolean shouldShowSelect() {
|
public boolean shouldShowSelect() {
|
||||||
boolean http = false;
|
boolean http = false;
|
||||||
@ -140,8 +167,8 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true only if we have a http URL
|
* @return true only if we have a http URL
|
||||||
* @since 0.9.33
|
* @since 0.9.33
|
||||||
*/
|
*/
|
||||||
public boolean shouldShowHTTPProxy() {
|
public boolean shouldShowHTTPProxy() {
|
||||||
for (String u : reseedList()) {
|
for (String u : reseedList()) {
|
||||||
@ -152,8 +179,8 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true only if we have a https URL
|
* @return true only if we have a https URL
|
||||||
* @since 0.9.33
|
* @since 0.9.33
|
||||||
*/
|
*/
|
||||||
public boolean shouldShowHTTPSProxy() {
|
public boolean shouldShowHTTPSProxy() {
|
||||||
for (String u : reseedList()) {
|
for (String u : reseedList()) {
|
||||||
|
@ -154,6 +154,11 @@
|
|||||||
<div class="formaction" id="resetreseed"><input type="submit" name="action" class="reload" value="<%=intl._t("Reset URL list")%>" /></div>
|
<div class="formaction" id="resetreseed"><input type="submit" name="action" class="reload" value="<%=intl._t("Reset URL list")%>" /></div>
|
||||||
</td></tr>
|
</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()) { %>
|
<% if (reseedHelper.shouldShowHTTPSProxy()) { %>
|
||||||
<tr><td align="right"><b><%=intl._t("Proxy type for HTTPS reseed URLs")%>:</b></td>
|
<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) %> >
|
<td><label><input type="radio" class="optbox" name="pmode" value="" <%=reseedHelper.pmodeChecked(0) %> >
|
||||||
|
@ -2,7 +2,10 @@ package net.i2p.router.networkdb.reseed;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -13,39 +16,42 @@ import net.i2p.util.Addresses;
|
|||||||
import net.i2p.util.AddressType;
|
import net.i2p.util.AddressType;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.SimpleTimer;
|
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
|
* Reseeding is not strictly a router function, it used to be
|
||||||
* in the routerconsole app, but this made it impossible to
|
* in the routerconsole app, but this made it impossible to
|
||||||
* bootstrap an embedded router lacking a routerconsole,
|
* bootstrap an embedded router lacking a routerconsole,
|
||||||
* in iMule or android for example, without additional modifications.
|
* in iMule or android for example, without additional modifications.
|
||||||
*
|
*
|
||||||
* Also, as this is now called from PersistentDataStore, not from the
|
* Also, as this is now called from PersistentDataStore, not from the
|
||||||
* routerconsole, we can get started as soon as the netdb has read
|
* routerconsole, we can get started as soon as the netdb has read
|
||||||
* the netDb/ directory, not when the console starts.
|
* the netDb/ directory, not when the console starts.
|
||||||
*/
|
*/
|
||||||
public class ReseedChecker {
|
public class ReseedChecker {
|
||||||
|
|
||||||
private final RouterContext _context;
|
private final RouterContext _context;
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
private final AtomicBoolean _inProgress = new AtomicBoolean();
|
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 _lastStatus = "";
|
||||||
private volatile String _lastError = "";
|
private volatile String _lastError = "";
|
||||||
private volatile boolean _networkLogged;
|
private volatile boolean _networkLogged;
|
||||||
private volatile boolean _alreadyRun;
|
private volatile boolean _alreadyRun;
|
||||||
|
|
||||||
public static final int MINIMUM = 50;
|
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
|
// 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.
|
* All reseeding must be done through this instance.
|
||||||
* Access through context.netDb().reseedChecker(), others should not instantiate
|
* Access through context.netDb().reseedChecker(), others should not instantiate
|
||||||
*
|
*
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
public ReseedChecker(RouterContext context) {
|
public ReseedChecker(RouterContext context) {
|
||||||
_context = context;
|
_context = context;
|
||||||
@ -53,10 +59,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
|
* @param count current number of known routers, includes us
|
||||||
* @return true if a reseed was started
|
* @return true if a reseed was started
|
||||||
*/
|
*/
|
||||||
public boolean checkReseed(int count) {
|
public boolean checkReseed(int count) {
|
||||||
if (_alreadyRun) {
|
if (_alreadyRun) {
|
||||||
@ -69,8 +75,8 @@ public class ReseedChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_context.getBooleanProperty(Reseeder.PROP_DISABLE) ||
|
if (_context.getBooleanProperty(Reseeder.PROP_DISABLE) ||
|
||||||
_context.getBooleanProperty("i2p.vmCommSystem")) {
|
_context.getBooleanProperty("i2p.vmCommSystem")) {
|
||||||
int x = count - 1; // us
|
int x = count - 1; // us
|
||||||
// no ngettext, this is rare
|
// no ngettext, this is rare
|
||||||
String s;
|
String s;
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
@ -99,8 +105,9 @@ public class ReseedChecker {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we check the i2p installation directory for a flag telling us not to reseed,
|
// 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
|
// 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.
|
// 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 noReseedFile = new File(new File(System.getProperty("user.home")), ".i2pnoreseed");
|
||||||
File noReseedFileAlt1 = new File(new File(System.getProperty("user.home")), "noreseed.i2p");
|
File noReseedFileAlt1 = new File(new File(System.getProperty("user.home")), "noreseed.i2p");
|
||||||
@ -122,7 +129,7 @@ public class ReseedChecker {
|
|||||||
_log.logAlways(Log.WARN, "Very few known peers remaining - reseeding now");
|
_log.logAlways(Log.WARN, "Very few known peers remaining - reseeding now");
|
||||||
return requestReseed();
|
return requestReseed();
|
||||||
} else {
|
} else {
|
||||||
int x = count - 1; // us
|
int x = count - 1; // us
|
||||||
// no ngettext, this is rare
|
// no ngettext, this is rare
|
||||||
String s;
|
String s;
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
@ -138,10 +145,10 @@ public class ReseedChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a reseed
|
* Start a reseed
|
||||||
*
|
*
|
||||||
* @return true if a reseed was started, false if already in progress
|
* @return true if a reseed was started, false if already in progress
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
public boolean requestReseed() {
|
public boolean requestReseed() {
|
||||||
if (_inProgress.compareAndSet(false, true)) {
|
if (_inProgress.compareAndSet(false, true)) {
|
||||||
@ -163,17 +170,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
|
* @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.53
|
||||||
* @since 0.9.19
|
|
||||||
*/
|
*/
|
||||||
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)) {
|
if (_inProgress.compareAndSet(false, true)) {
|
||||||
Reseeder reseeder = new Reseeder(_context, this);
|
Reseeder reseeder = new Reseeder(_context, this);
|
||||||
try {
|
try {
|
||||||
reseeder.requestReseed(url);
|
reseeder.requestReseed(url, proxyHost, proxyPort);
|
||||||
return true;
|
return true;
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
if (iae.getMessage() != null)
|
if (iae.getMessage() != null)
|
||||||
@ -193,11 +400,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
|
* @return true if a reseed was started, false if already in progress
|
||||||
* @throws IOException if already in progress or on most other errors
|
* @throws IOException if already in progress or on most other errors
|
||||||
* @since 0.9.19
|
* @since 0.9.19
|
||||||
*/
|
*/
|
||||||
public int requestReseed(InputStream in) throws IOException {
|
public int requestReseed(InputStream in) throws IOException {
|
||||||
// don't really need to check for in progress here
|
// don't really need to check for in progress here
|
||||||
@ -217,19 +424,20 @@ public class ReseedChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** .
|
/**
|
||||||
* Is a reseed in progress?
|
* .
|
||||||
|
* Is a reseed in progress?
|
||||||
*
|
*
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
public boolean inProgress() {
|
public boolean inProgress() {
|
||||||
return _inProgress.get();
|
return _inProgress.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The reseed is complete
|
* The reseed is complete
|
||||||
*
|
*
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
void done() {
|
void done() {
|
||||||
_inProgress.set(false);
|
_inProgress.set(false);
|
||||||
@ -237,50 +445,50 @@ public class ReseedChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status from current reseed attempt,
|
* Status from current reseed attempt,
|
||||||
* probably empty if no reseed in progress.
|
* probably empty if no reseed in progress.
|
||||||
* May include HTML.
|
* May include HTML.
|
||||||
*
|
*
|
||||||
* @return non-null, may be empty
|
* @return non-null, may be empty
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return _lastStatus;
|
return _lastStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status from current reseed attempt
|
* Status from current reseed attempt
|
||||||
*
|
*
|
||||||
* @param s non-null, may be empty
|
* @param s non-null, may be empty
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
void setStatus(String s) {
|
void setStatus(String s) {
|
||||||
_lastStatus = s;
|
_lastStatus = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error from last or current reseed attempt.
|
* Error from last or current reseed attempt.
|
||||||
* May include HTML.
|
* May include HTML.
|
||||||
*
|
*
|
||||||
* @return non-null, may be empty
|
* @return non-null, may be empty
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
public String getError() {
|
public String getError() {
|
||||||
return _lastError;
|
return _lastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status from last or current reseed attempt
|
* Status from last or current reseed attempt
|
||||||
*
|
*
|
||||||
* @param s non-null, may be empty
|
* @param s non-null, may be empty
|
||||||
* @since 0.9
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
void setError(String s) {
|
void setError(String s) {
|
||||||
_lastError = s;
|
_lastError = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 0.9.19
|
* @since 0.9.19
|
||||||
*/
|
*/
|
||||||
private class StatusCleaner implements SimpleTimer.TimedEvent {
|
private class StatusCleaner implements SimpleTimer.TimedEvent {
|
||||||
private final String _status, _error;
|
private final String _status, _error;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user