浏览代码

Wire up PortMapper in Android

Enables UPnP port mapping for Android client on networks with UPnP routers
Grant Limberg 8 年之前
父节点
当前提交
bcf697cc2b
共有 5 个文件被更改,包括 89 次插入20 次删除
  1. 6 0
      ext/miniupnpc/minisoap.c
  2. 6 0
      ext/miniupnpc/miniwget.c
  3. 30 4
      java/jni/Android.mk
  4. 15 1
      java/jni/com_zerotierone_sdk_Node.cpp
  5. 32 15
      osdep/PortMapper.cpp

+ 6 - 0
ext/miniupnpc/minisoap.c

@@ -26,6 +26,12 @@
 #define UPNP_VERSION_STRING "UPnP/1.1"
 #endif
 
+#ifdef __ANDROID__
+#define OS_STRING "Android"
+#define MINIUPNPC_VERSION_STRING "2.0"
+#define UPNP_VERSION_STRING "UPnP/1.1"
+#endif
+
 /* only for malloc */
 #include <stdlib.h>
 

+ 6 - 0
ext/miniupnpc/miniwget.c

@@ -55,6 +55,12 @@
 #define UPNP_VERSION_STRING "UPnP/1.1"
 #endif
 
+#ifdef __ANDROID__
+#define OS_STRING "Android"
+#define MINIUPNPC_VERSION_STRING "2.0"
+#define UPNP_VERSION_STRING "UPnP/1.1"
+#endif
+
 #include "miniwget.h"
 #include "connecthostport.h"
 #include "receivedata.h"

+ 30 - 4
java/jni/Android.mk

@@ -3,14 +3,21 @@ LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := ZeroTierOneJNI
-LOCAL_C_INCLUDES := $(ZT1)/include
-LOCAL_C_INCLUDES += $(ZT1)/node
+LOCAL_C_INCLUDES := \
+    $(ZT1)/include \
+    $(ZT1)/node \
+    $(ZT1)/osdep \
+    $(ZT1)/ext/miniupnpc \
+    $(ZT1)/ext/libnatpmp
+
 LOCAL_LDLIBS := -llog -latomic
 # LOCAL_CFLAGS := -g
 
+LOCAL_CFLAGS := -DZT_USE_MINIUPNPC
+
 # ZeroTierOne SDK source files
 LOCAL_SRC_FILES := \
-	$(ZT1)/node/C25519.cpp \
+    $(ZT1)/node/C25519.cpp \
 	$(ZT1)/node/Capability.cpp \
 	$(ZT1)/node/CertificateOfMembership.cpp \
 	$(ZT1)/node/CertificateOfOwnership.cpp \
@@ -35,8 +42,27 @@ LOCAL_SRC_FILES := \
 	$(ZT1)/node/Tag.cpp \
 	$(ZT1)/node/Topology.cpp \
 	$(ZT1)/node/Trace.cpp \
-	$(ZT1)/node/Utils.cpp
+	$(ZT1)/node/Utils.cpp \
+	$(ZT1)/osdep/OSUtils.cpp \
+	$(ZT1)/osdep/PortMapper.cpp
 
+# libminiupnpc and libnatpmp files
+LOCAL_SRC_FILES += \
+	$(ZT1)/ext/miniupnpc/connecthostport.c \
+	$(ZT1)/ext/miniupnpc/igd_desc_parse.c \
+	$(ZT1)/ext/miniupnpc/minisoap.c \
+	$(ZT1)/ext/miniupnpc/minissdpc.c \
+	$(ZT1)/ext/miniupnpc/miniupnpc.c \
+	$(ZT1)/ext/miniupnpc/miniwget.c \
+	$(ZT1)/ext/miniupnpc/minixml.c \
+	$(ZT1)/ext/miniupnpc/portlistingparse.c \
+	$(ZT1)/ext/miniupnpc/receivedata.c \
+	$(ZT1)/ext/miniupnpc/upnpcommands.c \
+	$(ZT1)/ext/miniupnpc/upnpdev.c \
+	$(ZT1)/ext/miniupnpc/upnperrors.c \
+	$(ZT1)/ext/miniupnpc/upnpreplyparse.c \
+	$(ZT1)/ext/libnatpmp/natpmp.c \
+	$(ZT1)/ext/libnatpmp/getgateway.c
 
 # JNI Files
 LOCAL_SRC_FILES += \

+ 15 - 1
java/jni/com_zerotierone_sdk_Node.cpp

@@ -32,6 +32,8 @@
 #include <ZeroTierOne.h>
 #include "Mutex.hpp"
 
+#include "PortMapper.hpp"
+
 #include <map>
 #include <string>
 #include <assert.h>
