use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class NTCPTransport method startListening.
/**
* Called by TransportManager.
* Caller should stop the transport first, then
* verify stopped with isAlive()
* Unfortunately TransportManager doesn't do that, so we
* check here to prevent two pumpers.
*/
public synchronized void startListening() {
// try once again to prevent two pumpers which is fatal
if (_pumper.isAlive())
return;
if (_log.shouldLog(Log.WARN))
_log.warn("Starting NTCP transport listening");
startIt();
RouterAddress addr = configureLocalAddress();
int port;
if (addr != null)
// probably not set
port = addr.getPort();
else
// received by externalAddressReceived() from TransportManager
port = _ssuPort;
RouterAddress myAddress = bindAddress(port);
if (myAddress != null) {
// fixed interface, or bound to the specified host
replaceAddress(myAddress);
} else if (addr != null) {
// specified host, bound to wildcard
replaceAddress(addr);
} else if (port > 0) {
// all detected interfaces
for (InetAddress ia : getSavedLocalAddresses()) {
OrderedProperties props = new OrderedProperties();
props.setProperty(RouterAddress.PROP_HOST, ia.getHostAddress());
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
int cost = getDefaultCost(ia instanceof Inet6Address);
myAddress = new RouterAddress(STYLE, props, cost);
replaceAddress(myAddress);
}
}
// TransportManager.startListening() calls router.rebuildRouterInfo()
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class NTCPTransport method bindAddress.
/**
* Only does something if myPort > 0 and myPort != current bound port
* (or there's no current port, or the configured interface or hostname changed).
* If we are changing the bound port, this restarts everything, which takes a long time.
*
* call from synchronized method
*
* @param myPort does nothing if <= 0
* @return new address ONLY if bound to specific address, otherwise null
*/
private RouterAddress bindAddress(int port) {
RouterAddress myAddress = null;
if (port > 0) {
InetAddress bindToAddr = null;
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
if (bindTo == null) {
// If we are configured with a fixed IP address,
// AND it's one of our local interfaces,
// bind only to that.
bindTo = getFixedHost();
}
if (bindTo != null) {
try {
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
_log.error("Invalid NTCP bind interface specified [" + bindTo + "]", uhe);
// this can be implemented later, just updates some stats
// see udp/UDPTransport.java
// setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
// return null;
// fall thru
}
}
try {
InetSocketAddress addr;
if (bindToAddr == null) {
addr = new InetSocketAddress(port);
} else {
addr = new InetSocketAddress(bindToAddr, port);
if (_log.shouldLog(Log.WARN))
_log.warn("Binding only to " + bindToAddr);
OrderedProperties props = new OrderedProperties();
props.setProperty(RouterAddress.PROP_HOST, bindTo);
props.setProperty(RouterAddress.PROP_PORT, Integer.toString(port));
int cost = getDefaultCost(false);
myAddress = new RouterAddress(STYLE, props, cost);
}
if (!_endpoints.isEmpty()) {
// require a restart.
if (_endpoints.contains(addr) || (bindToAddr != null && _endpoints.contains(new InetSocketAddress(port)))) {
if (_log.shouldLog(Log.WARN))
_log.warn("Already listening on " + addr);
return null;
}
// FIXME support multiple binds
// FIXME just close and unregister
stopWaitAndRestart();
}
if (!TransportUtil.isValidPort(port))
_log.error("Specified NTCP port is " + port + ", ports lower than 1024 not recommended");
ServerSocketChannel chan = ServerSocketChannel.open();
chan.configureBlocking(false);
chan.socket().bind(addr);
_endpoints.add(addr);
if (_log.shouldLog(Log.INFO))
_log.info("Listening on " + addr);
_pumper.register(chan);
} catch (IOException ioe) {
_log.error("Error listening", ioe);
myAddress = null;
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Outbound NTCP connections only - no listener configured");
}
return myAddress;
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class UDPTransport method locked_rebuildExternalAddress.
private RouterAddress locked_rebuildExternalAddress(String host, int port, boolean allowRebuildRouterInfo) {
if (_log.shouldDebug())
_log.debug("REA4 " + host + ':' + port);
if (_context.router().isHidden())
return null;
OrderedProperties options = new OrderedProperties();
boolean directIncluded;
// DNS name assumed IPv4
boolean isIPv6 = host != null && host.contains(":");
boolean introducersRequired = (!isIPv6) && introducersRequired();
if (!introducersRequired && allowDirectUDP() && port > 0 && host != null) {
options.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
options.setProperty(UDPAddress.PROP_HOST, host);
directIncluded = true;
} else {
directIncluded = false;
}
boolean introducersIncluded = false;
if (introducersRequired) {
// intro manager now sorts introducers, so
// deepEquals() below will not fail even with same introducers.
// Was only a problem when we had very very few peers to pick from.
RouterAddress current = getCurrentAddress(isIPv6);
int found = _introManager.pickInbound(current, options, PUBLIC_RELAY_COUNT);
if (found > 0) {
if (_log.shouldLog(Log.INFO))
_log.info("Direct? " + directIncluded + " reqd? " + introducersRequired + " picked introducers: " + found);
_introducersSelectedOn = _context.clock().now();
introducersIncluded = true;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Direct? " + directIncluded + " reqd? " + introducersRequired + " no introducers");
}
}
// if we have explicit external addresses, they had better be reachable
if (introducersRequired)
options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING);
else
options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING_INTRO);
// MTU since 0.9.2
int mtu;
if (host == null) {
mtu = _mtu;
} else {
try {
InetAddress ia = InetAddress.getByName(host);
mtu = setMTU(ia);
} catch (UnknownHostException uhe) {
mtu = _mtu;
}
}
if (mtu != PeerState.LARGE_MTU)
options.setProperty(UDPAddress.PROP_MTU, Integer.toString(mtu));
if (directIncluded || introducersIncluded) {
// Note that peers won't connect to us without this - see EstablishmentManager
if (_introKey != null)
options.setProperty(UDPAddress.PROP_INTRO_KEY, _introKey.toBase64());
// SSU seems to regulate at about 85%, so make it a little higher.
// If this is too low, both NTCP and SSU always have incremented cost and
// the whole mechanism is not helpful.
int cost = DEFAULT_COST;
if (ADJUST_COST && !haveCapacity(91))
cost += CONGESTION_COST_ADJUSTMENT;
if (introducersIncluded)
cost += 2;
if (isIPv6) {
TransportUtil.IPv6Config config = getIPv6Config();
if (config == IPV6_PREFERRED)
cost--;
else if (config == IPV6_NOT_PREFERRED)
cost++;
}
RouterAddress addr = new RouterAddress(STYLE, options, cost);
RouterAddress current = getCurrentAddress(isIPv6);
boolean wantsRebuild = !addr.deepEquals(current);
// save the external address, even if we didn't publish it
if (port > 0 && host != null) {
RouterAddress local;
if (directIncluded) {
local = addr;
} else {
OrderedProperties localOpts = new OrderedProperties();
localOpts.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
localOpts.setProperty(UDPAddress.PROP_HOST, host);
local = new RouterAddress(STYLE, localOpts, cost);
}
replaceCurrentExternalAddress(local, isIPv6);
}
if (wantsRebuild) {
if (_log.shouldLog(Log.INFO))
_log.info("Address rebuilt: " + addr, new Exception());
replaceAddress(addr);
// via CSFI.createAddresses->TM.getAddresses()->updateAddress()->REA
if (allowRebuildRouterInfo)
_context.router().rebuildRouterInfo();
} else {
addr = null;
}
if (!isIPv6)
_needsRebuild = false;
return addr;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Wanted to rebuild my SSU address, but couldn't specify either the direct or indirect info (needs introducers? " + introducersRequired + ")", new Exception("source"));
_needsRebuild = true;
// save the external address, even if we didn't publish it
if (port > 0 && host != null) {
OrderedProperties localOpts = new OrderedProperties();
localOpts.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
localOpts.setProperty(UDPAddress.PROP_HOST, host);
RouterAddress local = new RouterAddress(STYLE, localOpts, DEFAULT_COST);
replaceCurrentExternalAddress(local, isIPv6);
}
if (hasCurrentAddress()) {
// We must remove current address, otherwise the user will see
// "firewalled with inbound NTCP enabled" warning in console.
// Remove the IPv4 address only
removeAddress(false);
// via CSFI.createAddresses->TM.getAddresses()->updateAddress()->REA
if (allowRebuildRouterInfo)
_context.router().rebuildRouterInfo();
}
return null;
}
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class PluginUpdateRunner method processFinal.
/**
* @param pubkey null OK for su3
* @since 0.9.15
*/
private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
boolean update = false;
String appName = props.getProperty("name");
String version = props.getProperty("version");
if (appName == null || version == null || appName.length() <= 0 || version.length() <= 0 || appName.indexOf('<') >= 0 || appName.indexOf('>') >= 0 || version.indexOf('<') >= 0 || version.indexOf('>') >= 0 || appName.startsWith(".") || appName.indexOf('/') >= 0 || appName.indexOf('\\') >= 0) {
to.delete();
statusDone("<b>" + _t("Plugin from {0} has invalid name or version", url) + "</b>");
return;
}
if (!version.equals(sudVersion)) {
to.delete();
statusDone("<b>" + _t("Plugin {0} has mismatched versions", appName) + "</b>");
return;
}
// set so notifyComplete() will work
_appName = appName;
_newVersion = version;
String minVersion = PluginStarter.stripHTML(props, "min-i2p-version");
if (minVersion != null && VersionComparator.comp(CoreVersion.VERSION, minVersion) < 0) {
to.delete();
statusDone("<b>" + _t("This plugin requires I2P version {0} or higher", minVersion) + "</b>");
return;
}
minVersion = PluginStarter.stripHTML(props, "min-java-version");
if (minVersion != null && VersionComparator.comp(System.getProperty("java.version"), minVersion) < 0) {
to.delete();
statusDone("<b>" + _t("This plugin requires Java version {0} or higher", minVersion) + "</b>");
return;
}
boolean wasRunning = false;
File destDir = new SecureDirectory(appDir, appName);
if (destDir.exists()) {
if (Boolean.valueOf(props.getProperty("install-only")).booleanValue()) {
to.delete();
statusDone("<b>" + _t("Downloaded plugin is for new installs only, but the plugin is already installed", url) + "</b>");
return;
}
// compare previous version
File oldPropFile = new File(destDir, "plugin.config");
Properties oldProps = new OrderedProperties();
try {
DataHelper.loadProps(oldProps, oldPropFile);
} catch (IOException ioe) {
to.delete();
statusDone("<b>" + _t("Installed plugin does not contain the required configuration file", url) + "</b>");
return;
}
String oldPubkey = oldProps.getProperty("key");
String oldKeyName = oldProps.getProperty("signer");
String oldAppName = oldProps.getProperty("name");
if ((pubkey != null && !pubkey.equals(oldPubkey)) || (!signer.equals(oldKeyName)) || (!appName.equals(oldAppName))) {
to.delete();
statusDone("<b>" + _t("Signature of downloaded plugin does not match installed plugin") + "</b>");
return;
}
String oldVersion = oldProps.getProperty("version");
if (oldVersion == null || VersionComparator.comp(oldVersion, version) >= 0) {
to.delete();
statusDone("<b>" + _t("Downloaded plugin version {0} is not newer than installed plugin", version) + "</b>");
return;
}
minVersion = PluginStarter.stripHTML(props, "min-installed-version");
if (minVersion != null && VersionComparator.comp(minVersion, oldVersion) > 0) {
to.delete();
statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or higher", minVersion) + "</b>");
return;
}
String maxVersion = PluginStarter.stripHTML(props, "max-installed-version");
if (maxVersion != null && VersionComparator.comp(maxVersion, oldVersion) < 0) {
to.delete();
statusDone("<b>" + _t("Plugin update requires installed plugin version {0} or lower", maxVersion) + "</b>");
return;
}
oldVersion = RouterConsoleRunner.jettyVersion();
minVersion = PluginStarter.stripHTML(props, "min-jetty-version");
if (minVersion != null && VersionComparator.comp(minVersion, oldVersion) > 0) {
to.delete();
statusDone("<b>" + _t("Plugin requires Jetty version {0} or higher", minVersion) + "</b>");
return;
}
String blacklistVersion = PluginStarter.jetty9Blacklist.get(appName);
if (blacklistVersion != null && VersionComparator.comp(version, blacklistVersion) <= 0) {
to.delete();
statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", "8.9999") + "</b>");
return;
}
maxVersion = PluginStarter.stripHTML(props, "max-jetty-version");
if (maxVersion != null && VersionComparator.comp(maxVersion, oldVersion) < 0) {
to.delete();
statusDone("<b>" + _t("Plugin requires Jetty version {0} or lower", maxVersion) + "</b>");
return;
}
// do we defer extraction and installation?
if (Boolean.valueOf(props.getProperty("router-restart-required")).booleanValue()) {
// Yup!
try {
if (!FileUtil.copy(to, (new SecureFile(new SecureFile(appDir.getCanonicalPath() + "/" + appName + "/" + ZIP).getCanonicalPath())), true, true)) {
to.delete();
statusDone("<b>" + _t("Cannot copy plugin to directory {0}", destDir.getAbsolutePath()) + "</b>");
return;
}
} catch (Throwable t) {
to.delete();
_log.error("Error copying plugin {0}", t);
return;
}
// we don't need the original file anymore.
to.delete();
statusDone("<b>" + _t("Plugin will be installed on next restart.") + ' ' + appName + ' ' + version + "</b>");
return;
}
if (PluginStarter.isPluginRunning(appName, _context)) {
wasRunning = true;
try {
if (!PluginStarter.stopPlugin(_context, appName)) {
// failed, ignore
}
} catch (Throwable e) {
// no updateStatus() for this one
_log.error("Error stopping plugin " + appName, e);
}
}
update = true;
} else {
if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) {
to.delete();
statusDone("<b>" + _t("Plugin is for upgrades only, but the plugin is not installed") + ". " + appName + ' ' + version + "</b>");
return;
}
if (!destDir.mkdir()) {
to.delete();
statusDone("<b>" + _t("Cannot create plugin directory {0}", destDir.getAbsolutePath()) + "</b>");
return;
}
}
// Finally, extract the zip to the plugin directory
if (!FileUtil.extractZip(to, destDir, Log.WARN)) {
to.delete();
statusDone("<b>" + _t("Failed to install plugin in {0}", destDir.getAbsolutePath()) + "</b>");
return;
}
_updated = true;
to.delete();
// install != update. Changing the user's settings like this is probabbly a bad idea.
if (Boolean.valueOf(props.getProperty("dont-start-at-install")).booleanValue()) {
statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
if (!update) {
Properties pluginProps = PluginStarter.pluginProperties();
pluginProps.setProperty(PluginStarter.PREFIX + appName + PluginStarter.ENABLED, "false");
PluginStarter.storePluginProperties(pluginProps);
}
} else if (wasRunning || PluginStarter.isPluginEnabled(appName)) {
// start everything unless it was disabled and not running before
try {
if (PluginStarter.startPlugin(_context, appName)) {
String linkName = PluginStarter.stripHTML(props, "consoleLinkName_" + Messages.getLanguage(_context));
if (linkName == null)
linkName = PluginStarter.stripHTML(props, "consoleLinkName");
String linkURL = PluginStarter.stripHTML(props, "consoleLinkURL");
String link;
if (linkName != null && linkURL != null)
link = "<a target=\"_blank\" href=\"" + linkURL + "\"/>" + linkName + ' ' + version + "</a>";
else
link = appName + ' ' + version;
statusDone("<b>" + _t("Plugin {0} installed and started", link) + "</b>");
} else
statusDone("<b>" + _t("Plugin {0} installed but failed to start, check logs", appName + ' ' + version) + "</b>");
} catch (Throwable e) {
statusDone("<b>" + _t("Plugin {0} installed but failed to start", appName + ' ' + version) + ": " + e + "</b>");
_log.error("Error starting plugin " + appName + ' ' + version, e);
}
} else {
statusDone("<b>" + _t("Plugin {0} installed", appName + ' ' + version) + "</b>");
}
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class PluginUpdateRunner method getPluginConfig.
/**
* @since 0.9.15
* @return null on error
*/
private Properties getPluginConfig(File f, File to, String url) {
File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip");
if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) {
f.delete();
to.delete();
FileUtil.rmdir(tempDir, false);
statusDone("<b>" + _t("Plugin from {0} is corrupt", url) + "</b>");
return null;
}
File installProps = new File(tempDir, "plugin.config");
Properties props = new OrderedProperties();
try {
DataHelper.loadProps(props, installProps);
} catch (IOException ioe) {
f.delete();
to.delete();
statusDone("<b>" + _t("Plugin from {0} does not contain the required configuration file", url) + "</b>");
return null;
} finally {
// we don't need this anymore, we will unzip again
FileUtil.rmdir(tempDir, false);
}
return props;
}
Aggregations