Finished implementation of UPNP:

*) will try other ports if YaCy standard ports are not available
*) distinguish between internal and external port (not sure if this
works 100%)

Still to add: propery in config to enter own external port (in case of
manually configured NAT)
pull/1/head
Marc Nause 10 years ago
parent d0358e568b
commit 1e6e69bc40

@ -100,7 +100,7 @@ public class ConfigBasic {
port = post.getLong("port", 8090);
ssl = post.getBoolean("withssl");
} else {
port = env.getConfigLong("port", 8090); //this allows a low port, but it will only get one, if the user edits the config himself.
port = env.getLocalPort("port", 8090); //this allows a low port, but it will only get one, if the user edits the config himself.
ssl = env.getConfigBool("server.https", false);
}
if (ssl) prop.put("withsslenabled_sslport",env.getHttpServer().getSslPort());
@ -266,7 +266,7 @@ public class ConfigBasic {
// set default values
prop.putHTML("defaultName", sb.peers.mySeed().getName());
prop.putHTML("defaultPort", env.getConfig("port", "8090"));
prop.put("defaultPort", env.getLocalPort("port", 8090));
prop.put("withsslenabled", env.getConfigBool("server.https", false) ? 1 : 0);
lang = env.getConfig("locale.language", "default"); // re-assign lang, may have changed
prop.put("lang_de", "0");

@ -221,7 +221,7 @@ public class ConfigPortal {
String myaddress = (sb.peers == null) ? null : sb.peers.mySeed() == null ? null : sb.peers.mySeed().getPublicAddress();
if (myaddress == null) {
myaddress = "localhost:" + sb.getConfig("port", "8090");
myaddress = "localhost:" + sb.getLocalPort("port", 8090);
}
prop.put("myaddress", myaddress);
return prop;

@ -35,7 +35,7 @@ public class ConfigSearchBox {
final Switchboard sb = (Switchboard) env;
String myaddress = sb.peers.mySeed().getPublicAddress();
if (myaddress == null) myaddress = "localhost:" + sb.getConfig("port", "8090");
if (myaddress == null) myaddress = "localhost:" + sb.getLocalPort("port", 8090);
prop.put("myaddress", myaddress);
return prop;
}

@ -214,7 +214,7 @@ public class CrawlStartScanner_p
path += "&crawlingURL=" + url.toNormalform(true);
WorkTables.execAPICall(
Domains.LOCALHOST,
(int) sb.getConfigLong("port", 8090),
sb.getLocalPort("port", 8090),
path,
pk,
sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"),
@ -261,7 +261,7 @@ public class CrawlStartScanner_p
path += "&crawlingURL=" + urlString;
WorkTables.execAPICall(
Domains.LOCALHOST,
(int) sb.getConfigLong("port", 8090),
sb.getLocalPort("port", 8090),
path,
u.hash(),
sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"),

@ -39,7 +39,7 @@ public class Load_MediawikiWiki {
// define visible variables
String a = sb.peers.mySeed().getPublicAddress();
if (a == null) a = "localhost:" + sb.getConfig("port", "8090");
if (a == null) a = "localhost:" + sb.getLocalPort("port", 8090);
final boolean intranet = sb.getConfig(SwitchboardConstants.NETWORK_NAME, "").equals("intranet");
final String repository = "http://" + a + "/repository/";
prop.put("starturl", (intranet) ? repository : "http://");

@ -39,7 +39,7 @@ public class Load_PHPBB3 {
// define visible variables
String a = sb.peers.mySeed().getPublicAddress();
if (a == null) a = "localhost:" + sb.getConfig("port", "8090");
if (a == null) a = "localhost:" + sb.getLocalPort("port", 8090);
final boolean intranet = sb.getConfig(SwitchboardConstants.NETWORK_NAME, "").equals("intranet");
final String repository = "http://" + a + "/repository/";
prop.put("starturl", (intranet) ? repository : "http://");

@ -99,7 +99,7 @@ public class SettingsAck_p {
/*
* display port info
*/
prop.putHTML("info_port", env.getConfig("port", "8090"));
prop.put("info_port", env.getLocalPort("port", 8090));
prop.put("info_restart", "0");
// read and process data
@ -483,7 +483,7 @@ public class SettingsAck_p {
// change https port
if (post.containsKey("port.ssl")) {
int port = post.getInt("port.ssl", 8443);
if (port > 0 && port != env.getConfigInt("port", 8090)) {
if (port > 0 && port != env.getLocalPort("port", 8090)) {
env.setConfig("port.ssl", port);
}
prop.put("info_port.ssl", port);

@ -73,7 +73,7 @@ public final class Settings_p {
prop.put("settingsTables", "");
}
prop.put("port", env.getConfig("port", "8090"));
prop.put("port", env.getLocalPort("port", 8090));
prop.putHTML("peerName", sb.peers.mySeed().getName());
prop.putHTML("staticIP", env.getConfig("staticIP", ""));

@ -206,7 +206,7 @@ public class Table_API_p {
}
// now call the api URLs and store the result status
final Map<String, Integer> l = sb.tables.execAPICalls(Domains.LOCALHOST, (int) sb.getConfigLong("port", 8090), pks, sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""));
final Map<String, Integer> l = sb.tables.execAPICalls(Domains.LOCALHOST, sb.getLocalPort("port", 8090), pks, sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""));
// construct result table
prop.put("showexec", l.isEmpty() ? 0 : 1);
@ -297,7 +297,7 @@ public class Table_API_p {
} else {
prop.put("showtable_list_" + count + "_isCrawlerStart", 0);
}
prop.putHTML("showtable_list_" + count + "_inline_url", "http://" + sb.myPublicIP() + ":" + sb.getConfig("port", "8090") + UTF8.String(row.get(WorkTables.TABLE_API_COL_URL)));
prop.putHTML("showtable_list_" + count + "_inline_url", "http://" + sb.myPublicIP() + ":" + sb.getPublicPort("port", 8090) + UTF8.String(row.get(WorkTables.TABLE_API_COL_URL)));
prop.put("showtable_list_" + count + "_scheduler_inline", inline ? "true" : "false");
prop.put("showtable_list_" + count + "_scheduler_filter", typefilter.pattern());
prop.put("showtable_list_" + count + "_scheduler_query", query.pattern());

@ -122,7 +122,7 @@ public class push_p {
sb.indexingDocumentProcessor.enQueue(in);
}
prop.put("mode_results_" + i + "_success", "1");
prop.put("mode_results_" + i + "_success_message", "http://" + Domains.myPublicLocalIP().getHostAddress() + ":" + sb.getConfigInt("port", 8090) + "/solr/select?q=sku:%22" + u + "%22");
prop.put("mode_results_" + i + "_success_message", "http://" + Domains.myPublicLocalIP().getHostAddress() + ":" + sb.getLocalPort("port", 8090) + "/solr/select?q=sku:%22" + u + "%22");
countsuccess++;
} catch (MalformedURLException e) {
e.printStackTrace();

@ -40,7 +40,7 @@ public class opensearchdescription {
if (env.getConfigBool(SwitchboardConstants.GREETING_NETWORK_NAME, false)) promoteSearchPageGreeting = env.getConfig("network.unit.description", "");
String thisaddress = header.get("Host", Domains.LOCALHOST);
if (thisaddress.indexOf(':',0) == -1) thisaddress += ":" + env.getConfig("port", "8090");
if (thisaddress.indexOf(':',0) == -1) thisaddress += ":" + env.getLocalPort("port", 8090);
String thisprotocol = env.getConfigBool("server.https", false) ? "https" : "http";
final serverObjects prop = new serverObjects();

@ -146,7 +146,7 @@ public class yacysearch {
// adding some additional properties needed for the rss feed
String hostName = header.get("Host", Domains.LOCALHOST);
if ( hostName.indexOf(':', 0) == -1 ) {
hostName += ":" + env.getConfig("port", "8090");
hostName += ":" + env.getLocalPort("port", 8090);
}
prop.put("searchBaseURL", "http://" + hostName + "/yacysearch.html");
prop.put("rssYacyImageURL", "http://" + hostName + "/env/grafics/yacy.png");
@ -880,7 +880,7 @@ public class yacysearch {
// hostname and port (assume locahost if nothing helps)
final String hostIP = sb.peers.mySeed().getIP();
prop.put("myhost", hostIP != null ? hostIP : Domains.LOCALHOST);
prop.put("myport", sb.getConfig("port", "8090"));
prop.put("myport", Domains.LOCALHOST.equals(hostIP) ? sb.getLocalPort("port", 8090) : sb.getPublicPort("port", 8090));
// return rewrite properties
return prop;

@ -91,7 +91,7 @@ public class yacysearch_location {
if (query.length() > 0 && (metatag || search_title || search_publisher || search_creator || search_subject)) try {
// get a queue of search results
final String rssSearchServiceURL = "http://127.0.0.1:" + sb.getConfig("port", "8090") + "/yacysearch.rss";
final String rssSearchServiceURL = "http://127.0.0.1:" + sb.getLocalPort("port", 8090) + "/yacysearch.rss";
final BlockingQueue<RSSMessage> results = new LinkedBlockingQueue<RSSMessage>();
SRURSSConnector.searchSRURSS(results, rssSearchServiceURL, lon == 0.0d && lat == 0.0d ? query : query + " /radius/" + lat + "/" + lon + "/" + radius, maximumTime, Integer.MAX_VALUE, null, false, ClientIdentification.yacyInternetCrawlerAgent);
@ -121,7 +121,7 @@ public class yacysearch_location {
String promoteSearchPageGreeting = env.getConfig(SwitchboardConstants.GREETING, "");
if (env.getConfigBool(SwitchboardConstants.GREETING_NETWORK_NAME, false)) promoteSearchPageGreeting = env.getConfig("network.unit.description", "");
String hostName = header.get("Host", Domains.LOCALHOST);
if (hostName.indexOf(':',0) == -1) hostName += ":" + env.getConfig("port", "8090");
if (hostName.indexOf(':',0) == -1) hostName += ":" + env.getLocalPort("port", "8090");
final String originalquerystring = (post == null) ? "" : post.get("query", post.get("search", "")).trim(); // SRU compliance
final boolean global = post.get("kml_resource", "local").equals("global");

@ -239,8 +239,8 @@ public final class Tray {
}
private String readyMessage() {
if (deutsch) return "YaCy laeuft unter http://localhost:" + sb.getConfig("port", "8090");
return "YaCy is running at http://localhost:" + sb.getConfig("port", "8090");
if (deutsch) return "YaCy laeuft unter http://localhost:" + sb.getLocalPort("port", 8090);
return "YaCy is running at http://localhost:" + sb.getLocalPort("port", 8090);
}
private String shutdownMessage() {

@ -82,7 +82,7 @@ public class Jetty9HttpServerImpl implements YaCyHttpServer {
final SSLContext sslContext = initSslContext(sb);
if (sslContext != null) {
int sslport = sb.getConfigInt("port.ssl", 8443);
int sslport = sb.getLocalPort("port.ssl", 8443);
sslContextFactory.setSslContext(sslContext);
// SSL HTTP Configuration
@ -286,8 +286,8 @@ public class Jetty9HttpServerImpl implements YaCyHttpServer {
}
try { // reconnect with new settings (instead to stop/start server, just manipulate connectors
final Connector[] cons = server.getConnectors();
final int port = Switchboard.getSwitchboard().getConfigInt("port", 8090);
final int sslport = Switchboard.getSwitchboard().getConfigInt("port.ssl", 8443);
final int port = Switchboard.getSwitchboard().getLocalPort("port", 8090);
final int sslport = Switchboard.getSwitchboard().getLocalPort("port.ssl", 8443);
for (Connector con : cons) {
// check http connector
if (con.getName().startsWith("httpd") && ((ServerConnector)con).getPort() != port) {

@ -1162,9 +1162,9 @@ public class Seed implements Cloneable, Comparable<Seed>, Comparator<Seed>
final Seed newSeed = new Seed(hashs);
// now calculate other information about the host
final long port = Switchboard.getSwitchboard().getConfigLong("port", 8090); //get port from config
final int port = Switchboard.getSwitchboard().getPublicPort("port", 8090); //get port from config
newSeed.dna.put(Seed.NAME, defaultPeerName() );
newSeed.dna.put(Seed.PORT, Long.toString(port));
newSeed.dna.put(Seed.PORT, Integer.toString(port));
return newSeed;
}

@ -958,7 +958,7 @@ public final class SeedDB implements AlternativeDomainNames {
if (this.mySeed == null) initMySeed();
if ((seed == this.mySeed) && (!(seed.isOnline()))) {
// take local ip instead of external
return Switchboard.getSwitchboard().myPublicIP() + ":" + Switchboard.getSwitchboard().getConfig("port", "8090") + ((subdom == null) ? "" : ("/" + subdom));
return Switchboard.getSwitchboard().myPublicIP() + ":" + Switchboard.getSwitchboard().getLocalPort("port", 8090) + ((subdom == null) ? "" : ("/" + subdom));
}
return seed.getPublicAddress(seed.getIP()) + ((subdom == null) ? "" : ("/" + subdom));
} else {

@ -294,7 +294,7 @@ public final class Switchboard extends serverSwitch {
super(dataPath, appPath, initPath, configPath);
sb = this;
// check if port is already occupied
final int port = getConfigInt("port", 8090);
final int port = getLocalPort("port", 8090);
if (TimeoutRequest.ping(Domains.LOCALHOST, port, 500)) {
throw new RuntimeException(
"a server is already running on the YaCy port "
@ -2453,7 +2453,7 @@ public final class Switchboard extends serverSwitch {
startupAction = false;
// execute api calls
final Map<String, Integer> callResult = this.tables.execAPICalls("localhost", (int) getConfigLong("port", 8090), pks, getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""));
final Map<String, Integer> callResult = this.tables.execAPICalls("localhost", getLocalPort("port", 8090), pks, getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""));
for ( final Map.Entry<String, Integer> call : callResult.entrySet() ) {
this.log.info("Scheduler executed api call, response " + call.getValue() + ": " + call.getKey());
}
@ -3675,7 +3675,7 @@ public final class Switchboard extends serverSwitch {
private static long indeSizeCache = 0;
private static long indexSizeTime = 0;
public void updateMySeed() {
this.peers.mySeed().put(Seed.PORT, getConfig("port", "8090"));
this.peers.mySeed().put(Seed.PORT, Integer.toString(getPublicPort("port", 8090)));
//the speed of indexing (pages/minute) of the peer
final long uptime = (System.currentTimeMillis() - this.startupTime) / 1000;

@ -162,13 +162,13 @@ public final class HTTPDemon {
final InetAddress hostAddress = Domains.dnsResolve(clientIP);
if (hostAddress == null) {
tp.put("host", Domains.myPublicLocalIP().getHostAddress());
tp.put("port", switchboard.getConfig("port", "8090"));
tp.put("port", switchboard.getLocalPort("port", 8090));
} else if (hostAddress.isSiteLocalAddress() || hostAddress.isLoopbackAddress()) {
tp.put("host", Domains.myPublicLocalIP().getHostAddress());
tp.put("port", switchboard.getConfig("port", "8090"));
tp.put("port", switchboard.getLocalPort("port", 8090));
} else {
tp.put("host", switchboard.myPublicIP());
tp.put("port", switchboard.getConfig("port", "8090"));
tp.put("port", switchboard.getPublicPort("port", 8090));
}
tp.put("peerName", (switchboard.peers == null) ? "" : switchboard.peers.myName());

@ -56,8 +56,7 @@ import net.yacy.kelondro.workflow.WorkflowThread;
import net.yacy.peers.Seed;
import net.yacy.search.SwitchboardConstants;
public class serverSwitch
{
public class serverSwitch {
// configuration management
private final File configFile;
@ -71,12 +70,11 @@ public class serverSwitch
private final ConcurrentMap<String, String> configRemoved;
private final NavigableMap<String, BusyThread> workerThreads;
private YaCyHttpServer httpserver; // implemented HttpServer
private ConcurrentMap<String, Integer> upnpPortMap = new ConcurrentHashMap<>();
private boolean isConnectedViaUpnp;
public serverSwitch(
final File dataPath,
final File appPath,
final String initPath,
final String configPath) {
public serverSwitch(final File dataPath, final File appPath,
final String initPath, final String configPath) {
// we initialize the switchboard with a property file,
// but maintain these properties then later in a new 'config' file
// to reset all changed configs, the config file must
@ -85,10 +83,13 @@ public class serverSwitch
// file name of the config file
this.dataPath = dataPath;
this.appPath = appPath;
this.configComment = "This is an automatically generated file, updated by serverAbstractSwitch and initialized by " + initPath;
this.configComment = "This is an automatically generated file, updated by serverAbstractSwitch and initialized by "
+ initPath;
final File initFile = new File(appPath, initPath);
this.configFile = new File(dataPath, configPath); // propertiesFile(config);
this.firstInit = !this.configFile.exists(); // this is true if the application was started for the first time
this.firstInit = !this.configFile.exists(); // this is true if the
// application was started
// for the first time
new File(this.configFile.getParent()).mkdir();
// predefine init's
@ -124,7 +125,8 @@ public class serverSwitch
initProps.putAll(this.configProps);
this.configProps = initProps;
// save result; this may initially create a config file after initialization
// save result; this may initially create a config file after
// initialization
saveConfig();
}
@ -142,25 +144,30 @@ public class serverSwitch
}
/**
* get my public IP, either set statically or figure out dynamic
* This method is deprecated because there may be more than one public IPs of this peer,
* get my public IP, either set statically or figure out dynamic This method
* is deprecated because there may be more than one public IPs of this peer,
* i.e. one IPv4 and one IPv6. Please use myPublicIPs() instead
*
* @return the public IP of this peer, if known
*/
@Deprecated
public String myPublicIP() {
// if a static IP was configured, we have to return it here ...
final String staticIP = getConfig("staticIP", "");
if ( staticIP.length() > 0 ) return staticIP;
if (staticIP.length() > 0)
return staticIP;
// otherwise we return the real IP address of this host
final InetAddress pLIP = Domains.myPublicLocalIP();
if ( pLIP != null ) return pLIP.getHostAddress();
if (pLIP != null)
return pLIP.getHostAddress();
return null;
}
/**
* Get all my public IPs. If there was a static IP assignment, only one, that IP is returned.
* Get all my public IPs. If there was a static IP assignment, only one,
* that IP is returned.
*
* @return a set of IPs which are supposed to be my own public IPs
*/
public Set<String> myPublicIPs() {
@ -175,15 +182,57 @@ public class serverSwitch
Set<String> h = new LinkedHashSet<>();
for (InetAddress i : Domains.myPublicIPv6()) {
String s = i.getHostAddress();
if (Seed.isProperIP(s)) h.add(s);
if (Seed.isProperIP(s))
h.add(s);
}
for (InetAddress i : Domains.myPublicIPv4()) {
String s = i.getHostAddress();
if (Seed.isProperIP(s)) h.add(s);
if (Seed.isProperIP(s))
h.add(s);
}
return h;
}
/**
* Gets public port. May differ from local port due to NATting. This method
* will eventually removed once nobody used IPv4 anymore, but until then we
* have to live with it.
*
* @param key
* original key from config (for example "port" or "port.ssl")
* @param dflt
* default value which will be used if no value is found
* @return the public port of this system on its IPv4 address
*
* @see #getLocalPort(String, int)
*/
public int getPublicPort(final String key, final int dflt) {
if (isConnectedViaUpnp && upnpPortMap.containsKey(key)) {
return upnpPortMap.get(key).intValue();
}
// TODO: add way of setting and retrieving port for manual NAT
return getConfigInt(key, dflt);
}
/**
* Wrapper for {@link #getConfigInt(String, int)} to have a more consistent
* API.
*
* @param key
* original key from config (for example "port" or "port.ssl")
* @param dflt
* default value which will be used if no value is found
* @return the local port of this system
* @see #getPublicPort(String, int)
*/
public int getLocalPort(final String key, final int dflt) {
return getConfigInt(key, dflt);
}
// a logger for this switchboard
public void setLog(final ConcurrentLog log) {
this.log = log;
@ -195,10 +244,12 @@ public class serverSwitch
/**
* add whole map of key-value pairs to config
*
* @param otherConfigs
*/
public void setConfig(final Map<String, String> otherConfigs) {
final Iterator<Map.Entry<String, String>> i = otherConfigs.entrySet().iterator();
final Iterator<Map.Entry<String, String>> i = otherConfigs.entrySet()
.iterator();
Map.Entry<String, String> entry;
while (i.hasNext()) {
entry = i.next();
@ -237,8 +288,11 @@ public class serverSwitch
/**
* Gets a configuration parameter from the properties.
*
* @param key name of the configuration parameter
* @param dflt default value which will be used in case parameter can not be found or if it is invalid
* @param key
* name of the configuration parameter
* @param dflt
* default value which will be used in case parameter can not be
* found or if it is invalid
* @return value if the parameter or default value
*/
public String getConfig(final String key, final String dflt) {
@ -255,8 +309,11 @@ public class serverSwitch
/**
* Gets a configuration parameter from the properties.
*
* @param key name of the configuration parameter
* @param dflt default value which will be used in case parameter can not be found or if it is invalid
* @param key
* name of the configuration parameter
* @param dflt
* default value which will be used in case parameter can not be
* found or if it is invalid
* @return value if the parameter or default value
*/
public long getConfigLong(final String key, final long dflt) {
@ -270,8 +327,11 @@ public class serverSwitch
/**
* Gets a configuration parameter from the properties.
*
* @param key name of the configuration parameter
* @param dflt default value which will be used in case parameter can not be found or if it is invalid
* @param key
* name of the configuration parameter
* @param dflt
* default value which will be used in case parameter can not be
* found or if it is invalid
* @return value if the parameter or default value
*/
public float getConfigFloat(final String key, final float dflt) {
@ -282,16 +342,44 @@ public class serverSwitch
}
}
public boolean isConnectedViaUpnp() {
return isConnectedViaUpnp;
}
public void setConnectedViaUpnp(final boolean isConnectedViaUpnp) {
this.isConnectedViaUpnp = isConnectedViaUpnp;
if (!isConnectedViaUpnp) {
upnpPortMap.clear();
}
}
public void setUpnpPorts(final String key, final int port) {
upnpPortMap.put(key, Integer.valueOf(port));
}
public void removeUpnpPort(final String key) {
upnpPortMap.remove(key);
}
/**
* Gets a configuration parameter from the properties.
*
* @param key name of the configuration parameter
* @param dflt default value which will be used in case parameter can not be found or if it is invalid
* @param key
* name of the configuration parameter
* @param dflt
* default value which will be used in case parameter can not be
* found or if it is invalid
* @return value if the parameter or default value
*/
public int getConfigInt(final String key, final int dflt) {
try {
return Integer.parseInt(getConfig(key, Integer.toString(dflt)));
} catch (final NumberFormatException e) {
return dflt;
}
@ -300,8 +388,11 @@ public class serverSwitch
/**
* Gets a configuration parameter from the properties.
*
* @param key name of the configuration parameter
* @param dflt default value which will be used in case parameter can not be found or if it is invalid
* @param key
* name of the configuration parameter
* @param dflt
* default value which will be used in case parameter can not be
* found or if it is invalid
* @return value if the parameter or default value
*/
public boolean getConfigBool(final String key, final boolean dflt) {
@ -311,12 +402,15 @@ public class serverSwitch
/**
* Create a File instance for a configuration setting specifying a path.
*
* @param key config key
* @param dflt default path value, that is used when there is no value <code>key</code> in the
* configuration.
* @return if the value of the setting is an absolute path String, then the returned File is derived from
* this setting only. Otherwise the path's file is constructed from the applications root path +
* the relative path setting.
* @param key
* config key
* @param dflt
* default path value, that is used when there is no value
* <code>key</code> in the configuration.
* @return if the value of the setting is an absolute path String, then the
* returned File is derived from this setting only. Otherwise the
* path's file is constructed from the applications root path + the
* relative path setting.
*/
public File getDataPath(final String key, final String dflt) {
return getFileByPath(key, dflt, this.dataPath);
@ -324,6 +418,7 @@ public class serverSwitch
/**
* return file at path from config entry "key", or fallback to default dflt
*
* @param key
* @param dflt
* @return
@ -335,7 +430,8 @@ public class serverSwitch
private File getFileByPath(String key, String dflt, File prefix) {
final String path = getConfig(key, dflt).replace('\\', '/');
final File f = new File(path);
return (f.isAbsolute() ? new File(f.getAbsolutePath()) : new File(prefix, path));
return (f.isAbsolute() ? new File(f.getAbsolutePath()) : new File(
prefix, path));
}
public Iterator<String> configKeys() {
@ -352,7 +448,8 @@ public class serverSwitch
}
/**
* Gets configuration parameters which have been removed during initialization.
* Gets configuration parameters which have been removed during
* initialization.
*
* @return contains parameter name as key and parameter value as value
*/
@ -360,13 +457,10 @@ public class serverSwitch
return this.configRemoved;
}
public void deployThread(
final String threadName,
public void deployThread(final String threadName,
final String threadShortDescription,
final String threadLongDescription,
final String threadMonitorURL,
final BusyThread newThread,
final long startupDelay) {
final String threadLongDescription, final String threadMonitorURL,
final BusyThread newThread, final long startupDelay) {
deployThread(
threadName,
threadShortDescription,
@ -380,15 +474,11 @@ public class serverSwitch
Double.parseDouble(getConfig(threadName + "_loadprereq", "9.0")));
}
public void deployThread(
final String threadName,
public void deployThread(final String threadName,
final String threadShortDescription,
final String threadLongDescription,
final String threadMonitorURL,
final BusyThread newThread,
final long startupDelay,
final long initialIdleSleep,
final long initialBusySleep,
final String threadLongDescription, final String threadMonitorURL,
final BusyThread newThread, final long startupDelay,
final long initialIdleSleep, final long initialBusySleep,
final long initialMemoryPreRequisite,
final double initialLoadPreRequisite) {
if (newThread.isAlive()) {
@ -419,13 +509,16 @@ public class serverSwitch
setConfig(threadName + "_memprereq", initialMemoryPreRequisite);
}
try {
final double load = Double.parseDouble(getConfig(threadName + "_loadprereq", "novalue"));
final double load = Double.parseDouble(getConfig(threadName
+ "_loadprereq", "novalue"));
newThread.setLoadPreReqisite(load);
} catch (final NumberFormatException e) {
newThread.setLoadPreReqisite(initialLoadPreRequisite);
setConfig(threadName + "_loadprereq", (float)initialLoadPreRequisite);
setConfig(threadName + "_loadprereq",
(float) initialLoadPreRequisite);
}
newThread.setDescription(threadShortDescription, threadLongDescription, threadMonitorURL);
newThread.setDescription(threadShortDescription, threadLongDescription,
threadMonitorURL);
this.workerThreads.put(threadName, newThread);
// start the thread
if (this.workerThreads.containsKey(threadName)) {
@ -437,16 +530,15 @@ public class serverSwitch
return this.workerThreads.get(threadName);
}
public void setThreadPerformance(
final String threadName,
final long idleMillis,
final long busyMillis,
final long memprereqBytes,
final double loadprereq) {
public void setThreadPerformance(final String threadName,
final long idleMillis, final long busyMillis,
final long memprereqBytes, final double loadprereq) {
final BusyThread thread = this.workerThreads.get(threadName);
if (thread != null) {
setConfig(threadName + "_idlesleep", thread.setIdleSleep(idleMillis));
setConfig(threadName + "_busysleep", thread.setBusySleep(busyMillis));
setConfig(threadName + "_idlesleep",
thread.setIdleSleep(idleMillis));
setConfig(threadName + "_busysleep",
thread.setBusySleep(busyMillis));
setConfig(threadName + "_memprereq", memprereqBytes);
thread.setMemPreReqisite(memprereqBytes);
setConfig(threadName + "_loadprereq", (float) loadprereq);
@ -454,9 +546,11 @@ public class serverSwitch
}
}
public synchronized void terminateThread(final String threadName, final boolean waitFor) {
public synchronized void terminateThread(final String threadName,
final boolean waitFor) {
if (this.workerThreads.containsKey(threadName)) {
((WorkflowThread) this.workerThreads.get(threadName)).terminate(waitFor);
((WorkflowThread) this.workerThreads.get(threadName))
.terminate(waitFor);
this.workerThreads.remove(threadName);
}
}
@ -471,12 +565,14 @@ public class serverSwitch
public synchronized void terminateAllThreads(final boolean waitFor) {
Iterator<String> e = this.workerThreads.keySet().iterator();
while (e.hasNext()) {
((WorkflowThread) this.workerThreads.get(e.next())).terminate(false);
((WorkflowThread) this.workerThreads.get(e.next()))
.terminate(false);
}
if (waitFor) {
e = this.workerThreads.keySet().iterator();
while (e.hasNext()) {
((WorkflowThread) this.workerThreads.get(e.next())).terminate(true);
((WorkflowThread) this.workerThreads.get(e.next()))
.terminate(true);
e.remove();
}
}
@ -504,15 +600,18 @@ public class serverSwitch
}
/**
* Retrieve text data (e. g. config file) from file file may be an url or a filename with path relative to
* rootPath parameter
* Retrieve text data (e. g. config file) from file file may be an url or a
* filename with path relative to rootPath parameter
*
* @param file url or filename
* @param rootPath searchpath for file
* @param file file to use when remote fetching fails (null if unused)
* @param file
* url or filename
* @param rootPath
* searchpath for file
* @param file
* file to use when remote fetching fails (null if unused)
*/
public Reader getConfigFileFromWebOrLocally(final String uri, final String rootPath, final File file)
throws IOException,
public Reader getConfigFileFromWebOrLocally(final String uri,
final String rootPath, final File file) throws IOException,
FileNotFoundException {
if (uri.startsWith("http://") || uri.startsWith("https://")) {
final String[] uris = uri.split(",");
@ -520,10 +619,21 @@ public class serverSwitch
netdef = netdef.trim();
try {
final RequestHeader reqHeader = new RequestHeader();
reqHeader.put(HeaderFramework.USER_AGENT, ClientIdentification.yacyInternetCrawlerAgent.userAgent);
final HTTPClient client = new HTTPClient(ClientIdentification.yacyInternetCrawlerAgent);
reqHeader
.put(HeaderFramework.USER_AGENT,
ClientIdentification.yacyInternetCrawlerAgent.userAgent);
final HTTPClient client = new HTTPClient(
ClientIdentification.yacyInternetCrawlerAgent);
client.setHeader(reqHeader.entrySet());
byte[] data = client.GETbytes(uri, getConfig(SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME, "admin"), getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, ""), false);
byte[] data = client
.GETbytes(
uri,
getConfig(
SwitchboardConstants.ADMIN_ACCOUNT_USER_NAME,
"admin"),
getConfig(
SwitchboardConstants.ADMIN_ACCOUNT_B64MD5,
""), false);
if (data == null || data.length == 0) {
continue;
}
@ -533,7 +643,8 @@ public class serverSwitch
f.write(data);
f.close();
}
return new InputStreamReader(new BufferedInputStream(new ByteArrayInputStream(data)));
return new InputStreamReader(new BufferedInputStream(
new ByteArrayInputStream(data)));
} catch (final Exception e) {
continue;
}
@ -543,8 +654,10 @@ public class serverSwitch
}
throw new FileNotFoundException();
}
final File f = (uri.length() > 0 && uri.startsWith("/")) ? new File(uri) : new File(rootPath, uri);
if (f.exists()) return new FileReader(f);
final File f = (uri.length() > 0 && uri.startsWith("/")) ? new File(uri)
: new File(rootPath, uri);
if (f.exists())
return new FileReader(f);
throw new FileNotFoundException(f.toString());
}
@ -562,7 +675,8 @@ public class serverSwitch
/**
* Generates a random password of a given length.
*
* @param length length o password
* @param length
* length o password
* @return password of given length
*/
public String genRandomPassword(final int length) {
@ -570,13 +684,16 @@ public class serverSwitch
pwGenerator.nextBytes(bytes);
return Digest.encodeMD5Hex(bytes);
}
/**
* set/remember jetty server
*
* @param jettyserver
*/
public void setHttpServer(YaCyHttpServer jettyserver) {
this.httpserver = jettyserver;
}
public YaCyHttpServer getHttpServer() {
return httpserver;
}

@ -35,6 +35,7 @@ import net.yacy.search.Switchboard;
import org.bitlet.weupnp.GatewayDevice;
import org.bitlet.weupnp.GatewayDiscover;
import org.bitlet.weupnp.PortMappingEntry;
import org.xml.sax.SAXException;
public class UPnP {
@ -42,7 +43,7 @@ public class UPnP {
private static final ConcurrentLog LOG = new ConcurrentLog("UPNP");
private static final Switchboard SB = Switchboard.getSwitchboard();
private static Map<InetAddress, GatewayDevice> GATEWAY_DEVICES = null;
private static GatewayDevice gatewayDevice;
private static final Map<UPnPMappingType, UPnPMapping> MAPPINGS = new EnumMap<>(
UPnPMappingType.class);
@ -53,20 +54,23 @@ public class UPnP {
"server.https", "TCP", "YaCy HTTPS"));
}
private static final int MIN_CANDIDATE_PORT = 49152;
private static final int MAX_CANDIDATE_PORT = 65535;
private static boolean init() {
boolean init = true;
try {
if (GATEWAY_DEVICES == null) {
GATEWAY_DEVICES = new GatewayDiscover().discover();
if (gatewayDevice == null || !gatewayDevice.isConnected()) {
final GatewayDiscover discover = new GatewayDiscover();
discover.discover();
gatewayDevice = discover.getValidGateway();
}
} catch (IOException | SAXException | ParserConfigurationException e) {
init = false;
}
if (GATEWAY_DEVICES != null) {
for (final GatewayDevice gatewayDevice : GATEWAY_DEVICES.values()) {
if (gatewayDevice != null) {
LOG.info("found device: " + gatewayDevice.getFriendlyName());
}
} else {
LOG.info("no device found");
init = false;
@ -91,6 +95,8 @@ public class UPnP {
addPortMapping(entry.getKey(), mapping,
SB.getConfigInt(mapping.getConfigPortKey(), 0));
}
SB.setConnectedViaUpnp(true);
}
/**
@ -102,6 +108,8 @@ public class UPnP {
return;
}
SB.setConnectedViaUpnp(false);
UPnPMapping mapping;
for (final Entry<UPnPMappingType, UPnPMapping> entry : MAPPINGS
.entrySet()) {
@ -123,7 +131,7 @@ public class UPnP {
* @param port
* port number to map
*/
public static void addPortMapping(final UPnPMappingType type,
private static void addPortMapping(final UPnPMappingType type,
final UPnPMapping mapping, final int port) {
if (port < 1) {
@ -137,26 +145,44 @@ public class UPnP {
if ((mapping.isConfigEnabledKeyEmpty() || SB.getConfigBool(
mapping.getConfigEnabledKey(), false))
&& mapping.getPort() == 0
&& ((GATEWAY_DEVICES != null) || init())) {
&& ((gatewayDevice != null) || init())) {
String localHostIP;
boolean mapped;
String msg;
for (final GatewayDevice gatewayDevice : GATEWAY_DEVICES.values()) {
try {
localHostIP = toString(gatewayDevice.getLocalAddress());
mapped = gatewayDevice.addPortMapping(port, port,
int portCandidate = port;
while (isInUse(portCandidate) && portCandidate > 0) {
LOG.info(portCandidate + " in use, trying different port.");
portCandidate = getNewPortCandidate(portCandidate);
}
if (portCandidate > 0) {
mapped = gatewayDevice.addPortMapping(portCandidate, port,
localHostIP, mapping.getProtocol(),
mapping.getDescription());
msg = "port " + port + " on device "
+ gatewayDevice.getFriendlyName();
msg = "mapped port " + port + " to port " + portCandidate
+ " on device " + gatewayDevice.getFriendlyName()
+ ", external IP is "
+ gatewayDevice.getExternalIPAddress();
} else {
mapped = false;
msg = "no free port found";
}
if (mapped) {
LOG.info("mapped " + msg);
mapping.setPort(port);
mapping.setPort(portCandidate);
SB.setUpnpPorts(mapping.getConfigPortKey(), portCandidate);
} else {
LOG.warn("could not map " + msg);
}
@ -165,7 +191,6 @@ public class UPnP {
}
}
}
}
/**
* Delete current port mapping.
@ -173,16 +198,15 @@ public class UPnP {
* @param mapping
* to delete
*/
public static void deletePortMapping(final UPnPMapping mapping) {
if (mapping.getPort() > 0 && GATEWAY_DEVICES != null) {
private static void deletePortMapping(final UPnPMapping mapping) {
if (mapping.getPort() > 0 && gatewayDevice != null) {
boolean unmapped;
String msg;
for (final GatewayDevice gatewayDevice : GATEWAY_DEVICES.values()) {
try {
unmapped = gatewayDevice.deletePortMapping(
mapping.getPort(), mapping.getProtocol());
unmapped = gatewayDevice.deletePortMapping(mapping.getPort(),
mapping.getProtocol());
msg = "port " + mapping.getPort() + " on device "
+ gatewayDevice.getFriendlyName();
@ -200,7 +224,6 @@ public class UPnP {
mapping.setPort(0); // reset mapped port
}
}
/**
* Gets currently mapped port.
@ -219,6 +242,30 @@ public class UPnP {
return MAPPINGS.get(type).getPort();
}
public static int getNewPortCandidate(final int oldCandidate) {
int newPortCandidate = Math.min(
Math.max(MIN_CANDIDATE_PORT, oldCandidate + 1),
MAX_CANDIDATE_PORT);
if (newPortCandidate == MAX_CANDIDATE_PORT) {
newPortCandidate = -1;
}
return newPortCandidate;
}
private static boolean isInUse(final int port) {
try {
return gatewayDevice != null
&& gatewayDevice.getSpecificPortMappingEntry(port, "TCP",
new PortMappingEntry());
} catch (IOException | SAXException e) {
return false;
}
}
private static String toString(final InetAddress inetAddress) {
final String localHostIP;

@ -202,7 +202,7 @@ public final class yacy {
sb.setConfig("memoryTotalAfterStartup", startupMemTotal);
// start gui if wanted
if (gui) YaCyApp.start("localhost", (int) sb.getConfigLong("port", 8090));
if (gui) YaCyApp.start("localhost", sb.getLocalPort("port", 8090));
// hardcoded, forced, temporary value-migration
sb.setConfig("htTemplatePath", "htroot/env/templates");
@ -277,7 +277,7 @@ public final class yacy {
HTTPClient.setDefaultUserAgent(ClientIdentification.yacyInternetCrawlerAgent.userAgent);
// start main threads
final int port = sb.getConfigInt("port", 8090);
final int port = sb.getLocalPort("port", 8090);
try {
// start http server
YaCyHttpServer httpServer;

Loading…
Cancel
Save