@@ -58,6 +60,7 @@ namespace {
             , configListener(NULL)
             , pathChecker(NULL)
             , callbacks(NULL)
+            , portMapper(NULL)
         {
             callbacks = (ZT_Node_Callbacks*)malloc(sizeof(ZT_Node_Callbacks));
             memset(callbacks, 0, sizeof(ZT_Node_Callbacks));
@@ -78,6 +81,9 @@ namespace {
 
             free(callbacks);
             callbacks = NULL;
+
+            delete portMapper;
+            portMapper = NULL;
         }
 
         uint64_t id;
@@ -95,6 +101,8 @@ namespace {
         jobject pathChecker;
 
         ZT_Node_Callbacks *callbacks;
+
+        ZeroTier::PortMapper *portMapper;
     };
 
 
@@ -833,11 +841,17 @@ JNIEXPORT jobject JNICALL Java_com_zerotier_sdk_Node_node_1init(
         return resultObject;
     }
 
+    uint64_t nodeId = ZT_Node_address(node);
+    if (nodeId != 0) {
+        char uniqueName[64];
+        snprintf(uniqueName, sizeof(uniqueName), "ZeroTier Android/%.10llx@%u", (unsigned long long)nodeId, 9993);
+        ref->portMapper = new ZeroTier::PortMapper(9993, uniqueName);
+    }
+
     ZeroTier::Mutex::Lock lock(nodeMapMutex);
     ref->node = node;
     nodeMap.insert(std::make_pair(ref->id, ref));
 
-
     return resultObject;
 }
 

+ 32 - 15
osdep/PortMapper.cpp

@@ -29,6 +29,13 @@
 // Uncomment to dump debug messages
 //#define ZT_PORTMAPPER_TRACE 1
 
+#ifdef __ANDROID__
+#include <android/log.h>
+#define PM_TRACE(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "PortMapper", __VA_ARGS__))
+#else
+#define PM_TRACE(...) fprintf(stderr, __VA_ARGS__)
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -53,15 +60,24 @@
 #include <miniupnpc/miniupnpc.h>
 #include <miniupnpc/upnpcommands.h>
 #else
+#ifdef __ANDROID__
+#include "miniupnpc.h"
+#include "upnpcommands.h"
+#else
 #include "../ext/miniupnpc/miniupnpc.h"
 #include "../ext/miniupnpc/upnpcommands.h"
 #endif
+#endif
 
 #ifdef ZT_USE_SYSTEM_NATPMP
 #include <natpmp.h>
 #else
+#ifdef __ANDROID__
+#include "natpmp.h"
+#else
 #include "../ext/libnatpmp/natpmp.h"
 #endif
+#endif
 
 namespace ZeroTier {
 
@@ -83,7 +99,7 @@ public:
 		int mode = 0; // 0 == NAT-PMP, 1 == UPnP
 
 #ifdef ZT_PORTMAPPER_TRACE
-		fprintf(stderr,"PortMapper: started for UDP port %d"ZT_EOL_S,localPort);
+		fprintf(stderr,"PortMapper: started for UDP port %d" ZT_EOL_S,localPort);
 #endif
 
 		while (run) {
@@ -108,7 +124,7 @@ public:
 					if (initnatpmp(&natpmp,0,0) != 0) {
 						mode = 1;
 #ifdef ZT_PORTMAPPER_TRACE
-						fprintf(stderr,"PortMapper: NAT-PMP: init failed, switching to UPnP mode"ZT_EOL_S);
+                        PM_TRACE("PortMapper: NAT-PMP: init failed, switching to UPnP mode" ZT_EOL_S);
 #endif
 						break;
 					}
@@ -131,7 +147,7 @@ public:
 						publicAddress = InetAddress((uint32_t)response.pnu.publicaddress.addr.s_addr,0);
 					} else {
 #ifdef ZT_PORTMAPPER_TRACE
-						fprintf(stderr,"PortMapper: NAT-PMP: request for external address failed, aborting..."ZT_EOL_S);
+                        PM_TRACE("PortMapper: NAT-PMP: request for external address failed, aborting..." ZT_EOL_S);
 #endif
 						closenatpmp(&natpmp);
 						break;
@@ -153,7 +169,8 @@ public:
 					if (r == 0) {
 						publicAddress.setPort(response.pnu.newportmapping.mappedpublicport);
 #ifdef ZT_PORTMAPPER_TRACE
-						fprintf(stderr,"PortMapper: NAT-PMP: mapped %u to %s"ZT_EOL_S,(unsigned int)localPort,publicAddress.toString().c_str());
+                        char paddr[128];
+                        PM_TRACE("PortMapper: NAT-PMP: mapped %u to %s" ZT_EOL_S,(unsigned int)localPort,publicAddress.toString(paddr));
 #endif
 						Mutex::Lock sl(surface_l);
 						surface.clear();
@@ -170,7 +187,7 @@ public:
 				if (!natPmpSuccess) {
 					mode = 1;
 #ifdef ZT_PORTMAPPER_TRACE
-					fprintf(stderr,"PortMapper: NAT-PMP: request failed, switching to UPnP mode"ZT_EOL_S);
+                    PM_TRACE("PortMapper: NAT-PMP: request failed, switching to UPnP mode" ZT_EOL_S);
 #endif
 				}
 			}
@@ -195,7 +212,7 @@ public:
 					{
 						UPNPDev *dev = devlist;
 						while (dev) {
-							fprintf(stderr,"PortMapper: found UPnP device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st);
+                            PM_TRACE("PortMapper: found UPnP device at URL '%s': %s" ZT_EOL_S,dev->descURL,dev->st);
 							dev = dev->pNext;
 						}
 					}
@@ -209,11 +226,11 @@ public:
 
 					if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
 #ifdef ZT_PORTMAPPER_TRACE
-						fprintf(stderr,"PortMapper: UPnP: my LAN IP address: %s"ZT_EOL_S,lanaddr);
+                        PM_TRACE("PortMapper: UPnP: my LAN IP address: %s" ZT_EOL_S,lanaddr);
 #endif
 						if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) {
 #ifdef ZT_PORTMAPPER_TRACE
-							fprintf(stderr,"PortMapper: UPnP: my external IP address: %s"ZT_EOL_S,externalip);
+                            PM_TRACE("PortMapper: UPnP: my external IP address: %s" ZT_EOL_S,externalip);
 #endif
 
 							for(int tries=0;tries<60;++tries) {
@@ -239,7 +256,7 @@ public:
 									memset(haveLeaseDuration,0,sizeof(haveLeaseDuration));
 									if ((UPNP_GetSpecificPortMappingEntry(urls.controlURL,data.first.servicetype,outport,"UDP",(const char *)0,haveIntClient,haveIntPort,haveDesc,haveEnabled,haveLeaseDuration) == UPNPCOMMAND_SUCCESS)&&(uniqueName == haveDesc)) {
 #ifdef ZT_PORTMAPPER_TRACE
-										fprintf(stderr,"PortMapper: UPnP: reusing previously reserved external port: %s"ZT_EOL_S,outport);
+                                        PM_TRACE("PortMapper: UPnP: reusing previously reserved external port: %s" ZT_EOL_S,outport);
 #endif
 										Mutex::Lock sl(surface_l);
 										surface.clear();
@@ -254,7 +271,7 @@ public:
 								int mapResult = 0;
 								if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,uniqueName.c_str(),"UDP",(const char *)0,"0")) == UPNPCOMMAND_SUCCESS) {
 #ifdef ZT_PORTMAPPER_TRACE
-									fprintf(stderr,"PortMapper: UPnP: reserved external port: %s"ZT_EOL_S,outport);
+                                    PM_TRACE("PortMapper: UPnP: reserved external port: %s" ZT_EOL_S,outport);
 #endif
 									Mutex::Lock sl(surface_l);
 									surface.clear();
@@ -264,7 +281,7 @@ public:
 									break;
 								} else {
 #ifdef ZT_PORTMAPPER_TRACE
-									fprintf(stderr,"PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult);
+                                    PM_TRACE("PortMapper: UPnP: UPNP_AddPortMapping(%s) failed: %d" ZT_EOL_S,outport,mapResult);
 #endif
 									Thread::sleep(1000);
 								}
@@ -273,13 +290,13 @@ public:
 						} else {
 							mode = 0;
 #ifdef ZT_PORTMAPPER_TRACE
-							fprintf(stderr,"PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode"ZT_EOL_S);
+                            PM_TRACE("PortMapper: UPnP: UPNP_GetExternalIPAddress failed, returning to NAT-PMP mode" ZT_EOL_S);
 #endif
 						}
 					} else {
 						mode = 0;
 #ifdef ZT_PORTMAPPER_TRACE
-						fprintf(stderr,"PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode"ZT_EOL_S);
+                        PM_TRACE("PortMapper: UPnP: UPNP_GetValidIGD failed, returning to NAT-PMP mode" ZT_EOL_S);
 #endif
 					}
 
@@ -288,14 +305,14 @@ public:
 				} else {
 					mode = 0;
 #ifdef ZT_PORTMAPPER_TRACE
-					fprintf(stderr,"PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d"ZT_EOL_S,upnpError);
+                    PM_TRACE("PortMapper: upnpDiscover failed, returning to NAT-PMP mode: %d" ZT_EOL_S,upnpError);
 #endif
 				}
 			}
 			// ---------------------------------------------------------------------
 
 #ifdef ZT_PORTMAPPER_TRACE
-			fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_PORTMAPPER_REFRESH_DELAY);
+            PM_TRACE("UPNPClient: rescanning in %d ms" ZT_EOL_S,ZT_PORTMAPPER_REFRESH_DELAY);
 #endif
 			Thread::sleep(ZT_PORTMAPPER_REFRESH_DELAY);
 		}