diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9dbd1991..47285027 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@ CHANGELOG
=========
-2.0.0 (2018-XX-XX)
+2.0.0 (2018-21-09)
------------------
-* Initial release
\ No newline at end of file
+* Initial release of POP-Java 2.0
\ No newline at end of file
diff --git a/README.rst b/README.rst
index d317f9a4..a1587b85 100755
--- a/README.rst
+++ b/README.rst
@@ -82,6 +82,16 @@ Netbeans
Open the project as a Gradle project. Nothing more should be required.
+Maven
+~~~~~
+
+.. code::
+
+
+ ch.icosys
+ popjava
+ 2.0.0
+
LICENCE
-------
diff --git a/build.gradle b/build.gradle
index 066712ad..2b8237e4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,7 +9,7 @@ description = 'A Java distributed system'
group = "ch.icosys"
archivesBaseName = "popjava"
-version = "1.5.3"
+version = "2.0.2"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
@@ -264,7 +264,7 @@ uploadArchives {
licenses {
license {
name 'The GNU Lesser General Public License, Version 3.0'
- url 'https://www.gnu.org/licenses/gpl-3.0.txt'
+ url 'https://www.gnu.org/licenses/lgpl-3.0.txt'
}
}
diff --git a/docs/dev/contributing.rst b/docs/dev/contributing.rst
index 6adacd71..71262dc2 100644
--- a/docs/dev/contributing.rst
+++ b/docs/dev/contributing.rst
@@ -10,7 +10,7 @@ Coding conventions
When writing new code for POP-Java you should always:
-* Indent with a hard-tab ``\t``, ASCII ``0x09``
+* Indent with 4 spaces
* Always surround blocks with ``{ }``
* ...
* ...
@@ -85,6 +85,14 @@ Creation of a new release
ossrhPassword=your-jira-password
* The signing data must be generated, e.g. with `GnuPG `_.
+ * Newer (2.1+) GPG versions use a new keyring file format (.kbx). You need to convert/export your key to the old format.
+
+ ``gpg --export-secret-keys -o secring.gpg``
+
+ * With the 2.1+ GPG version you also need to use a special command to list the available keys to get the correct id.
+
+ ``gpg --list-keys --keyid-format short``
+
* More information about the Maven packaging process is given on the `OSSRH Guide `_.
@@ -123,4 +131,5 @@ Creation of a new release
.. note::
* To pass this step, the deployed files are verified and thus must fulfil some `requirements `_.
* This step was fully automatized thanks to the `Gradle Nexus Staging Plugin `_. However, it can manually be done on the `OSSRH website `_ as described `here `_.
+ * It takes about 2 hours to synchronize between OSSRH and the Central Repository
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/base/POPObject.java b/workspace/popjava/src/ch/icosys/popjava/core/base/POPObject.java
index 88704816..da205c6e 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/base/POPObject.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/base/POPObject.java
@@ -730,15 +730,15 @@ public void exit() {
*/
public void printMethodInfo() {
System.out.println("===========ConstructorInfo============");
- constructorInfos.forEach((mi, c) -> System.out.format("ClassId:%d.ConstructorId:%d.Sign:%s", mi.getClassId(),
+ constructorInfos.forEach((mi, c) -> System.out.format("ClassId:%d.ConstructorId:%d.Sign:%s\n", mi.getClassId(),
mi.getMethodId(), c.toGenericString()));
System.out.println("===========MethodInfo============");
- methodInfos.forEach((mi, m) -> System.out.format("ClassId:%d.MethodId:%d.Sign:%s", mi.getClassId(),
+ methodInfos.forEach((mi, m) -> System.out.format("ClassId:%d.MethodId:%d.Sign:%s\n", mi.getClassId(),
mi.getMethodId(), m.toGenericString()));
System.out.println("===========SemanticsInfo============");
- semantics.forEach((mi, s) -> System.out.format("ClassId:%d.ConstructorId:%d.Semantics:%d", mi.getClassId(),
+ semantics.forEach((mi, s) -> System.out.format("ClassId:%d.ConstructorId:%d.Semantics:%d\n", mi.getClassId(),
mi.getMethodId(), s));
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/baseobject/AccessPoint.java b/workspace/popjava/src/ch/icosys/popjava/core/baseobject/AccessPoint.java
index 8ab46c17..e3e3e8fa 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/baseobject/AccessPoint.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/baseobject/AccessPoint.java
@@ -4,6 +4,7 @@
import ch.icosys.popjava.core.system.POPSystem;
import ch.icosys.popjava.core.util.Configuration;
+import ch.icosys.popjava.core.util.SystemUtil;
/**
* This class represent an access to a broker-side parallel object
@@ -187,6 +188,14 @@ public boolean isEmpty() {
return false;
}
+ /**
+ * Returns true if the IP/Host is in a private subnet
+ * @return
+ */
+ public boolean isPrivateIP() {
+ return SystemUtil.isHostInPrivateSubnet(host);
+ }
+
/**
* Format the access point as a string value
*/
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/baseobject/POPAccessPoint.java b/workspace/popjava/src/ch/icosys/popjava/core/baseobject/POPAccessPoint.java
index 7eb897a2..12e39a82 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/baseobject/POPAccessPoint.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/baseobject/POPAccessPoint.java
@@ -218,6 +218,16 @@ public boolean hasSameAccessPoint(POPAccessPoint ap) {
return false;
}
+
+ public boolean hasAccessPointIP(String ip) {
+ for (int i = 0; i < accessPoints.size(); i++) {
+ if(accessPoints.get(i).getHost().equals(ip)){
+ return true;
+ }
+ }
+
+ return false;
+ }
@Override
public int hashCode() {
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/broker/Broker.java b/workspace/popjava/src/ch/icosys/popjava/core/broker/Broker.java
index ab65b0f5..c930f6f3 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/broker/Broker.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/broker/Broker.java
@@ -511,6 +511,9 @@ private boolean invokeMethod(Request request) throws InterruptedException {
} catch (NoSuchMethodException e) {
exception = POPException.createReflectMethodNotFoundException(popInfo.getClass().getName(),
request.getClassId(), request.getMethodId(), e.getMessage());
+
+ popInfo.printMethodInfo();
+ System.out.println(accessPoint);
}
if (method != null) {
@@ -673,7 +676,7 @@ private boolean invokeMethod(Request request) throws InterruptedException {
}
}
- if (tracking && remote != null) {
+ if (tracking && remote != null && method != null) {
registerTracking(remote, method.toGenericString(), trackingTime, inputSize, outputSize);
}
@@ -724,7 +727,7 @@ public boolean invoke(Request request) throws InterruptedException {
remoteCaller.set(caller);
// check for localhost only execution and throw exception if we can't
- if (request.isLocalhost() && !caller.isLocalHost()) {
+ if (request.isLocalhost() && !caller.isLocalHost(accessPoint)) {
if (request.isSynchronous()) {
POPException exception = new POPException(POPErrorCode.METHOD_ANNOTATION_EXCEPTION,
"You can't call a localhost method from a remote location. "+caller.getRemote().getHostAddress());
@@ -1068,11 +1071,6 @@ public boolean initialize(List argvs) {
// hadle multiple times the same protocol
String port;
while ((port = Util.removeStringFromList(argvs, prefix)) != null) {
- // if we don't have a port, abort
- /*
- * if (port == null) { continue; }
- */
-
int iPort = 0;
if (port.length() > 0) {
try {
@@ -1105,8 +1103,9 @@ public boolean initialize(List argvs) {
if (externalIP != null && !externalIP.isEmpty()) {
for (int i = 0; i < accessPoint.size(); i++) {
AccessPoint ap = new AccessPoint(accessPoint.get(i));
- // TODO: The port might also be diferent
ap.setHost(externalIP);
+
+ UPNPManager.mapAccessPoint(ap, 1000);
accessPoint.addAccessPoint(ap);
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/combox/Combox.java b/workspace/popjava/src/ch/icosys/popjava/core/combox/Combox.java
index 6187e055..60deeabc 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/combox/Combox.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/combox/Combox.java
@@ -185,7 +185,9 @@ public void run() {
if (System.currentTimeMillis() - lastCommunication > KEEP_ALIVE_INTERVAL) {
POPBuffer buffer = createServicePacket(PING);
- send(buffer);
+ if(send(buffer) < 0) {
+ break;
+ }
}
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/combox/ComboxUtils.java b/workspace/popjava/src/ch/icosys/popjava/core/combox/ComboxUtils.java
index 3232fa3c..c469f93d 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/combox/ComboxUtils.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/combox/ComboxUtils.java
@@ -8,6 +8,7 @@
import javax.net.ServerSocketFactory;
import ch.icosys.popjava.core.util.Configuration;
+import ch.icosys.popjava.core.util.Tuple;
import ch.icosys.popjava.core.util.upnp.UPNPManager;
/**
@@ -90,7 +91,7 @@ private static ServerSocket createServerSocket(int port, PreOperation op, boolea
if (upnp) {
@SuppressWarnings("unused")
- Future externalIP = UPNPManager.registerPort(server.getLocalPort());
+ Future> externalIP = UPNPManager.registerPort(server.getLocalPort());
}
return server;
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ComboxSocket.java b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ComboxSocket.java
index 08f77d8a..b78f86b7 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ComboxSocket.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ComboxSocket.java
@@ -20,6 +20,7 @@
import ch.icosys.popjava.core.buffer.POPBuffer;
import ch.icosys.popjava.core.combox.Combox;
import ch.icosys.popjava.core.util.LogWriter;
+import ch.icosys.popjava.core.util.SystemUtil;
public abstract class ComboxSocket extends Combox {
@@ -285,14 +286,19 @@ public void closeInternal() {
}
} catch (IOException e) {
} finally {
- try {
- outputStream.close();
- } catch (IOException e) {
+ if(outputStream != null) {
+ try {
+ outputStream.close();
+ } catch (IOException e) {
+ }
}
- try {
- inputStream.close();
- } catch (IOException e) {
+ if(inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
}
+
if (peerConnection != null) {
try {
peerConnection.close();
@@ -369,8 +375,8 @@ public int compare(AccessPoint o1, AccessPoint o2) {
return 1;
}
- boolean privateSubnet1 = isHostInPrivateSubnet(o1.getHost());
- boolean privateSubnet2 = isHostInPrivateSubnet(o2.getHost());
+ boolean privateSubnet1 = SystemUtil.isHostInPrivateSubnet(o1.getHost());
+ boolean privateSubnet2 = SystemUtil.isHostInPrivateSubnet(o2.getHost());
if (privateSubnet1 && !privateSubnet2) {
return 1;
@@ -391,8 +397,4 @@ public int compare(AccessPoint o1, AccessPoint o2) {
return aps;
}
-
- private static boolean isHostInPrivateSubnet(String host) {
- return host.startsWith("10.") || host.startsWith("172.16.") || host.startsWith("192.168.");
- }
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/raw/ComboxRawSocket.java b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/raw/ComboxRawSocket.java
index 97813a85..4976ab37 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/raw/ComboxRawSocket.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/raw/ComboxRawSocket.java
@@ -53,29 +53,31 @@ protected boolean connectToServer() {
for (int i = 0; i < aps.size() && !available; i++) {
AccessPoint ap = aps.get(i);
-
- String host = ap.getHost();
- int port = ap.getPort();
- try {
- // Create an unbound socket
- if (timeOut > 0) {
- SocketAddress sockaddress = new InetSocketAddress(host, port);
- peerConnection = new Socket();
- peerConnection.connect(sockaddress, timeOut);
-
- // LogWriter.writeExceptionLog(new Exception());
- // LogWriter.writeExceptionLog(new Exception("Open
- // connection to "+host+":"+port+" remote:
- // "+peerConnection.getLocalPort()));
- } else {
- peerConnection = new Socket(host, port);
+
+ if(ap.getProtocol().equals(ComboxSocketFactory.PROTOCOL)) {
+ String host = ap.getHost();
+ int port = ap.getPort();
+ try {
+ // Create an unbound socket
+ if (timeOut > 0) {
+ SocketAddress sockaddress = new InetSocketAddress(host, port);
+ peerConnection = new Socket();
+ peerConnection.connect(sockaddress, timeOut);
+
+ // LogWriter.writeExceptionLog(new Exception());
+ // LogWriter.writeExceptionLog(new Exception("Open
+ // connection to "+host+":"+port+" remote:
+ // "+peerConnection.getLocalPort()));
+ } else {
+ peerConnection = new Socket(host, port);
+ }
+ inputStream = new BufferedInputStream(peerConnection.getInputStream());
+ outputStream = new BufferedOutputStream(peerConnection.getOutputStream());
+ available = true;
+ } catch (IOException e) {
+ available = false;
+ LogWriter.writeExceptionLog(e);
}
- inputStream = new BufferedInputStream(peerConnection.getInputStream());
- outputStream = new BufferedOutputStream(peerConnection.getOutputStream());
- available = true;
- } catch (IOException e) {
- available = false;
- LogWriter.writeExceptionLog(e);
}
}
return available;
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ssl/ComboxSecureSocket.java b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ssl/ComboxSecureSocket.java
index 35f3f7c8..5aba5b33 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ssl/ComboxSecureSocket.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/combox/socket/ssl/ComboxSecureSocket.java
@@ -68,48 +68,50 @@ protected boolean connectToServer() {
for (int i = 0; i < aps.size() && !available; i++) {
AccessPoint ap = aps.get(i);
-
- String host = ap.getHost();
- int port = ap.getPort();
-
- try {
- // Create an unbound socket
- SocketAddress sockaddress = new InetSocketAddress(host, port);
- if (timeOut > 0) {
- peerConnection = (SSLSocket) factory.createSocket();
-
- // LogWriter.writeExceptionLog(new Exception());
- // LogWriter.writeExceptionLog(new Exception("Open
- // connection to "+host+":"+port+" remote:
- // "+peerConnection.getLocalPort()));
- } else {
- peerConnection = (SSLSocket) factory.createSocket();
- timeOut = 0;
+
+ if(ap.getProtocol().equals(ComboxSecureSocketFactory.PROTOCOL)) {
+ String host = ap.getHost();
+ int port = ap.getPort();
+
+ try {
+ // Create an unbound socket
+ SocketAddress sockaddress = new InetSocketAddress(host, port);
+ if (timeOut > 0) {
+ peerConnection = (SSLSocket) factory.createSocket();
+
+ // LogWriter.writeExceptionLog(new Exception());
+ // LogWriter.writeExceptionLog(new Exception("Open
+ // connection to "+host+":"+port+" remote:
+ // "+peerConnection.getLocalPort()));
+ } else {
+ peerConnection = (SSLSocket) factory.createSocket();
+ timeOut = 0;
+ }
+ peerConnection.setUseClientMode(true);
+
+ // setup SNI
+ SNIServerName network = new SNIHostName(getNetworkUUID());
+ List nets = new ArrayList<>(1);
+ nets.add(network);
+
+ // set SNI as part of the parameters
+ SSLParameters parameters = peerConnection.getSSLParameters();
+ parameters.setServerNames(nets);
+ peerConnection.setSSLParameters(parameters);
+
+ // connect and start handshake
+ peerConnection.connect(sockaddress);
+
+ // setup communication buffers
+ inputStream = new BufferedInputStream(peerConnection.getInputStream());
+ outputStream = new BufferedOutputStream(peerConnection.getOutputStream());
+
+ available = true;
+ } catch (IOException e) {
+ exceptions.add(e);
+ available = false;
}
- peerConnection.setUseClientMode(true);
-
- // setup SNI
- SNIServerName network = new SNIHostName(getNetworkUUID());
- List nets = new ArrayList<>(1);
- nets.add(network);
-
- // set SNI as part of the parameters
- SSLParameters parameters = peerConnection.getSSLParameters();
- parameters.setServerNames(nets);
- peerConnection.setSSLParameters(parameters);
-
- // connect and start handshake
- peerConnection.connect(sockaddress);
-
- // setup communication buffers
- inputStream = new BufferedInputStream(peerConnection.getInputStream());
- outputStream = new BufferedOutputStream(peerConnection.getOutputStream());
-
- available = true;
- } catch (IOException e) {
- exceptions.add(e);
- available = false;
- }
+ }
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/interfacebase/Interface.java b/workspace/popjava/src/ch/icosys/popjava/core/interfacebase/Interface.java
index c5958f5d..aac813da 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/interfacebase/Interface.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/interfacebase/Interface.java
@@ -423,7 +423,7 @@ protected boolean bind(POPAccessPoint accesspoint) throws POPException {
networkUUID = conf.getDefaultNetwork();
}
combox = new ComboxConnection(factory.createClientCombox(networkUUID), 1);
- } catch (IOException e) {
+ } catch (Throwable e) {
LogWriter.writeExceptionLog(e);
continue;
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/scripts/Popjrun.java b/workspace/popjava/src/ch/icosys/popjava/core/scripts/Popjrun.java
index 1d7b3ee6..31a72286 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/scripts/Popjrun.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/scripts/Popjrun.java
@@ -216,7 +216,9 @@ private static void runForkedApplication(String main, String objectMap, List hostIPS = POPSystem.getAllHostIPs(true);
+ List hostIPSReduced = new ArrayList<>(hostIPS);
List duplicates = new ArrayList<>();
for(int i = 0; i < me.size(); i++) {
AccessPoint ap = me.get(i);
- if(hostIPS.contains(ap.getHost())) {
- hostIPS.remove(ap.getHost());
+ for(InterfaceAddress iAHost : hostIPS) {
+ if(iAHost.getAddress().getHostAddress().equals(ap.getHost())) {
+ hostIPSReduced.remove(iAHost);
+ }
}
for(String host : hostnames) {
@@ -1932,7 +1955,7 @@ private POPAccessPoint getGeneralizedAccessPoint() {
for(int i = 0; i < me.size(); i++) {
AccessPoint ap = me.get(i);
- for(InterfaceAddress localIP : hostIPS) {
+ for(InterfaceAddress localIP : hostIPSReduced) {
duplicates.add(new AccessPoint(ap.getProtocol(), localIP.getAddress().getHostAddress(), ap.getPort()));
}
}
@@ -1996,8 +2019,12 @@ public void rerouteResponse(@POPParameter(Direction.IN) SNResponse response,
// get next node to contact
POPAccessPoint jm = wayback.pop();
POPJavaJobManager njm = connectToJobmanager(jm, response.getNetworkUUID());
- // route request through it
- njm.rerouteResponse(response, wayback);
+ if(njm != null) {
+ // route request through it
+ njm.rerouteResponse(response, wayback);
+ }else {
+ LogWriter.writeDebugInfo("[PSN] Unable to reroute response ;%s;DEST;%s", response.getUID(), wayback.toString());
+ }
} // is the last node, give the answer to the original JM who
// launched the request
else {
@@ -2038,6 +2065,38 @@ public boolean knowsJobManager(String network, POPAccessPoint ap) {
private final Set> jmConnectionLock = Collections.synchronizedSet(new HashSet<>());
+ private final Map, FutureTask> jmConnectorThreads = Collections.synchronizedMap(new HashMap<>());
+
+ private POPJavaJobManager connectToJM(POPAccessPoint ap, String network) {
+ final POPJavaJobManager me = this;
+
+ FutureTask task = new FutureTask<>(new Callable() {
+
+ @Override
+ public POPJavaJobManager call() throws Exception {
+ return PopJava.connect(me, POPJavaJobManager.class, network, ap);
+ }
+ });
+
+
+ Tuple key = new Tuple(network, ap);
+ jmConnectorThreads.put(key, task);
+
+ Thread thread = new Thread(task);
+ thread.setDaemon(true);
+ thread.start();
+
+ POPJavaJobManager jm = null;
+ try {
+ jm = task.get(10, TimeUnit.SECONDS);
+ }catch (Exception e) {
+ }
+
+ jmConnectorThreads.remove(key);
+
+ return jm;
+ }
+
public POPJavaJobManager connectToJobmanager(POPAccessPoint ap, String network) throws InterruptedException {
Tuple key = new Tuple(network, ap);
@@ -2053,27 +2112,36 @@ public POPJavaJobManager connectToJobmanager(POPAccessPoint ap, String network)
try {
//Connect to JM first time if necessary
if (!cachedJobManangers.containsKey(key)) {
- POPJavaJobManager jm = PopJava.connect(this, POPJavaJobManager.class, network, ap);
-
- cachedJobManangers.put(key, jm);
+ LogWriter.writeDebugInfo("[PSN] JM unknown, connect to " + ap+" "+network+" "+System.currentTimeMillis());
+ POPJavaJobManager jm = connectToJM(ap, network);
+ if(jm != null) {
+ LogWriter.writeDebugInfo("[PSN] Connection open " + ap+" "+network+" "+System.currentTimeMillis());
+ cachedJobManangers.put(key, jm);
+ }else {
+ LogWriter.writeDebugInfo("[PSN] Connection failed " + ap+" "+network+" "+System.currentTimeMillis());
+ }
}
POPJavaJobManager jm = cachedJobManangers.get(key);
- try {
- //Check if the neighbour knows us, this also implicitely tests the connection
- POPAccessPoint myAP = getAccessPoint();
-
- jm.registerNeighbourJobmanager(getAccessPoint(), network, this);
- /*if(!jm.knowsJobManager(network, myAP)) {
+ if(jm != null) {
+ try {
+ //Check if the neighbour knows us, this also implicitely tests the connection
+ POPAccessPoint myAP = getAccessPoint();
+ LogWriter.writeDebugInfo("[PSN] Register self at " + ap+" "+network+" "+System.currentTimeMillis());
jm.registerNeighbourJobmanager(getAccessPoint(), network, this);
- }*/
- } catch (Exception e) {
- //If the connection we have is down, reconnect
- cachedJobManangers.remove(key);
- jm = PopJava.connect(this, POPJavaJobManager.class, network, ap);
+ /*if(!jm.knowsJobManager(network, myAP)) {
+ jm.registerNeighbourJobmanager(getAccessPoint(), network, this);
+ }*/
+ } catch (Exception e) {
+ LogWriter.writeDebugInfo("[PSN] JM not available, reconnect to " + ap+" "+network+" "+System.currentTimeMillis());
+
+ //If the connection we have is down, reconnect
+ cachedJobManangers.remove(key);
+ jm = connectToJM(ap, network);
- cachedJobManangers.put(key, jm);
+ cachedJobManangers.put(key, jm);
+ }
}
return jm;
@@ -2088,28 +2156,44 @@ public POPJavaJobManager connectToJobmanager(POPAccessPoint ap, String network)
@POPSyncConc
public POPAccessPoint[] newTFCSearchOn(POPAccessPoint ap, String network, String objectName) {
try {
- return connectToJobmanager(ap, network).localTFCSearch(network, objectName);
+ POPJavaJobManager jm = connectToJobmanager(ap, network);
+
+ if(jm != null) {
+ return jm.localTFCSearch(network, objectName);
+ }
}catch (InterruptedException e) {
- return new POPAccessPoint[0];
}
-
+
+ return new POPAccessPoint[0];
}
@POPSyncConc
public void registerNeighbourJobmanager(POPAccessPoint ap, String network, POPJavaJobManager jm) {
+
+ LogWriter.writeDebugInfo("[PSN] register " + ap+" "+network);
+
Tuple key = new Tuple(network, ap);
if (!cachedJobManangers.containsKey(key)) {
+ LogWriter.writeDebugInfo("[PSN] JM was unknown, keep connection " + ap+" "+network);
jm.makePermanent();
cachedJobManangers.put(key, jm);
+
+ if(jmConnectorThreads.containsKey(key)) {
+ jmConnectorThreads.get(key).cancel(true);
+ }
} else {
try {
POPJavaJobManager current = cachedJobManangers.get(key);
POPString val = new POPString();
current.query("power", val);
+
+ LogWriter.writeDebugInfo("[PSN] JM was known, keep old " + ap+" "+network);
} catch (Exception e) {
jm.makePermanent();
cachedJobManangers.put(key, jm);
+
+ LogWriter.writeDebugInfo("[PSN] Old JM unavailabe, keep new " + ap+" "+network);
}
}
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/system/POPSystem.java b/workspace/popjava/src/ch/icosys/popjava/core/system/POPSystem.java
index 304cb090..e9b2d4ae 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/system/POPSystem.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/system/POPSystem.java
@@ -30,6 +30,8 @@
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import javassist.util.proxy.ProxyFactory;
+
import ch.icosys.popjava.core.PopJava;
import ch.icosys.popjava.core.base.POPException;
import ch.icosys.popjava.core.baseobject.ObjectDescription;
@@ -44,7 +46,6 @@
import ch.icosys.popjava.core.util.Util;
import ch.icosys.popjava.core.util.Util.OSType;
import ch.icosys.popjava.core.util.upnp.UPNPManager;
-import javassist.util.proxy.ProxyFactory;
/**
* This class is responsible for the initialization of a POP-Java application.
@@ -61,6 +62,18 @@ public class POPSystem {
private static final List localHooks = new ArrayList<>();
+ private static final Configuration conf = Configuration.getInstance();
+
+ private static String jobservice = String.format("%s:%d", POPSystem.getHostIP().getAddress().getHostAddress(), conf.getJobManagerPorts()[0]);
+
+ private static String codeconf;
+
+ private static String appservicecode;
+
+ private static String proxy;
+
+ private static String appservicecontact;
+
/**
* POP-Java location environement variable name
*/
@@ -72,43 +85,41 @@ public class POPSystem {
public static POPAccessPoint jobService = new POPAccessPoint();
private static AppService coreServiceManager;
- // private static POPJobService jobmanager;
/**
* POP-Java application service access point
*/
public static POPAccessPoint appServiceAccessPoint = new POPAccessPoint();
- private static final Configuration conf = Configuration.getInstance();
-
public static void writeLog(String log) {
if (!conf.isDebug()) {
System.out.println(log);
}
LogWriter.writeDebugInfo(log);
- /*
- * try { POPAppService app =
- * (POPAppService)PopJava.newActive(POPAppService.class,
- * POPSystem.AppServiceAccessPoint); if(app != null){
- * app.logPJ(app.getPOPCAppID(), log); }else{ System.out.println(log); }
- *
- * } catch (Exception e) { System.out.println(log); try{ POPAppService app =
- * (POPAppService)PopJava.newActive(POPJavaAppService.class,
- * POPSystem.AppServiceAccessPoint); app.logPJ(app.getPOPCAppID(), log); } catch
- * (POPException e2) { e2.printStackTrace(); } }
- */
}
static {
// Trick :(( I don't know why the system i386 doesn't work
- String osName = System.getProperty("os.name");
- String osArchitect = System.getProperty("os.arch");
+ try {
+ String osName = System.getProperty("os.name");
+ String osArchitect = System.getProperty("os.arch");
- if (osArchitect.contains("64")) {
- osArchitect = "x86_64";
- }
+ if(osName == null) {
+ osName = "";
+ }
+
+ if(osArchitect == null) {
+ osArchitect = "";
+ }
+
+ if (osArchitect.contains("64")) {
+ osArchitect = "x86_64";
+ }
- platform = String.format("%s-%s", osArchitect, osName);
+ platform = String.format("%s-%s", osArchitect, osName);
+ }catch (Throwable e) {
+ e.printStackTrace();
+ }
}
/**
@@ -179,7 +190,7 @@ public static InterfaceAddress getHostIP() {
}
//Find first non local address
- Enumeration en;
+ Enumeration en = null;
try {
en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
@@ -194,26 +205,52 @@ public static InterfaceAddress getHostIP() {
}
//Find first non local address
- try {
- en = NetworkInterface.getNetworkInterfaces();
+ if(en != null) {
while (en.hasMoreElements()) {
NetworkInterface ni = en.nextElement();
InterfaceAddress ip = getInterfaceIP(ni, true);
if (ip != null) {
return ip;
}
-
}
- } catch (SocketException e) {
}
-
+
try {
InetAddress localHost = Inet4Address.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
- for(InterfaceAddress addr : networkInterface.getInterfaceAddresses()) {
- if(addr.getAddress().isLoopbackAddress() && addr.getAddress() instanceof Inet4Address) {
- return addr;
+ if(networkInterface != null) {
+ for(InterfaceAddress addr : networkInterface.getInterfaceAddresses()) {
+ if(addr.getAddress().isLoopbackAddress() && addr.getAddress() instanceof Inet4Address) {
+ return addr;
+ }
+ }
+
+ //Fallback to whatever we find
+ for(InterfaceAddress addr : networkInterface.getInterfaceAddresses()) {
+ if(addr.getAddress() instanceof Inet4Address) {
+ return addr;
+ }
+ }
+ }else {
+ en = NetworkInterface.getNetworkInterfaces();
+ while (en.hasMoreElements()) {
+ NetworkInterface ni = en.nextElement();
+
+ for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
+
+ if(interfaceAddress.getAddress() instanceof Inet4Address) {
+ return interfaceAddress;
+ }
+ }
+ }
+
+ while (en.hasMoreElements()) {
+ NetworkInterface ni = en.nextElement();
+
+ for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
+ return interfaceAddress;
+ }
}
}
}catch (SocketException e) {
@@ -387,16 +424,6 @@ public static void registerCode(String file, String clazz) {
}
}
- private static String jobservice = String.format("%s:%d", POPSystem.getHostIP().getAddress().getHostAddress(), conf.getJobManagerPorts()[0]);
-
- private static String codeconf;
-
- private static String appservicecode;
-
- private static String proxy;
-
- private static String appservicecontact;
-
/**
* Initialize the application scope services
*
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/util/Configuration.java b/workspace/popjava/src/ch/icosys/popjava/core/util/Configuration.java
index b9bff472..58c196a5 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/util/Configuration.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/util/Configuration.java
@@ -42,10 +42,10 @@ private enum Settable {
private static final Boolean ENV_DEBUG;
static {
String location = System.getenv("POPJAVA_LOCATION");
- if (location == null) {
- POPJAVA_LOCATION = new File("./").getAbsolutePath();
- } else {
+ if (location != null) {
POPJAVA_LOCATION = new File(location).getAbsolutePath();
+ } else {
+ POPJAVA_LOCATION = new File("./").getAbsolutePath();
}
String debug = System.getenv("POPJAVA_DEBUG");
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/util/POPRemoteCaller.java b/workspace/popjava/src/ch/icosys/popjava/core/util/POPRemoteCaller.java
index 920a82aa..488fa64c 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/util/POPRemoteCaller.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/util/POPRemoteCaller.java
@@ -102,7 +102,11 @@ public boolean isUsingConfidenceLink() {
*
* @return true if the address is our own machine
*/
- public boolean isLocalHost() {
+ public boolean isLocalHost(POPAccessPoint ap) {
+ if(ap.hasAccessPointIP(remote.getHostAddress())) {
+ return true;
+ }
+
return Util.isLocal(remote.getHostAddress());
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/util/SystemUtil.java b/workspace/popjava/src/ch/icosys/popjava/core/util/SystemUtil.java
index 939b18dd..0cb9a64c 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/util/SystemUtil.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/util/SystemUtil.java
@@ -370,4 +370,20 @@ public static synchronized void registerLocalJVM(Broker broker) {
Objects.requireNonNull(broker);
localJVM.add(broker);
}
+
+ public static boolean isHostInPrivateSubnet(String host) {
+ if(host.startsWith("10.") || host.startsWith("192.168.")) {
+ return true;
+ }
+
+ if(host.startsWith("172.")) {
+ for(int i = 16; i < 32; i++) {
+ if(host.startsWith("172."+i+".")) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/workspace/popjava/src/ch/icosys/popjava/core/util/upnp/UPNPManager.java b/workspace/popjava/src/ch/icosys/popjava/core/util/upnp/UPNPManager.java
index 10d51cad..9d58df6d 100644
--- a/workspace/popjava/src/ch/icosys/popjava/core/util/upnp/UPNPManager.java
+++ b/workspace/popjava/src/ch/icosys/popjava/core/util/upnp/UPNPManager.java
@@ -5,12 +5,17 @@
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import javax.xml.parsers.ParserConfigurationException;
@@ -19,7 +24,9 @@
import org.bitlet.weupnp.PortMappingEntry;
import org.xml.sax.SAXException;
+import ch.icosys.popjava.core.baseobject.AccessPoint;
import ch.icosys.popjava.core.util.LogWriter;
+import ch.icosys.popjava.core.util.Tuple;
public class UPNPManager {
@@ -29,7 +36,8 @@ public class UPNPManager {
private static GatewayDevice d = null;
- private static final Set mappedPorts = Collections.synchronizedSet(new HashSet());
+ private static final Map mappedPorts = Collections.synchronizedMap(new HashMap<>());
+ private static final Map>> mappingTasks = Collections.synchronizedMap(new HashMap<>());
private static boolean inited = false;
@@ -67,15 +75,15 @@ public synchronized static String getExternalIP() {
return externalIP;
}
- public synchronized static Future registerPort(int port) {
- if (mappedPorts.contains(port)) {
- return CompletableFuture.completedFuture(externalIP);
+ public synchronized static Future> registerPort(int port) {
+ if (mappedPorts.containsKey(port)) {
+ return CompletableFuture.completedFuture(new Tuple(externalIP, mappedPorts.get(port)));
}
- Callable mapper = new Callable() {
+ Callable> mapper = new Callable>() {
@Override
- public String call() throws Exception {
+ public Tuple call() throws Exception {
init();
if (null != d) {
@@ -83,9 +91,11 @@ public String call() throws Exception {
"Found gateway device.\n" + d.getModelName() + " (" + d.getModelDescription() + ")");
} else {
LogWriter.writeDebugInfo("No valid gateway device found.");
- return "";
+ return new Tuple("", -1);
}
+ int newPort = port;
+
InetAddress localAddress = d.getLocalAddress();
String externalIPAddress = "";
try {
@@ -96,15 +106,30 @@ public String call() throws Exception {
PortMappingEntry portMapping = new PortMappingEntry();
+ boolean directMapping = false;
if (d.getSpecificPortMappingEntry(port, "TCP", portMapping)) {
- LogWriter.writeDebugInfo("Port " + port + " is already forwarded");
- } else {
+ if(portMapping.getInternalClient().equals(localAddress.getHostAddress())) {
+ directMapping = true;
+ LogWriter.writeDebugInfo("Port " + port + " is already forwarded to ourself");
+ }else {
+ LogWriter.writeDebugInfo("Port " + port + " is already forwarded to "+portMapping.getInternalClient());
+ newPort = getFreeNATPort(localAddress, port);
+ if(newPort < 0) {
+ newPort *= -1;
+ LogWriter.writeDebugInfo("Remap of " + port + " to "+newPort+" is already in place");
+ directMapping = true;
+ }else {
+ LogWriter.writeDebugInfo("Remap " + port + " to "+newPort);
+ }
+ }
+ }
+
+ if(!directMapping) {
LogWriter.writeDebugInfo("Sending port mapping request");
- if (!d.addPortMapping(port, port, localAddress.getHostAddress(), "TCP", "POP-Java")) {
+ if (!d.addPortMapping(newPort, port, localAddress.getHostAddress(), "TCP", "POP-Java")) {
LogWriter.writeDebugInfo("Port mapping attempt failed");
- } else {
- mappedPorts.add(port);
+ newPort = -1;
}
}
} catch (SAXException e) {
@@ -112,26 +137,90 @@ public String call() throws Exception {
} catch (IOException e) {
LogWriter.writeExceptionLog(e);
}
-
- return externalIP;
+
+ if(newPort != -1) {
+ mappedPorts.put(port, newPort);
+ }
+
+ mappingTasks.remove(port);
+
+ return new Tuple(externalIP, newPort);
}
};
- FutureTask task = new FutureTask<>(mapper);
+ FutureTask> task = new FutureTask<>(mapper);
Thread upnpThread = new Thread(task);
upnpThread.setDaemon(true);
upnpThread.start();
+
+ mappingTasks.put(port, task);
return task;
}
+
+ public static void mapAccessPoint(final AccessPoint ap, long timeOutMS) {
+ Future> futurePort = mappingTasks.get(ap.getPort());
+
+ if(mappedPorts.containsKey(ap.getPort())) {
+ ap.setPort(mappedPorts.get(ap.getPort()));
+ }
+
+ if(futurePort != null) {
+
+ Thread thread = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ ap.setPort(futurePort.get(2, TimeUnit.SECONDS).getB());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ } catch (TimeoutException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ thread.setDaemon(true);
+ thread.start();
+
+ try {
+ thread.join(timeOutMS);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ private static int getFreeNATPort(InetAddress localAddress, int port) throws IOException, SAXException {
+
+ int counter = 0;
+ do {
+ port++;
+ PortMappingEntry portMapping = new PortMappingEntry();
+ if (!d.getSpecificPortMappingEntry(port, "TCP", portMapping)) {
+ return port;
+ }
+
+ if(portMapping.getInternalClient().equals(localAddress.getHostAddress())) {
+ return -port;
+ }
+
+ //Abort after 1000 ports
+ if(counter++ > 1000) {
+ return 0;
+ }
+ }while(true);
+
+ }
public static synchronized void close() {
if (mappedPorts.size() > 0) {
GatewayDevice d = discover.getValidGateway();
- for (int port : mappedPorts) {
+ for (int port : mappedPorts.keySet()) {
try {
d.deletePortMapping(port, "TCP");
} catch (IOException e) {
diff --git a/workspace/popjava/test/ch/icosys/popjava/junit/localtests/deamontest/DeamonTest.java b/workspace/popjava/test/ch/icosys/popjava/junit/localtests/deamontest/DeamonTest.java
index 7f920e78..1ea7ea74 100644
--- a/workspace/popjava/test/ch/icosys/popjava/junit/localtests/deamontest/DeamonTest.java
+++ b/workspace/popjava/test/ch/icosys/popjava/junit/localtests/deamontest/DeamonTest.java
@@ -2,8 +2,10 @@
import static org.junit.Assert.*;
+import java.io.File;
import java.io.IOException;
+import org.junit.Assume;
import org.junit.Test;
import ch.icosys.popjava.core.PopJava;
@@ -20,6 +22,7 @@ public class DeamonTest {
*/
@Test
public void testDynamicCreationFail() {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
try {
@@ -33,6 +36,7 @@ public void testDynamicCreationFail() {
}
private static POPJavaDeamon startDeamon(String password) throws InterruptedException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
final POPJavaDeamon deamon = new POPJavaDeamon(password);
Thread thread = new Thread(new Runnable() {
@@ -51,6 +55,7 @@ public void run() {
@Test
public void testSuccess() throws IOException, InterruptedException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
POPJavaDeamon deamon = startDeamon("");
@@ -65,6 +70,7 @@ public void testSuccess() throws IOException, InterruptedException {
@Test
public void testDynamicCreation() throws IOException, InterruptedException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
POPJavaDeamon deamon = startDeamon("");
TestClass test = PopJava.newActive(this, TestClass.class, ConnectionType.DAEMON, "");
@@ -79,6 +85,7 @@ public void testDynamicCreation() throws IOException, InterruptedException {
@Test
public void testDynamicCreationPassword() throws IOException, InterruptedException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
String password = "12345";
POPJavaDeamon deamon = startDeamon(password);
@@ -93,6 +100,7 @@ public void testDynamicCreationPassword() throws IOException, InterruptedExcepti
@Test
public void testDynamicCreationPasswordMissmatch() throws IOException, InterruptedException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
String password = "12345";
POPJavaDeamon deamon = startDeamon(password);
@@ -111,6 +119,7 @@ public void testDynamicCreationPasswordMissmatch() throws IOException, Interrupt
@Test
public void testMultiObjectCreation() throws InterruptedException, IOException {
+ Assume.assumeTrue(new File(POPJavaDeamon.BACKUP_JAR).exists());
POPSystem.initialize();
String password = "12345";
POPJavaDeamon deamon = startDeamon(password);
diff --git a/workspace/popjava/test/ch/icosys/popjava/junit/system/POPSystemTest.java b/workspace/popjava/test/ch/icosys/popjava/junit/system/POPSystemTest.java
index e019acda..978fd36c 100644
--- a/workspace/popjava/test/ch/icosys/popjava/junit/system/POPSystemTest.java
+++ b/workspace/popjava/test/ch/icosys/popjava/junit/system/POPSystemTest.java
@@ -12,6 +12,7 @@
import ch.icosys.popjava.core.serviceadapter.POPAppService;
import ch.icosys.popjava.core.system.POPJavaConfiguration;
import ch.icosys.popjava.core.system.POPSystem;
+import ch.icosys.popjava.core.util.SystemUtil;
import ch.icosys.popjava.core.util.Util;
import ch.icosys.popjava.core.util.Util.OSType;
@@ -69,4 +70,14 @@ public void testParameterCleaning() {
* Util.removeStringFromList(argvList, "-appservicecontact=");
*/
}
+
+ @Test
+ public void testSubnetID() {
+ assertTrue(SystemUtil.isHostInPrivateSubnet("10.0.0.1"));
+ assertFalse(SystemUtil.isHostInPrivateSubnet("1.2.3.4"));
+ assertTrue(SystemUtil.isHostInPrivateSubnet("192.168.10.1"));
+ assertTrue(SystemUtil.isHostInPrivateSubnet("172.16.10.1"));
+ assertFalse(SystemUtil.isHostInPrivateSubnet("172.3.10.1"));
+ assertTrue(SystemUtil.isHostInPrivateSubnet("172.31.10.1"));
+ }
}