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 latest libzt version -Last Commit +Last Commit Build Status (master branch) @@ -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) | version|[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` | version| [C/C++](./examples/c) | | macOS | `brew install zerotier/tap/libzt`| version| [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"); + } +}