diff --git a/.version b/.version
deleted file mode 100644
index bfa363e7..00000000
--- a/.version
+++ /dev/null
@@ -1 +0,0 @@
-1.8.4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7a95b8c5..24b1d79f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,8 +82,6 @@ endif()
# ------------------------------------------------------------------------------
# | INCLUDE DIRECTORIES |
# ------------------------------------------------------------------------------
-# Temporary measure to test GitHub workflow on Ubuntu
-include_directories(/usr/lib/jvm/java-11-openjdk-amd64/include/linux/)
# ZeroTier
include_directories(${ZTO_SRC_DIR})
include_directories(${ZTO_SRC_DIR}/include)
@@ -92,6 +90,8 @@ include_directories(${ZTO_SRC_DIR}/osdep)
# ZeroTier (ext)
#include_directories(${ZTO_SRC_DIR}/ext/miniupnpc)
include_directories(${ZTO_SRC_DIR}/ext/libnatpmp)
+include_directories(${ZTO_SRC_DIR}/ext/prometheus-cpp-lite-1.0/core/include)
+include_directories(${ZTO_SRC_DIR}/ext/prometheus-cpp-lite-1.0/simpleapi/include)
# libzt
include_directories(${PROJ_DIR}/src)
include_directories(${PROJ_DIR}/include)
@@ -116,7 +116,7 @@ if (ZTS_ENABLE_PINVOKE)
# Features
set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE)
# Sources and libraries
@@ -129,7 +129,7 @@ if (ZTS_ENABLE_RUST)
# Features
set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB FALSE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE)
endif()
@@ -142,7 +142,7 @@ if (ZTS_ENABLE_PYTHON)
# Targets
set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
set(BUILD_HOST_SELFTEST FALSE)
# Sources and libraries
@@ -190,15 +190,17 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(BUILD_STATIC_LIB FALSE)
set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_SELFTEST FALSE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
+ set(LANG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/java/*.cxx)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_JAVA=1")
endif()
if(BUILD_MACOS_FRAMEWORK)
set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_SELFTEST FALSE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1")
@@ -213,7 +215,7 @@ if(BUILD_IOS_FRAMEWORK)
set(BUILD_STATIC_LIB TRUE)
set(BUILD_SHARED_LIB TRUE)
set(BUILD_HOST_SELFTEST FALSE)
- set(BUILD_EXAMPLES FALSE)
+ set(BUILD_HOST_EXAMPLES FALSE)
set(ALLOW_INSTALL_TARGET FALSE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1")
@@ -221,7 +223,7 @@ if(BUILD_IOS_FRAMEWORK)
"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer")
if(IOS_ARM64)
set(CMAKE_OSX_ARCHITECTURES arm64)
- set(SDKVER "11.4")
+ set(SDKVER "16.4")
endif()
if(IOS_ARMV7)
# armv7 armv7s
@@ -277,7 +279,6 @@ endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "debug")
set(BUILD_DEBUG ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
- set(DEBUG_OPTIMIZATION "-O3")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "release")
set(BUILD_RELEASE ON)
@@ -396,7 +397,6 @@ else()
set(CMAKE_C_FLAGS_DEBUG
"${CMAKE_C_FLAGS_DEBUG} \
- ${DEBUG_OPTIMIZATION} \
-DLWIP_DEBUG=1 -DLIBZT_DEBUG=1")
set(CMAKE_C_FLAGS_RELEASE
@@ -409,7 +409,6 @@ else()
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} \
- ${DEBUG_OPTIMIZATION} \
-DLWIP_DEBUG=1 -DLIBZT_DEBUG=1")
set(CMAKE_CXX_FLAGS_RELEASE
@@ -467,37 +466,40 @@ endif()
if(ZTS_ENABLE_JAVA OR (BUILD_ANDROID AND NOT ZTS_NDK_ONLY))
message(STATUS "Looking for JNI")
-
- if(BUILD_WIN)
- # We are only interested in finding jni.h: we do not care about extended JVM
- # functionality or the AWT library. set(JAVA_AWT_LIBRARY NotNeeded)
- # set(JAVA_JVM_LIBRARY NotNeeded) set(JAVA_INCLUDE_PATH2 NotNeeded)
- # set(JAVA_AWT_INCLUDE_PATH NotNeeded)
- set(JAVA_INCLUDE_PATH "C:\\Program Files\\Java\\jdk-10.0.2\\include")
- endif()
-
+ message(STATUS "Ignore seeing \"Found JNI: NotNeeded\" below; check that JNI_INCLUDE_DIRS is valid")
+
+ #
+ # "trick" CMake into thinking that we have already found these
+ # https://stackoverflow.com/a/51764145
+ #
+ # These may be missing, but we do not need them
+ #
+ # There is no official way of telling CMake: "skip looking for AWT, etc."
+ #
set(JAVA_AWT_LIBRARY NotNeeded)
set(JAVA_JVM_LIBRARY NotNeeded)
- set(JAVA_INCLUDE_PATH2 NotNeeded)
set(JAVA_AWT_INCLUDE_PATH NotNeeded)
- find_package(JNI REQUIRED)
-
- if(JNI_FOUND)
- message(STATUS "JNI_INCLUDE_DIR=${JNI_INCLUDE_DIRS}")
- message(STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
- list(GET JNI_INCLUDE_DIRS 0 JNI_INCLUDE_DIR)
- message(STATUS "jni path=${JNI_INCLUDE_DIR}")
- include_directories("${JNI_INCLUDE_DIR}")
- # include_directories ("${JNI_INCLUDE_DIRS}")
- if(BUILD_WIN)
- include_directories("${JNI_INCLUDE_DIR}\\win32")
- endif()
- if(BUILD_MACOS)
- include_directories("${JNI_INCLUDE_DIR}/darwin")
- endif()
- if(BUILD_LINUX)
- include_directories("${JNI_INCLUDE_DIR}/linux")
- endif()
+
+ #
+ # Do NOT make REQUIRED
+ # Until there is an official way of telling CMake to skip AWT, etc.,
+ # then JNI will be considered as "not found"
+ #
+ find_package(JNI)
+
+ list(FILTER JNI_INCLUDE_DIRS EXCLUDE REGEX NotNeeded)
+ list(FILTER JNI_LIBRARIES EXCLUDE REGEX NotNeeded)
+
+ #
+ # Do NOT check JNI_FOUND here, check JNI_INCLUDE_DIRS instead
+ # because of setting the above variables to NotNeeded,
+ # the variable JNI_FOUND is now set to NotNeeded, which is annoying
+ #
+ # We only care about JNI_INCLUDE_DIRS
+ #
+ if(JNI_INCLUDE_DIRS)
+ message(STATUS "JNI_INCLUDE_DIRS: ${JNI_INCLUDE_DIRS}")
+ include_directories("${JNI_INCLUDE_DIRS}")
else()
message(STATUS "JNI not found")
endif()
diff --git a/README.md b/README.md
index 2968623b..32114537 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,6 @@ Peer-to-peer and cross-platform encrypted connections built right into your app
Examples |
Documentation |
-Community |
Report a Bug
@@ -19,7 +18,7 @@ Peer-to-peer and cross-platform encrypted connections built right into your app
-
+
@@ -29,7 +28,7 @@ Peer-to-peer and cross-platform encrypted connections built right into your app
| C# | `Install-Package ZeroTier.Sockets` | |[C#](./examples/csharp) |
| Python | `pip install libzt`| |[Python](./examples/python) |
| Rust | See: [crates.io/crates/libzt](https://crates.io/crates/libzt) | |[Rust](./examples/rust) |
-| Java | `./build.sh host-jar` | |[Java](./examples/java) |
+| Java | Install JDK, then: `./build.sh host-jar` | |[Java](./examples/java) |
| Linux | `brew install zerotier/tap/libzt` | | [C/C++](./examples/c) |
| macOS | `brew install zerotier/tap/libzt`| | [C/C++](./examples/c) |
| iOS / iPadOS | `./build.sh iphoneos-framework` | | [Objective-C](./attic/objective-c), [Swift](./attic/swift) |
@@ -93,7 +92,7 @@ Important directories:
We provide ways for your app or enterprise to function independently from any of our services if desired.
-While we do operate a global network of redundant root servers, network controllers and an admin API/UI called [Central](https://my.zerotier.com), some use-cases require full control over the infrastructure and we try to make it as easy as possible to set up your own controllers and root servers: See [here](https://github.com/zerotier/ZeroTierOne/tree/master/controller) to learn more about how to set up your own network controller, and [here](https://www.zerotier.com/manual/#4_4) to learn more about setting up your own roots.
+While we do operate a global network of redundant root servers, network controllers and an admin API/UI called [Central](https://my.zerotier.com), some use-cases require full control over the infrastructure and we try to make it as easy as possible to set up your own controllers and root servers: See [here](https://github.com/zerotier/ZeroTierOne/tree/main/controller) to learn more about how to set up your own network controller, and [here](https://docs.zerotier.com/zerotier/moons) to learn more about setting up your own roots.
# Help
diff --git a/build.sh b/build.sh
index dfd3bea4..bbe2049c 100755
--- a/build.sh
+++ b/build.sh
@@ -350,6 +350,8 @@ host()
mkdir -p $BIN_OUTPUT_DIR
$CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE
$CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY
+ rm -f $BUILD_OUTPUT_DIR/native
+ ln -s $TARGET_BUILD_DIR $BUILD_OUTPUT_DIR/native
cp -f $CACHE_DIR/lib/libzt.* $LIB_OUTPUT_DIR
cp -f $CACHE_DIR/bin/* $BIN_OUTPUT_DIR
echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n"
@@ -494,12 +496,12 @@ host-jar()
{
check_submodules
ARTIFACT="jar"
- PKG_VERSION=$(cat .version)
+ PKG_VERSION=$(git describe --tags --abbrev=0)
# Default to release
BUILD_TYPE=${1:-release}
if [[ $1 = *"docs"* ]]; then
# Generate documentation
- javadoc src/bindings/java/*.java -d docs/java
+ javadoc src/bindings/java/com/zerotier/sockets/*.java -d docs/java
exit 0
fi
VARIANT="-DZTS_ENABLE_JAVA=True"
@@ -512,7 +514,7 @@ host-jar()
JAVA_JAR_DIR=$CACHE_DIR/pkg/jar
JAVA_JAR_SOURCE_TREE_DIR=$JAVA_JAR_DIR/com/zerotier/sockets/
mkdir -p $JAVA_JAR_SOURCE_TREE_DIR
- cp -f src/bindings/java/*.java $JAVA_JAR_SOURCE_TREE_DIR
+ cp -f src/bindings/java/com/zerotier/sockets/*.java $JAVA_JAR_SOURCE_TREE_DIR
# Build
$CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE
$CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY
@@ -520,7 +522,7 @@ host-jar()
cp -f $CACHE_DIR/lib/libzt.* $JAVA_JAR_DIR
cd $JAVA_JAR_DIR
export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8
- javac -Xlint:deprecation com/zerotier/sockets/*.java
+ javac -Xlint:all com/zerotier/sockets/*.java
jar cf libzt-$PKG_VERSION.jar $SHARED_LIB_NAME com/zerotier/sockets/*.class
rm -rf com $SHARED_LIB_NAME
@@ -596,18 +598,12 @@ android-aar()
PKG_OUTPUT_DIR=$BUILD_OUTPUT_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE
mkdir -p $CACHE_DIR
mkdir -p $PKG_OUTPUT_DIR
- # Unsure why, but Gradle's build script chokes on this non-source file now
- rm -rf ext/ZeroTierOne/ext/miniupnpc/VERSION
- export PATH=$ANDROID_HOME/cmdline-tools/tools/bin:$PATH
- # Copy source files into project
- mkdir -p ${ANDROID_PKG_PROJ_DIR}/app/src/main/java/com/zerotier/sockets
- cp -f src/bindings/java/*.java ${ANDROID_PKG_PROJ_DIR}/app/src/main/java/com/zerotier/sockets
# Build
UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}"
CMAKE_FLAGS="-D${CMAKE_SWITCH}=1 -D${CMAKE_SWITCH}=ON"
cd $ANDROID_PKG_PROJ_DIR
./gradlew $GRADLE_ARGS assemble$UPPERCASE_BUILD_TYPE # assembleRelease / assembleDebug
- mv $ANDROID_PKG_PROJ_DIR/app/build/outputs/aar/*.aar \
+ cp $ANDROID_PKG_PROJ_DIR/app/build/outputs/aar/libzt-$BUILD_TYPE.aar \
$PKG_OUTPUT_DIR/libzt-$BUILD_TYPE.aar
cd -
echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n"
@@ -652,21 +648,21 @@ format-code()
if [[ ! $(which $CLANG_FORMAT) = "" ]];
then
# Eventually: find . -path ./ext -prune -false -o -type f \( -iname \*.c -o -iname \*.h -o -iname \*.cpp -o -iname \*.hpp \) -exec clang-format -i {} \;
- $CLANG_FORMAT -i --verbose include/*.h \
- src/*.c \
- src/*.cpp \
- src/*.hpp \
- examples/c/*.c \
- examples/csharp/*.cs \
- examples/java/*.java \
- test/*.c \
- test/*.cs \
- src/bindings/csharp/*.cs \
- src/bindings/csharp/*.cxx \
- src/bindings/java/*.java \
- src/bindings/java/*.cxx \
- examples/csharp/*.cs \
- src/bindings/python/PythonSockets.cxx \
+ $CLANG_FORMAT -i --verbose include/*.h \
+ src/*.c \
+ src/*.cpp \
+ src/*.hpp \
+ examples/c/*.c \
+ examples/csharp/*.cs \
+ examples/java/*.java \
+ test/*.c \
+ test/*.cs \
+ src/bindings/csharp/*.cs \
+ src/bindings/csharp/*.cxx \
+ src/bindings/java/com/zerotier/sockets/*.java \
+ src/bindings/java/*.cxx \
+ examples/csharp/*.cs \
+ src/bindings/python/PythonSockets.cxx \
src/bindings/python/PythonSocket.h
return 0
else
@@ -745,13 +741,12 @@ clean()
find . -type d -name "__pycache__" -exec rm -rf {} +
# Python pkg
- cd pkg/pypi && ./build.sh clean
+ # cd pkg/pypi && ./build.sh clean
}
tag_release()
{
git tag -a $1 -m $2
- "$(git describe --tags --abbrev=0)" >> .version
git push origin --tags
}
diff --git a/examples/c/callbackapi.c b/examples/c/callbackapi.c
index 02d92ec2..8bb17223 100644
--- a/examples/c/callbackapi.c
+++ b/examples/c/callbackapi.c
@@ -52,7 +52,7 @@ int main(int argc, char** argv)
{
if (argc != 2) {
printf("\nUsage:\n");
- printf("pingable-node \n");
+ printf("callbackapi \n");
exit(0);
}
long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits
diff --git a/examples/c/nonblockingclient.c b/examples/c/nonblockingclient.c
index 4d7f4d5d..78f77e18 100644
--- a/examples/c/nonblockingclient.c
+++ b/examples/c/nonblockingclient.c
@@ -14,7 +14,7 @@ int main(int argc, char** argv)
{
if (argc != 5) {
printf("\nlibzt example client\n");
- printf("client \n");
+ printf("nonblockingclient \n");
exit(0);
}
char* storage_path = argv[1];
diff --git a/examples/c/nonblockingserver.c b/examples/c/nonblockingserver.c
index 81a33b93..8b5c3120 100644
--- a/examples/c/nonblockingserver.c
+++ b/examples/c/nonblockingserver.c
@@ -14,7 +14,7 @@ int main(int argc, char** argv)
{
if (argc != 5) {
printf("\nlibzt example server\n");
- printf("server \n");
+ printf("nonblockingserver \n");
exit(0);
}
char* storage_path = argv[1];
@@ -95,7 +95,7 @@ int main(int argc, char** argv)
// zts_bsd_accept(int fd, struct zts_sockaddr* addr, zts_socklen_t* addrlen)
char remote_ipstr[ZTS_INET6_ADDRSTRLEN] = { 0 };
- unsigned int port = 0;
+ unsigned short port = 0;
printf("Accepting on listening socket...\n");
if ((accfd = zts_accept(fd, remote_ipstr, ZTS_INET6_ADDRSTRLEN, &port)) < 0) {
printf("Error (fd=%d, ret=%d, zts_errno=%d). Exiting.\n", fd, err, zts_errno);
diff --git a/examples/c/server.c b/examples/c/server.c
index b3c606ca..e43a00f7 100644
--- a/examples/c/server.c
+++ b/examples/c/server.c
@@ -75,7 +75,7 @@ int main(int argc, char** argv)
// Can also use traditional: zts_bsd_socket(), zts_bsd_bind(), zts_bsd_listen(), zts_bsd_accept(), etc.
char remote_addr[ZTS_INET6_ADDRSTRLEN] = { 0 };
- int remote_port = 0;
+ unsigned short remote_port = 0;
int len = ZTS_INET6_ADDRSTRLEN;
if ((accfd = zts_tcp_server(local_addr, local_port, remote_addr, len, &remote_port)) < 0) {
printf("Error (fd=%d, zts_errno=%d). Exiting.\n", accfd, zts_errno);
diff --git a/examples/c/statistics.c b/examples/c/statistics.c
index 6fa59d2d..4f143062 100644
--- a/examples/c/statistics.c
+++ b/examples/c/statistics.c
@@ -14,7 +14,7 @@ int main(int argc, char** argv)
{
if (argc != 2) {
printf("\nUsage:\n");
- printf("pingable-node \n");
+ printf("statistics \n");
exit(0);
}
long long int net_id = strtoull(argv[1], NULL, 16); // At least 64 bits
diff --git a/examples/java/Example.java b/examples/java/Example.java
index 344c3dde..736496ea 100644
--- a/examples/java/Example.java
+++ b/examples/java/Example.java
@@ -5,7 +5,7 @@
import java.net.DatagramPacket;
import java.net.InetAddress;
-public class selftest {
+public class Example {
public static void main(String[] args)
{
if (args.length < 4 || args.length > 5) {
@@ -110,7 +110,7 @@ public static void main(String[] args)
/**
* (OPTIONAL) event handler
*/
-class MyZeroTierEventListener implements ZeroTierEventListener {
+class MyZeroTierEventListener implements com.zerotier.sockets.ZeroTierEventListener {
public void onZeroTierEvent(long id, int eventCode)
{
if (eventCode == ZeroTierNative.ZTS_EVENT_NODE_UP) {
diff --git a/examples/java/Makefile b/examples/java/Makefile
deleted file mode 100644
index 4424d0aa..00000000
--- a/examples/java/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-all:
- jar xf *.jar libzt.dylib
- javac -cp *.jar Example.java
-
-clean:
- rm -rf *.class
-
-superclean: clean
- rm -rf *.dylib *.so *.jar
diff --git a/examples/java/README.md b/examples/java/README.md
index 870f020b..40db2d89 100644
--- a/examples/java/README.md
+++ b/examples/java/README.md
@@ -1,11 +1,54 @@
# Java example
-Build or download the `libzt-${VERSION}.jar`, and copy it to this directory.
+## Build the JAR
+
+From the top-level `libzt` directory:
+
+```
+./build.sh host-jar
+```
+
+Should result in something like:
+
+```
+dist
+└── linux-x64-jar-release
+ └── pkg
+ └── libzt-1.8.10.jar
+```
+
+Copy the JAR to the working directory:
+
+*NOTE: If you've built multiple variants of the JAR such as debug/release or mac/linux you will need to specify their exact path in the following command. If not, you can use the wildcard form:*
+
+
+```
+cp -f dist/*/pkg/*.jar examples/java/libzt.jar
+```
+
+Navigate to the `examples/java` directory and extract the `libzt.so|dylib|dll` dynamic library from the JAR into the working directory:
+
+```
+jar xf *.jar libzt.dylib libzt.so libzt.dll
+```
+
+## Build the example app
+
+```
+javac -cp *.jar Example.java
+```
+
+## Run the example app
+
+```
+java -Djava.library.path=. -cp ".:libzt.jar" Example server id_path 0123456789abcdef 9997
+java -Djava.library.path=. -cp ".:libzt.jar" Example client id_path 0123456789abcdef ip.ip.ip.ip 9997
+```
+
+## Clean
```
-make
-java -cp ".:libzt-${VERSION}.jar" Example server id_path 0123456789abcdef 9997
-java -cp ".:libzt-${VERSION}.jar" Example client id_path 0123456789abcdef ip.ip.ip.ip 9997
+rm -rf *.dylib *.so *.jar *.dll *.class
```
## Links
diff --git a/ext/ZeroTierOne b/ext/ZeroTierOne
index 7e46c835..c53c6bd9 160000
--- a/ext/ZeroTierOne
+++ b/ext/ZeroTierOne
@@ -1 +1 @@
-Subproject commit 7e46c8359231b4aa55c5d739462c4e5682d35755
+Subproject commit c53c6bd9c320ea839c525972d8afba448a58606e
diff --git a/include/ZeroTierSockets.h b/include/ZeroTierSockets.h
index 98058e9b..ba9732ae 100644
--- a/include/ZeroTierSockets.h
+++ b/include/ZeroTierSockets.h
@@ -338,7 +338,7 @@ typedef enum {
/**
* Maximum number of direct network paths to a given peer
*/
-#define ZTS_MAX_PEER_NETWORK_PATHS 16
+#define ZTS_MAX_PEER_NETWORK_PATHS 64
/**
* Maximum number of multicast groups a device / network interface can be
@@ -437,6 +437,12 @@ typedef void (*CppCallback)(void* msg);
/** 255.255.255.255 */
#define ZTS_INADDR_BROADCAST ZTS_IPADDR_BROADCAST
+
+#define ZTS_IN6ADDR_ANY_INIT {{{0,0,0,0}}}
+
+
+
+
// Socket protocol types
#define ZTS_SOCK_STREAM 0x0001
#define ZTS_SOCK_DGRAM 0x0002
@@ -503,6 +509,8 @@ struct zts_in6_addr {
//#define s6_addr un.u8_addr
};
+const struct zts_in6_addr zts_in6addr_any = ZTS_IN6ADDR_ANY_INIT;
+
/**
* Address structure to specify an IPv4 endpoint
*/
@@ -1023,7 +1031,7 @@ typedef struct {
#ifndef ZTS_DISABLE_CENTRAL_API
#define ZTS_CENTRAL_DEFAULT_URL "https://my.zerotier.com"
-#define ZTS_CENRTAL_MAX_URL_LEN 128
+#define ZTS_CENTRAL_MAX_URL_LEN 128
#define ZTS_CENTRAL_TOKEN_LEN 32
#define ZTS_CENTRAL_RESP_BUF_DEFAULT_SZ (128 * 1024)
@@ -1274,6 +1282,24 @@ int zts_init_set_event_handler(jobject obj_ref, jmethodID id);
ZTS_API int ZTCALL zts_init_set_event_handler(void (*callback)(void*));
#endif
+/**
+ * @brief Set TCP relay for ZeroTier to use instead of P2P UDP
+ *
+ * @param tcp_relay_addr IP address of TCP relay
+ * @param tcp_relay_port Port of TCP relay
+ */
+ZTS_API int ZTCALL zts_init_set_tcp_relay(const char* tcp_relay_addr, unsigned short tcp_relay_port);
+
+/**
+ * @brief Allow TCP relay for ZeroTier to use instead of P2P UDP
+ */
+ZTS_API int ZTCALL zts_init_allow_tcp_relay(int enabled);
+
+/**
+ * @brief Force TCP relay for ZeroTier to use instead of P2P UDP
+ */
+ZTS_API int ZTCALL zts_init_force_tcp_relay(int enabled);
+
/**
* @brief Blacklist an interface prefix (or name). This prevents ZeroTier from
* sending traffic over matching interfaces. This is an initialization function that can
@@ -1297,6 +1323,23 @@ ZTS_API int ZTCALL zts_init_blacklist_if(const char* prefix, unsigned int len);
*/
ZTS_API int ZTCALL zts_init_set_roots(const void* roots_data, unsigned int len);
+/**
+ * @brief Enable or disable low-bandwidth mode. This is an initialization function that can
+ * only be called before `zts_node_start()`.
+ *
+ * Low-bandwidth mode reduces the ambient traffic that ZeroTier sends
+ * at the expense of responsiveness to network changes. It does not reduce your
+ * established connection speeds. It is an adjustment to multiple internal
+ * timers that results in fewer keepalive probes and network configuration
+ * requests being sent. This is a good option if your underlying physical network
+ * doesn't change much.
+ *
+ * @param enabled Whether low-bandwidth mode is enabled or not (default: false)
+ * @return `ZTS_ERR_OK` if successful, `ZTS_ERR_SERVICE` if the node
+ * experiences a problem.
+ */
+ZTS_API int ZTCALL zts_init_set_low_bandwidth_mode(int enabled);
+
/**
* @brief Set the port to which the node should bind. This is an initialization function that can
* only be called before `zts_node_start()`.
diff --git a/pkg/android/app/build.gradle b/pkg/android/app/build.gradle
index ca413359..06c81eb6 100644
--- a/pkg/android/app/build.gradle
+++ b/pkg/android/app/build.gradle
@@ -1,16 +1,18 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 28
+ compileSdkVersion 33
defaultConfig {
- minSdkVersion 14
- targetSdkVersion 23
+ minSdkVersion 21
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
+ version '3.22.1'
+ arguments "-DZTS_ENABLE_JAVA=ON"
}
}
ndk {
@@ -28,15 +30,34 @@ android {
externalNativeBuild {
cmake {
path "../../../CMakeLists.txt"
+ version '3.22.1'
+ }
+ }
+
+ ndkVersion '25.1.8937393'
+
+ namespace 'com.example.zerotier'
+
+ sourceSets {
+ main {
+ java {
+ srcDir 'src/main/java'
+ srcDir '../../../src/bindings/java'
+ }
+ }
+ }
+
+ android.libraryVariants.all { variant ->
+ variant.outputs.all { file ->
+ file.outputFileName = "libzt-${variant.buildType.name}.aar"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
- implementation 'com.android.support.constraint:constraint-layout:1.1.2'
- testImplementation 'junit:junit:4.12'
+ implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
\ No newline at end of file
diff --git a/pkg/android/app/src/main/AndroidManifest.xml b/pkg/android/app/src/main/AndroidManifest.xml
index 53854075..0465e5bb 100644
--- a/pkg/android/app/src/main/AndroidManifest.xml
+++ b/pkg/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
-
+
diff --git a/pkg/android/app/src/main/java/com/example/zerotier/MainActivity.java b/pkg/android/app/src/main/java/com/example/zerotier/MainActivity.java
deleted file mode 100644
index 8b137891..00000000
--- a/pkg/android/app/src/main/java/com/example/zerotier/MainActivity.java
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/pkg/android/build.gradle b/pkg/android/build.gradle
index 43c07085..186f8f44 100644
--- a/pkg/android/build.gradle
+++ b/pkg/android/build.gradle
@@ -4,10 +4,10 @@ buildscript {
repositories {
google()
- jcenter()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.1.3'
+ classpath 'com.android.tools.build:gradle:7.3.1'
// NOTE: Do not place your application dependencies here; they belong
@@ -18,7 +18,7 @@ buildscript {
allprojects {
repositories {
google()
- jcenter()
+ mavenCentral()
}
}
diff --git a/pkg/android/gradle/wrapper/gradle-wrapper.properties b/pkg/android/gradle/wrapper/gradle-wrapper.properties
index 9fe8d05d..567ad65a 100644
--- a/pkg/android/gradle/wrapper/gradle-wrapper.properties
+++ b/pkg/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
diff --git a/pkg/crate/libzt/Cargo.lock b/pkg/crate/libzt/Cargo.lock
index 854a2901..113d5356 100644
--- a/pkg/crate/libzt/Cargo.lock
+++ b/pkg/crate/libzt/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "aho-corasick"
version = "0.7.18"
@@ -18,17 +20,78 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "anstream"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is-terminal",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.18",
"libc",
"winapi",
]
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
[[package]]
name = "bindgen"
version = "0.58.1"
@@ -38,8 +101,8 @@ dependencies = [
"bitflags",
"cexpr",
"clang-sys",
- "clap",
- "env_logger",
+ "clap 2.33.3",
+ "env_logger 0.8.3",
"lazy_static",
"lazycell",
"log",
@@ -99,12 +162,63 @@ dependencies = [
"ansi_term",
"atty",
"bitflags",
- "strsim",
+ "strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
]
+[[package]]
+name = "clap"
+version = "4.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "401a4694d2bf92537b6867d94de48c4842089645fdcdf6c71865b175d836e9c2"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+ "once_cell",
+]
+
+[[package]]
+name = "clap-num"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488557e97528174edaa2ee268b23a809e0c598213a4bbcb4f34575a46fda147e"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "bitflags",
+ "clap_lex",
+ "strsim 0.10.0",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
+
[[package]]
name = "cmake"
version = "0.1.45"
@@ -114,6 +228,33 @@ dependencies = [
"cc",
]
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "dirs"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
+dependencies = [
+ "libc",
+ "option-ext",
+ "redox_users",
+ "windows-sys",
+]
+
[[package]]
name = "env_logger"
version = "0.8.3"
@@ -127,12 +268,63 @@ dependencies = [
"termcolor",
]
+[[package]]
+name = "env_logger"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
+dependencies = [
+ "humantime",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
[[package]]
name = "hermit-abi"
version = "0.1.18"
@@ -142,12 +334,41 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys",
+]
+
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -162,9 +383,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.95"
+version = "0.2.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
+checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81"
[[package]]
name = "libloading"
@@ -180,20 +401,40 @@ dependencies = [
name = "libzt"
version = "0.1.2"
dependencies = [
+ "anyhow",
"bindgen",
+ "clap 4.3.2",
+ "clap-num",
"cmake",
+ "dirs",
+ "env_logger 0.10.0",
"libc",
+ "log",
+ "parking_lot",
]
[[package]]
-name = "log"
-version = "0.4.14"
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "lock_api"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
- "cfg-if",
+ "autocfg",
+ "scopeguard",
]
+[[package]]
+name = "log"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+
[[package]]
name = "memchr"
version = "2.4.0"
@@ -210,6 +451,50 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "option-ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.3.5",
+ "smallvec",
+ "windows-targets",
+]
+
[[package]]
name = "peeking_take_while"
version = "0.1.2"
@@ -218,27 +503,56 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro2"
-version = "1.0.27"
+version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
+checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
dependencies = [
- "unicode-xid",
+ "unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.9"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [
"proc-macro2",
]
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall 0.2.16",
+ "thiserror",
+]
+
[[package]]
name = "regex"
-version = "1.5.4"
+version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
dependencies = [
"aho-corasick",
"memchr",
@@ -247,9 +561,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.25"
+version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "rustc-hash"
@@ -257,18 +571,61 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+[[package]]
+name = "rustix"
+version = "0.37.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
[[package]]
name = "shlex"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "termcolor"
version = "1.1.2"
@@ -287,6 +644,32 @@ dependencies = [
"unicode-width",
]
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+
[[package]]
name = "unicode-width"
version = "0.1.8"
@@ -294,10 +677,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
-name = "unicode-xid"
-version = "0.2.2"
+name = "utf8parse"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "vec_map"
@@ -311,6 +694,12 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
[[package]]
name = "which"
version = "3.1.1"
@@ -350,3 +739,69 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/pkg/crate/libzt/Cargo.toml b/pkg/crate/libzt/Cargo.toml
index b1e8207d..b9e9a89e 100644
--- a/pkg/crate/libzt/Cargo.toml
+++ b/pkg/crate/libzt/Cargo.toml
@@ -13,6 +13,15 @@ keywords = ["zerotier", "p2p", "vpn", "socket", "network"]
categories = ["network-programming", "cryptography"]
[dependencies]
+log = "0.4.18"
+dirs = "5.0.1"
+
+[dev-dependencies]
+anyhow = "1.0"
+clap = { version = "4.3.0", features = ["derive"] }
+clap-num = "1.0"
+env_logger = "0.10"
+parking_lot = { version = "0.12", features = ["send_guard"] }
[build-dependencies]
bindgen = "0.58"
@@ -22,8 +31,3 @@ cmake = "0.1"
[lib]
name = "libzt"
path = "src/lib.rs"
-
-[[example]]
-name = "libzt-test-app"
-path = "src/examples/libzt-test-app.rs"
-
diff --git a/pkg/crate/libzt/build.rs b/pkg/crate/libzt/build.rs
index aabcc1b9..7521feb1 100644
--- a/pkg/crate/libzt/build.rs
+++ b/pkg/crate/libzt/build.rs
@@ -1,10 +1,15 @@
extern crate bindgen;
use std::env;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
fn main() {
- println!("cargo:rustc-link-lib=zt");
+ let dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+ let lib_dir = Path::new(&dir).join("../../../dist/native/lib").canonicalize().unwrap();
+
+ println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy());
+ println!("cargo:rustc-link-lib=static=zt");
+ println!("cargo:rustc-link-lib=dylib=c++");
let bindings = bindgen::Builder::default()
.header("src/include/ZeroTierSockets.h")
diff --git a/pkg/crate/libzt/examples/forwarding.rs b/pkg/crate/libzt/examples/forwarding.rs
new file mode 100644
index 00000000..217486af
--- /dev/null
+++ b/pkg/crate/libzt/examples/forwarding.rs
@@ -0,0 +1,202 @@
+use std::{
+ error::Error,
+ fmt, fs,
+ io::{self, Read, Write},
+ net::{self, Shutdown},
+ sync::Arc,
+ thread,
+ time::Duration,
+};
+
+use anyhow::Result;
+use clap::Parser;
+use parking_lot::FairMutex;
+
+use libzt::{node::ZeroTierNode, tcp as zt_tcp};
+
+const BUF_SIZE: usize = 1024;
+const SOCKET_IO_TIMEOUT: Duration = Duration::new(1, 0);
+const DEFAULT_LISTEN_PORT: u16 = 9080;
+
+#[derive(Debug)]
+enum ForwardingError {
+ BindFailed(String),
+ ConnectFailed(String),
+ CopyFailed(String),
+}
+
+impl Error for ForwardingError {}
+
+#[derive(Parser, Debug)]
+struct Args {
+ #[arg(short, long, value_parser=clap_num::maybe_hex::)]
+ network_id: u64,
+ #[arg(short, long)]
+ connect: String,
+ #[arg(short, long, default_value_t = DEFAULT_LISTEN_PORT)]
+ port: u16,
+}
+
+fn setup_node(network_id: u64) -> Result {
+ log::info!("joining network: {:#x}", network_id);
+
+ let mut storage_path = dirs::data_local_dir().unwrap();
+ storage_path.push("libzt");
+ storage_path.push("forwarding");
+
+ fs::create_dir_all(&storage_path)?;
+
+ log::debug!(
+ "initializing from state dir: {}",
+ storage_path.to_string_lossy()
+ );
+
+ let node = ZeroTierNode {};
+
+ node.init_set_port(0);
+ node.init_from_storage(&storage_path.join("libzt-examples").to_string_lossy());
+ node.start();
+
+ log::debug!("waiting for node to come online...");
+ while !node.is_online() {
+ node.delay(250);
+ }
+
+ log::info!("node id: {:#x}", node.id());
+
+ node.net_join(network_id);
+
+ log::debug!("waiting for transport...");
+ while !node.net_transport_is_ready(network_id) {
+ node.delay(250);
+ }
+
+ let addr = node.addr_get(network_id).unwrap();
+ log::info!("got ZT addr: {}", addr.to_string());
+
+ Ok(node)
+}
+
+impl fmt::Display for ForwardingError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+fn main() -> Result<()> {
+ env_logger::init();
+
+ let Args {
+ connect: remote_addr,
+ network_id,
+ port: local_port,
+ } = Args::parse();
+
+ let _node = setup_node(network_id)?;
+
+ let local_addr = format!("localhost:{}", local_port);
+ let listener = net::TcpListener::bind(&local_addr)
+ .map_err(|_| ForwardingError::BindFailed(local_addr.clone()))?;
+
+ log::info!("listener bound to {}", local_addr);
+
+ for conn in listener.incoming() {
+ log::debug!("incoming: {:?}", conn);
+
+ if let Ok(client) = conn {
+ client.set_read_timeout(Some(SOCKET_IO_TIMEOUT))?;
+ client.set_write_timeout(Some(SOCKET_IO_TIMEOUT))?;
+
+ let client = Arc::new(FairMutex::new(client));
+
+ log::info!("connecting to remote: {}", remote_addr);
+
+ let remote = zt_tcp::TcpStream::connect(&remote_addr)
+ .map_err(|_| ForwardingError::ConnectFailed(remote_addr.clone()))?;
+
+ remote.set_read_timeout(Some(SOCKET_IO_TIMEOUT))?;
+ remote.set_write_timeout(Some(SOCKET_IO_TIMEOUT))?;
+
+ let remote = Arc::new(FairMutex::new(remote));
+
+ log::info!("connected");
+
+ let client_ = client.clone();
+ let remote_ = remote.clone();
+
+ thread::spawn(move || {
+ let mut buf = [0u8; BUF_SIZE];
+ let mut running = true;
+
+ while running {
+ let mut client = client.lock();
+ let mut remote = remote.lock();
+
+ match client.read(&mut buf) {
+ Ok(n) if n > 0 => {
+ log::debug!("got {} bytes from remote", n);
+ running = remote
+ .write(&buf)
+ .map(|_| {
+ remote.flush().unwrap();
+ true
+ })
+ .unwrap_or_else(|e| {
+ let msg = format!("failed to write to remote: {:?}", e);
+ log::error!("{}", msg);
+ false
+ });
+ }
+ Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
+ thread::sleep(Duration::new(0, 5000));
+ }
+ other => {
+ log::debug!("closing client connection: {:?}", other);
+ let _ = client.shutdown(Shutdown::Read);
+ let _ = remote.shutdown(Shutdown::Write);
+ break;
+ }
+ }
+
+ buf.fill(0);
+ }
+ });
+ thread::spawn(move || {
+ let mut buf = [0u8; BUF_SIZE];
+ let mut running = true;
+
+ while running {
+ let mut client = client_.lock();
+ let mut remote = remote_.lock();
+
+ match remote.read(&mut buf) {
+ Ok(n) if n > 0 => {
+ log::debug!("got {} bytes from remote", n);
+ running = client
+ .write(&buf)
+ .map(|_| {
+ client.flush().unwrap();
+ true
+ })
+ .unwrap_or_else(|e| {
+ let msg = format!("failed to write to remote: {:?}", e);
+ log::error!("{}", msg);
+ false
+ });
+ }
+ other => {
+ log::debug!("closing remote connection: {:?}", other);
+ let _ = remote.shutdown(Shutdown::Read);
+ let _ = client.shutdown(Shutdown::Write);
+ break;
+ }
+ }
+
+ buf.fill(0);
+ }
+ });
+ }
+ }
+
+ Ok(())
+}
diff --git a/pkg/crate/libzt/src/examples/libzt-test-app.rs b/pkg/crate/libzt/examples/libzt-test-app.rs
similarity index 100%
rename from pkg/crate/libzt/src/examples/libzt-test-app.rs
rename to pkg/crate/libzt/examples/libzt-test-app.rs
diff --git a/pkg/crate/libzt/src/include/ZeroTierSockets.h b/pkg/crate/libzt/src/include/ZeroTierSockets.h
index fe01d43f..7d306e62 100644
--- a/pkg/crate/libzt/src/include/ZeroTierSockets.h
+++ b/pkg/crate/libzt/src/include/ZeroTierSockets.h
@@ -338,7 +338,7 @@ typedef enum {
/**
* Maximum number of direct network paths to a given peer
*/
-#define ZTS_MAX_PEER_NETWORK_PATHS 16
+#define ZTS_MAX_PEER_NETWORK_PATHS 64
/**
* Maximum number of multicast groups a device / network interface can be
diff --git a/pkg/pypi/build.py b/pkg/pypi/build.py
index 3ab8c575..557a648d 100644
--- a/pkg/pypi/build.py
+++ b/pkg/pypi/build.py
@@ -26,6 +26,7 @@
os.path.join(ROOT_DIR, "ext/lwip-contrib/ports/unix/port/include"),
os.path.join(ROOT_DIR, "ext/ZeroTierOne/include"),
os.path.join(ROOT_DIR, "ext/ZeroTierOne"),
+ os.path.join(ROOT_DIR, "ext/ZeroTierOne/ext"),
os.path.join(ROOT_DIR, "ext/ZeroTierOne/node"),
os.path.join(ROOT_DIR, "ext/ZeroTierOne/service"),
os.path.join(ROOT_DIR, "ext/ZeroTierOne/osdep"),
diff --git a/src/Central.cpp b/src/Central.cpp
index 247d0b2d..e6ea8b07 100644
--- a/src/Central.cpp
+++ b/src/Central.cpp
@@ -25,7 +25,7 @@
#define REQ_LEN 64
-char api_url[ZTS_CENRTAL_MAX_URL_LEN];
+char api_url[ZTS_CENTRAL_MAX_URL_LEN];
char api_token[ZTS_CENTRAL_TOKEN_LEN + 1];
char* _resp_buf;
@@ -97,12 +97,12 @@ int zts_central_init(const char* url_str, const char* token_str, char* resp_buf,
// Initialize all curl internal submodules
curl_global_init(CURL_GLOBAL_ALL);
- int url_len = strnlen(url_str, ZTS_CENRTAL_MAX_URL_LEN);
- if (url_len < 3 || url_len > ZTS_CENRTAL_MAX_URL_LEN) {
+ int url_len = strnlen(url_str, ZTS_CENTRAL_MAX_URL_LEN);
+ if (url_len < 3 || url_len > ZTS_CENTRAL_MAX_URL_LEN) {
return ZTS_ERR_ARG;
}
else {
- memset(api_url, 0, ZTS_CENRTAL_MAX_URL_LEN);
+ memset(api_url, 0, ZTS_CENTRAL_MAX_URL_LEN);
strncpy(api_url, url_str, url_len);
}
int token_len = strnlen(token_str, ZTS_CENTRAL_TOKEN_LEN);
@@ -146,19 +146,19 @@ int central_req(
return ZTS_ERR_SERVICE;
}
zts_central_clear_resp_buf();
- int central_strlen = strnlen(central_str, ZTS_CENRTAL_MAX_URL_LEN);
- int api_route_strlen = strnlen(api_route_str, ZTS_CENRTAL_MAX_URL_LEN);
+ int central_strlen = strnlen(central_str, ZTS_CENTRAL_MAX_URL_LEN);
+ int api_route_strlen = strnlen(api_route_str, ZTS_CENTRAL_MAX_URL_LEN);
int token_strlen = strnlen(token_str, ZTS_CENTRAL_TOKEN_LEN);
int url_len = central_strlen + api_route_strlen;
if (token_strlen > ZTS_CENTRAL_TOKEN_LEN) {
return ZTS_ERR_ARG;
}
- if (url_len > ZTS_CENRTAL_MAX_URL_LEN) {
+ if (url_len > ZTS_CENTRAL_MAX_URL_LEN) {
return ZTS_ERR_ARG;
}
- char req_url[ZTS_CENRTAL_MAX_URL_LEN] = { 0 };
- strncpy(req_url, central_str, ZTS_CENRTAL_MAX_URL_LEN);
- strncat(req_url, api_route_str, ZTS_CENRTAL_MAX_URL_LEN);
+ char req_url[ZTS_CENTRAL_MAX_URL_LEN] = { 0 };
+ strncpy(req_url, central_str, ZTS_CENTRAL_MAX_URL_LEN);
+ strncat(req_url, api_route_str, ZTS_CENTRAL_MAX_URL_LEN);
CURL* curl;
CURLcode res;
diff --git a/src/Controls.cpp b/src/Controls.cpp
index 536868f1..8aa0a722 100644
--- a/src/Controls.cpp
+++ b/src/Controls.cpp
@@ -121,6 +121,27 @@ int zts_init_set_event_handler(PythonDirectorCallbackClass* callback)
return ZTS_ERR_OK;
}
+int zts_init_set_tcp_relay(const char* tcp_relay_addr, unsigned short tcp_relay_port)
+{
+ ACQUIRE_SERVICE_OFFLINE();
+ zts_service->setTcpRelayAddress(tcp_relay_addr, tcp_relay_port);
+ return ZTS_ERR_OK;
+}
+
+int zts_init_allow_tcp_relay(int enabled)
+{
+ ACQUIRE_SERVICE_OFFLINE();
+ zts_service->allowTcpRelay(enabled);
+ return ZTS_ERR_OK;
+}
+
+int zts_init_force_tcp_relay(int enabled)
+{
+ ACQUIRE_SERVICE_OFFLINE();
+ zts_service->forceTcpRelay(enabled);
+ return ZTS_ERR_OK;
+}
+
int zts_init_blacklist_if(const char* prefix, unsigned int len)
{
ACQUIRE_SERVICE_OFFLINE();
@@ -133,6 +154,12 @@ int zts_init_set_roots(const void* roots_data, unsigned int len)
return zts_service->setRoots(roots_data, len);
}
+int zts_init_set_low_bandwidth_mode(int enabled)
+{
+ ACQUIRE_SERVICE_OFFLINE();
+ return zts_service->setLowBandwidthMode(enabled);
+}
+
int zts_init_set_port(unsigned short port)
{
ACQUIRE_SERVICE_OFFLINE();
diff --git a/src/Events.cpp b/src/Events.cpp
index 20760388..f5497820 100644
--- a/src/Events.cpp
+++ b/src/Events.cpp
@@ -35,14 +35,14 @@ void PythonDirectorCallbackClass::on_zerotier_event(zts_event_msg_t* msg)
}
#endif
-#define ZTS_NODE_EVENT(code) code >= ZTS_EVENT_NODE_UP&& code <= ZTS_EVENT_NODE_FATAL_ERROR
-#define ZTS_NETWORK_EVENT(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND&& code <= ZTS_EVENT_NETWORK_UPDATE
-#define ZTS_STACK_EVENT(code) code >= ZTS_EVENT_STACK_UP&& code <= ZTS_EVENT_STACK_DOWN
-#define ZTS_NETIF_EVENT(code) code >= ZTS_EVENT_NETIF_UP&& code <= ZTS_EVENT_NETIF_LINK_DOWN
-#define ZTS_PEER_EVENT(code) code >= ZTS_EVENT_PEER_DIRECT&& code <= ZTS_EVENT_PEER_PATH_DEAD
-#define ZTS_ROUTE_EVENT(code) code >= ZTS_EVENT_ROUTE_ADDED&& code <= ZTS_EVENT_ROUTE_REMOVED
-#define ZTS_ADDR_EVENT(code) code >= ZTS_EVENT_ADDR_ADDED_IP4&& code <= ZTS_EVENT_ADDR_REMOVED_IP6
-#define ZTS_STORE_EVENT(code) code >= ZTS_EVENT_STORE_IDENTITY_SECRET&& code <= ZTS_EVENT_STORE_NETWORK
+#define ZTS_NODE_EVENT(code) code >= ZTS_EVENT_NODE_UP && code <= ZTS_EVENT_NODE_FATAL_ERROR
+#define ZTS_NETWORK_EVENT(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_UPDATE
+#define ZTS_STACK_EVENT(code) code >= ZTS_EVENT_STACK_UP && code <= ZTS_EVENT_STACK_DOWN
+#define ZTS_NETIF_EVENT(code) code >= ZTS_EVENT_NETIF_UP && code <= ZTS_EVENT_NETIF_LINK_DOWN
+#define ZTS_PEER_EVENT(code) code >= ZTS_EVENT_PEER_DIRECT && code <= ZTS_EVENT_PEER_PATH_DEAD
+#define ZTS_ROUTE_EVENT(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED
+#define ZTS_ADDR_EVENT(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6
+#define ZTS_STORE_EVENT(code) code >= ZTS_EVENT_STORE_IDENTITY_SECRET && code <= ZTS_EVENT_STORE_NETWORK
namespace ZeroTier {
@@ -93,11 +93,18 @@ void Events::run()
}
}
-void Events::enqueue(unsigned int event_code, const void* arg, int len)
+bool Events::enqueue(unsigned int event_code, const void* arg, int len)
{
if (! _enabled) {
- return;
+ return false;
}
+ if (_callbackMsgQueue.size_approx() > 1024) {
+ /* Rate-limit number of events. This value should only grow if the
+ user application isn't returning from the event handler in a timely manner.
+ For most applications it should hover around 1 to 2 */
+ return false;
+ }
+
zts_event_msg_t* msg = new zts_event_msg_t();
msg->event_code = event_code;
@@ -132,15 +139,12 @@ void Events::enqueue(unsigned int event_code, const void* arg, int len)
msg->cache = (void*)arg;
msg->len = len;
}
- if (msg && _callbackMsgQueue.size_approx() > 1024) {
- /* Rate-limit number of events. This value should only grow if the
- user application isn't returning from the event handler in a timely manner.
- For most applications it should hover around 1 to 2 */
- destroy(msg);
- }
- else {
- _callbackMsgQueue.enqueue(msg);
- }
+
+ //
+ // ownership of arg is now transferred
+ //
+ _callbackMsgQueue.enqueue(msg);
+ return true;
}
void Events::destroy(zts_event_msg_t* msg)
@@ -182,11 +186,10 @@ void Events::sendToUser(zts_event_msg_t* msg)
if (javaCbMethodId) {
JNIEnv* env;
#if defined(__ANDROID__)
- jint rs = jvm->AttachCurrentThread(&env, NULL);
+ jvm->AttachCurrentThread(&env, NULL);
#else
- jint rs = jvm->AttachCurrentThread((void**)&env, NULL);
+ jvm->AttachCurrentThread((void**)&env, NULL);
#endif
- uint64_t arg = 0;
uint64_t id = 0;
if (ZTS_NODE_EVENT(msg->event_code)) {
id = msg->node ? msg->node->node_id : 0;
@@ -198,6 +201,8 @@ void Events::sendToUser(zts_event_msg_t* msg)
id = msg->peer ? msg->peer->peer_id : 0;
}
env->CallVoidMethod(javaCbObjRef, javaCbMethodId, id, msg->event_code);
+
+ jvm->DetachCurrentThread();
}
#endif // ZTS_ENABLE_JAVA
#ifdef ZTS_ENABLE_PINVOKE
diff --git a/src/Events.hpp b/src/Events.hpp
index da911fc7..9064d69b 100644
--- a/src/Events.hpp
+++ b/src/Events.hpp
@@ -28,7 +28,7 @@
/* Macro substitutions to standardize state checking of service, node, callbacks, and TCP/IP
* stack. These are used only for control functions that are called at a low frequency. All higher
- * frequency socket calls use a unguarded state flags */
+ * frequency socket calls use unguarded state flags */
// Lock service and check that it is running
#define ACQUIRE_SERVICE(x) \
@@ -115,8 +115,12 @@ class Events {
/**
* Enqueue an event to be sent to the user application
+ *
+ * Returns true if arg was enqueued.
+ * If enqueued, then ownership of arg has been transferred.
+ * If NOT enqueued, then ownership of arg has NOT been transferred.
*/
- void enqueue(unsigned int event_code, const void* arg, int len = 0);
+ bool enqueue(unsigned int event_code, const void* arg, int len = 0);
/**
* Send callback message to user application
diff --git a/src/NodeService.cpp b/src/NodeService.cpp
index 15b18ad1..501bc13c 100644
--- a/src/NodeService.cpp
+++ b/src/NodeService.cpp
@@ -17,6 +17,8 @@
* ZeroTier Node Service
*/
+#include
+
#include "NodeService.hpp"
#include "../version.h"
@@ -28,14 +30,16 @@
#include "VirtualTap.hpp"
#if defined(__WINDOWS__)
-#include
-#include
-#include
#include
#include
+#include
+#include
+#include
#define stat _stat
#endif
+#define ZT_TCP_FALLBACK_RELAY "204.80.128.1/443"
+
namespace ZeroTier {
static int SnodeVirtualNetworkConfigFunction(
@@ -173,6 +177,11 @@ NodeService::NodeService()
, _randomPortRangeEnd(0)
, _udpPortPickerCounter(0)
, _lastDirectReceiveFromGlobal(0)
+ , _fallbackRelayAddress(ZT_TCP_FALLBACK_RELAY)
+ , _allowTcpRelay(true)
+ , _forceTcpRelay(false)
+ , _lastSendToGlobalV4(0)
+ , _tcpFallbackTunnel((TcpConnection*)0)
, _lastRestart(0)
, _nextBackgroundTaskDeadline(0)
, _run(false)
@@ -286,7 +295,8 @@ NodeService::ReasonForTermination NodeService::run()
if (_allowSecondaryPort) {
if (_secondaryPort) {
_ports[1] = _secondaryPort;
- } else {
+ }
+ else {
_ports[1] = _getRandomPort(minPort, maxPort);
}
}
@@ -301,9 +311,10 @@ NodeService::ReasonForTermination NodeService::run()
if (_ports[1]) {
if (_tertiaryPort) {
_ports[2] = _tertiaryPort;
- } else {
+ }
+ else {
_ports[2] = minPort + (_ports[0] % 40000);
- for(int i=0;;++i) {
+ for (int i = 0;; ++i) {
if (i > 1000) {
_ports[2] = 0;
break;
@@ -398,7 +409,10 @@ NodeService::ReasonForTermination NodeService::run()
p[pc++] = _ports[i];
}
}
- _binder.refresh(_phy, p, pc, explicitBind, *this);
+ if (! _forceTcpRelay) {
+ // Only bother binding UDP ports if we aren't forcing TCP-relay mode
+ _binder.refresh(_phy, p, pc, explicitBind, *this);
+ }
}
// Generate callback messages for user application
@@ -411,6 +425,12 @@ NodeService::ReasonForTermination NodeService::run()
dl = _nextBackgroundTaskDeadline;
}
+ // Close TCP fallback tunnel if we have direct UDP
+ if (! _forceTcpRelay && (_tcpFallbackTunnel)
+ && ((now - _lastDirectReceiveFromGlobal) < (ZT_TCP_FALLBACK_AFTER / 2))) {
+ _phy.close(_tcpFallbackTunnel->sock);
+ }
+
// Sync multicast group memberships
if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) {
lastTapMulticastGroupCheck = now;
@@ -616,6 +636,9 @@ void NodeService::phyOnDatagram(
void* data,
unsigned long len)
{
+ if (_forceTcpRelay) {
+ return;
+ }
ZTS_UNUSED_ARG(uptr);
ZTS_UNUSED_ARG(localAddr);
if ((len >= 16) && (reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL))
@@ -639,6 +662,189 @@ void NodeService::phyOnDatagram(
}
}
+void NodeService::phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
+{
+ if (! success) {
+ phyOnTcpClose(sock, uptr);
+ return;
+ }
+
+ TcpConnection* const tc = reinterpret_cast(*uptr);
+ if (! tc) { // sanity check
+ _phy.close(sock, true);
+ return;
+ }
+ tc->sock = sock;
+
+ if (tc->type == TcpConnection::TCP_TUNNEL_OUTGOING) {
+ if (_tcpFallbackTunnel)
+ _phy.close(_tcpFallbackTunnel->sock);
+ _tcpFallbackTunnel = tc;
+ _phy.streamSend(sock, ZT_TCP_TUNNEL_HELLO, sizeof(ZT_TCP_TUNNEL_HELLO));
+ }
+ else {
+ _phy.close(sock, true);
+ }
+}
+
+void NodeService::phyOnTcpClose(PhySocket* sock, void** uptr)
+{
+ TcpConnection* tc = (TcpConnection*)*uptr;
+ if (tc) {
+ if (tc == _tcpFallbackTunnel) {
+ _tcpFallbackTunnel = (TcpConnection*)0;
+ }
+ {
+ Mutex::Lock _l(_tcpConnections_m);
+ _tcpConnections.erase(
+ std::remove(_tcpConnections.begin(), _tcpConnections.end(), tc),
+ _tcpConnections.end());
+ }
+ delete tc;
+ }
+}
+
+void NodeService::phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
+{
+ try {
+ if (! len) {
+ return; // sanity check, should never happen
+ }
+ TcpConnection* tc = reinterpret_cast(*uptr);
+ tc->lastReceive = OSUtils::now();
+ switch (tc->type) {
+ case TcpConnection::TCP_UNCATEGORIZED_INCOMING:
+ case TcpConnection::TCP_HTTP_INCOMING:
+ case TcpConnection::TCP_HTTP_OUTGOING:
+ break;
+ case TcpConnection::TCP_TUNNEL_OUTGOING:
+ tc->readq.append((const char*)data, len);
+ while (tc->readq.length() >= 5) {
+ const char* data = tc->readq.data();
+ const unsigned long mlen =
+ (((((unsigned long)data[3]) & 0xff) << 8) | (((unsigned long)data[4]) & 0xff));
+ if (tc->readq.length() >= (mlen + 5)) {
+ InetAddress from;
+
+ unsigned long plen = mlen; // payload length, modified if there's an IP header
+ data += 5; // skip forward past pseudo-TLS junk and mlen
+ if (plen == 4) {
+ // Hello message, which isn't sent by proxy and would be ignored by client
+ }
+ else if (plen) {
+ // Messages should contain IPv4 or IPv6 source IP address data
+ switch (data[0]) {
+ case 4: // IPv4
+ if (plen >= 7) {
+ from.set(
+ (const void*)(data + 1),
+ 4,
+ ((((unsigned int)data[5]) & 0xff) << 8) | (((unsigned int)data[6]) & 0xff));
+ data += 7; // type + 4 byte IP + 2 byte port
+ plen -= 7;
+ }
+ else {
+ _phy.close(sock);
+ return;
+ }
+ break;
+ case 6: // IPv6
+ if (plen >= 19) {
+ from.set(
+ (const void*)(data + 1),
+ 16,
+ ((((unsigned int)data[17]) & 0xff) << 8)
+ | (((unsigned int)data[18]) & 0xff));
+ data += 19; // type + 16 byte IP + 2 byte port
+ plen -= 19;
+ }
+ else {
+ _phy.close(sock);
+ return;
+ }
+ break;
+ case 0: // none/omitted
+ ++data;
+ --plen;
+ break;
+ default: // invalid address type
+ _phy.close(sock);
+ return;
+ }
+
+ if (from) {
+ InetAddress fakeTcpLocalInterfaceAddress((uint32_t)0xffffffff, 0xffff);
+ const ZT_ResultCode rc = _node->processWirePacket(
+ (void*)0,
+ OSUtils::now(),
+ -1,
+ reinterpret_cast(&from),
+ data,
+ plen,
+ &_nextBackgroundTaskDeadline);
+ if (ZT_ResultCode_isFatal(rc)) {
+ char tmp[256];
+ OSUtils::ztsnprintf(
+ tmp,
+ sizeof(tmp),
+ "fatal error code from processWirePacket: %d",
+ (int)rc);
+ Mutex::Lock _l(_termReason_m);
+ _termReason = ONE_UNRECOVERABLE_ERROR;
+ _fatalErrorMessage = tmp;
+ this->terminate();
+ _phy.close(sock);
+ return;
+ }
+ }
+ }
+
+ if (tc->readq.length() > (mlen + 5)) {
+ tc->readq.erase(tc->readq.begin(), tc->readq.begin() + (mlen + 5));
+ }
+ else {
+ tc->readq.clear();
+ }
+ }
+ else {
+ break;
+ }
+ }
+ return;
+ }
+ }
+ catch (...) {
+ _phy.close(sock);
+ }
+}
+
+void NodeService::phyOnTcpWritable(PhySocket* sock, void** uptr)
+{
+ TcpConnection* tc = reinterpret_cast(*uptr);
+ bool closeit = false;
+ {
+ Mutex::Lock _l(tc->writeq_m);
+ if (tc->writeq.length() > 0) {
+ long sent = (long)_phy.streamSend(sock, tc->writeq.data(), (unsigned long)tc->writeq.length(), true);
+ if (sent > 0) {
+ if ((unsigned long)sent >= (unsigned long)tc->writeq.length()) {
+ tc->writeq.clear();
+ _phy.setNotifyWritable(sock, false);
+ }
+ else {
+ tc->writeq.erase(tc->writeq.begin(), tc->writeq.begin() + sent);
+ }
+ }
+ }
+ else {
+ _phy.setNotifyWritable(sock, false);
+ }
+ }
+ if (closeit) {
+ _phy.close(sock);
+ }
+}
+
int NodeService::nodeVirtualNetworkConfigFunction(
uint64_t net_id,
void** nuptr,
@@ -751,13 +957,17 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
void* objptr = NULL;
+ zts_node_info_t* nd;
+ zts_net_info_t* nt;
+ zts_peer_info_t* pr;
+
switch (zt_event_code) {
case ZTS_EVENT_NODE_UP:
case ZTS_EVENT_NODE_ONLINE:
case ZTS_EVENT_NODE_OFFLINE:
case ZTS_EVENT_NODE_DOWN:
case ZTS_EVENT_NODE_FATAL_ERROR: {
- zts_node_info_t* nd = new zts_node_info_t;
+ nd = new zts_node_info_t;
nd->node_id = _nodeId;
nd->ver_major = ZEROTIER_ONE_VERSION_MAJOR;
nd->ver_minor = ZEROTIER_ONE_VERSION_MINOR;
@@ -774,9 +984,9 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_NETWORK_ACCESS_DENIED:
case ZTS_EVENT_NETWORK_DOWN: {
NetworkState* ns = (NetworkState*)obj;
- zts_net_info_t* nd = new zts_net_info_t();
- nd->net_id = ns->config.nwid;
- objptr = (void*)nd;
+ nt = new zts_net_info_t();
+ nt->net_id = ns->config.nwid;
+ objptr = (void*)nt;
break;
}
case ZTS_EVENT_NETWORK_UPDATE:
@@ -784,33 +994,33 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_NETWORK_READY_IP6:
case ZTS_EVENT_NETWORK_OK: {
NetworkState* ns = (NetworkState*)obj;
- zts_net_info_t* nd = new zts_net_info_t();
- nd->net_id = ns->config.nwid;
- nd->mac = ns->config.mac;
- strncpy(nd->name, ns->config.name, sizeof(ns->config.name));
- nd->status = (zts_network_status_t)ns->config.status;
- nd->type = (zts_net_info_type_t)ns->config.type;
- nd->mtu = ns->config.mtu;
- nd->dhcp = ns->config.dhcp;
- nd->bridge = ns->config.bridge;
- nd->broadcast_enabled = ns->config.broadcastEnabled;
- nd->port_error = ns->config.portError;
- nd->netconf_rev = ns->config.netconfRevision;
+ nt = new zts_net_info_t();
+ nt->net_id = ns->config.nwid;
+ nt->mac = ns->config.mac;
+ strncpy(nt->name, ns->config.name, sizeof(ns->config.name));
+ nt->status = (zts_network_status_t)ns->config.status;
+ nt->type = (zts_net_info_type_t)ns->config.type;
+ nt->mtu = ns->config.mtu;
+ nt->dhcp = ns->config.dhcp;
+ nt->bridge = ns->config.bridge;
+ nt->broadcast_enabled = ns->config.broadcastEnabled;
+ nt->port_error = ns->config.portError;
+ nt->netconf_rev = ns->config.netconfRevision;
// Copy and convert address structures
- nd->assigned_addr_count = ns->config.assignedAddressCount;
+ nt->assigned_addr_count = ns->config.assignedAddressCount;
for (unsigned int i = 0; i < ns->config.assignedAddressCount; i++) {
- native_ss_to_zts_ss(&(nd->assigned_addrs[i]), &(ns->config.assignedAddresses[i]));
+ native_ss_to_zts_ss(&(nt->assigned_addrs[i]), &(ns->config.assignedAddresses[i]));
}
- nd->route_count = ns->config.routeCount;
+ nt->route_count = ns->config.routeCount;
for (unsigned int i = 0; i < ns->config.routeCount; i++) {
- native_ss_to_zts_ss(&(nd->routes[i].target), &(ns->config.routes[i].target));
- native_ss_to_zts_ss(&(nd->routes[i].via), &(ns->config.routes[i].via));
- nd->routes[i].flags = ns->config.routes[i].flags;
- nd->routes[i].metric = ns->config.routes[i].metric;
+ native_ss_to_zts_ss(&(nt->routes[i].target), &(ns->config.routes[i].target));
+ native_ss_to_zts_ss(&(nt->routes[i].via), &(ns->config.routes[i].via));
+ nt->routes[i].flags = ns->config.routes[i].flags;
+ nt->routes[i].metric = ns->config.routes[i].metric;
}
- nd->multicast_sub_count = ns->config.multicastSubscriptionCount;
- memcpy(nd->multicast_subs, &(ns->config.multicastSubscriptions), sizeof(ns->config.multicastSubscriptions));
- objptr = (void*)nd;
+ nt->multicast_sub_count = ns->config.multicastSubscriptionCount;
+ memcpy(nt->multicast_subs, &(ns->config.multicastSubscriptions), sizeof(ns->config.multicastSubscriptions));
+ objptr = (void*)nt;
break;
}
case ZTS_EVENT_ADDR_ADDED_IP4:
@@ -845,13 +1055,13 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_PEER_UNREACHABLE:
case ZTS_EVENT_PEER_PATH_DISCOVERED:
case ZTS_EVENT_PEER_PATH_DEAD: {
- zts_peer_info_t* pd = new zts_peer_info_t();
+ pr = new zts_peer_info_t();
ZT_Peer* peer = (ZT_Peer*)obj;
- memcpy(pd, peer, sizeof(zts_peer_info_t));
+ memcpy(pr, peer, sizeof(zts_peer_info_t));
for (unsigned int j = 0; j < peer->pathCount; j++) {
- native_ss_to_zts_ss(&(pd->paths[j].address), &(peer->paths[j].address));
+ native_ss_to_zts_ss(&(pr->paths[j].address), &(peer->paths[j].address));
}
- objptr = (void*)pd;
+ objptr = (void*)pr;
break;
}
default:
@@ -861,7 +1071,64 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
// Send event
if (objptr) {
- _events->enqueue(zt_event_code, objptr, len);
+ if (!_events->enqueue(zt_event_code, objptr, len)) {
+ //
+ // ownership of objptr was NOT transferred, so delete any news from above
+ //
+ switch (zt_event_code) {
+ case ZTS_EVENT_NODE_UP:
+ case ZTS_EVENT_NODE_ONLINE:
+ case ZTS_EVENT_NODE_OFFLINE:
+ case ZTS_EVENT_NODE_DOWN:
+ case ZTS_EVENT_NODE_FATAL_ERROR: {
+ delete nd;
+ break;
+ }
+ case ZTS_EVENT_NETWORK_NOT_FOUND:
+ case ZTS_EVENT_NETWORK_CLIENT_TOO_OLD:
+ case ZTS_EVENT_NETWORK_REQ_CONFIG:
+ case ZTS_EVENT_NETWORK_ACCESS_DENIED:
+ case ZTS_EVENT_NETWORK_DOWN: {
+ delete nt;
+ break;
+ }
+ case ZTS_EVENT_NETWORK_UPDATE:
+ case ZTS_EVENT_NETWORK_READY_IP4:
+ case ZTS_EVENT_NETWORK_READY_IP6:
+ case ZTS_EVENT_NETWORK_OK: {
+ delete nt;
+ break;
+ }
+ case ZTS_EVENT_ADDR_ADDED_IP4:
+ break;
+ case ZTS_EVENT_ADDR_ADDED_IP6:
+ break;
+ case ZTS_EVENT_ADDR_REMOVED_IP4:
+ break;
+ case ZTS_EVENT_ADDR_REMOVED_IP6:
+ break;
+ case ZTS_EVENT_STORE_IDENTITY_PUBLIC:
+ break;
+ case ZTS_EVENT_STORE_IDENTITY_SECRET:
+ break;
+ case ZTS_EVENT_STORE_PLANET:
+ break;
+ case ZTS_EVENT_STORE_PEER:
+ break;
+ case ZTS_EVENT_STORE_NETWORK:
+ break;
+ case ZTS_EVENT_PEER_DIRECT:
+ case ZTS_EVENT_PEER_RELAY:
+ case ZTS_EVENT_PEER_UNREACHABLE:
+ case ZTS_EVENT_PEER_PATH_DISCOVERED:
+ case ZTS_EVENT_PEER_PATH_DEAD: {
+ delete pr;
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
}
@@ -1061,25 +1328,24 @@ int NodeService::getRouteAtIdx(
return ZTS_ERR_ARG;
}
// target
- const char* err = NULL;
struct sockaddr* sa = (struct sockaddr*)&(netState.config.routes[idx].target);
if (sa->sa_family == AF_INET) {
struct sockaddr_in* in4 = (struct sockaddr_in*)sa;
- err = inet_ntop(AF_INET, &(in4->sin_addr), target, ZTS_INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET, &(in4->sin_addr), target, ZTS_INET6_ADDRSTRLEN);
}
if (sa->sa_family == AF_INET6) {
struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa;
- err = inet_ntop(AF_INET6, &(in6->sin6_addr), target, ZTS_INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6, &(in6->sin6_addr), target, ZTS_INET6_ADDRSTRLEN);
}
// via
struct sockaddr* sa_via = (struct sockaddr*)&(netState.config.routes[idx].via);
if (sa_via->sa_family == AF_INET) {
struct sockaddr_in* in4 = (struct sockaddr_in*)sa_via;
- err = inet_ntop(AF_INET, &(in4->sin_addr), via, ZTS_INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET, &(in4->sin_addr), via, ZTS_INET6_ADDRSTRLEN);
}
if (sa_via->sa_family == AF_INET6) {
struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa_via;
- err = inet_ntop(AF_INET6, &(in6->sin6_addr), via, ZTS_INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6, &(in6->sin6_addr), via, ZTS_INET6_ADDRSTRLEN);
}
if (strlen(via) == 0) {
strncpy(via, "0.0.0.0", 7);
@@ -1226,7 +1492,7 @@ uint64_t NodeService::getNodeId()
int NodeService::setIdentity(const char* keypair, unsigned int len)
{
if (keypair == NULL || len < ZT_IDENTITY_STRING_BUFFER_LENGTH) {
- return ZTS_ERR_ARG;
+ // return ZTS_ERR_ARG;
}
// Double check user-provided keypair
Identity id;
@@ -1455,6 +1721,79 @@ int NodeService::nodeWirePacketSendFunction(
unsigned int len,
unsigned int ttl)
{
+ if (_allowTcpRelay) {
+ if (addr->ss_family == AF_INET) {
+ // TCP fallback tunnel support, currently IPv4 only
+ if ((len >= 16)
+ && (reinterpret_cast(addr)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) {
+ // Engage TCP tunnel fallback if we haven't received anything valid from a global
+ // IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting
+ // valid direct traffic we'll stop using it and close the socket after a while.
+ const int64_t now = OSUtils::now();
+ if (_forceTcpRelay
+ || (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)
+ && ((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER))) {
+ if (_tcpFallbackTunnel) {
+ bool flushNow = false;
+ {
+ Mutex::Lock _l(_tcpFallbackTunnel->writeq_m);
+ if (_tcpFallbackTunnel->writeq.size() < (1024 * 64)) {
+ if (_tcpFallbackTunnel->writeq.length() == 0) {
+ _phy.setNotifyWritable(_tcpFallbackTunnel->sock, true);
+ flushNow = true;
+ }
+ const unsigned long mlen = len + 7;
+ _tcpFallbackTunnel->writeq.push_back((char)0x17);
+ _tcpFallbackTunnel->writeq.push_back((char)0x03);
+ _tcpFallbackTunnel->writeq.push_back((char)0x03); // fake TLS 1.2 header
+ _tcpFallbackTunnel->writeq.push_back((char)((mlen >> 8) & 0xff));
+ _tcpFallbackTunnel->writeq.push_back((char)(mlen & 0xff));
+ _tcpFallbackTunnel->writeq.push_back((char)4); // IPv4
+ _tcpFallbackTunnel->writeq.append(
+ reinterpret_cast(reinterpret_cast(
+ &(reinterpret_cast(addr)->sin_addr.s_addr))),
+ 4);
+ _tcpFallbackTunnel->writeq.append(
+ reinterpret_cast(reinterpret_cast(
+ &(reinterpret_cast(addr)->sin_port))),
+ 2);
+ _tcpFallbackTunnel->writeq.append((const char*)data, len);
+ }
+ }
+ if (flushNow) {
+ void* tmpptr = (void*)_tcpFallbackTunnel;
+ phyOnTcpWritable(_tcpFallbackTunnel->sock, &tmpptr);
+ }
+ }
+ else if (
+ _forceTcpRelay
+ || (((now - _lastSendToGlobalV4) < ZT_TCP_FALLBACK_AFTER)
+ && ((now - _lastSendToGlobalV4) > (ZT_PING_CHECK_INTERVAL / 2)))) {
+ const InetAddress addr(_fallbackRelayAddress);
+ TcpConnection* tc = new TcpConnection();
+ {
+ Mutex::Lock _l(_tcpConnections_m);
+ _tcpConnections.push_back(tc);
+ }
+ tc->type = TcpConnection::TCP_TUNNEL_OUTGOING;
+ tc->remoteAddr = addr;
+ tc->lastReceive = OSUtils::now();
+ tc->parent = this;
+ tc->sock = (PhySocket*)0; // set in connect handler
+ bool connected = false;
+ _phy.tcpConnect(reinterpret_cast(&addr), connected, (void*)tc, true);
+ }
+ }
+ _lastSendToGlobalV4 = now;
+ }
+ }
+ }
+
+ if (_forceTcpRelay) {
+ // Shortcut here so that we don't emit any UDP packets
+ return 0;
+ }
+
// Even when relaying we still send via UDP. This way if UDP starts
// working we can instantly "fail forward" to it and stop using TCP
// proxy fallback, which is slow.
@@ -1683,9 +2022,9 @@ int NodeService::shouldBindInterface(const char* ifname, const InetAddress& ifad
unsigned int NodeService::_getRandomPort(unsigned int minPort, unsigned int maxPort)
{
unsigned int randp = 0;
- Utils::getSecureRandom(&randp,sizeof(randp));
+ Utils::getSecureRandom(&randp, sizeof(randp));
randp = (randp % (maxPort - minPort + 1)) + minPort;
- for(int i=0;;++i) {
+ for (int i = 0;; ++i) {
if (i > 1000) {
return 0;
}
@@ -1813,6 +2152,21 @@ void NodeService::enableEvents()
_events->enable();
}
+void NodeService::setTcpRelayAddress(const char* tcpRelayAddr, unsigned short tcpRelayPort)
+{
+ _fallbackRelayAddress = InetAddress(std::string(std::string(tcpRelayAddr) + std::string("/") + std::to_string(tcpRelayPort)).c_str());
+}
+
+void NodeService::allowTcpRelay(bool enabled)
+{
+ _allowTcpRelay = enabled;
+}
+
+void NodeService::forceTcpRelay(bool enabled)
+{
+ _forceTcpRelay = enabled;
+}
+
int NodeService::setRoots(const void* rootsData, unsigned int len)
{
if (! rootsData || len <= 0 || len > ZTS_STORE_DATA_LEN) {
@@ -1829,6 +2183,16 @@ int NodeService::setRoots(const void* rootsData, unsigned int len)
return ZTS_ERR_OK;
}
+int NodeService::setLowBandwidthMode(bool enabled)
+{
+ Mutex::Lock _lr(_run_m);
+ if (_run) {
+ return ZTS_ERR_SERVICE;
+ }
+ _node->setLowBandwidthMode(enabled);
+ return ZTS_ERR_OK;
+}
+
int NodeService::addInterfacePrefixToBlacklist(const char* prefix, unsigned int len)
{
if (! prefix || len == 0 || len > 15) {
diff --git a/src/NodeService.hpp b/src/NodeService.hpp
index d9a99250..c600bbc6 100644
--- a/src/NodeService.hpp
+++ b/src/NodeService.hpp
@@ -28,6 +28,7 @@
#include "Phy.hpp"
#include "PortMapper.hpp"
#include "ZeroTierSockets.h"
+#include "version.h"
#include
#include
@@ -43,17 +44,53 @@
// How often to check for local interface addresses
#define ZT_LOCAL_INTERFACE_CHECK_INTERVAL 60000
+// Attempt to engage TCP fallback after this many ms of no reply to packets sent to global-scope IPs
+#define ZT_TCP_FALLBACK_AFTER 30000
+
+// Fake TLS hello for TCP tunnel outgoing connections (TUNNELED mode)
+static const char ZT_TCP_TUNNEL_HELLO[9] = { 0x17,
+ 0x03,
+ 0x03,
+ 0x00,
+ 0x04,
+ (char)ZEROTIER_ONE_VERSION_MAJOR,
+ (char)ZEROTIER_ONE_VERSION_MINOR,
+ (char)((ZEROTIER_ONE_VERSION_REVISION >> 8) & 0xff),
+ (char)(ZEROTIER_ONE_VERSION_REVISION & 0xff) };
+
#ifdef __WINDOWS__
#include
#endif
namespace ZeroTier {
+class NodeService;
struct InetAddress;
class VirtualTap;
class MAC;
class Events;
+/**
+ * A TCP connection and related state and buffers
+ */
+struct TcpConnection {
+ enum {
+ TCP_UNCATEGORIZED_INCOMING, // uncategorized incoming connection
+ TCP_HTTP_INCOMING,
+ TCP_HTTP_OUTGOING,
+ TCP_TUNNEL_OUTGOING // TUNNELED mode proxy outbound connection
+ } type;
+
+ NodeService* parent;
+ PhySocket* sock;
+ InetAddress remoteAddr;
+ uint64_t lastReceive;
+
+ std::string readq;
+ std::string writeq;
+ Mutex writeq_m;
+};
+
/**
* ZeroTier node service
*/
@@ -161,6 +198,16 @@ class NodeService {
// Time we last received a packet from a global address
uint64_t _lastDirectReceiveFromGlobal;
+ InetAddress _fallbackRelayAddress;
+ bool _allowTcpRelay;
+ bool _forceTcpRelay;
+ uint64_t _lastSendToGlobalV4;
+
+ // Active TCP/IP connections
+ std::vector _tcpConnections;
+ Mutex _tcpConnections_m;
+ TcpConnection* _tcpFallbackTunnel;
+
// Last potential sleep/wake event
uint64_t _lastRestart;
@@ -255,6 +302,8 @@ class NodeService {
void* data,
unsigned long len);
+ void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success);
+
int nodeVirtualNetworkConfigFunction(
uint64_t net_id,
void** nuptr,
@@ -393,11 +442,23 @@ class NodeService {
/** Set the event system instance used to convey messages to the user */
int setUserEventSystem(Events* events);
+ /** Set the address and port for the tcp relay that ZeroTier should use */
+ void setTcpRelayAddress(const char* tcpRelayAddr, unsigned short tcpRelayPort);
+
+ /** Allow ZeroTier to use the TCP relay */
+ void allowTcpRelay(bool enabled);
+
+ /** Force ZeroTier to only use the the TCP relay */
+ void forceTcpRelay(bool enabled);
+
void enableEvents();
/** Set the roots definition */
int setRoots(const void* data, unsigned int len);
+ /** Enable or disable low-bandwidth mode (sends less ambient traffic, network updates happen less frequently) */
+ int setLowBandwidthMode(bool enabled);
+
/** Add Interface prefix to blacklist (prevents ZeroTier from using that interface) */
int addInterfacePrefixToBlacklist(const char* prefix, unsigned int len);
@@ -443,12 +504,6 @@ class NodeService {
/** Return whether an address of the given family has been assigned by the network */
int addrIsAssigned(uint64_t net_id, unsigned int family);
- void phyOnTcpConnect(PhySocket* sock, void** uptr, bool success)
- {
- ZTS_UNUSED_ARG(sock);
- ZTS_UNUSED_ARG(uptr);
- ZTS_UNUSED_ARG(success);
- }
void phyOnTcpAccept(PhySocket* sockL, PhySocket* sockN, void** uptrL, void** uptrN, const struct sockaddr* from)
{
ZTS_UNUSED_ARG(sockL);
@@ -457,23 +512,13 @@ class NodeService {
ZTS_UNUSED_ARG(uptrN);
ZTS_UNUSED_ARG(from);
}
- void phyOnTcpClose(PhySocket* sock, void** uptr)
- {
- ZTS_UNUSED_ARG(sock);
- ZTS_UNUSED_ARG(uptr);
- }
- void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len)
- {
- ZTS_UNUSED_ARG(sock);
- ZTS_UNUSED_ARG(uptr);
- ZTS_UNUSED_ARG(data);
- ZTS_UNUSED_ARG(len);
- }
- void phyOnTcpWritable(PhySocket* sock, void** uptr)
- {
- ZTS_UNUSED_ARG(sock);
- ZTS_UNUSED_ARG(uptr);
- }
+
+ void phyOnTcpClose(PhySocket* sock, void** uptr);
+
+ void phyOnTcpData(PhySocket* sock, void** uptr, void* data, unsigned long len);
+
+ void phyOnTcpWritable(PhySocket* sock, void** uptr);
+
void phyOnFileDescriptorActivity(PhySocket* sock, void** uptr, bool readable, bool writable)
{
ZTS_UNUSED_ARG(sock);
diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp
index a13dcbd7..933a4d76 100644
--- a/src/VirtualTap.cpp
+++ b/src/VirtualTap.cpp
@@ -312,6 +312,10 @@ static void zts_main_lwip_driver_loop(void* arg)
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
}
_has_exited = true;
+
+ //
+ // no need to check if event was enqueued since NULL is being passed
+ //
zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL);
}
@@ -572,7 +576,20 @@ void zts_lwip_init_interface(void* tapref, const InetAddress& ip)
LOCK_TCPIP_CORE();
if (isNewNetif) {
vtap->netif6 = (void*)n;
- netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, ethernet_input);
+
+ //
+ // was:
+ // netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, ethernet_input);
+ //
+ // but there is this documentation:
+ // > With NO_SYS=0, this must be set to tcpip_input for all netif types (whether ethernet, PPP, slipif, etc.)
+ // https://lwip.fandom.com/wiki/Writing_a_device_driver
+ //
+ // and also with ethernet_input and lwIP asserts turned on, we get:
+ // Assertion "Function called without core lock" failed at line 236 in /Users/brenton/development/github/libzt/ext/lwip-contrib/ports/unix/port/sys_arch.c
+ //
+ netif_add(n, NULL, NULL, NULL, (void*)vtap, zts_netif_init6, tcpip_input);
+
n->ip6_autoconfig_enabled = 1;
vtap->_mac.copyTo(n->hwaddr, n->hwaddr_len);
netif_create_ip6_linklocal_address(n, 1);
diff --git a/src/bindings/java/JavaSockets.cxx b/src/bindings/java/JavaSockets.cxx
index d3de89b7..e37f702e 100644
--- a/src/bindings/java/JavaSockets.cxx
+++ b/src/bindings/java/JavaSockets.cxx
@@ -37,7 +37,7 @@ extern JavaVM* jvm;
void java_detach_from_thread()
{
- jint rs = jvm->DetachCurrentThread();
+ jvm->DetachCurrentThread();
}
#ifdef __cplusplus
@@ -53,7 +53,7 @@ void fdset2ztfdset(JNIEnv* env, int nfds, zts_fd_set* src_fd_set, jobject dest_z
* Called from Java, saves a static reference to the VM so it can be used
* later to call a user-specified callback method from C.
*/
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1init(JNIEnv* env, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1init(JNIEnv* env, jclass clazz)
{
jint rs = env->GetJavaVM(&jvm);
return rs != JNI_OK ? ZTS_ERR_GENERAL : ZTS_ERR_OK;
@@ -61,7 +61,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1init(JNIEnv
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1socket(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint family,
jint type,
jint protocol)
@@ -71,7 +71,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1socket
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1listen(JNIEnv* env, jobject thisObj, jint fd, int backlog)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1listen(JNIEnv* env, jclass clazz, jint fd, int backlog)
{
int retval = zts_bsd_listen(fd, backlog);
return retval > -1 ? retval : -(zts_errno);
@@ -79,10 +79,9 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1listen(JNIEnv* env, jobject t
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1accept(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
- jobject addr,
- jint port)
+ jobject addr)
{
struct zts_sockaddr_storage ss;
zts_socklen_t addrlen = sizeof(struct zts_sockaddr_storage);
@@ -92,7 +91,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1accept
}
JNIEXPORT jboolean JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getsockname(JNIEnv* env, jobject thisObj, jint fd, jobject addr)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getsockname(JNIEnv* env, jclass clazz, jint fd, jobject addr)
{
struct zts_sockaddr_storage ss;
zts_socklen_t addrlen = sizeof(struct zts_sockaddr_storage);
@@ -102,7 +101,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getsockname(JNIEnv* env, jobj
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getpeername(JNIEnv* env, jobject thisObj, jint fd, jobject addr)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getpeername(JNIEnv* env, jclass clazz, jint fd, jobject addr)
{
struct zts_sockaddr_storage ss;
int retval =
@@ -111,14 +110,14 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1getpeername(JNIEnv* env, jobj
return retval > -1 ? retval : -(zts_errno);
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1close(JNIEnv* env, jobject thisObj, jint fd)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1close(JNIEnv* env, jclass clazz, jint fd)
{
return zts_bsd_close(fd);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1select(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint nfds,
jobject readfds,
jobject writefds,
@@ -159,7 +158,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1select
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1fcntl(JNIEnv* env, jobject thisObj, jint fd, jint cmd, jint flags)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1fcntl(JNIEnv* env, jclass clazz, jint fd, jint cmd, jint flags)
{
int retval = zts_bsd_fcntl(fd, cmd, flags);
return retval > -1 ? retval : -(zts_errno);
@@ -194,7 +193,7 @@ JNIEXPORT int JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1ioctl(
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1send(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
int flags)
@@ -207,7 +206,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1send(
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1sendto(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint flags,
@@ -225,7 +224,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1sendto
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1recv(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint flags)
@@ -238,7 +237,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1recv(
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1recvfrom(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint flags,
@@ -254,7 +253,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1recvfr
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read(JNIEnv* env, jobject thisObj, jint fd, jbyteArray buf)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read(JNIEnv* env, jclass clazz, jint fd, jbyteArray buf)
{
void* data = env->GetPrimitiveArrayCritical(buf, NULL);
int retval = zts_bsd_read(fd, data, env->GetArrayLength(buf));
@@ -270,7 +269,7 @@ ssize_t zts_bsd_read_offset(int fd, void* buf, size_t offset, size_t len)
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read_1offset(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint offset,
@@ -284,7 +283,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read_1
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read_1length(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint len)
@@ -296,7 +295,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1read_1
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write__IB(JNIEnv* env, jobject thisObj, jint fd, jbyteArray buf)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write(JNIEnv* env, jclass clazz, jint fd, jbyteArray buf)
{
void* data = env->GetPrimitiveArrayCritical(buf, NULL);
int retval = zts_bsd_write(fd, data, env->GetArrayLength(buf));
@@ -306,7 +305,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write__IB(JNIEnv* env, jobjec
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write_1offset(
JNIEnv* env,
- jobject thisObj,
+ jclass clazz,
jint fd,
jbyteArray buf,
jint offset,
@@ -319,14 +318,14 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write_
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write_1byte(JNIEnv* env, jobject thisObj, jint fd, jbyte buf)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1write_1byte(JNIEnv* env, jclass clazz, jint fd, jbyte buf)
{
int retval = zts_bsd_write(fd, &buf, 1);
return retval > -1 ? retval : -(zts_errno);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1shutdown(JNIEnv* env, jobject thisObj, int fd, int how)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bsd_1shutdown(JNIEnv* env, jclass clazz, int fd, int how)
{
return zts_bsd_shutdown(fd, how);
}
@@ -434,9 +433,8 @@ void zta2ss(JNIEnv* env, struct zts_sockaddr_storage* ss, jobject addr)
}
if (family == ZTS_AF_INET6) {
struct zts_sockaddr_in6* in6 = (struct zts_sockaddr_in6*)ss;
- jfieldID fid = env->GetFieldID(c, "_port", "I");
+ fid = env->GetFieldID(c, "_port", "I");
in6->sin6_port = lwip_htons(env->GetIntField(addr, fid));
- fid = env->GetFieldID(c, "_family", "I");
in6->sin6_family = ZTS_AF_INET6;
fid = env->GetFieldID(c, "_ip6", "[B");
jobject ipData = env->GetObjectField(addr, fid);
@@ -448,19 +446,19 @@ void zta2ss(JNIEnv* env, struct zts_sockaddr_storage* ss, jobject addr)
}
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1get_1port(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1get_1port(JNIEnv* jenv, jclass clazz)
{
return zts_node_get_port();
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1stop(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1stop(JNIEnv* jenv, jclass clazz)
{
int res = zts_node_stop();
java_detach_from_thread();
return res;
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1free(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1free(JNIEnv* jenv, jclass clazz)
{
int res = zts_node_free();
java_detach_from_thread();
@@ -468,13 +466,13 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1free(
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1join(JNIEnv* env, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1join(JNIEnv* env, jclass clazz, jlong net_id)
{
return zts_net_join((uint64_t)net_id);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1leave(JNIEnv* env, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1leave(JNIEnv* env, jclass clazz, jlong net_id)
{
return zts_net_leave((uint64_t)net_id);
}
@@ -492,7 +490,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1id_1pair_1is_1valid(JNIEnv* jenv,
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1from_1storage(JNIEnv* jenv, jobject thisObj, jstring path)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1from_1storage(JNIEnv* jenv, jclass clazz, jstring path)
{
if (! path) {
return ZTS_ERR_ARG;
@@ -507,7 +505,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1from_1storage(JNIEnv* jenv,
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_1event_1handler(JNIEnv* env, jobject thisObj, jobject callback)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_1event_1handler(JNIEnv* env, jclass clazz, jobject callback)
{
jclass eventListenerClass = env->GetObjectClass(callback);
if (eventListenerClass == NULL) {
@@ -523,7 +521,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_1event_1handler(JNIEnv*
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_1port(JNIEnv* jenv, jobject thisObj, short port)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_1port(JNIEnv* jenv, jclass clazz, short port)
{
return zts_init_set_port(port);
}
@@ -536,7 +534,7 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1from_1memory(JNIEnv* jenv, j
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1blacklist_1if(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jstring prefix,
jint len)
{
@@ -559,50 +557,50 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1set_roots(JNIEnv* jenv, jobj
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1net_1cache(JNIEnv* jenv, jobject thisObj, jint allowed)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1net_1cache(JNIEnv* jenv, jclass clazz, jint allowed)
{
return zts_init_allow_net_cache(allowed);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1peer_1cache(JNIEnv* jenv, jobject thisObj, jint allowed)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1peer_1cache(JNIEnv* jenv, jclass clazz, jint allowed)
{
return zts_init_allow_peer_cache(allowed);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1roots_1cache(JNIEnv* jenv, jobject thisObj, jint allowed)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1roots_1cache(JNIEnv* jenv, jclass clazz, jint allowed)
{
return zts_init_allow_roots_cache(allowed);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1id_1cache(JNIEnv* jenv, jobject thisObj, jint allowed)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1init_1allow_1id_1cache(JNIEnv* jenv, jclass clazz, jint allowed)
{
return zts_init_allow_id_cache(allowed);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1is_1assigned(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jint family)
{
return zts_addr_is_assigned(net_id, family);
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get(
- JNIEnv* jenv,
- jobject thisObj,
- long net_id,
- jint family,
- struct sockaddr_storage* addr)
-{
- // Use Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1str instead
-}
+//JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get(
+// JNIEnv* jenv,
+// jobject thisObj,
+// long net_id,
+// jint family,
+// struct sockaddr_storage* addr)
+//{
+// // Use Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1str instead
+//}
JNIEXPORT jstring JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1str(JNIEnv* jenv, jobject thisObj, long net_id, jint family)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1str(JNIEnv* jenv, jclass clazz, jlong net_id, jint family)
{
char ip_str[ZTS_IP_MAX_STR_LEN] = { 0 };
zts_addr_get_str(net_id, family, ip_str, ZTS_IP_MAX_STR_LEN);
@@ -610,38 +608,38 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1str(JNIEnv* jenv, jobje
return result;
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1all(
- JNIEnv* jenv,
- jobject thisObj,
- long net_id,
- struct sockaddr_storage* addr,
- jint* count)
-{
- /* This feature will be implemented once the lower-level
- limitation of one addr per family per network is removed. */
-}
-
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_16plane(
- JNIEnv* jenv,
- jobject thisObj,
- jlong net_id,
- jlong node_id,
- struct sockaddr_storage* addr)
-{
-}
-
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_1rfc4193(
- JNIEnv* jenv,
- jobject thisObj,
- jlong net_id,
- jlong node_id,
- struct sockaddr_storage* addr)
-{
-}
+//JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1get_1all(
+// JNIEnv* jenv,
+// jobject thisObj,
+// long net_id,
+// struct sockaddr_storage* addr,
+// jint* count)
+//{
+// /* This feature will be implemented once the lower-level
+// limitation of one addr per family per network is removed. */
+//}
+
+//JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_16plane(
+// JNIEnv* jenv,
+// jobject thisObj,
+// jlong net_id,
+// jlong node_id,
+// struct sockaddr_storage* addr)
+//{
+//}
+
+//JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_1rfc4193(
+// JNIEnv* jenv,
+// jobject thisObj,
+// jlong net_id,
+// jlong node_id,
+// struct sockaddr_storage* addr)
+//{
+//}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_1rfc4193_1str(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jlong node_id,
jstring dst,
@@ -652,7 +650,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compu
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compute_16plane_1str(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jlong node_id,
jstring dst,
@@ -661,9 +659,9 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1addr_1compu
return ZTS_ERR_OK;
}
-JNIEXPORT uint64_t JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1compute_1adhoc_1id(
+JNIEXPORT jlong JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1compute_1adhoc_1id(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
short start_port,
short end_port)
{
@@ -671,19 +669,19 @@ JNIEXPORT uint64_t JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1co
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1transport_1is_1ready(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1transport_1is_1ready(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_transport_is_ready(net_id);
}
-JNIEXPORT uint64_t JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_get_mac(JNIEnv* jenv, jobject thisObj, jlong net_id)
+JNIEXPORT jlong JNICALL
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mac(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_get_mac(net_id);
}
JNIEXPORT jstring JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mac_1str(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mac_1str(JNIEnv* jenv, jclass clazz, jlong net_id)
{
char mac_str[ZTS_MAC_ADDRSTRLEN] = { 0 };
zts_net_get_mac_str(net_id, mac_str, ZTS_MAC_ADDRSTRLEN);
@@ -692,20 +690,20 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mac_1str(JNIEnv* jenv, j
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1broadcast(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1broadcast(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_get_broadcast(net_id);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mtu(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1mtu(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_get_mtu(net_id);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1name(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jstring dst,
jint len)
@@ -714,37 +712,37 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1n
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1status(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1status(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_get_status(net_id);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1type(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1net_1get_1type(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_net_get_type(net_id);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1route_1is_1assigned(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jint family)
{
return zts_route_is_assigned(net_id, family);
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1start(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1start(JNIEnv* jenv, jclass clazz)
{
return zts_node_start();
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1is_1online(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1is_1online(JNIEnv* jenv, jclass clazz)
{
return zts_node_is_online();
}
-JNIEXPORT uint64_t JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1get_1id(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jlong JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1get_1id(JNIEnv* jenv, jclass clazz)
{
return zts_node_get_id();
}
@@ -760,7 +758,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1node_1get_1
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1moon_1orbit(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong moon_roots_id,
jlong moon_seed)
{
@@ -768,14 +766,14 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1moon_1orbit
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1moon_1deorbit(JNIEnv* jenv, jobject thisObj, jlong moon_roots_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1moon_1deorbit(JNIEnv* jenv, jclass clazz, jlong moon_roots_id)
{
return zts_moon_deorbit(moon_roots_id);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1connect(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jint fd,
jstring ipstr,
jint port,
@@ -794,7 +792,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1connect(
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1bind(JNIEnv* jenv, jobject thisObj, jint fd, jstring ipstr, jint port)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1bind(JNIEnv* jenv, jclass clazz, jint fd, jstring ipstr, jint port)
{
if (! ipstr) {
return ZTS_ERR_ARG;
@@ -827,20 +825,20 @@ Java_com_zerotier_sockets_ZeroTierNative_zts_1udp_1client(JNIEnv* jenv, jobject
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1no_1delay(JNIEnv* jenv, jobject thisObj, jint fd, jint enabled)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1no_1delay(JNIEnv* jenv, jclass clazz, jint fd, jint enabled)
{
return zts_set_no_delay(fd, enabled);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1no_1delay(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1no_1delay(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_no_delay(fd);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1linger(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jint fd,
jint enabled,
jint value)
@@ -849,38 +847,38 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1linger
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1linger_1enabled(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1linger_1enabled(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_linger_enabled(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1linger_1value(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1linger_1value(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_linger_value(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1pending_1data_1size(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1pending_1data_1size(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_pending_data_size(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1reuse_1addr(JNIEnv* jenv, jobject thisObj, jint fd, jint enabled)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1reuse_1addr(JNIEnv* jenv, jclass clazz, jint fd, jint enabled)
{
return zts_set_reuse_addr(fd, enabled);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1reuse_1addr(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1reuse_1addr(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_reuse_addr(fd);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1recv_1timeout(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jint fd,
jint seconds,
jint microseconds)
@@ -889,14 +887,14 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1recv_1
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1recv_1timeout(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1recv_1timeout(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_recv_timeout(fd);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1send_1timeout(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jint fd,
jint seconds,
jint microseconds)
@@ -905,66 +903,66 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1send_1
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1send_1timeout(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1send_1timeout(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_send_timeout(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1send_1buf_1size(JNIEnv* jenv, jobject thisObj, jint fd, jint size)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1send_1buf_1size(JNIEnv* jenv, jclass clazz, jint fd, jint size)
{
return zts_set_send_buf_size(fd, size);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1send_1buf_1size(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1send_1buf_1size(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_send_buf_size(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1recv_1buf_1size(JNIEnv* jenv, jobject thisObj, jint fd, jint size)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1recv_1buf_1size(JNIEnv* jenv, jclass clazz, jint fd, jint size)
{
return zts_set_recv_buf_size(fd, size);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1recv_1buf_1size(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1recv_1buf_1size(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_recv_buf_size(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1ttl(JNIEnv* jenv, jobject thisObj, jint fd, jint ttl)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1ttl(JNIEnv* jenv, jclass clazz, jint fd, jint ttl)
{
return zts_set_ttl(fd, ttl);
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1ttl(JNIEnv* jenv, jobject thisObj, jint fd)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1ttl(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_ttl(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1blocking(JNIEnv* jenv, jobject thisObj, jint fd, jint enabled)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1blocking(JNIEnv* jenv, jclass clazz, jint fd, jint enabled)
{
return zts_set_blocking(fd, enabled);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1blocking(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1blocking(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_blocking(fd);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1keepalive(JNIEnv* jenv, jobject thisObj, jint fd, jint enabled)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1set_1keepalive(JNIEnv* jenv, jclass clazz, jint fd, jint enabled)
{
return zts_set_keepalive(fd, enabled);
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1keepalive(JNIEnv* jenv, jobject thisObj, jint fd)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1get_1keepalive(JNIEnv* jenv, jclass clazz, jint fd)
{
return zts_get_keepalive(fd);
}
@@ -989,25 +987,25 @@ JNIEXPORT ip_addr* JNICALL dns_1get_1server(JNIEnv* jenv, jobject thisObj, uint8
return NULL;
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1lock_1obtain(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1lock_1obtain(JNIEnv* jenv, jclass clazz)
{
return zts_core_lock_obtain();
}
-JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1lock_1release(JNIEnv* jenv, jobject thisObj)
+JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1lock_1release(JNIEnv* jenv, jclass clazz)
{
return zts_core_lock_release();
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1addr_1count(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1addr_1count(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_core_query_addr_count(net_id);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1addr(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong net_id,
jint idx,
jstring addr,
@@ -1017,7 +1015,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1route_1count(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1route_1count(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_core_query_route_count(net_id);
}
@@ -1037,14 +1035,14 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1path_1count(JNIEnv* jenv, jobject thisObj, jlong peer_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1path_1count(JNIEnv* jenv, jclass clazz, jlong peer_id)
{
return zts_core_query_path_count(peer_id);
}
JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1path(
JNIEnv* jenv,
- jobject thisObj,
+ jclass clazz,
jlong peer_id,
jint idx,
jstring dst,
@@ -1054,7 +1052,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query
}
JNIEXPORT jint JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1mc_1count(JNIEnv* jenv, jobject thisObj, jlong net_id)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1core_1query_1mc_1count(JNIEnv* jenv, jclass clazz, jlong net_id)
{
return zts_core_query_mc_count(net_id);
}
@@ -1087,7 +1085,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_sockets_ZeroTierNative_zts_1util_1roots
}
JNIEXPORT void JNICALL
-Java_com_zerotier_sockets_ZeroTierNative_zts_1util_1delay(JNIEnv* jenv, jobject thisObj, jlong milliseconds)
+Java_com_zerotier_sockets_ZeroTierNative_zts_1util_1delay(JNIEnv* jenv, jclass clazz, jlong milliseconds)
{
zts_util_delay(milliseconds);
}
diff --git a/src/bindings/java/ZeroTierDatagramSocket.java b/src/bindings/java/com/zerotier/sockets/ZeroTierDatagramSocket.java
similarity index 97%
rename from src/bindings/java/ZeroTierDatagramSocket.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierDatagramSocket.java
index a37608d0..34d44700 100644
--- a/src/bindings/java/ZeroTierDatagramSocket.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierDatagramSocket.java
@@ -165,7 +165,7 @@ public void receive(DatagramPacket packet) throws IOException
0,
packet.getLength());
if ((bytesRead <= 0) | (bytesRead == -104) /* EINTR, from SO_RCVTIMEO */) {
- throw new IOException("read(DatagramPacket), errno=" + bytesRead);
+ throw new IOException("read(DatagramPacket), errno=" + bytesRead);
}
}
@@ -277,16 +277,16 @@ public int getSoTimeout() throws SocketException
* Return whether this ZeroTierSocket is bound to a local address
* @return true or false
*/
- public boolean isBound()
+ public boolean isBound()
{
- return _socket.isBound();
+ return _socket.isBound();
}
/**
* Return whether this ZeroTierSocket has been closed
* @return true or false
*/
- public boolean isClosed()
+ public boolean isClosed()
{
return _socket.isClosed();
}
@@ -295,7 +295,7 @@ public int getSoTimeout() throws SocketException
* Return whether this ZeroTierSocket is connected to a remote address
* @return true or false
*/
- public boolean isConnected()
+ public boolean isConnected()
{
return _socket.isConnected();
}
diff --git a/src/bindings/java/ZeroTierEventListener.java b/src/bindings/java/com/zerotier/sockets/ZeroTierEventListener.java
similarity index 92%
rename from src/bindings/java/ZeroTierEventListener.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierEventListener.java
index 0154b7e2..8eef5325 100644
--- a/src/bindings/java/ZeroTierEventListener.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierEventListener.java
@@ -18,7 +18,7 @@
*/
public interface ZeroTierEventListener {
/*
- * Called when an even occurs within ZeroTier
+ * Called when an event occurs within ZeroTier
*/
public void onZeroTierEvent(long id, int eventCode);
}
diff --git a/src/bindings/java/ZeroTierFileDescriptorSet.java b/src/bindings/java/com/zerotier/sockets/ZeroTierFileDescriptorSet.java
similarity index 100%
rename from src/bindings/java/ZeroTierFileDescriptorSet.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierFileDescriptorSet.java
diff --git a/src/bindings/java/ZeroTierInputStream.java b/src/bindings/java/com/zerotier/sockets/ZeroTierInputStream.java
similarity index 87%
rename from src/bindings/java/ZeroTierInputStream.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierInputStream.java
index 8d23d881..e5d2d4f3 100644
--- a/src/bindings/java/ZeroTierInputStream.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierInputStream.java
@@ -30,7 +30,7 @@ public class ZeroTierInputStream extends InputStream {
* Close the ZeroTierInputStream
* @exception IOException when an I/O error occurs
*/
- public void close() throws IOException
+ public void close() throws IOException
{
/* Note: this operation currently only stops RX on a socket that is shared
between both I/OStreams. This means that closing this stream will only shutdown
@@ -47,7 +47,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Number of bytes transferred
* @exception IOException when an I/O error occurs
*/
- public long transferTo(OutputStream destStream) throws IOException
+ public long transferTo(OutputStream destStream) throws IOException
{
Objects.requireNonNull(destStream, "destStream must not be null");
int bytesTransferred = 0, bytesRead;
@@ -64,7 +64,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Single byte read
* @exception IOException when an I/O error occurs
*/
- public int read() throws IOException
+ public int read() throws IOException
{
byte[] buf = new byte[1];
// Unlike a native read(), if nothing is read we should return -1
@@ -73,7 +73,7 @@ public class ZeroTierInputStream extends InputStream {
return -1;
}
if (retval < 0) {
- throw new IOException("read(), errno=" + retval);
+ throw new IOException("read(), errno=" + retval);
}
return buf[0];
}
@@ -84,7 +84,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Number of bytes read
* @exception IOException when an I/O error occurs
*/
- public int read(byte[] destBuffer) throws IOException
+ public int read(byte[] destBuffer) throws IOException
{
Objects.requireNonNull(destBuffer, "input byte array must not be null");
// Unlike a native read(), if nothing is read we should return -1
@@ -93,7 +93,7 @@ public class ZeroTierInputStream extends InputStream {
return -1;
}
if (retval < 0) {
- throw new IOException("read(destBuffer), errno=" + retval);
+ throw new IOException("read(destBuffer), errno=" + retval);
}
return retval;
}
@@ -106,7 +106,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Number of bytes read.
* @exception IOException when an I/O error occurs
*/
- public int read(byte[] destBuffer, int offset, int numBytes) throws IOException
+ public int read(byte[] destBuffer, int offset, int numBytes) throws IOException
{
Objects.requireNonNull(destBuffer, "input byte array must not be null");
if (offset < 0) {
@@ -127,7 +127,7 @@ public class ZeroTierInputStream extends InputStream {
return -1;
}
if (retval < 0) {
- throw new IOException("read(destBuffer, offset, numBytes), errno=" + retval);
+ throw new IOException("read(destBuffer, offset, numBytes), errno=" + retval);
}
return retval;
}
@@ -137,7 +137,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Array of bytes
* @exception IOException when an I/O error occurs
*/
- public byte[] readAllBytes() throws IOException
+ public byte[] readAllBytes() throws IOException
{
int pendingDataSize = ZeroTierNative.zts_get_pending_data_size(zfd);
byte[] buf = new byte[pendingDataSize];
@@ -146,7 +146,7 @@ public class ZeroTierInputStream extends InputStream {
// No action needed
}
if (retval < 0) {
- throw new IOException("readAllBytes(), errno=" + retval);
+ throw new IOException("readAllBytes(), errno=" + retval);
}
return buf;
}
@@ -159,7 +159,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Nothing.
* @exception IOException when an I/O error occurs
*/
- public int readNBytes(byte[] destBuffer, int offset, int numBytes) throws IOException
+ public int readNBytes(byte[] destBuffer, int offset, int numBytes) throws IOException
{
Objects.requireNonNull(destBuffer, "input byte array must not be null");
if (offset < 0) {
@@ -179,7 +179,7 @@ public class ZeroTierInputStream extends InputStream {
// No action needed
}
if (retval < 0) {
- throw new IOException("readNBytes(destBuffer, offset, numBytes), errno=" + retval);
+ throw new IOException("readNBytes(destBuffer, offset, numBytes), errno=" + retval);
}
return retval;
}
@@ -190,7 +190,7 @@ public class ZeroTierInputStream extends InputStream {
* @return Nothing.
* @exception IOException when an I/O error occurs
*/
- public long skip(long numBytes) throws IOException
+ public long skip(long numBytes) throws IOException
{
if (numBytes <= 0) {
return 0;
diff --git a/src/bindings/java/ZeroTierNative.java b/src/bindings/java/com/zerotier/sockets/ZeroTierNative.java
similarity index 99%
rename from src/bindings/java/ZeroTierNative.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierNative.java
index 0300e1da..aa797117 100644
--- a/src/bindings/java/ZeroTierNative.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierNative.java
@@ -228,7 +228,7 @@ public class ZeroTierNative {
public static int ZTS_SO_DONTROUTE = 0x00000010; // NOT YET SUPPORTED
public static int ZTS_SO_USELOOPBACK = 0x00000040; // NOT YET SUPPORTED
public static int ZTS_SO_LINGER = 0x00000080;
- public static int ZTS_SO_DONTLINGER = ((int)(~ZTS_SO_LINGER));
+ public static int ZTS_SO_DONTLINGER = (~ZTS_SO_LINGER);
public static int ZTS_SO_OOBINLINE = 0x00000100; // NOT YET SUPPORTED
public static int ZTS_SO_REUSEPORT = 0x00000200; // NOT YET SUPPORTED
public static int ZTS_SO_SNDBUF = 0x00001001; // NOT YET SUPPORTED
@@ -407,7 +407,7 @@ public class ZeroTierNative {
/**
* Maximum number of direct network paths to a given peer
*/
- public static int ZTS_MAX_PEER_NETWORK_PATHS = 16;
+ public static int ZTS_MAX_PEER_NETWORK_PATHS = 64;
/**
* Maximum number of multicast groups a device / network interface can be
diff --git a/src/bindings/java/ZeroTierNode.java b/src/bindings/java/com/zerotier/sockets/ZeroTierNode.java
similarity index 100%
rename from src/bindings/java/ZeroTierNode.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierNode.java
diff --git a/src/bindings/java/ZeroTierOutputStream.java b/src/bindings/java/com/zerotier/sockets/ZeroTierOutputStream.java
similarity index 100%
rename from src/bindings/java/ZeroTierOutputStream.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierOutputStream.java
diff --git a/src/bindings/java/ZeroTierPeerDetails.java b/src/bindings/java/com/zerotier/sockets/ZeroTierPeerDetails.java
similarity index 100%
rename from src/bindings/java/ZeroTierPeerDetails.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierPeerDetails.java
diff --git a/src/bindings/java/ZeroTierServerSocket.java b/src/bindings/java/com/zerotier/sockets/ZeroTierServerSocket.java
similarity index 91%
rename from src/bindings/java/ZeroTierServerSocket.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierServerSocket.java
index ac1e25ff..1a3cc576 100644
--- a/src/bindings/java/ZeroTierServerSocket.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierServerSocket.java
@@ -76,7 +76,6 @@ public ZeroTierSocket accept() throws IOException
/**
* Bind to a local address
* @param localAddr Local address to which this socket should bind
- * @param localPort Local port to which this socket should bind
*
* @exception IOException when an I/O error occurs
*/
@@ -86,19 +85,6 @@ public void bind(SocketAddress localAddr) throws IOException
_socket.bind(inetAddr.getHostName(), inetAddr.getPort());
}
- /**
- * Bind to a local address
- * @param localAddr Local address to which this socket should bind
- * @param localPort Local port to which this socket should bind
- *
- * @exception IOException when an I/O error occurs
- */
- public void bind(SocketAddress localAddr, int backlog) throws IOException
- {
- InetSocketAddress inetAddr = (InetSocketAddress)localAddr;
- _socket.bind(inetAddr.getHostName(), inetAddr.getPort());
- }
-
/**
* Close the ZeroTierSocket.
*
diff --git a/src/bindings/java/ZeroTierSocket.java b/src/bindings/java/com/zerotier/sockets/ZeroTierSocket.java
similarity index 98%
rename from src/bindings/java/ZeroTierSocket.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierSocket.java
index ffedb3bc..7b0fea30 100644
--- a/src/bindings/java/ZeroTierSocket.java
+++ b/src/bindings/java/com/zerotier/sockets/ZeroTierSocket.java
@@ -232,12 +232,12 @@ public ZeroTierSocket accept() throws IOException
if (_zfd < 0) {
throw new IOException("Invalid socket (fd < 0)");
}
- int accetpedFd = -1;
+ int acceptedFd = -1;
ZeroTierSocketAddress addr = new ZeroTierSocketAddress();
- if ((accetpedFd = ZeroTierNative.zts_bsd_accept(_zfd, addr)) < 0) {
- throw new IOException("Error while accepting connection (" + accetpedFd + ")");
+ if ((acceptedFd = ZeroTierNative.zts_bsd_accept(_zfd, addr)) < 0) {
+ throw new IOException("Error while accepting connection (" + acceptedFd + ")");
}
- return new ZeroTierSocket(_family, _type, _protocol, accetpedFd);
+ return new ZeroTierSocket(_family, _type, _protocol, acceptedFd);
}
/**
@@ -421,7 +421,7 @@ public boolean tcpNoDelayEnabled() throws SocketException
* Return whether this ZeroTierSocket is bound to a local address
* @return true or false
*/
- public boolean isBound()
+ public boolean isBound()
{
return _isBound;
}
@@ -430,7 +430,7 @@ public boolean tcpNoDelayEnabled() throws SocketException
* Return whether this ZeroTierSocket has been closed
* @return true or false
*/
- public boolean isClosed()
+ public boolean isClosed()
{
return _isClosed;
}
@@ -439,7 +439,7 @@ public boolean tcpNoDelayEnabled() throws SocketException
* Return whether this ZeroTierSocket is connected to a remote address
* @return true or false
*/
- public boolean isConnected()
+ public boolean isConnected()
{
return _isConnected;
}
@@ -526,7 +526,7 @@ public ZeroTierOutputStream getOutputStream() throws SocketException
* Return whether the input-aspect of the ZeroTierSocket has been disabled.
* @return true or false
*/
- public boolean inputStreamHasBeenShutdown()
+ public boolean inputStreamHasBeenShutdown()
{
return _inputHasBeenShutdown;
}
@@ -535,7 +535,7 @@ public ZeroTierOutputStream getOutputStream() throws SocketException
* Return whether the output-aspect of the ZeroTierSocket has been disabled.
* @return true or false
*/
- public boolean outputStreamHasBeenShutdown()
+ public boolean outputStreamHasBeenShutdown()
{
return _outputHasBeenShutdown;
}
diff --git a/src/bindings/java/ZeroTierSocketAddress.java b/src/bindings/java/com/zerotier/sockets/ZeroTierSocketAddress.java
similarity index 100%
rename from src/bindings/java/ZeroTierSocketAddress.java
rename to src/bindings/java/com/zerotier/sockets/ZeroTierSocketAddress.java
diff --git a/src/lwipopts.h b/src/lwipopts.h
index 20e74378..5ddb269c 100644
--- a/src/lwipopts.h
+++ b/src/lwipopts.h
@@ -149,7 +149,7 @@ happening sooner than they should.
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL
#endif /* TCP_FAST_INTERVAL */
-#ifndef TCP_SLOW_INTERVALs
+#ifndef TCP_SLOW_INTERVAL
/* the coarse grained timeout in milliseconds */
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL)
#endif /* TCP_SLOW_INTERVAL */
diff --git a/test/ExitTest.java b/test/ExitTest.java
new file mode 100644
index 00000000..be5b28e1
--- /dev/null
+++ b/test/ExitTest.java
@@ -0,0 +1,77 @@
+import com.zerotier.sockets.*;
+
+//
+// Test for:
+// Java process does not exit after finishing libzt work
+// https://github.com/zerotier/libzt/issues/242
+//
+// Run and ensure that process exits
+//
+public class ExitTest {
+
+ public static void main(String[] args) throws InterruptedException {
+
+ long networkId = Long.parseUnsignedLong("ebe7fbd445e76ac6", 16);
+ String storagePath = "exittest_storage";
+
+ ZeroTierNode node = new ZeroTierNode();
+ node.initFromStorage(storagePath);
+ node.initSetEventHandler(new ZeroTierEventListener() {
+ @Override
+ public void onZeroTierEvent(long l, int eventCode) {
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NODE_UP) {
+ System.err.println("ZTS_EVENT_NODE_UP");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NODE_ONLINE) {
+ System.err.println("ZTS_EVENT_NODE_ONLINE");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NODE_OFFLINE) {
+ System.err.println("ZTS_EVENT_NODE_OFFLINE");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NODE_DOWN) {
+ System.err.println("ZTS_EVENT_NODE_DOWN");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_READY_IP4) {
+ System.err.println("ZTS_EVENT_NETWORK_READY_IP4");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_READY_IP6) {
+ System.err.println("ZTS_EVENT_NETWORK_READY_IP6");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_DOWN) {
+ System.err.println("ZTS_EVENT_NETWORK_DOWN");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_OK) {
+ System.err.println("ZTS_EVENT_NETWORK_OK");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_ACCESS_DENIED) {
+ System.err.println("ZTS_EVENT_NETWORK_ACCESS_DENIED");
+ }
+ if (eventCode == ZeroTierNative.ZTS_EVENT_NETWORK_NOT_FOUND) {
+ System.err.println("ZTS_EVENT_NETWORK_NOT_FOUND");
+ }
+ }
+ });
+
+ System.err.println("start");
+ node.start();
+
+ System.err.println("delay until online");
+ while (!node.isOnline()) {
+ ZeroTierNative.zts_util_delay(50);
+ }
+ System.err.println("done delaying");
+
+ System.out.println("join");
+ node.join(networkId);
+
+ System.out.println("delaying until transport ready");
+ while (! node.isNetworkTransportReady(networkId)) {
+ ZeroTierNative.zts_util_delay(50);
+ }
+
+ System.err.println("stop");
+ node.stop();
+
+ System.err.println("exiting");
+ }
+}