diff --git a/modP2pImpl/build.xml b/modP2pImpl/build.xml
index ddeb7430f6..a1a3d2242f 100644
--- a/modP2pImpl/build.xml
+++ b/modP2pImpl/build.xml
@@ -16,6 +16,7 @@
+
diff --git a/modP2pImpl/module-info.java b/modP2pImpl/module-info.java
index 83be492ae3..b35397be18 100644
--- a/modP2pImpl/module-info.java
+++ b/modP2pImpl/module-info.java
@@ -1,4 +1,5 @@
module aion.p2p.impl {
requires aion.p2p;
+ requires miniupnpc.linux;
exports org.aion.p2p.impl;
}
\ No newline at end of file
diff --git a/modP2pImpl/src/org/aion/p2p/impl/P2pMgr.java b/modP2pImpl/src/org/aion/p2p/impl/P2pMgr.java
index d62c9cc9ee..3e577dd859 100644
--- a/modP2pImpl/src/org/aion/p2p/impl/P2pMgr.java
+++ b/modP2pImpl/src/org/aion/p2p/impl/P2pMgr.java
@@ -61,6 +61,7 @@ public final class P2pMgr implements IP2pMgr {
private final static int TIMEOUT_OUTBOUND_CONNECT = 10000;
private final static int TIMEOUT_OUTBOUND_NODES = 10000;
+ private final static int PERIOD_UPNP_PORT_MAPPING = 3600000;
private final static int TIMEOUT_MSG_READ = 10000;
@@ -678,10 +679,6 @@ private void handleKernelMsg(int _nodeIdHash, int _route, final byte[] _msgBytes
}
}
- private void runUpnp() {
- // TODO: implement
- }
-
@Override
public void run() {
try {
@@ -697,13 +694,13 @@ public void run() {
tcpServer.socket().bind(new InetSocketAddress(Node.ipBytesToStr(selfIp), selfPort));
tcpServer.register(selector, SelectionKey.OP_ACCEPT);
- if (this.upnpEnable)
- runUpnp();
-
Thread boss = new Thread(new TaskInbound(), "p2p-pi");
boss.setPriority(Thread.MAX_PRIORITY);
boss.start();
+ if (upnpEnable)
+ scheduledWorkers.scheduleWithFixedDelay(new TaskUPnPManager(selfPort), 1, PERIOD_UPNP_PORT_MAPPING, TimeUnit.MILLISECONDS);
+
if (showStatus)
scheduledWorkers.scheduleWithFixedDelay(new TaskStatus(), 2, PERIOD_SHOW_STATUS, TimeUnit.MILLISECONDS);
scheduledWorkers.scheduleWithFixedDelay(new TaskRequestActiveNodes(this), 5, PERIOD_REQUEST_ACTIVE_NODES,
diff --git a/modP2pImpl/src/org/aion/p2p/impl/TaskUPnPManager.java b/modP2pImpl/src/org/aion/p2p/impl/TaskUPnPManager.java
new file mode 100644
index 0000000000..284411037f
--- /dev/null
+++ b/modP2pImpl/src/org/aion/p2p/impl/TaskUPnPManager.java
@@ -0,0 +1,103 @@
+package org.aion.p2p.impl;
+
+import fr.free.miniupnp.IGDdatas;
+import fr.free.miniupnp.MiniupnpcLibrary;
+import fr.free.miniupnp.UPNPDev;
+import fr.free.miniupnp.UPNPUrls;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+
+public class TaskUPnPManager implements Runnable {
+
+ private final static String UPNP_PROTOCOL_TCP = "TCP";
+ private final static String UPNP_PORT_MAPPING_DESCRIPTION = "aion-UPnP";
+ private final static int DEFAULT_UPNP_PORT_MAPPING_LIFETIME_IN_SECONDS = 3600;
+ private final static int UPNP_DELAY = 2000;
+
+ private int port;
+ MiniupnpcLibrary miniupnpc;
+
+ TaskUPnPManager(int port){
+ this.port = port;
+ miniupnpc = MiniupnpcLibrary.INSTANCE;
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("p2p-UPnP");
+
+ UPNPUrls urls = new UPNPUrls();
+ IGDdatas data = new IGDdatas();
+
+ ByteBuffer lanaddr = ByteBuffer.allocate(16);
+
+ UPNPDev devlist = miniupnpc.upnpDiscover(UPNP_DELAY, null, null, 0, 0, (byte) 2, IntBuffer.allocate(1));
+ if (devlist != null) {
+ if (miniupnpc.UPNP_GetValidIGD(devlist, urls, data, lanaddr, 16) != 0) {
+ System.out.println("");
+ System.out.println("");
+
+ getExternalIpAddress(urls, data);
+ addPortMapping(urls, data, lanaddr);
+ getMappedPortInfo(urls, data);
+
+ miniupnpc.FreeUPNPUrls(urls);
+ } else {
+ System.out.println("");
+ }
+ } else {
+ System.out.println("");
+ }
+ }
+
+ private void addPortMapping(UPNPUrls urls, IGDdatas data, ByteBuffer lanaddr) {
+ int ret = miniupnpc.UPNP_AddPortMapping(
+ urls.controlURL.getString(0),
+ new String(data.first.servicetype),
+ String.valueOf(port),
+ String.valueOf(port),
+ new String(lanaddr.array()),
+ UPNP_PORT_MAPPING_DESCRIPTION,
+ UPNP_PROTOCOL_TCP,
+ null,
+ String.valueOf(DEFAULT_UPNP_PORT_MAPPING_LIFETIME_IN_SECONDS));
+
+ if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS)
+ System.out.println("");
+ }
+
+ private void getMappedPortInfo(UPNPUrls urls, IGDdatas data) {
+ ByteBuffer intClient = ByteBuffer.allocate(16);
+ ByteBuffer intPort = ByteBuffer.allocate(6);
+ ByteBuffer desc = ByteBuffer.allocate(80);
+ ByteBuffer enabled = ByteBuffer.allocate(4);
+ ByteBuffer leaseDuration = ByteBuffer.allocate(16);
+
+ int ret = miniupnpc.UPNP_GetSpecificPortMappingEntry(
+ urls.controlURL.getString(0), new String(data.first.servicetype),
+ String.valueOf(port), UPNP_PROTOCOL_TCP, null, intClient, intPort,
+ desc, enabled, leaseDuration);
+
+ if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) {
+ System.out.println("");
+ return;
+ }
+
+ System.out.println("");
+ }
+
+ private void getExternalIpAddress(UPNPUrls urls, IGDdatas data) {
+ ByteBuffer externalAddress = ByteBuffer.allocate(16);
+ int ret = miniupnpc.UPNP_GetExternalIPAddress(urls.controlURL.getString(0),
+ new String(data.first.servicetype), externalAddress);
+
+ if(ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) {
+ System.out.println("");
+ return;
+ }
+
+ System.out.println("");
+ }
+}
\ No newline at end of file