diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ba2824..1e0a733 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,29 +28,63 @@ cmake_minimum_required (VERSION 3.0) project (zt) set (CMAKE_VERBOSE_MAKEFILE ON) -set (CMAKE_SUPPRESS_REGENERATION true) -set (PROJ_DIR ${PROJECT_SOURCE_DIR}) -set (CMAKE_BINARY_DIR ${PROJECT_SOURCE_DIR}/bin) -set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) -set (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) -set (INCLUDE_PATH ${PROJ_DIR}/include) - -# ----------------------------------------------------------------------------- -# | BUILD CONFIG | -# ----------------------------------------------------------------------------- - -# Default build type: Release - -# Release - Optimization and no debug info -# Debug - No optimization, debug info -# RelWithDebInfo - Release optimizations and debug info -# MinSizeRel - Similar to Release but with optimizations to minimize size +# Library and executable output paths if (NOT CMAKE_BUILD_TYPE) - set (CMAKE_BUILD_TYPE Release) + message( FATAL_ERROR "Must specify CMAKE_BUILD_TYPE, CMake will exit." ) endif () -set (SILENCE "-Wno-unused-parameter -Wno-unused-variable -Wno-missing-field-initializers") +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set (CMAKE_BINARY_DIR ${PROJECT_SOURCE_DIR}/bin/debug) +endif() +if (CMAKE_BUILD_TYPE STREQUAL "Release") + set (CMAKE_BINARY_DIR ${PROJECT_SOURCE_DIR}/bin/release) +endif() + +set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +set (LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) +set (INTERMEDIATE_LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/intermediate) + +# ----------------------------------------------------------------------------- +# | LIBRARY NAMES | +# ----------------------------------------------------------------------------- + +if (IN_XCODE) + set (XCODE_FRAMEWORK_NAME ${PROJECT_NAME}) +endif () + +if (BUILDING_WIN) + # Possibly a CMake limitation? -- Can't share target output names + set (STATIC_LIB_NAME ${PROJECT_NAME}-static) + set (STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-static) + set (DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) + set (DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-shared) +else () + set (STATIC_LIB_NAME ${PROJECT_NAME}-static) + set (STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) + set (DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) + set (DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) +endif () + +# ----------------------------------------------------------------------------- +# | FLAGS | +# ----------------------------------------------------------------------------- + +set (SILENCE "-Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-missing-field-initializers") +set (LIBZT_FLAGS "-D_USING_LWIP_DEFINITIONS_=1 -DZT_SDK") +set (ZTCORE_FLAGS "-DZT_USE_MINIUPNPC=1 -DZT_SOFTWARE_UPDATE_DEFAULT=0") + +if (BUILDING_WIN) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNOMINMAX") +else () + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBZT_FLAGS} -fstack-protector") + set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${LIBZT_FLAGS} -DLWIP_DEBUG=1 -DLIBZT_DEBUG=1") + set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${LIBZT_FLAGS} -fstack-protector") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SILENCE} ${LIBZT_FLAGS} -O3 -Wall -Wextra -std=c++11") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SILENCE} ${LIBZT_FLAGS} -std=c++11 -DLWIP_DEBUG=1 -DLIBZT_DEBUG=1") + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${SILENCE} ${LIBZT_FLAGS} -O3 -std=c++11") +endif () # ----------------------------------------------------------------------------- # | PLATFORM/FEATURE AND IDE DETECTION | @@ -77,6 +111,9 @@ if (${CMAKE_GENERATOR} STREQUAL "Xcode") #set_target_properties (${STATIC_LIB_NAME} PROPERTIES XCODE_ATTRIBUTE_MY_BUILD_ONLY_ACTIVE_ARCH YES) #set_target_properties (${STATIC_LIB_NAME} PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "${MY_BUILD_ONLY_ACTIVE_ARCH}) endif () +if (BUILDING_WIN32 OR BUILDING_WIN64 OR MSVC) + set (BUILDING_WIN TRUE) +endif () if (NOT BUILDING_ANDROID AND NOT IN_XCODE AND NOT BUILD_TESTS EQUAL 0) set(SHOULD_BUILD_TESTS TRUE) endif () @@ -128,9 +165,41 @@ if ((BUILDING_ANDROID OR JNI) AND JNI_FOUND) endif () # ----------------------------------------------------------------------------- -# | LWIP PORT | +# | SOURCE FILE GLOBS | # ----------------------------------------------------------------------------- +set (PROJ_DIR ${PROJECT_SOURCE_DIR}) +set (LWIP_SRC_DIR "${PROJ_DIR}/ext/lwip/src") +set (ZTO_SRC_DIR "${PROJ_DIR}/ext/ZeroTierOne") +set (LIBZT_SRC_DIR "${PROJ_DIR}/src") + +file (GLOB zerotiercoreSrcGlob + ${ZTO_SRC_DIR}/node/*.cpp + ${ZTO_SRC_DIR}/osdep/OSUtils.cpp + ${ZTO_SRC_DIR}/osdep/PortMapper.cpp + ${ZTO_SRC_DIR}/osdep/ManagedRoute.cpp) + +file (GLOB libnatpmpSrcGlob + ${ZTO_SRC_DIR}/ext/libnatpmp/natpmp.c + ${ZTO_SRC_DIR}/ext/libnatpmp/getgateway.c) + +file (GLOB libminiupnpcSrcGlob + ${ZTO_SRC_DIR}/ext/miniupnpc/connecthostport.c + ${ZTO_SRC_DIR}/ext/miniupnpc/igd_desc_parse.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minisoap.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minissdpc.c + ${ZTO_SRC_DIR}/ext/miniupnpc/miniupnpc.c + ${ZTO_SRC_DIR}/ext/miniupnpc/miniwget.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minixml.c + ${ZTO_SRC_DIR}/ext/miniupnpc/portlistingparse.c + ${ZTO_SRC_DIR}/ext/miniupnpc/receivedata.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpcommands.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpdev.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnperrors.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpreplyparse.c) + +file (GLOB libztSrcGlob ${LIBZT_SRC_DIR}/*.cpp) + if (UNIX) set (LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/unix/port) endif () @@ -139,69 +208,6 @@ if (BUILDING_WIN) set (LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/win32) endif () -# ----------------------------------------------------------------------------- -# | LIBRARY NAMES | -# ----------------------------------------------------------------------------- - -if (IN_XCODE) - set (XCODE_FRAMEWORK_NAME ${PROJECT_NAME}) -endif () - -if (BUILDING_WIN) - # Possibly a CMake limitation? -- Can't share target output names - set (STATIC_LIB_NAME ${PROJECT_NAME}-static) - set (STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-static) - set (DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) - set (DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-shared) -else () - set (STATIC_LIB_NAME ${PROJECT_NAME}-static) - set (STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) - set (DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) - set (DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) -endif () - -# ----------------------------------------------------------------------------- -# | FLAGS | -# ----------------------------------------------------------------------------- - -set (LIBZT_FLAGS "-DZT_SDK=1 -D_USING_LWIP_DEFINITIONS_=1") -set (LIBZT_FLAGS_DEBUG "-DZT_SDK=1 -DLIBZT_TRACE=1 -DLWIP_DEBUG=1 -DLIBZT_DEBUG=1 -DNS_TRACE=1 -DNS_DEBUG=1") - -set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${LIBZT_FLAGS_DEBUG}") -set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${LIBZT_FLAGS_DEBUG}") - -if (BUILDING_WIN) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNOMINMAX") -else () - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") - set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fstack-protector") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBZT_FLAGS} ${SILENCE} -O3 -Wall -Wextra -std=c++11") - set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${SILENCE} -std=c++11") - set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${LIBZT_FLAGS} ${SILENCE} -O3 -std=c++11") -endif () - -#set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") -#set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-omit-frame-pointer -fsanitize=address") - -# ----------------------------------------------------------------------------- -# | SOURCE FILE GLOBS | -# ----------------------------------------------------------------------------- - -set (LWIP_SRC_DIR "${PROJ_DIR}/ext/lwip/src") -set (ZTO_SRC_DIR "${PROJ_DIR}/ext/ZeroTierOne") -set (LIBZT_SRC_DIR "${PROJ_DIR}/src") - -include_directories ("${LIBZT_SRC_DIR}") -include_directories ("${ZTO_SRC_DIR}/include") -include_directories ("${PROJ_DIR}") -include_directories ("${ZTO_SRC_DIR}/osdep") -include_directories ("${ZTO_SRC_DIR}/node") -include_directories ("${ZTO_SRC_DIR}/service") -include_directories ("${PROJ_DIR}/include") -include_directories ("${LWIP_SRC_DIR}/include") -include_directories ("${LWIP_PORT_DIR}/include") - file (GLOB lwipSrcGlob ${LWIP_SRC_DIR}/netif/*.c ${LWIP_SRC_DIR}/api/*.c @@ -211,176 +217,117 @@ file (GLOB lwipSrcGlob ${LWIP_SRC_DIR}/core/ipv6/*.c) list(REMOVE_ITEM lwipSrcGlob ${LWIP_SRC_DIR}/netif/slipif.c) -file (GLOB ztoSrcGlob - ${ZTO_SRC_DIR}/node/*.cpp - ${ZTO_SRC_DIR}/service/*.cpp - ${ZTO_SRC_DIR}/osdep/OSUtils.cpp - ${ZTO_SRC_DIR}/controller/*.cpp - ${ZTO_SRC_DIR}/osdep/ManagedRoute.cpp) - -file (GLOB libztSrcGlob ${LIBZT_SRC_DIR}/*.cpp) - -file (GLOB ExampleAppSrcGlob - ${PROJ_DIR}/examples/cpp/*.cpp - ${PROJ_DIR}/examples/cpp/ipv4simple/*.cpp - ${PROJ_DIR}/examples/cpp/ipv6simple/*.cpp - ${PROJ_DIR}/examples/cpp/ipv6adhoc/*.cpp - ${PROJ_DIR}/examples/cpp/sharedlib/*.cpp - ${PROJ_DIR}/examples/ztproxy/*.cpp) - - -# header globs for xcode frameworks -file (GLOB frameworkPrivateHeaderGlob - ${INCLUDE_PATH}/libzt.h - ${INCLUDE_PATH}/libztDebug.h) -file (GLOB frameworkPublicHeaderGlob ${INCLUDE_PATH}/Xcode-Bridging-Header.h) -file (GLOB frameworkHeaderGlob ${frameworkPublicHeaderGlob} ${frameworkPrivateHeaderGlob}) - # ----------------------------------------------------------------------------- -# | PLATFORM-SPECIFIC CONFIG | +# | INCLUDES | # ----------------------------------------------------------------------------- -# ANDROID-specific -if (BUILDING_ANDROID) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DSOCKLEN_T_DEFINED=1") - set (ANDROID_NDK /Users/$ENV{USER}/Library/Android/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi) - include_directories (${ANDROID_NDK}) -endif () - -# WINDOWS-specific MSVC flags and libraries -if (BUILDING_WIN) - # 32-bit - if(NOT BUILDING_WIN64) - set (WINLIBDIR, "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x86") - endif () - # 64-bit - if(BUILDING_WIN64) - set (WINLIBDIR, "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x64") - endif () - #find_library (ws2_32_LIBRARY_PATH NAMES WS2_32 HINTS ${WINLIBDIR}) - #find_library (shlwapi_LIBRARY_PATH NAMES ShLwApi HINTS ${WINLIBDIR}) - set (ws2_32_LIBRARY_PATH "${WINLIBDIR}/WS2_32.Lib") - set (shlwapi_LIBRARY_PATH "${WINLIBDIR}/ShLwApi.Lib") - set (iphlpapi_LIBRARY_PATH "${WINLIBDIR}/iphlpapi.Lib") - message (STATUS ${WINLIBDIR}) - message (STATUS "WS2_32=${ws2_32_LIBRARY_PATH}") - message (STATUS "ShLwApi=${shlwapi_LIBRARY_PATH}") - message (STATUS "liphlpapi=${iphlpapi_LIBRARY_PATH}") - add_definitions (-DZT_SDK=1) - add_definitions (-DADD_EXPORTS=1) -endif () - -# ----------------------------------------------------------------------------- -# | OBJECTS-PIC (INTERMEDIATE) | -# ----------------------------------------------------------------------------- - -add_library (lwip_pic ${lwipSrcGlob}) -set_target_properties (lwip_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) -add_library (zto_pic ${ztoSrcGlob}) -set_target_properties (zto_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) -add_library (http_pic "${ZTO_SRC_DIR}/ext/http-parser/http_parser.c") -set_target_properties (http_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) +include_directories (${ZTO_SRC_DIR}) +include_directories (${ZTO_SRC_DIR}/node) +include_directories (${ZTO_SRC_DIR}/osdep) +include_directories (${ZTO_SRC_DIR}/include) +include_directories (${ZTO_SRC_DIR}/ext/miniupnpc) +include_directories (${ZTO_SRC_DIR}/ext/libnatpmp) +include_directories (${PROJ_DIR}/src) +include_directories (${PROJ_DIR}/include) +include_directories (${LWIP_SRC_DIR}/include) +include_directories (${LWIP_PORT_DIR}/include) +include_directories (${PROJ_DIR}/ext/concurrentqueue) # ----------------------------------------------------------------------------- # | OBJECT LIBRARIES (INTERMEDIATE) | # ----------------------------------------------------------------------------- -# lwip_obj -add_library (lwip_obj OBJECT ${lwipSrcGlob}) # zto_obj -add_library (zto_obj OBJECT ${ztoSrcGlob}) +add_library (zto_obj OBJECT ${zerotiercoreSrcGlob}) +set_target_properties (zto_obj PROPERTIES COMPILE_FLAGS "${SILENCE} -std=c++11 -DZT_USE_MINIUPNPC=1 -DZT_SOFTWARE_UPDATE_DEFAULT=0") if (BUILDING_WIN) target_link_libraries (zto_obj ws2_32) target_link_libraries (zto_obj ${shlwapi_LIBRARY_PATH}) target_link_libraries (zto_obj ${iphlpapi_LIBRARY_PATH}) endif () -# http_obj -add_library (http_obj OBJECT "${ZTO_SRC_DIR}/ext/http-parser/http_parser.c") + +# libnatpmp_obj +add_library (libnatpmp_obj OBJECT ${libnatpmpSrcGlob}) +set_target_properties (libnatpmp_obj PROPERTIES COMPILE_FLAGS "") + +# miniupnpc_obj +add_library (miniupnpc_obj OBJECT ${libminiupnpcSrcGlob}) +target_compile_definitions(miniupnpc_obj PRIVATE MACOSX ZT_USE_MINIUPNPC MINIUPNP_STATICLIB _DARWIN_C_SOURCE MINIUPNPC_SET_SOCKET_TIMEOUT MINIUPNPC_GET_SRC_ADDR _BSD_SOURCE _DEFAULT_SOURCE MINIUPNPC_VERSION_STRING=\"2.0\" UPNP_VERSION_STRING=\"UPnP/1.1\" ENABLE_STRNATPMPERR OS_STRING=\"Darwin/15.0.0\") + +# lwip_obj +add_library (lwip_obj OBJECT ${lwipSrcGlob}) +set_target_properties (lwip_obj PROPERTIES COMPILE_FLAGS "") + +# libzt_obj +add_library (libzt_obj OBJECT ${libztSrcGlob}) +set_target_properties (libzt_obj PROPERTIES COMPILE_FLAGS "-std=c++11") + +add_library (lwip_pic ${lwipSrcGlob}) +set_target_properties (lwip_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) +add_library (zto_pic ${zerotiercoreSrcGlob}) +set_target_properties (zto_pic PROPERTIES COMPILE_FLAGS "${SILENCE} -std=c++11") +set_target_properties (zto_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) # ----------------------------------------------------------------------------- -# | LIBZT BUILD TARGETS (FINAL PRODUCT) | +# | BUILD TARGETS (FINAL PRODUCT) | # ----------------------------------------------------------------------------- -# static -add_library (${STATIC_LIB_NAME} STATIC - $ - $ - $ ${libztSrcGlob}) -set_target_properties (${STATIC_LIB_NAME} PROPERTIES OUTPUT_NAME ${STATIC_LIB_OUTPUT_NAME}) +# libzerotiercore.a +add_library (zerotiercore STATIC $) +set_target_properties (zerotiercore PROPERTIES + OUTPUT_NAME zerotiercore + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) -# dynamic -add_library (${DYNAMIC_LIB_NAME} SHARED ${libztSrcGlob}) +# libnatpmp.a +add_library (natpmp STATIC $) +set_target_properties (natpmp PROPERTIES + OUTPUT_NAME natpmp + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + +# libminiupnpc.a +add_library (miniupnpc STATIC $) +set_target_properties (miniupnpc PROPERTIES + OUTPUT_NAME miniupnpc + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + +# liblwip.a +add_library (lwip STATIC $) +set_target_properties (lwip PROPERTIES + OUTPUT_NAME lwip + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + +# libzt.a +add_library (zt STATIC $ +$ +$ +$ +$) +set_target_properties (zt PROPERTIES + OUTPUT_NAME zt + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + +# libzt.so/dylib/dll +add_library (zt-shared SHARED ${libztSrcGlob}) message (STATUS ${libztSrcGlob}) -target_link_libraries (${DYNAMIC_LIB_NAME} lwip_pic zto_pic http_pic) -set_target_properties (${DYNAMIC_LIB_NAME} PROPERTIES OUTPUT_NAME ${DYNAMIC_LIB_OUTPUT_NAME}) -set_target_properties (${DYNAMIC_LIB_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS true) +target_link_libraries (zt-shared lwip_pic zto_pic) +set_target_properties (zt-shared PROPERTIES COMPILE_FLAGS "${SILENCE} -std=c++11 -DZT_SDK") +set_target_properties (zt-shared PROPERTIES OUTPUT_NAME ${DYNAMIC_LIB_OUTPUT_NAME} + WINDOWS_EXPORT_ALL_SYMBOLS true) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) if (BUILDING_ANDROID) - target_link_libraries (${DYNAMIC_LIB_NAME} android log) -endif () - -if (BUILDING_WIN) - target_link_libraries (${STATIC_LIB_NAME} ws2_32) - target_link_libraries (${STATIC_LIB_NAME} ${shlwapi_LIBRARY_PATH}) - target_link_libraries (${STATIC_LIB_NAME} ${iphlpapi_LIBRARY_PATH}) - target_link_libraries (${DYNAMIC_LIB_NAME} ws2_32) - target_link_libraries (${DYNAMIC_LIB_NAME} ${shlwapi_LIBRARY_PATH}) - target_link_libraries (${DYNAMIC_LIB_NAME} ${iphlpapi_LIBRARY_PATH}) -endif () - -if (BUILDING_LINUX OR BUILDING_DARWIN) - target_link_libraries (${STATIC_LIB_NAME} pthread) - target_link_libraries (${DYNAMIC_LIB_NAME} pthread) -endif () - -# xcode framework -if (IN_XCODE) - add_library(${XCODE_FRAMEWORK_NAME} STATIC - $ - $ - $ - ${libztSrcGlob} - ${frameworkHeaderGlob}) - - set_target_properties(${XCODE_FRAMEWORK_NAME} PROPERTIES - FRAMEWORK TRUE - FRAMEWORK_VERSION A - DEFINES_MODULE TRUE - MACOSX_FRAMEWORK_IDENTIFIER com.cmake.${XCODE_FRAMEWORK_NAME} - MODULE_MAP "~/op/zt/libzt/packages/module.modulemap" - PUBLIC_HEADER "${frameworkHeaderGlob}" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer" - ) + target_link_libraries (zt-shared android log) endif () # ----------------------------------------------------------------------------- -# | TEST APPLICATIONS AND EXAMPLES | +# | EXECUTABLES | # ----------------------------------------------------------------------------- if (SHOULD_BUILD_TESTS) -# foreach (testsourcefile ${ExampleAppSrcGlob}) -# string (REPLACE ".cpp" "" testname ${testsourcefile}) -# get_filename_component (testname ${testname} NAME) -# add_executable (${testname} ${testsourcefile}) -# if (BUILDING_WIN) -# target_link_libraries (${testname} ${STATIC_LIB_NAME}) -# else () -# target_link_libraries (${testname} ${STATIC_LIB_NAME} pthread dl) -# endif () -# endforeach (testsourcefile ${ExampleAppSrcGlob}) + add_executable (example ${PROJ_DIR}/test/example.cpp) + target_link_libraries(example zt) -if (NOT BUILDING_WIN) # only necessary for raw driver development - # selftest - #add_executable (selftest ${PROJ_DIR}/test/selftest.cpp) - #target_compile_options (selftest PRIVATE -D__SELFTEST__) - #if (BUILDING_WIN) - # target_link_libraries (selftest ${STATIC_LIB_NAME} ${ws2_32_LIBRARY_PATH} ${shlwapi_LIBRARY_PATH} ${iphlpapi_LIBRARY_PATH}) - #else () - # target_link_libraries (selftest ${STATIC_LIB_NAME} pthread) - #endif () - # nativetest - #add_executable (nativetest ${PROJ_DIR}/test/selftest.cpp) - #target_compile_options (nativetest PRIVATE -D__NATIVETEST__) -endif () -endif () + add_executable (selftest ${PROJ_DIR}/test/selftest.cpp) + target_link_libraries(selftest zt) + set_target_properties (selftest PROPERTIES COMPILE_FLAGS "${SILENCE} -D__SELFTEST__") +endif () \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index aa9609f..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env groovy - -node('master') { - checkout scm - def changelog = getChangeLog currentBuild - mattermostSend "Building ${env.JOB_NAME} #${env.BUILD_NUMBER} \n Change Log: \n ${changelog}" -} - -parallel 'centos7': { - node('centos7') { - try { - checkout scm - sh 'git submodule update --init' - stage('linux') { - sh 'cmake -H. -Bbuild; cmake --build build' - } - } - catch (err) { - currentBuild.result = "FAILURE" - slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on linux (<${env.BUILD_URL}|Open>)" - throw err - } - } -}, - -'macOS': { - node('macOS') { - unlockKeychainMac "~/Library/Keychains/login.keychain-db" - try { - checkout scm - sh 'git submodule update --init' - stage('macOS') { - sh 'cmake -H. -Bbuild; cmake --build build' - } - } - catch (err) { - currentBuild.result = "FAILURE" - slackSend color: '#ff0000', message: "${env.JOB_NAME} broken on macOS (<${env.BUILD_URL}|Open>)" - throw err - } - } -} - -mattermostSend color: "#00ff00", message: "${env.JOB_NAME} #${env.BUILD_NUMBER} Complete (<${env.BUILD_URL}|Show More...>)" \ No newline at end of file diff --git a/Makefile b/Makefile index 914e439..bc0ca4e 100644 --- a/Makefile +++ b/Makefile @@ -1,50 +1,68 @@ -# NOTE: This file only exists as a convenience for cleaning and building -# products for release. To build, use CMake. Instructions in README.md +# +# ZeroTier SDK - Network Virtualization Everywhere +# Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# -- +# +# You can be released from the requirements of the license by purchasing +# a commercial license. Buying such a license is mandatory as soon as you +# develop commercial closed-source software that incorporates or links +# directly against ZeroTier software without disclosing the source code +# of your own application. +# ifeq ($(OS),Windows_NT) -DIST_BUILD_SCRIPT := packages\dist.bat -CLEAN_SCRIPT := packages\clean.bat +DIST_BUILD_SCRIPT := ports\dist.bat +CLEAN_SCRIPT := ports\clean.bat else -DIST_BUILD_SCRIPT := ./packages/dist.sh -CLEAN_SCRIPT := ./packages/clean.sh -PACKAGE_SCRIPT := ./packages/package.sh +DIST_BUILD_SCRIPT := ./ports/dist.sh +CLEAN_SCRIPT := ./ports/clean.sh +PACKAGE_SCRIPT := ./ports/package.sh endif -.PHONY: clean -clean: - $(CLEAN_SCRIPT) - -# Build and package everything -# This command shall be run twice: -# (1) Generates projects -# -# (2) Build products and package everything - -.PHONY: dist -dist: patch - $(DIST_BUILD_SCRIPT) - -.PHONY: package -package: - $(PACKAGE_SCRIPT) - -# Initialize submodules and apply patches -.PHONY: all -all: update patch - cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release - cmake --build build - -# Remove any CMake-generated library-building projects -clean_packages: - rm -rf packages/xcode_ios - rm -rf packages/xcode_macos - -.PHONY: update -update: - git submodule update --init --recursive +CONCURRENT_BUILD_JOBS=2 # Patch submodules patch: -git -C ext/lwip apply ../lwip.patch -git -C ext/lwip-contrib apply ../lwip-contrib.patch - -git -C ext/ZeroTierOne apply ../ZeroTierOne.patch + #-git -C ext/ZeroTierOne apply ../ZeroTierOne.patch + +.PHONY: clean +clean: + rm -rf bin staging generated + +all: debug release + +release: + -mkdir generated + cmake -H. -Bgenerated/release -DCMAKE_BUILD_TYPE=Release + cmake --build generated/release -j $(CONCURRENT_BUILD_JOBS) + +debug: + -mkdir generated + cmake -H. -Bgenerated/debug -DCMAKE_BUILD_TYPE=Debug + cmake --build generated/debug -j $(CONCURRENT_BUILD_JOBS) + +# dist: +# Build and package everything +# This command shall be run twice: +# (1) Generates projects +# +# (2) Build products and package everything +.PHONY: dist +dist: patch + $(DIST_BUILD_SCRIPT) diff --git a/README.md b/README.md index 4e37aba..385488a 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ Java JNI API: [ZeroTier.java](packages/android/app/src/main/java/ZeroTier.java) ### C++ Example ``` +#include #include +#include #include "libzt.h" @@ -36,15 +38,14 @@ int main() char *remoteIp = "10.8.8.42"; int remotePort = 8080; int fd, err = 0; - struct zts_sockaddr_in addr; - addr.sin_family = ZTS_AF_INET; + struct sockaddr_in addr; + addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(remoteIp); addr.sin_port = htons(remotePort); zts_startjoin("path", 0xc7cd7c981b0f52a2); // config path, network ID - printf("nodeId=%llx\n", zts_get_node_id()); - if ((fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0)) < 0) { + if ((fd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("error creating socket\n"); } if ((err = zts_connect(fd, (const struct sockaddr *)&addr, sizeof(addr))) < 0) { diff --git a/examples/android/ExampleAndroidApp/.project b/examples/android/ExampleAndroidApp/.project new file mode 100644 index 0000000..552deba --- /dev/null +++ b/examples/android/ExampleAndroidApp/.project @@ -0,0 +1,17 @@ + + + ExampleAndroidApp + Project ExampleAndroidApp created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/examples/android/ExampleAndroidApp/.settings/org.eclipse.buildship.core.prefs b/examples/android/ExampleAndroidApp/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..e889521 --- /dev/null +++ b/examples/android/ExampleAndroidApp/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/examples/android/ExampleAndroidApp/app/.classpath b/examples/android/ExampleAndroidApp/app/.classpath new file mode 100644 index 0000000..7c0adb0 --- /dev/null +++ b/examples/android/ExampleAndroidApp/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/examples/android/ExampleAndroidApp/app/.project b/examples/android/ExampleAndroidApp/app/.project new file mode 100644 index 0000000..ac485d7 --- /dev/null +++ b/examples/android/ExampleAndroidApp/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/examples/android/ExampleAndroidApp/app/.settings/org.eclipse.buildship.core.prefs b/examples/android/ExampleAndroidApp/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..b1886ad --- /dev/null +++ b/examples/android/ExampleAndroidApp/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/examples/android/ExampleAndroidApp/app/build.gradle b/examples/android/ExampleAndroidApp/app/build.gradle index 7fedf3e..09578e2 100644 --- a/examples/android/ExampleAndroidApp/app/build.gradle +++ b/examples/android/ExampleAndroidApp/app/build.gradle @@ -20,15 +20,25 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } + release { + debuggable true + jniDebuggable true + minifyEnabled false + } } } dependencies { + implementation 'com.squareup.picasso:picasso:2.71828' implementation files('libs/libzt-android-debug.aar') implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0-alpha3' + implementation("com.squareup.okhttp3:okhttp:3.12.0") implementation 'com.android.support.constraint:constraint-layout:1.1.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + + implementation 'com.github.bumptech.glide:glide:4.6.1' + annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1' } diff --git a/examples/android/ExampleAndroidApp/app/libs/libzt-android-debug.aar b/examples/android/ExampleAndroidApp/app/libs/libzt-android-debug.aar new file mode 100644 index 0000000..b0f4345 Binary files /dev/null and b/examples/android/ExampleAndroidApp/app/libs/libzt-android-debug.aar differ diff --git a/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/HTTPWorker.java b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/HTTPWorker.java new file mode 100644 index 0000000..0f15fb8 --- /dev/null +++ b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/HTTPWorker.java @@ -0,0 +1,79 @@ +package com.example.exampleandroidapp; + +import com.zerotier.libzt.ZeroTierSocketFactory; +import com.zerotier.libzt.ZeroTier; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.concurrent.ThreadLocalRandom; + +import okhttp3.FormBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +public class HTTPWorker extends Thread { + + @Override + public void run() { + long tid = Thread.currentThread().getId(); + // Test: Perform randomly-delayed HTTP GET requests + if (true) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.socketFactory(new ZeroTierSocketFactory()); + OkHttpClient client = builder.build(); + Request request1 = new Request.Builder() + .url("http://11.7.7.223:80/warandpeace.txt") + .build(); + Request request2 = new Request.Builder() + .url("http://11.7.7.223:8082/pumpkin.jpg") + .build(); + RequestBody formBody = new FormBody.Builder() + .add("message", "Your message") + .build(); + Request request3 = new Request.Builder() + .url("http://11.7.7.223:8082/") + .post(formBody) + .build(); + + long i = 0; + for (;;) { + try { + System.out.println("PEER STATUS IS = " + ZeroTier.get_peer_status(0x7caea82fc4L)); + int randomNum = ThreadLocalRandom.current().nextInt(0, 2 + 1); + i++; + Response response = null; + if (randomNum == 0) { + response = client.newCall(request1).execute(); + } + if (randomNum == 1) { + //response = client.newCall(request2).execute(); + response = client.newCall(request1).execute(); + } + if (randomNum == 2) { + //response = client.newCall(request3).execute(); + response = client.newCall(request1).execute(); + //System.out.println(tid+"::POST"); + //continue; + } + InputStream in = response.body().byteStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[16384]; + while ((nRead = in.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + System.out.println(tid+"::GET: i="+i+", len="+buffer.toByteArray().length); + + } catch (Exception e) { + System.out.println(e); + e.printStackTrace(); + //System.exit(0); + } + + } + } + } + +} \ No newline at end of file diff --git a/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MainActivity.java b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MainActivity.java index 3e8edae..12a6425 100644 --- a/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MainActivity.java +++ b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MainActivity.java @@ -1,103 +1,442 @@ package com.example.exampleandroidapp; +import java.util.concurrent.ThreadLocalRandom; +import java.io.ByteArrayOutputStream; +import java.net.*; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okhttp3.FormBody; + import com.zerotier.libzt.ZeroTier; -import com.zerotier.libzt.ZTSocketAddress; -import com.zerotier.libzt.ZTFDSet; +import com.zerotier.libzt.ZeroTierSocket; +import com.zerotier.libzt.ZeroTierSocketFactory; +import com.zerotier.libzt.ZeroTierSSLSocketFactory; +//import com.zerotier.libzt.ZeroTierEventListener; +import com.zerotier.libzt.ZeroTierSocketImplFactory; +import com.example.exampleandroidapp.MyZeroTierEventListener; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +//import java.net.HttpURLConnection; +import javax.net.ssl.HttpsURLConnection; +import java.net.URL; +import javax.net.ssl.SSLContext; + +import com.squareup.picasso.Picasso; +import com.squareup.picasso.Callback; +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.RequestManager; +import android.widget.ImageView; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; public class MainActivity extends AppCompatActivity { + String requestURL = "http://11.7.7.223:80/"; - // Used to load the 'native-lib' library on application startup. - static { - System.loadLibrary("zt-shared"); + private static String createDataSize(int msgSize) { + StringBuilder sb = new StringBuilder(msgSize); + for (int i=0; i threads = new ArrayList<>(); + for(int i = 0;i < 5;i++){ + try { + Thread.sleep(500); + } catch (Exception e) {} + HTTPWorker thread = new HTTPWorker(); + thread.start(); + threads.add(thread); + } + + System.out.println("sleeping..."); + try { + Thread.sleep(60000000); + } catch (Exception e) {} + + System.exit(0); + + // Test: setsockopt() and getsockopt() [non-exhaustive] + /* + if (true) { + try { + ZeroTierSocket zts = new ZeroTierSocket(); + zts.connect(new InetSocketAddress("11.7.7.223", 8082)); + zts.setSoTimeout(1337); + int to = zts.getSoTimeout(); + assert to == 1337; + + } catch (Exception e) { + + } + } + */ + + // Test: Perform randomly-delayed HTTP GET requests + if (false) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.socketFactory(new ZeroTierSocketFactory()); + OkHttpClient client = builder.build(); + Request request1 = new Request.Builder() + .url("http://11.7.7.223:8082/") + .build(); + + long i = 0; + for (;;) { + try { + Thread.sleep((long)(Math.random() * 250)); + Response response = client.newCall(request1).execute(); + i++; + System.out.println("GET: i="+i+", len="+response.toString().length()); + //response.close(); + + } catch (Exception e) { + System.out.println(e); + System.exit(0); + e.printStackTrace(); + } + + } + } + + // Test: Perform randomly-delayed HTTP GET requests + if (true) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.socketFactory(new ZeroTierSocketFactory()); + OkHttpClient client = builder.build(); + Request request1 = new Request.Builder() + .url("http://11.7.7.223:80/warandpeace.txt") + .header("Transfer-Encoding", "chunked") + //.header("Connection","close") + .build(); + + Request request2 = new Request.Builder() + .url("http://11.7.7.223:8082/pumpkin.jpg") + .header("Transfer-Encoding", "chunked") + .header("Connection","close") + .build(); + + String postMessage = "what?"; + try { + postMessage = new String(createDataSize(1024).getBytes(), "UTF8"); + } + catch (Exception e) + { + System.out.println(e); + } + + MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + okhttp3.RequestBody body = RequestBody.create(JSON, postMessage); + + //RequestBody formBody = new FormBody.Builder() + // .add("message", postMessage) + // .build(); + Request request3 = new Request.Builder() + .url("http://11.7.7.223:8082/") + //.retryOnConnectionFailure(true) + .header("Transfer-Encoding", "chunked") + .header("Connection","close") + //.header("Connection","keep-alive") + .post(body) + .build(); + + long i = 0; + for (;;) { + try { + System.out.println("iteration="+i); + int randomNum = ThreadLocalRandom.current().nextInt(0, 2 + 1); + Thread.sleep(10); + i++; + Response response = null; + if (randomNum == 0) { + System.out.println("(0) GET: war"); + response = client.newCall(request1).execute(); + + } + if (randomNum == 1) { + System.out.println("(1) GET: pumpkin"); + response = client.newCall(request2).execute(); + + } + if (randomNum == 2) { + System.out.println("(2) POST: data"); + response = client.newCall(request3).execute(); + response.close(); + continue; + } + InputStream in = response.body().byteStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[16384]; + while ((nRead = in.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + System.out.println("GET: i="+i+", len="+buffer.toByteArray().length); + response.close(); + + } catch (Exception e) { + System.out.println(e); + e.printStackTrace(); + } + + } + } + + + // Test: Perform randomly-delayed HTTP GET requests + if (true) { + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.socketFactory(new ZeroTierSocketFactory()); + OkHttpClient client = builder.build(); + + Request request = new Request.Builder() + .url(requestURL+"warandpeace.txt") + .build(); + + long i = 0; + for (;;) { + try { + //Thread.sleep((long)(Math.random()) ); + //System.out.println("iteration="+i); + i++; + Response response = client.newCall(request).execute(); + //System.out.println(response.body().string()); + + InputStream in = response.body().byteStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[16384]; + while ((nRead = in.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + System.out.println("\tCOMPLETE, i="+i+", len="+buffer.toByteArray().length); + + + /* + //Bitmap bitmap = BitmapFactory.decodeByteArray(buffer.toByteArray(), 0, buffer.toByteArray().length); + //ImageView imageView = (ImageView) findViewById(R.id.imageView); + //imageView.setImageBitmap(bitmap); + */ + /* + BufferedInputStream bufferedInputStream = new BufferedInputStream(in); + Bitmap bitmap=BitmapFactory.decodeStream(bufferedInputStream); + ImageView imageView = (ImageView) findViewById(R.id.imageView); + imageView.setImageBitmap(bitmap); + */ + + // + // Thread.sleep(5000); + //response.close(); + } catch (Exception e) { + System.out.println("EXCEPTION:"+e); + //System.exit(0); + e.printStackTrace(); + } + + } + } + + + + // ... + + // Test #2: HttpURLConnection + if (false) + { + + + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + + SSLContext context = null; + + // Set runtime default socket implementation factory + try { + //Socket.setSocketImplFactory(new ZeroTierSocketImplFactory()); + //SSLSocket.setSocketImplFactory(new ZeroTierSocketImplFactory()); + + context = SSLContext.getInstance("SSL"); + //context.init(null, null, null); + context.init(null, trustAllCerts, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); + } catch (Exception e) { + e.printStackTrace(); + } + + // Create all-trusting host name verifier + HostnameVerifier allHostsValid = new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + // Install the all-trusting host verifier + HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); + + + ZeroTierSSLSocketFactory customSocketFactory = new ZeroTierSSLSocketFactory(context.getSocketFactory()); + HttpsURLConnection.setDefaultSSLSocketFactory(customSocketFactory); + + + + + // Test HTTP client + String GET_URL = "https://10.6.6.152"; + String USER_AGENT = "Mozilla/5.0"; + try { + URL obj = new URL(GET_URL); + HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); + + con.setSSLSocketFactory(customSocketFactory); + + con.setRequestMethod("GET"); + con.setRequestProperty("User-Agent", USER_AGENT); + System.out.println("neat?"); + int responseCode = con.getResponseCode(); + System.out.println("GET Response Code :: " + responseCode); + if (responseCode == HttpsURLConnection.HTTP_OK) + { + // success + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + System.out.println(response.toString()); + } else { + System.out.println("GET request failed"); + } + } catch (Exception e) { + e.printStackTrace(); + System.out.println(e); + } } - ).start(); } } diff --git a/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MyZeroTierEventListener.java b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MyZeroTierEventListener.java new file mode 100644 index 0000000..27c6d89 --- /dev/null +++ b/examples/android/ExampleAndroidApp/app/src/main/java/com/example/exampleandroidapp/MyZeroTierEventListener.java @@ -0,0 +1,82 @@ +package com.example.exampleandroidapp; + +import com.zerotier.libzt.ZeroTier; +import com.zerotier.libzt.ZeroTierEventListener; + +public class MyZeroTierEventListener implements ZeroTierEventListener { + + public boolean isNetworkReady = false; + public boolean isOnline = false; + + public void onZeroTierEvent(long id, int eventCode) + { + if (eventCode == ZeroTier.EVENT_NODE_UP) { + System.out.println("EVENT_NODE_UP: nodeId=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NODE_ONLINE) { + // The core service is running properly and can join networks now + System.out.println("EVENT_NODE_ONLINE: nodeId=" + Long.toHexString(ZeroTier.get_node_id())); + isOnline = true; + } + if (eventCode == ZeroTier.EVENT_NODE_OFFLINE) { + // Network does not seem to be reachable by any available strategy + System.out.println("EVENT_NODE_OFFLINE"); + } + if (eventCode == ZeroTier.EVENT_NODE_DOWN) { + // Called when the node is shutting down + System.out.println("EVENT_NODE_DOWN"); + } + if (eventCode == ZeroTier.EVENT_NODE_IDENTITY_COLLISION) { + // Another node with this identity already exists + System.out.println("EVENT_NODE_IDENTITY_COLLISION"); + } + if (eventCode == ZeroTier.EVENT_NODE_UNRECOVERABLE_ERROR) { + // Try again + System.out.println("EVENT_NODE_UNRECOVERABLE_ERROR"); + } + if (eventCode == ZeroTier.EVENT_NODE_NORMAL_TERMINATION) { + // Normal closure + System.out.println("EVENT_NODE_NORMAL_TERMINATION"); + } + if (eventCode == ZeroTier.EVENT_NETWORK_READY_IP4) { + // We have at least one assigned address and we've received a network configuration + System.out.println("ZTS_EVENT_NETWORK_READY_IP4: nwid=" + Long.toHexString(id)); + isNetworkReady = true; + } + if (eventCode == ZeroTier.EVENT_NETWORK_READY_IP6) { + // We have at least one assigned address and we've received a network configuration + System.out.println("ZTS_EVENT_NETWORK_READY_IP6: nwid=" + Long.toHexString(id)); + isNetworkReady = true; + } + if (eventCode == ZeroTier.EVENT_NETWORK_DOWN) { + // Someone called leave(), we have no assigned addresses, or otherwise cannot use this interface + System.out.println("EVENT_NETWORK_DOWN: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NETWORK_REQUESTING_CONFIG) { + // Waiting for network configuration + System.out.println("EVENT_NETWORK_REQUESTING_CONFIG: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NETWORK_OK) { + // Config received and this node is authorized for this network + System.out.println("EVENT_NETWORK_OK: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NETWORK_ACCESS_DENIED) { + // You are not authorized to join this network + System.out.println("EVENT_NETWORK_ACCESS_DENIED: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NETWORK_NOT_FOUND) { + // The virtual network does not exist + System.out.println("EVENT_NETWORK_NOT_FOUND: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_NETWORK_CLIENT_TOO_OLD) { + // The core version is too old + System.out.println("EVENT_NETWORK_CLIENT_TOO_OLD: nwid=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_PEER_P2P) { + System.out.println("EVENT_PEER_P2P: id=" + Long.toHexString(id)); + } + if (eventCode == ZeroTier.EVENT_PEER_RELAY) { + System.out.println("EVENT_PEER_RELAY: id=" + Long.toHexString(id)); + } + } +} diff --git a/examples/android/ExampleAndroidApp/app/src/main/res/layout/activity_main.xml b/examples/android/ExampleAndroidApp/app/src/main/res/layout/activity_main.xml index 84f1951..6b12ce5 100644 --- a/examples/android/ExampleAndroidApp/app/src/main/res/layout/activity_main.xml +++ b/examples/android/ExampleAndroidApp/app/src/main/res/layout/activity_main.xml @@ -15,4 +15,12 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.sln b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.sln deleted file mode 100644 index 618e086..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2027 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleWindowsCSharpApp", "ExampleWindowsCSharpApp\ExampleWindowsCSharpApp.csproj", "{74F548E3-64FD-41FF-9416-0AE1FC24E8BE}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {74F548E3-64FD-41FF-9416-0AE1FC24E8BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {74F548E3-64FD-41FF-9416-0AE1FC24E8BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {74F548E3-64FD-41FF-9416-0AE1FC24E8BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {74F548E3-64FD-41FF-9416-0AE1FC24E8BE}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BC236939-C661-4FEB-8935-4A61C2ECEC19} - EndGlobalSection -EndGlobal diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/App.config b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/App.config deleted file mode 100644 index 00bfd11..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.csproj b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.csproj deleted file mode 100644 index 8dd76e7..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp.csproj +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Debug - AnyCPU - {74F548E3-64FD-41FF-9416-0AE1FC24E8BE} - Exe - ExampleWindowsCSharpApp - ExampleWindowsCSharpApp - v4.6.1 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Program.cs b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Program.cs deleted file mode 100644 index 03fc748..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Program.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -using System.Net; - -using ZeroTier; - -namespace ExampleWindowsCSharpApp -{ - class Program - { - static void Main(string[] args) - { - ulong nwid = 0xe4da7455b2b9ee6a; - - Console.Write("waiting for libzt to come online...\n"); - libzt.zts_startjoin("config_path", nwid); - Console.Write("I am " + libzt.zts_get_node_id().ToString("X") +"\n"); - Console.Write("ZT ready\n"); - - int fd; - int err = 0; - bool clientMode = false; - - if ((fd = libzt.zts_socket(2, 1, 0)) < 0) - { - Console.Write("error creating socket\n"); - } - - // CLIENT - if (clientMode == true) - { - string remoteAddrStr = "172.28.221.116"; - Int16 remotePort = 2323; - // Convert managed address object to pointer for unmanaged code - libzt.SockAddrIn addr = new libzt.SockAddrIn(); - addr.Family = (byte)libzt.SockAddrFamily.Inet; - addr.Port = IPAddress.HostToNetworkOrder((Int16)remotePort); - addr.Addr = (uint)IPAddress.Parse(remoteAddrStr).Address; - IntPtr addrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(libzt.SockAddrIn))); - Marshal.StructureToPtr(addr, addrPtr, false); - int addrlen = Marshal.SizeOf(addr); - - if ((err = libzt.zts_connect(fd, addrPtr, addrlen)) < 0) - { - Console.Write("error connecting to remote server\n"); - } - - // Send message - string msgStr = "Hello from C#!"; - byte[] msgBuf = Encoding.ASCII.GetBytes(msgStr); - int buflen = System.Text.ASCIIEncoding.ASCII.GetByteCount(msgStr); - - if ((err = libzt.zts_write(fd, msgBuf, buflen)) < 0) - { - Console.Write("error writing to remote server\n"); - } - - libzt.zts_close(fd); - Marshal.FreeHGlobal(addrPtr); - } - else // SERVER - { - string localAddrStr = "0.0.0.0"; - Int16 bindPort = 5050; - libzt.SockAddrIn addr = new libzt.SockAddrIn(); - addr.Family = (byte)libzt.SockAddrFamily.Inet; - addr.Port = IPAddress.HostToNetworkOrder((Int16)bindPort); - addr.Addr = (uint)IPAddress.Parse(localAddrStr).Address; - IntPtr addrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(libzt.SockAddrIn))); - Marshal.StructureToPtr(addr, addrPtr, false); - int addrlen = Marshal.SizeOf(addr); - - if ((err = libzt.zts_bind(fd, addrPtr, addrlen)) < 0) - { - Console.Write("error binding to local port\n"); - } - if ((err = libzt.zts_listen(fd, 1)) < 0) - { - Console.Write("error putting socket in listening state\n"); - } - int accfd; - Console.Write("waiting to accept connection...\n"); - if ((accfd = libzt.zts_accept(fd, IntPtr.Zero, IntPtr.Zero)) < 0) - { - Console.Write("error accepting incoming connection\n"); - } - Console.Write("accepted connection!\n"); - - - // Read message - byte[] msgBuf = new byte[32]; - int buflen = 32; - Console.Write("reading from client...\n"); - if ((err = libzt.zts_read(accfd, msgBuf, buflen)) < 0) - { - Console.Write("error reading from remote client\n"); - } - Console.Write("read " + err + " bytes from client\n"); - string msgStr = System.Text.Encoding.UTF8.GetString(msgBuf, 0, msgBuf.Length); - Console.Write("msg from client = " + msgStr + "\n"); - - libzt.zts_close(fd); - libzt.zts_close(accfd); - Marshal.FreeHGlobal(addrPtr); - } - - Console.Write("fd=" + fd); - Console.Write("wrote=" + err); - - libzt.zts_stop(); - } - } -} diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Properties/AssemblyInfo.cs b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Properties/AssemblyInfo.cs deleted file mode 100644 index 86e2265..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ExampleWindowsCSharpApp")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ExampleWindowsCSharpApp")] -[assembly: AssemblyCopyright("Copyright © 2018")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("74f548e3-64fd-41ff-9416-0ae1fc24e8be")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/libzt.cs b/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/libzt.cs deleted file mode 100644 index d1683e7..0000000 --- a/examples/csharp/ExampleWindowsCSharpApp/ExampleWindowsCSharpApp/libzt.cs +++ /dev/null @@ -1,184 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using System.Runtime.InteropServices; - -namespace ZeroTier -{ - static class libzt - { - public enum SockAddrFamily - { - Inet = 2, - Inet6 = 10 - } - - [StructLayout(LayoutKind.Sequential)] - public struct SockAddr - { - public ushort Family; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] - public byte[] Data; - }; - - [StructLayout(LayoutKind.Sequential)] - public struct SockAddrIn - { - byte len; // unique to lwIP - public byte Family; - public Int16 Port; - public uint Addr; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] Zero; - } - - [StructLayout(LayoutKind.Sequential)] - public struct SockAddrIn6 - { - public ushort Family; - public ushort Port; - public uint FlowInfo; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] - public byte[] Addr; - public uint ScopeId; - }; - - /****************************************************************************/ - /* ZeroTier Service Controls */ - /****************************************************************************/ - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_start(string path); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_startjoin(string path, ulong nwid); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_stop(); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_join(ulong nwid); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_leave(ulong nwid); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_get_homepath(string homePath, int len); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern Int64 zts_get_node_id(); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_running(); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_has_address(ulong nwid); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_get_address(ulong nwid, IntPtr addr, int address_family); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_get_6plane_addr(IntPtr addr, string nwid, string nodeId); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void zts_get_rfc4193_addr(IntPtr addr, string nwid, string nodeId); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern long zts_get_peer_count(); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_get_peer_address(string peer, ulong nodeId); - - /****************************************************************************/ - /* Socket-like API */ - /****************************************************************************/ - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_socket(int socket_family, int socket_type, int protocol); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_connect(int fd, IntPtr addr, int addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_bind(int fd, IntPtr addr, int addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_listen(int fd, int backlog); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_accept(int fd, IntPtr addr, IntPtr addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_setsockopt(int fd, int level, int optname, IntPtr optval, int optlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_getsockopt(int fd, int level, int optname, IntPtr optval, IntPtr optlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_getsockname(int fd, IntPtr addr, IntPtr addrlen); - - /* - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_getpeername(int fd, System.IntPtr addr, IntPtr addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_gethostname(string name, int len); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_sethostname(string name, int len); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - unsafe public static extern IntPtr *zts_gethostbyname(string name); - */ - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_close(int fd); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_select(int nfds, IntPtr readfds, IntPtr writefds, IntPtr exceptfds, IntPtr timeout); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_fcntl(int fd, int cmd, int flags); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_ioctl(int fd, ulong request, IntPtr argp); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_send(int fd, byte[] buf, int len, int flags); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_sendto(int fd, byte[] buf, int len, int flags, IntPtr addr, int addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_sendmsg(int fd, byte[] msg, int flags); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_recv(int fd, byte[] buf, int len, int flags); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_recvfrom(int fd, byte[] buf, int len, int flags, IntPtr addr, IntPtr addrlen); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_recvmsg(int fd, byte[] msg, int flags); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_read(int fd, byte[] buf, int len); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_write(int fd, byte[] buf, int len); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_shutdown(int fd, int how); - -/* - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_add_dns_nameserver(System.IntPtr addr); - - [DllImport("libzt.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int zts_del_dns_nameserver(System.IntPtr addr); -*/ - } -} diff --git a/examples/java/ExampleApp.java b/examples/java/ExampleApp.java deleted file mode 100644 index 245e194..0000000 --- a/examples/java/ExampleApp.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -// Simple Java example for libzt using JNI - -import com.zerotier.libzt.ZeroTier; -import com.zerotier.libzt.ZTSocketAddress; -import com.zerotier.libzt.ZTFDSet; - -import java.lang.Thread; - -public class ExampleApp { - - static { System.loadLibrary("zt"); } // load libzt.dylib or libzt.so - - static void sleep(int ms) - { - try { Thread.sleep(ms); } - catch (InterruptedException e) { e.printStackTrace(); } - } - - public static void main(String[] args) - { - - final ZeroTier zt = new ZeroTier(); - - new Thread(new Runnable() - { - public void run() - { - String path = "/Users/joseph/op/zt/libzt/ztjni"; // Where node's config files are stored - long nwid = 0xa09acf7233e4b071L; - - // Test modes - boolean blocking_start_call = true; - boolean client_mode = false; - boolean tcp = false; - boolean loop = true; // RX/TX multiple times - boolean idle = false; // Idle loop after node comes online. For testing reachability - boolean use_select = true; - - int fd = -1, client_fd = -1, err, r, w, lengthToRead = 0, flags = 0; - byte[] rxBuffer; - byte[] txBuffer = "welcome to the machine".getBytes(); - String remoteAddrStr = "11.7.7.107"; - String localAddrStr = "0.0.0.0"; - int portNo = 4040; - - ZTSocketAddress remoteAddr, localAddr; - ZTSocketAddress sockname = new ZTSocketAddress(); - ZTSocketAddress addr = new ZTSocketAddress(); - - // METHOD 1 (easy) - // Blocking call that waits for all components of the service to start - System.out.println("Starting ZT service..."); - if (blocking_start_call) { - zt.startjoin(path, nwid); - } - // METHOD 2 - // Optional. Non-blocking call to start service. You'll have to use the below process to determine - // when you are allowed to start making socket calls. - if (!blocking_start_call) { - zt.start(path, true); - while(!zt.ready()) { - try { // Wait for core service to start - Thread.sleep(250); - } - catch(InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - System.out.println("Core started. Networks can be joined after this point"); - zt.join(nwid); - // Wait for userspace stack to start, we trigger this by joining a network - while(!zt.stack_running()) { - try { - Thread.sleep(1000); - } - catch(InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - System.out.println("ZT service ready."); - // Device/Node address info - System.out.println("path=" + zt.get_path()); - long nodeId = zt.get_node_id(); - System.out.println("nodeId=" + Long.toHexString(nodeId)); - int numAddresses = zt.get_num_assigned_addresses(nwid); - System.out.println("this node has (" + numAddresses + ") assigned addresses on network " + Long.toHexString(nwid)); - for (int i=0; i 0) { - System.out.println("select detected something to read on"); - for (int i = 0; i < nfds; i++) - { - if (master_set.ISSET(i)) - { - System.out.println("attempting to read from: " + i); - r = zt.recvfrom(fd, rxBuffer, flags, remoteAddr); - System.out.println("read (" + r + ") bytes from " + remoteAddr.toString() + ", buffer = " + new String(rxBuffer)); - } - } - } - } - } - if (!use_select) - { - while(true) { - addr = new ZTSocketAddress(); - r = zt.recvfrom(fd, rxBuffer, flags, remoteAddr); - System.out.println("read (" + r + ") bytes from " + remoteAddr.toString() + ", buffer = " + new String(rxBuffer)); - } - } - } - } - - zt.close(client_fd); - zt.close(fd); - } - }).start(); - - while(true) - { - try { Thread.sleep(3000); } - catch (InterruptedException e) { e.printStackTrace(); } - } - } -} \ No newline at end of file diff --git a/examples/java/README.md b/examples/java/README.md deleted file mode 100644 index c5472b9..0000000 --- a/examples/java/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## ZeroTier with Java via JNI -*** - -### ExampleApp - -Copy `zt.jar` file into this directory -Extract shared library from JAR file: `jar xf zt.jar libzt.dylib` -Build ExampleApp: `javac -cp ".:zt.jar" ExampleApp.java` \ No newline at end of file diff --git a/examples/java/com/zerotier/libzt/ZTFDSet.java b/examples/java/com/zerotier/libzt/ZTFDSet.java deleted file mode 100644 index cf5bd7b..0000000 --- a/examples/java/com/zerotier/libzt/ZTFDSet.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -public class ZTFDSet -{ - byte[] fds_bits = new byte[1024]; - - public void CLR(int fd) - { - fds_bits[fd] = 0x00; - } - - public boolean ISSET(int fd) - { - return fds_bits[fd] == 0x01; - } - - public void SET(int fd) - { - fds_bits[fd] = 0x01; - } - - public void ZERO() - { - for (int i=0; i<1024; i++) { - fds_bits[i] = 0x00; - } - } -} \ No newline at end of file diff --git a/examples/java/com/zerotier/libzt/ZTSocketAddress.java b/examples/java/com/zerotier/libzt/ZTSocketAddress.java deleted file mode 100644 index c922251..0000000 --- a/examples/java/com/zerotier/libzt/ZTSocketAddress.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import com.zerotier.libzt.ZeroTier; - -import java.net.InetAddress; - -// Designed to transport address information across the JNI boundary -public class ZTSocketAddress -{ - public byte[] _ip6 = new byte[16]; - public byte[] _ip4 = new byte[4]; - - public int _family; - public int _port; // Also reused for netmask or prefix - - public ZTSocketAddress() {} - - public ZTSocketAddress(String ipStr, int port) - { - if(ipStr.contains(":")) { - _family = ZeroTier.AF_INET6; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip6 = ip.getAddress(); - } - catch (Exception e) { } - } - else if(ipStr.contains(".")) { - _family = ZeroTier.AF_INET; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip4 = ip.getAddress(); - } - catch (Exception e) { } - } - _port = port; - } - - public int getPort() { return _port; } - public int getNetmask() { return _port; } - public int getPrefix() { return _port; } - - private String ipString() - { - if (_family == ZeroTier.AF_INET) { - try { - InetAddress inet = InetAddress.getByAddress(_ip4); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - if (_family == ZeroTier.AF_INET6) { - try { - InetAddress inet = InetAddress.getByAddress(_ip6); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - return ""; - } - - public String toString() { return ipString() + ":" + _port; } - public String toCIDR() { return ipString() + "/" + _port; } -} diff --git a/examples/java/com/zerotier/libzt/ZeroTier.java b/examples/java/com/zerotier/libzt/ZeroTier.java deleted file mode 100644 index 26e337b..0000000 --- a/examples/java/com/zerotier/libzt/ZeroTier.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import java.net.*; - -public class ZeroTier { - - public static int AF_INET = 2; - public static int AF_INET6 = 30; - public static int SOCK_STREAM = 1; - public static int SOCK_DGRAM = 2; - public static int O_APPEND = 1024; - public static int O_NONBLOCK = 2048; - public static int O_ASYNC = 8192; - public static int O_DIRECT = 65536; - public static int O_NOATIME = 262144; - public static int F_GETFL = 3; - public static int F_SETFL = 4; - - public native void start(String homePath, boolean blocking); - public native void startjoin(String homePath, long nwid); - public native void stop(); - public native boolean core_running(); - public native boolean stack_running(); - public native boolean ready(); - public native int join(long nwid); - public native int leave(long nwid); - public native String get_path(); - public native long get_node_id(); - public native int get_num_assigned_addresses(long nwid); - public native boolean get_address_at_index(long nwid, int index, ZTSocketAddress addr); - public native boolean has_address(long nwid); - public native boolean get_address(long nwid, int address_family, ZTSocketAddress addr); - public native void get_6plane_addr(long nwid, long nodeId, ZTSocketAddress addr); - public native void get_rfc4193_addr(long nwid, long nodeId, ZTSocketAddress addr); - - public native int socket(int family, int type, int protocol); - public native int connect(int fd, ZTSocketAddress addr); - public native int bind(int fd, ZTSocketAddress addr); - public native int listen(int fd, int backlog); - public native int accept(int fd, ZTSocketAddress addr); - public native int accept4(int fd, String addr, int port); - public native int close(int fd); - public native int setsockopt(int fd, int level, int optname, int optval, int optlen); - public native int getsockopt(int fd, int level, int optname, int optval, int optlen); - public native int sendto(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int send(int fd, byte[] buf, int flags); - public native int recv(int fd, byte[] buf, int flags); - public native int recvfrom(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int read(int fd, byte[] buf); - public native int write(int fd, byte[] buf); - public native int shutdown(int fd, int how); - public native boolean getsockname(int fd, ZTSocketAddress addr); - public native int getpeername(int fd, ZTSocketAddress addr); - public native int fcntl(int sock, int cmd, int flag); - public native int select(int nfds, ZTFDSet readfds, ZTFDSet writefds, ZTFDSet exceptfds, int timeout_sec, int timeout_usec); -} \ No newline at end of file diff --git a/examples/layer2/layer2.cpp b/examples/layer2/layer2.cpp deleted file mode 100644 index 50b82ce..0000000 --- a/examples/layer2/layer2.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// This file is built with libzt.a via `make tests` - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if defined(__APPLE__) -#include -#endif -#if defined(__linux__) -#include -#include -#include -#include -#endif - -#include "libzt.h" - -unsigned short csum(unsigned short *buf, int nwords) -{ - unsigned long sum; - for(sum=0; nwords>0; nwords--) - sum += *buf++; - sum = (sum >> 16) + (sum &0xffff); - sum += (sum >> 16); - return (unsigned short)(~sum); -} - -int main(int argc , char *argv[]) -{ - if (argc < 3) { - fprintf(stderr, "usage: layer2 \n"); - return 1; - } - - // initialize library - printf("Starting libzt...\n"); - zts_startjoin(argv[1], strtoull(argv[2], NULL, 16)); - uint64_t device_id = zts_get_node_id(); - fprintf(stderr, "Complete. I am %llx\n", device_id); - - // create socket - int fd; - if ((fd = zts_socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) { - printf("There was a problem creating the raw socket\n"); - exit(-1); - } - fprintf(stderr, "Created raw socket (%d)\n", fd); - -#if defined(__APPLE__) - fprintf(stderr, "SOCK_RAW not supported on mac builds yet. exiting"); - exit(0); -#endif -#if defined(__linux__) // The rest of this file isn't yet supported on non-linux platforms - // get interface index to bind on - struct ifreq if_idx; - memset(&if_idx, 0, sizeof(struct ifreq)); - strncpy(if_idx.ifr_name, "libzt0", IFNAMSIZ-1); - if (zts_ioctl(fd, SIOCGIFINDEX, &if_idx) < 0) { - perror("SIOCGIFINDEX"); - exit(-1); - } - fprintf(stderr, "if_idx.ifr_ifindex=%d\n", if_idx.ifr_ifindex); - - // get MAC address of interface to send on - struct ifreq if_mac; - memset(&if_mac, 0, sizeof(struct ifreq)); - strncpy(if_mac.ifr_name, "libzt0", IFNAMSIZ-1); - if (zts_ioctl(fd, SIOCGIFHWADDR, &if_mac) < 0) { - perror("SIOCGIFHWADDR"); - exit(-1); - } - const unsigned char* mac=(unsigned char*)if_mac.ifr_hwaddr.sa_data; - fprintf(stderr, "hwaddr=%02X:%02X:%02X:%02X:%02X:%02X\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); - - // get IP address of interface to send on - struct ifreq if_ip; - memset(&if_ip, 0, sizeof(struct ifreq)); - strncpy(if_ip.ifr_name, "libzt0", IFNAMSIZ-1); - if (zts_ioctl(fd, SIOCGIFADDR, &if_ip) < 0) { - perror("SIOCGIFADDR"); - exit(-1); - } - char ipv4_str[INET_ADDRSTRLEN]; - struct sockaddr_in *in4 = (struct sockaddr_in *)&if_ip.ifr_addr; - inet_ntop(AF_INET, (const void *)&in4->sin_addr.s_addr, ipv4_str, INET_ADDRSTRLEN); - fprintf(stderr, "addr=%s", ipv4_str); - - // construct ethernet header - int tx_len = 0; - char sendbuf[1024]; - struct ether_header *eh = (struct ether_header *) sendbuf; - memset(sendbuf, 0, 1024); - - // Ethernet header - eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0]; - eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1]; - eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2]; - eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3]; - eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4]; - eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5]; - - // set destination MAC - int MY_DEST_MAC0 = 0x72; - int MY_DEST_MAC1 = 0x92; - int MY_DEST_MAC2 = 0xd4; - int MY_DEST_MAC3 = 0xfd; - int MY_DEST_MAC4 = 0x43; - int MY_DEST_MAC5 = 0x45; - - eh->ether_dhost[0] = MY_DEST_MAC0; - eh->ether_dhost[1] = MY_DEST_MAC1; - eh->ether_dhost[2] = MY_DEST_MAC2; - eh->ether_dhost[3] = MY_DEST_MAC3; - eh->ether_dhost[4] = MY_DEST_MAC4; - eh->ether_dhost[5] = MY_DEST_MAC5; - eh->ether_type = htons(ETH_P_IP); - tx_len += sizeof(struct ether_header); - - - // Construct the IP header - int ttl = 64; - struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header)); - iph->ihl = 5; - iph->version = 4; - iph->tos = 16; // Low delay - iph->id = htons(54321); - iph->ttl = ttl; // hops - iph->protocol = 17; // UDP - // Source IP address, can be spoofed - iph->saddr = inet_addr(inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr)); - // iph->saddr = inet_addr("192.168.0.112"); - // Destination IP address - iph->daddr = inet_addr("10.7.7.1"); - tx_len += sizeof(struct iphdr); - - // Construct UDP header - struct udphdr *udph = (struct udphdr *) (sendbuf + sizeof(struct iphdr) + sizeof(struct ether_header)); - udph->source = htons(3423); - udph->dest = htons(5342); - udph->check = 0; // skip - tx_len += sizeof(struct udphdr); - - // Fill in UDP payload - sendbuf[tx_len++] = 0xde; - sendbuf[tx_len++] = 0xad; - sendbuf[tx_len++] = 0xbe; - sendbuf[tx_len++] = 0xef; - - // Fill in remaining header info - // Length of UDP payload and header - udph->len = htons(tx_len - sizeof(struct ether_header) - sizeof(struct iphdr)); - // Length of IP payload and header - iph->tot_len = htons(tx_len - sizeof(struct ether_header)); - // Calculate IP checksum on completed header - iph->check = csum((unsigned short *)(sendbuf+sizeof(struct ether_header)), sizeof(struct iphdr)/2); - - // Send packet - // Destination address - struct sockaddr_ll socket_address; - // Index of the network device - socket_address.sll_ifindex = if_idx.ifr_ifindex; - // Address length - socket_address.sll_halen = ETH_ALEN; - // Destination MAC - socket_address.sll_addr[0] = MY_DEST_MAC0; - socket_address.sll_addr[1] = MY_DEST_MAC1; - socket_address.sll_addr[2] = MY_DEST_MAC2; - socket_address.sll_addr[3] = MY_DEST_MAC3; - socket_address.sll_addr[4] = MY_DEST_MAC4; - socket_address.sll_addr[5] = MY_DEST_MAC5; - - while(1) - { - usleep(10000); - // Send packet - if (zts_sendto(fd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) - fprintf(stderr, "Send failed\n"); - } - - // dismantle all zt virtual taps - zts_stop(); -#endif - return 0; -} \ No newline at end of file diff --git a/examples/scala/ExampleApp.scala b/examples/scala/ExampleApp.scala deleted file mode 100644 index d774169..0000000 --- a/examples/scala/ExampleApp.scala +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -import zerotier.ZeroTier - -object ExampleApp extends App { - // load libzt.dylib or libzt.so - System.loadLibrary("zt") - val libzt = new ZeroTier - libzt.startjoin("/Users/joseph/op/zt/libzt/ztjni", 0xa09acf0232a930f7L) - val fd = libzt.socket(2, 1, 0) - println(s"libzt.socket(): $fd") -} \ No newline at end of file diff --git a/examples/scala/Makefile b/examples/scala/Makefile deleted file mode 100644 index 5c18202..0000000 --- a/examples/scala/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -OSTYPE=$(shell uname -s | tr '[A-Z]' '[a-z]') -BUILD=build/$(OSTYPE) - -ifeq ($(OSTYPE),darwin) -SHARED_LIB=libzt.dylib -endif -ifeq ($(OSTYPE),linux) -SHARED_LIB=libzt.so -endif - -example_scala_app: - scalac *.scala - -copy_dynamic_lib: - cp ../../../$(BUILD)/$(SHARED_LIB) . - -clean: - -find . -type f \( -name '*.class' \) -delete \ No newline at end of file diff --git a/examples/scala/README.md b/examples/scala/README.md deleted file mode 100644 index 08c1d99..0000000 --- a/examples/scala/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## ZeroTier with Scala via JNI -*** - -To get this example project to work, do the following: - -- From libzt main directory, build shared library: `make shared_jni_lib` -- Copy the resultant dynamic library (`*.so` or `*.dylib`) from `build/` to this current directory -- Change to this directory and `make example_scala_app` -- Run: `scala -Djava.library.path=$(pwd) -cp "." ExampleApp` - - -Notes: - -Upon execution, it will load the libzt dynamic library via the `loadLibrary` method and begin generating an identity. \ No newline at end of file diff --git a/examples/scala/libzt.scala b/examples/scala/libzt.scala deleted file mode 100644 index 4ee304c..0000000 --- a/examples/scala/libzt.scala +++ /dev/null @@ -1,76 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package zerotier; - -class ZeroTier { - - // socket families - // socket types - // basic service controls - @native def start(path: String, blocking: Boolean): Int - @native def startjoin(path: String, nwid: Long): Int - @native def stop(): Unit - @native def running(): Int - @native def join(nwid: Long): Unit - @native def leave(nwid: Long): Unit - // advanced service controls - //@native def get_path(): Unit - @native def get_node_id(): Long - //@native def get_6plane_addr(): Unit - //@native def get_rfc4193_addr(): Unit - // socket API - @native def socket(socket_family: Int, socket_type: Int, protocol: Int): Int - @native def connect(fd: Int, addr: String, port: Int): Int - @native def bind(fd: Int, addr: String, port: Int): Int - @native def listen(fd: Int, backlog: Int): Int - @native def accept(fd: Int, addr: Object, addrlen: Int): Int - @native def accept4(fd: Int, addr: Object, addrlen: Int, flags: Int): Int - @native def close(fd: Int): Int - @native def setsockopt(fd: Int, level: Int, optname: Int, optval: Object, optlen: Int): Int - @native def getsockopt(fd: Int, level: Int, optname: Int, optval: Object, optlen: Int): Int - @native def read(fd: Int, buf: Object, len: Int): Int - @native def write(fd: Int, buf: Object, len: Int): Int - @native def send(fd: Int, buf: Object, len: Int, flags: Int): Int - @native def sendto(fd: Int, buf: Object, len: Int, addr: Object, addrlen: Int): Int - @native def sendmsg(fd: Int, msg: Object, flags: Int): Int - @native def recv(fd: Int, buf: Object, len: Int, flags: Int): Int - @native def recvfrom(fd: Int, buf: Object, len: Int, addr: Object, addrlen: Int): Int - @native def recvmsg(fd: Int, msg: Object, flags: Int): Int - @native def shutdown(fd: Int, how: Int): Int - //@native def getsockname(): Int - //@native def getpeername(): Int - //@native def gethostname(): Int - //@native def sethostname(): Int - //@native def gethostbyname(): Object - //@native def poll(): Int - //@native def select(): Int - @native def fcntl(fd: Int, cmd: Int, flags: Int): Int - @native def ioctl(fd: Int, request: Long, argp: Object): Int - // stack controls - //@native def add_dns(): Int - //@native def del_dns(): Int -} diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.pbxproj b/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.pbxproj deleted file mode 100644 index b840018..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,374 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 7C6D474121126417004C82ED /* libzt-static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7CC090842112516900AB1506 /* libzt-static.a */; }; - 7CC0908021124A1200AB1506 /* wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0907E21124A1200AB1506 /* wrapper.cpp */; }; - 7CC0908221124F8900AB1506 /* Example.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC0908121124F8900AB1506 /* Example.swift */; }; - 7CFEEDAA21123E550071915A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFEEDA921123E550071915A /* AppDelegate.swift */; }; - 7CFEEDAC21123E550071915A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFEEDAB21123E550071915A /* ViewController.swift */; }; - 7CFEEDAF21123E550071915A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CFEEDAD21123E550071915A /* Main.storyboard */; }; - 7CFEEDB121123E560071915A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CFEEDB021123E560071915A /* Assets.xcassets */; }; - 7CFEEDB421123E560071915A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CFEEDB221123E560071915A /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 7CC0907D21124A1100AB1506 /* ExampleSwiftApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ExampleSwiftApp-Bridging-Header.h"; sourceTree = ""; }; - 7CC0907E21124A1200AB1506 /* wrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrapper.cpp; sourceTree = ""; }; - 7CC0907F21124A1200AB1506 /* wrapper.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wrapper.hpp; sourceTree = ""; }; - 7CC0908121124F8900AB1506 /* Example.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example.swift; sourceTree = ""; }; - 7CC090842112516900AB1506 /* libzt-static.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libzt-static.a"; path = "../../../bin/lib/Debug/libzt-static.a"; sourceTree = ""; }; - 7CFEEDA621123E550071915A /* ExampleSwiftApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExampleSwiftApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 7CFEEDA921123E550071915A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7CFEEDAB21123E550071915A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 7CFEEDAE21123E550071915A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 7CFEEDB021123E560071915A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 7CFEEDB321123E560071915A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 7CFEEDB521123E560071915A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7CFEEDA321123E550071915A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7C6D474121126417004C82ED /* libzt-static.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7CC090832112516800AB1506 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 7CC090842112516900AB1506 /* libzt-static.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 7CFEED9D21123E550071915A = { - isa = PBXGroup; - children = ( - 7CFEEDA821123E550071915A /* ExampleSwiftApp */, - 7CFEEDA721123E550071915A /* Products */, - 7CC090832112516800AB1506 /* Frameworks */, - ); - sourceTree = ""; - }; - 7CFEEDA721123E550071915A /* Products */ = { - isa = PBXGroup; - children = ( - 7CFEEDA621123E550071915A /* ExampleSwiftApp.app */, - ); - name = Products; - sourceTree = ""; - }; - 7CFEEDA821123E550071915A /* ExampleSwiftApp */ = { - isa = PBXGroup; - children = ( - 7CFEEDA921123E550071915A /* AppDelegate.swift */, - 7CFEEDAB21123E550071915A /* ViewController.swift */, - 7CFEEDAD21123E550071915A /* Main.storyboard */, - 7CFEEDB021123E560071915A /* Assets.xcassets */, - 7CFEEDB221123E560071915A /* LaunchScreen.storyboard */, - 7CFEEDB521123E560071915A /* Info.plist */, - 7CC0907E21124A1200AB1506 /* wrapper.cpp */, - 7CC0907F21124A1200AB1506 /* wrapper.hpp */, - 7CC0907D21124A1100AB1506 /* ExampleSwiftApp-Bridging-Header.h */, - 7CC0908121124F8900AB1506 /* Example.swift */, - ); - path = ExampleSwiftApp; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7CFEEDA521123E550071915A /* ExampleSwiftApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7CFEEDB821123E560071915A /* Build configuration list for PBXNativeTarget "ExampleSwiftApp" */; - buildPhases = ( - 7CFEEDA221123E550071915A /* Sources */, - 7CFEEDA321123E550071915A /* Frameworks */, - 7CFEEDA421123E550071915A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ExampleSwiftApp; - productName = ExampleSwiftApp; - productReference = 7CFEEDA621123E550071915A /* ExampleSwiftApp.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7CFEED9E21123E550071915A /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0940; - LastUpgradeCheck = 0940; - ORGANIZATIONNAME = ZeroTier; - TargetAttributes = { - 7CFEEDA521123E550071915A = { - CreatedOnToolsVersion = 9.4.1; - LastSwiftMigration = 0940; - }; - }; - }; - buildConfigurationList = 7CFEEDA121123E550071915A /* Build configuration list for PBXProject "ExampleSwiftApp" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 7CFEED9D21123E550071915A; - productRefGroup = 7CFEEDA721123E550071915A /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7CFEEDA521123E550071915A /* ExampleSwiftApp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 7CFEEDA421123E550071915A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7CFEEDB421123E560071915A /* LaunchScreen.storyboard in Resources */, - 7CFEEDB121123E560071915A /* Assets.xcassets in Resources */, - 7CFEEDAF21123E550071915A /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7CFEEDA221123E550071915A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7CC0908221124F8900AB1506 /* Example.swift in Sources */, - 7CFEEDAC21123E550071915A /* ViewController.swift in Sources */, - 7CFEEDAA21123E550071915A /* AppDelegate.swift in Sources */, - 7CC0908021124A1200AB1506 /* wrapper.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 7CFEEDAD21123E550071915A /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7CFEEDAE21123E550071915A /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 7CFEEDB221123E560071915A /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 7CFEEDB321123E560071915A /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 7CFEEDB621123E560071915A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 7CFEEDB721123E560071915A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.4; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 7CFEEDB921123E560071915A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 57AG88JR8A; - INFOPLIST_FILE = ExampleSwiftApp/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - "LIBRARY_SEARCH_PATHS[arch=*]" = /Users/joseph/op/zt/libzt_new/bin/lib/Debug; - PRODUCT_BUNDLE_IDENTIFIER = zerotier.ExampleSwiftApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "ExampleSwiftApp/ExampleSwiftApp-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 7CFEEDBA21123E560071915A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 57AG88JR8A; - INFOPLIST_FILE = ExampleSwiftApp/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = zerotier.ExampleSwiftApp; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "ExampleSwiftApp/ExampleSwiftApp-Bridging-Header.h"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7CFEEDA121123E550071915A /* Build configuration list for PBXProject "ExampleSwiftApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7CFEEDB621123E560071915A /* Debug */, - 7CFEEDB721123E560071915A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7CFEEDB821123E560071915A /* Build configuration list for PBXNativeTarget "ExampleSwiftApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7CFEEDB921123E560071915A /* Debug */, - 7CFEEDBA21123E560071915A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7CFEED9E21123E550071915A /* Project object */; -} diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index accca7f..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/xcuserdata/joseph.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/xcuserdata/joseph.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 967e6fd..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp.xcodeproj/xcuserdata/joseph.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,14 +0,0 @@ - - - - - SchemeUserState - - ExampleSwiftApp.xcscheme - - orderHint - 0 - - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/AppDelegate.swift b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/AppDelegate.swift deleted file mode 100644 index 5602efc..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// ExampleSwiftApp -// -// Created by Joseph Henry on 8/1/18. -// Copyright © 2018 ZeroTier. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } - - func applicationWillResignActive(_ application: UIApplication) { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. - } - - func applicationDidEnterBackground(_ application: UIApplication) { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - } - - func applicationWillEnterForeground(_ application: UIApplication) { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. - } - - func applicationDidBecomeActive(_ application: UIApplication) { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. - } - - func applicationWillTerminate(_ application: UIApplication) { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. - } - - -} - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d8db8d6..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/Contents.json b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/LaunchScreen.storyboard b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f83f6fd..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/Main.storyboard b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/Main.storyboard deleted file mode 100644 index 03c13c2..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Example.swift b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Example.swift deleted file mode 100644 index 3635613..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Example.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// Example.swift -// ExampleSwiftApp -// -// Created by Joseph Henry on 8/1/18. -// Copyright © 2018 ZeroTier. All rights reserved. -// - -import Foundation -import UIKit - -class MyApplication: UIResponder, UIApplicationDelegate { - static func libzt_example_function() - { - var fd: Int32 = -1; - var err: Int32 = -1; - let clientMode = true; - let remotePort = 4545; - let remoteAddress = "192.168.195.1"; - let appDir = String(NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]) - - // Start up and create socket - print("starting..."); - zts_startjoin(appDir, 0x1c33c1ceb0aa9251); - print("I am ", NSString(format:"%llx", zts_get_node_id())); - fd = zts_socket(2, 1, 0); - if(fd < 0) { - print("error creating socket"); - } - print("fd = ", fd); - - // Remote address - var in4 = sockaddr_in(sin_len: UInt8(MemoryLayout.size), - sin_family: UInt8(AF_INET), - sin_port: UInt16(remotePort).bigEndian, - sin_addr: in_addr(s_addr: 0), - sin_zero: (0,0,0,0,0,0,0,0)) - inet_pton(AF_INET, remoteAddress, &(in4.sin_addr)); - - // CLIENT - if (clientMode) - { - print("connecting..."); - let addrlen = socklen_t(MemoryLayout.size(ofValue: in4)) - let a = withUnsafeMutablePointer(to: &in4) { - $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { - err = zts_connect(fd, $0, addrlen) - } - } - if(err < 0) { - print("error connecting to remote server"); - } - print("connected"); - - print("sending message to server"); - var msg: String = "Hello from Swift!"; - err = zts_write(fd, msg, msg.count) - if(err < 0) { - print("error creating socket"); - } - print("wrote ", err, " bytes"); - zts_close(fd); - } - else // SERVER - { - - } - - zts_stop(); - } -} - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ExampleSwiftApp-Bridging-Header.h b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ExampleSwiftApp-Bridging-Header.h deleted file mode 100644 index d74b530..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ExampleSwiftApp-Bridging-Header.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef LIBZT_BRIDGING_HEADER_H -#define LIBZT_BRIDGING_HEADER_H - -#include -#include "/Users/joseph/op/zt/libzt_new/include/libzt.h" - -// ZT SERVICE CONTROLS -int zts_start(const char *path, int blocking); -int zts_startjoin(const char *path, const uint64_t nwid); -void zts_stop(); -int zts_core_running(); -int zts_stack_running(); -int zts_ready(); -int zts_join(uint64_t nwid); -int zts_leave(uint64_t nwid); -uint64_t zts_get_node_id(); -// SOCKET API -int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); -int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); -int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); -int zts_listen(int fd, int backlog); -int zts_socket(int socket_family, int socket_type, int protocol); -int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); -int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); -int zts_close(int fd); -int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); -int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); -ssize_t zts_send(int fd, const void *buf, size_t len, int flags); -ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); -ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags); -ssize_t zts_recv(int fd, void *buf, size_t len, int flags); -ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); -ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags); -int zts_read(int fd, void *buf, size_t len); -int zts_write(int fd, const void *buf, size_t len); -int zts_shutdown(int fd, int how); -int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -int zts_fcntl(int fd, int cmd, int flags); -int zts_ioctl(int fd, unsigned long request, void *argp); - -#endif /* LIBZT_BRIDGING_HEADER_H */ - - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Info.plist b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Info.plist deleted file mode 100644 index 16be3b6..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ViewController.swift b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ViewController.swift deleted file mode 100644 index f265acd..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/ViewController.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// ViewController.swift -// ExampleSwiftApp -// -// Created by Joseph Henry on 8/1/18. -// Copyright © 2018 ZeroTier. All rights reserved. -// - -import UIKit - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - MyApplication.libzt_example_function(); - - // Do any additional setup after loading the view, typically from a nib. - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. - } - - -} - diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.cpp b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.cpp deleted file mode 100644 index 51326d8..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// wrapper.cpp -// ExampleSwiftApp -// -// Created by Joseph Henry on 8/1/18. -// Copyright © 2018 ZeroTier. All rights reserved. -// - -#include "wrapper.hpp" -#include "/Users/joseph/op/zt/libzt_new/include/libzt.h" - -#ifdef __cplusplus -extern "C" { -#endif - - // Nothing, implementation is in src/libzt.cpp - -#ifdef __cplusplus -} -#endif diff --git a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.hpp b/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.hpp deleted file mode 100644 index 2cfc87d..0000000 --- a/examples/swift/ExampleSwiftApp/ExampleSwiftApp/wrapper.hpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// wrapper.hpp -// ExampleSwiftApp -// -// Created by Joseph Henry on 8/1/18. -// Copyright © 2018 ZeroTier. All rights reserved. -// - -#ifndef wrapper_hpp -#define wrapper_hpp - -#include - -#endif /* wrapper_hpp */ diff --git a/examples/ztproxy/ztproxy.cpp b/examples/ztproxy/ztproxy.cpp deleted file mode 100644 index 5203851..0000000 --- a/examples/ztproxy/ztproxy.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#if defined(__linux__) || defined(__APPLE__) -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libzt.h" - -#include "RingBuffer.h" -#include "ztproxy.hpp" - -#if defined(_WIN32) -#include -void sleep(unsigned long ms) -{ - Sleep(ms); -} -#endif - -namespace ZeroTier { - - typedef void PhySocket; - - ZTProxy::ZTProxy(int proxy_listen_port, std::string nwid, std::string path, std::string internal_addr, - int internal_port, std::string dns_nameserver) - : - _enabled(true), - _run(true), - _proxy_listen_port(proxy_listen_port), - _internal_port(internal_port), - _nwid(nwid), - _internal_addr(internal_addr), - _dns_nameserver(dns_nameserver), - _phy(this,false,true) - { - // Set up TCP listen sockets - // IPv4 - struct sockaddr_in in4; - memset(&in4,0,sizeof(in4)); - in4.sin_family = AF_INET; - in4.sin_addr.s_addr = Utils::hton((uint32_t)(0x7f000001)); // listen for TCP @127.0.0.1 - in4.sin_port = Utils::hton((uint16_t)proxy_listen_port); - _tcpListenSocket = _phy.tcpListen((const struct sockaddr *)&in4,this); - if (!_tcpListenSocket) { - DEBUG_ERROR("Error binding on port %d for IPv4 HTTP listen socket", proxy_listen_port); - } - // IPv6 - /* - struct sockaddr_in6 in6; - memset((void *)&in6,0,sizeof(in6)); - in6.sin6_family = AF_INET6; - in6.sin6_port = in4.sin_port; - in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1 - in6.sin6_port = Utils::hton((uint16_t)proxy_listen_port); - _tcpListenSocket6 = _phy.tcpListen((const struct sockaddr *)&in6,this); - */ - /* - if (!_tcpListenSocket6) { - DEBUG_ERROR("Error binding on port %d for IPv6 HTTP listen socket", proxy_listen_port); - } - */ - _thread = Thread::start(this); - } - - ZTProxy::~ZTProxy() - { - _run = false; - _phy.whack(); - Thread::join(_thread); - _phy.close(_tcpListenSocket,false); - _phy.close(_tcpListenSocket6,false); - } - - void ZTProxy::threadMain() - throw() - { - // Add DNS nameserver - if (_dns_nameserver.length() > 0) { - DEBUG_INFO("setting DNS nameserver (%s)", _dns_nameserver.c_str()); - struct sockaddr_in dns_address; - dns_address.sin_addr.s_addr = inet_addr(_dns_nameserver.c_str()); - zts_add_dns_nameserver((struct sockaddr*)&dns_address); - } - - TcpConnection *conn = NULL; - uint32_t msecs = 1; - struct timeval tv; - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - int ret = 0; - // Main I/O loop - // Moves data between client application socket and libzt VirtualSocket - while(_run) { - - _phy.poll(1); - - conn_m.lock(); - // build fd_sets to select upon - FD_ZERO(&read_set); - FD_ZERO(&write_set); - nfds = 0; - for (size_t i=0; izfd, &read_set); - FD_SET(clist[i]->zfd, &write_set); - nfds = clist[i]->zfd > nfds ? clist[i]->zfd : nfds; - } - - ret = zts_select(nfds + 1, &read_set, &write_set, NULL, &tv); - if (ret > 0) { - for (int fd_i=0; fd_irx_m.lock(); - if (conn->RXbuf->count() > 0) { - //DEBUG_INFO("libzt has incoming data on fd=%d, RXing via conn=%p, sock=%p", - // conn->zfd, conn, conn->client_sock); - } - if ((rd = zts_read(conn->zfd, conn->RXbuf->get_buf(),ZT_MAX_MTU)) < 0) { - DEBUG_ERROR("error while reading data from libzt, err=%d", rd); - } - else { - //DEBUG_INFO("LIBZT -> RXBUFFER = %d bytes", rd); - conn->RXbuf->produce(rd); - } - // attempt to write data to client from buffer - if ((wr = _phy.streamSend(conn->client_sock, conn->RXbuf->get_buf(), conn->RXbuf->count())) < 0) { - DEBUG_ERROR("error while writing the data from the RXbuf to the client PhySocket, err=%d", wr); - } - else { - //DEBUG_INFO("RXBUFFER -> CLIENT = %d bytes", wr); - conn->RXbuf->consume(wr); - } - conn->rx_m.unlock(); - } - - // TX, Handle data outgoing from client to libzt - if (FD_ISSET(fd_i, &write_set)) { - int wr = 0; - conn = zmap[fd_i]; - if (conn == NULL) { - DEBUG_ERROR("invalid conn, possibly closed before transmit was possible"); - } - // read data from client and place it on ring buffer - conn->tx_m.lock(); - if (conn->TXbuf->count() > 0) { - // DEBUG_INFO("client has outgoing data of len=%d on fd=%d, TXing via conn=%p, sock=%p", - // conn->TXbuf->count(), conn->zfd, conn, conn->client_sock); - if ((wr = zts_write(conn->zfd, conn->TXbuf->get_buf(), conn->TXbuf->count())) < 0) { - DEBUG_ERROR("error while sending the data over libzt, err=%d", wr); - } - else { - //DEBUG_INFO("TXBUFFER -> LIBZT = %d bytes", wr); - conn->TXbuf->consume(wr); // data is presumed sent, mark it as such in the ringbuffer - } - } - conn->tx_m.unlock(); - } - } - } - conn_m.unlock(); - } - } - - bool isValidIPAddress(const char *ip) - { - struct sockaddr_in sa; - return inet_pton(AF_INET, ip, &(sa.sin_addr)) == 1; - } - - void ZTProxy::phyOnTcpData(PhySocket *sock, void **uptr, void *data, unsigned long len) - { - int wr = 0, zfd = -1, err = 0; - DEBUG_EXTRA("sock=%p, len=%lu", sock, len); - std::string host = _internal_addr; - TcpConnection *conn = cmap[sock]; - if (conn == NULL) { - DEBUG_ERROR("invalid conn"); - exit(0); - } - if (conn->zfd < 0) { // no connection yet - if (host == "") { - DEBUG_ERROR("invalid hostname or address (empty)"); - return; - } - DEBUG_INFO("establishing proxy connection..."); - - uint16_t dest_port, ipv; - dest_port = _internal_port; - host = _internal_addr; - - if (isValidIPAddress(host.c_str()) == false) { - // try to resolve this if it isn't an IP address - struct hostent *h = zts_gethostbyname(host.c_str()); - if (h == NULL) { - DEBUG_ERROR("unable to resolve hostname (%s) (errno=%d)", host.c_str(), errno); - return; - } - // TODO - // host = h->h_addr_list[0]; - } - - // determine address type - ipv = host.find(":") != std::string::npos ? 6 : 4; - - // connect to remote host - if (ipv == 4) { - DEBUG_INFO("attempting to proxy [0.0.0.0:%d -> %s:%d]", _proxy_listen_port, host.c_str(), dest_port); - struct sockaddr_in in4; - memset(&in4,0,sizeof(in4)); - in4.sin_family = AF_INET; - in4.sin_addr.s_addr = inet_addr(host.c_str()); - in4.sin_port = Utils::hton(dest_port); - if ((zfd = zts_socket(AF_INET, SOCK_STREAM, 0)) < 0) { - DEBUG_ERROR("unable to create socket (errno=%d)", errno); - return; - } - if ((err = zts_connect(zfd, (const struct sockaddr *)&in4, sizeof(in4))) < 0) { - DEBUG_ERROR("unable to connect to remote host (errno=%d)", errno); - return; - } - } - if (ipv == 6) { - //DEBUG_INFO("attempting to proxy [0.0.0.0:%d -> %s:%d]", _proxy_listen_port, host.c_str(), dest_port); - /* - struct sockaddr_in6 in6; - memset(&in6,0,sizeof(in6)); - in6.sin6_family = AF_INET; - struct hostent *server; - server = gethostbyname2((char*)host.c_str(),AF_INET6); - memmove((char *) &in6.sin6_addr.s6_addr, (char *) server->h_addr, server->h_length); - in6.sin6_port = Utils::hton(dest_port); - zfd = zts_socket(AF_INET, SOCK_STREAM, 0); - err = zts_connect(zfd, (const struct sockaddr *)&in6, sizeof(in6)); - */ - } - if (zfd < 0 || err < 0) { - // now release TX buffer contents we previously saved, since we can't connect - DEBUG_ERROR("error while connecting to remote host (zfd=%d, err=%d)", zfd, err); - conn->tx_m.lock(); - conn->TXbuf->reset(); - conn->tx_m.unlock(); - return; - } - else { - DEBUG_INFO("successfully connected to remote host"); - } - - conn_m.lock(); - // on success, add connection entry to map, set physock for later - clist.push_back(conn); - conn->zfd = zfd; - conn->client_sock = sock; - cmap[conn->client_sock] = conn; - zmap[zfd] = conn; - conn_m.unlock(); - } - // Write data coming from client TCP connection to its TX buffer, later emptied into libzt by threadMain I/O loop - conn->tx_m.lock(); - if ((wr = conn->TXbuf->write((const char *)data, len)) < 0) { - DEBUG_ERROR("there was an error while writing data from client to tx buffer, err=%d", wr); - } - else { - // DEBUG_INFO("CLIENT -> TXBUFFER = %d bytes", wr); - } - conn->tx_m.unlock(); - } - - void ZTProxy::phyOnTcpAccept(PhySocket *sockL, PhySocket *sockN, void **uptrL, void **uptrN, - const struct sockaddr *from) - { - DEBUG_INFO("sockL=%p, sockN=%p", sockL, sockN); - TcpConnection *conn = new TcpConnection(); - conn->client_sock = sockN; - cmap[sockN]=conn; - } - - void ZTProxy::phyOnTcpClose(PhySocket *sock, void **uptr) - { - DEBUG_INFO("sock=%p", sock); - conn_m.lock(); - TcpConnection *conn = cmap[sock]; - if (conn) { - conn->client_sock=NULL; - if (conn->zfd >= 0) { - zts_close(conn->zfd); - } - cmap.erase(sock); - for (size_t i=0; izfd] = NULL; - delete conn; - conn = NULL; - } -#if defined(_WIN32) - closesocket(_phy.getDescriptor(sock)); -#else - close(_phy.getDescriptor(sock)); -#endif - conn_m.unlock(); - } - - void ZTProxy::phyOnDatagram(PhySocket *sock, void **uptr, const struct sockaddr *localAddr, - const struct sockaddr *from, void *data, unsigned long len) { - DEBUG_INFO(); - } - void ZTProxy::phyOnTcpWritable(PhySocket *sock, void **uptr) { - DEBUG_INFO(); - } - void ZTProxy::phyOnFileDescriptorActivity(PhySocket *sock, void **uptr, bool readable, bool writable) { - DEBUG_INFO("sock=%p", sock); - } - void ZTProxy::phyOnTcpConnect(PhySocket *sock, void **uptr, bool success) { - DEBUG_INFO("sock=%p", sock); - } - void ZTProxy::phyOnUnixClose(PhySocket *sock, void **uptr) { - DEBUG_INFO("sock=%p", sock); - } - void ZTProxy::phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len) { - DEBUG_INFO("sock=%p, len=%lu", sock, len); - } - void ZTProxy::phyOnUnixWritable(PhySocket *sock, void **uptr, bool lwip_invoked) { - DEBUG_INFO("sock=%p", sock); - } -} - -int main(int argc, char **argv) -{ - if (argc < 6 || argc > 7) { - printf("\nZeroTier TCP Proxy Service\n"); - printf("ztproxy [config_file_path] [local_listen_port] [nwid] [zt_host_addr] [zt_resource_port] [optional_dns_nameserver]\n"); - exit(0); - } - std::string path = argv[1]; - int proxy_listen_port = atoi(argv[2]); - std::string nwidstr = argv[3]; - std::string internal_addr = argv[4]; - int internal_port = atoi(argv[5]); - std::string dns_nameserver= "";//argv[6]; - - // Start ZeroTier Node - // Join Network which contains resources we need to proxy - DEBUG_INFO("waiting for libzt to come online"); - uint64_t nwid = strtoull(nwidstr.c_str(),NULL,16); - zts_startjoin(path.c_str(), nwid); - - ZeroTier::ZTProxy *proxy = new ZeroTier::ZTProxy(proxy_listen_port, nwidstr, path, internal_addr, internal_port, dns_nameserver); - - if (proxy) { - printf("\nZTProxy started. Listening on %d\n", proxy_listen_port); - printf("Traffic will be proxied to and from %s:%d on network %s\n", internal_addr.c_str(), internal_port, nwidstr.c_str()); - printf("Proxy Node config files and key stored in: %s/\n\n", path.c_str()); - while(1) { - sleep(1); - } - } - else { - printf("unable to create proxy\n"); - } - return 0; -} diff --git a/examples/ztproxy/ztproxy.hpp b/examples/ztproxy/ztproxy.hpp deleted file mode 100644 index 9bbfa21..0000000 --- a/examples/ztproxy/ztproxy.hpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -#ifndef ZT_ZTPROXY_HPP -#define ZT_ZTPROXY_HPP - -#include "Constants.hpp" -#include "Thread.hpp" -#include "InetAddress.hpp" -#include "Mutex.hpp" -#include "Phy.hpp" -#include "OSUtils.hpp" - -#if defined(__linux__) || defined(__APPLE__) - #include -#endif - -#include -#include -#include - -#define BUF_SZ 1024*1024 - -namespace ZeroTier { - - typedef void PhySocket; - class ZTProxy; - - class TcpConnection - { - public: - int zfd; - PhySocket *client_sock; - RingBuffer *TXbuf, *RXbuf; - Mutex tx_m, rx_m; - - TcpConnection() { - zfd = -1; - TXbuf = new RingBuffer(BUF_SZ); - RXbuf = new RingBuffer(BUF_SZ); - } - - ~TcpConnection() { - delete TXbuf; - delete RXbuf; - client_sock = NULL; - TXbuf = NULL; - RXbuf = NULL; - } - }; - - class ZTProxy - { - friend class Phy; - - public: - ZTProxy(int proxy_listen_port, std::string nwid, std::string path, std::string internal_addr, int internal_port, std::string _dns_nameserver); - ~ZTProxy(); - - // Send incoming data to intended host - void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len); - void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len); - void phyOnTcpWritable(PhySocket *sock,void **uptr); - void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable); - // Establish outgoing connection to intended host - void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success); - // Accept connection - void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from); - // Handle the closure of a Unix Domain socket - void phyOnUnixClose(PhySocket *sock,void **uptr); - void phyOnUnixData(PhySocket *sock,void **uptr,void *data,ssize_t len); - void phyOnUnixWritable(PhySocket *sock,void **uptr,bool lwip_invoked); - // Handle the closure of a TCP connection - void phyOnTcpClose(PhySocket *sock,void **uptr); - - void threadMain() - throw(); - - TcpConnection *getConnection(PhySocket *sock); - - private: - volatile bool _enabled; - volatile bool _run; - - Mutex conn_m; - fd_set read_set, write_set; - int nfds; - - int _proxy_listen_port; - int _internal_port; - std::string _nwid; - std::string _internal_addr; - std::string _dns_nameserver; - - Thread _thread; - Phy _phy; - PhySocket *_tcpListenSocket; - PhySocket *_tcpListenSocket6; - - // mapping from ZeroTier VirtualSocket fd to TcpConnection pointer - std::map zmap; - // mapping from ZeroTier PhySocket to TcpConnection pointer - std::map cmap; - - std::vector clist; - }; -} - -#endif \ No newline at end of file diff --git a/ext/ZeroTierOne.patch b/ext/ZeroTierOne.patch index 4094e39..dbae021 100644 --- a/ext/ZeroTierOne.patch +++ b/ext/ZeroTierOne.patch @@ -36,29 +36,3 @@ index 74c22d33..58979e26 100644 if (i < nqcb->oldQueues.size()) { if (nqcb->oldQueues[i]->byteLength > maxQueueLength) { maxQueueLength = nqcb->oldQueues[i]->byteLength; -diff --git a/service/OneService.cpp b/service/OneService.cpp -index a1c53764..e3034059 100644 ---- a/service/OneService.cpp -+++ b/service/OneService.cpp -@@ -625,6 +625,8 @@ public: - break; - if (!pkt) - break; -+ if (!_run) -+ break; - - const ZT_ResultCode rc = _node->processWirePacket(nullptr,pkt->now,pkt->sock,&(pkt->from),pkt->data,pkt->size,&_nextBackgroundTaskDeadline); - { -@@ -2244,6 +2246,12 @@ public: - #endif - syncManagedStuff(n,true,true); - n.tap->setMtu(nwc->mtu); -+#if defined(ZT_SDK) -+ // Inform the virtual tap of the update -+ if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE) { -+ n.tap->lastConfigUpdate(OSUtils::now()); -+ } -+#endif - } else { - _nets.erase(nwid); - return -999; // tap init failed diff --git a/ext/concurrentqueue/LICENSE.md b/ext/concurrentqueue/LICENSE.md new file mode 100644 index 0000000..c4e7588 --- /dev/null +++ b/ext/concurrentqueue/LICENSE.md @@ -0,0 +1,61 @@ +This license file applies to everything in this repository except that which +is explicitly annotated as being written by other authors, i.e. the Boost +queue (included in the benchmarks for comparison), Intel's TBB library (ditto), +the CDSChecker tool (used for verification), the Relacy model checker (ditto), +and Jeff Preshing's semaphore implementation (used in the blocking queue) which +has a zlib license (embedded in blockingconcurrentqueue.h). + +--- + +Simplified BSD License: + +Copyright (c) 2013-2016, Cameron Desrochers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other materials +provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +I have also chosen to dual-license under the Boost Software License as an alternative to +the Simplified BSD license above: + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/ext/concurrentqueue/concurrentqueue.h b/ext/concurrentqueue/concurrentqueue.h new file mode 100644 index 0000000..09e810f --- /dev/null +++ b/ext/concurrentqueue/concurrentqueue.h @@ -0,0 +1,3635 @@ +// Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue. +// An overview, including benchmark results, is provided here: +// http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++ +// The full design is also described in excruciating detail at: +// http://moodycamel.com/blog/2014/detailed-design-of-a-lock-free-queue + +// Simplified BSD license: +// Copyright (c) 2013-2016, Cameron Desrochers. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// - Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#pragma once + +#if defined(__GNUC__) +// Disable -Wconversion warnings (spuriously triggered when Traits::size_t and +// Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings +// upon assigning any computed values) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + +#ifdef MCDBGQ_USE_RELACY +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#endif +#endif + +#if defined(__APPLE__) +#include "TargetConditionals.h" +#endif + +#ifdef MCDBGQ_USE_RELACY +#include "relacy/relacy_std.hpp" +#include "relacy_shims.h" +// We only use malloc/free anyway, and the delete macro messes up `= delete` method declarations. +// We'll override the default trait malloc ourselves without a macro. +#undef new +#undef delete +#undef malloc +#undef free +#else +#include // Requires C++11. Sorry VS2010. +#include +#endif +#include // for max_align_t +#include +#include +#include +#include +#include +#include +#include // for CHAR_BIT +#include +#include // partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading + +// Platform-specific definitions of a numeric thread ID type and an invalid value +namespace moodycamel { namespace details { + template struct thread_id_converter { + typedef thread_id_t thread_id_numeric_size_t; + typedef thread_id_t thread_id_hash_t; + static thread_id_hash_t prehash(thread_id_t const& x) { return x; } + }; +} } +#if defined(MCDBGQ_USE_RELACY) +namespace moodycamel { namespace details { + typedef std::uint32_t thread_id_t; + static const thread_id_t invalid_thread_id = 0xFFFFFFFFU; + static const thread_id_t invalid_thread_id2 = 0xFFFFFFFEU; + static inline thread_id_t thread_id() { return rl::thread_index(); } +} } +#elif defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__) +// No sense pulling in windows.h in a header, we'll manually declare the function +// we use and rely on backwards-compatibility for this not to break +extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(void); +namespace moodycamel { namespace details { + static_assert(sizeof(unsigned long) == sizeof(std::uint32_t), "Expected size of unsigned long to be 32 bits on Windows"); + typedef std::uint32_t thread_id_t; + static const thread_id_t invalid_thread_id = 0; // See http://blogs.msdn.com/b/oldnewthing/archive/2004/02/23/78395.aspx + static const thread_id_t invalid_thread_id2 = 0xFFFFFFFFU; // Not technically guaranteed to be invalid, but is never used in practice. Note that all Win32 thread IDs are presently multiples of 4. + static inline thread_id_t thread_id() { return static_cast(::GetCurrentThreadId()); } +} } +#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE) +namespace moodycamel { namespace details { + static_assert(sizeof(std::thread::id) == 4 || sizeof(std::thread::id) == 8, "std::thread::id is expected to be either 4 or 8 bytes"); + + typedef std::thread::id thread_id_t; + static const thread_id_t invalid_thread_id; // Default ctor creates invalid ID + + // Note we don't define a invalid_thread_id2 since std::thread::id doesn't have one; it's + // only used if MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is defined anyway, which it won't + // be. + static inline thread_id_t thread_id() { return std::this_thread::get_id(); } + + template struct thread_id_size { }; + template<> struct thread_id_size<4> { typedef std::uint32_t numeric_t; }; + template<> struct thread_id_size<8> { typedef std::uint64_t numeric_t; }; + + template<> struct thread_id_converter { + typedef thread_id_size::numeric_t thread_id_numeric_size_t; +#ifndef __APPLE__ + typedef std::size_t thread_id_hash_t; +#else + typedef thread_id_numeric_size_t thread_id_hash_t; +#endif + + static thread_id_hash_t prehash(thread_id_t const& x) + { +#ifndef __APPLE__ + return std::hash()(x); +#else + return *reinterpret_cast(&x); +#endif + } + }; +} } +#else +// Use a nice trick from this answer: http://stackoverflow.com/a/8438730/21475 +// In order to get a numeric thread ID in a platform-independent way, we use a thread-local +// static variable's address as a thread identifier :-) +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +#define MOODYCAMEL_THREADLOCAL __thread +#elif defined(_MSC_VER) +#define MOODYCAMEL_THREADLOCAL __declspec(thread) +#else +// Assume C++11 compliant compiler +#define MOODYCAMEL_THREADLOCAL thread_local +#endif +namespace moodycamel { namespace details { + typedef std::uintptr_t thread_id_t; + static const thread_id_t invalid_thread_id = 0; // Address can't be nullptr + static const thread_id_t invalid_thread_id2 = 1; // Member accesses off a null pointer are also generally invalid. Plus it's not aligned. + static inline thread_id_t thread_id() { static MOODYCAMEL_THREADLOCAL int x; return reinterpret_cast(&x); } +} } +#endif + +// Exceptions +#ifndef MOODYCAMEL_EXCEPTIONS_ENABLED +#if (defined(_MSC_VER) && defined(_CPPUNWIND)) || (defined(__GNUC__) && defined(__EXCEPTIONS)) || (!defined(_MSC_VER) && !defined(__GNUC__)) +#define MOODYCAMEL_EXCEPTIONS_ENABLED +#endif +#endif +#ifdef MOODYCAMEL_EXCEPTIONS_ENABLED +#define MOODYCAMEL_TRY try +#define MOODYCAMEL_CATCH(...) catch(__VA_ARGS__) +#define MOODYCAMEL_RETHROW throw +#define MOODYCAMEL_THROW(expr) throw (expr) +#else +#define MOODYCAMEL_TRY if (true) +#define MOODYCAMEL_CATCH(...) else if (false) +#define MOODYCAMEL_RETHROW +#define MOODYCAMEL_THROW(expr) +#endif + +#ifndef MOODYCAMEL_NOEXCEPT +#if !defined(MOODYCAMEL_EXCEPTIONS_ENABLED) +#define MOODYCAMEL_NOEXCEPT +#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) true +#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) true +#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1800 +// VS2012's std::is_nothrow_[move_]constructible is broken and returns true when it shouldn't :-( +// We have to assume *all* non-trivial constructors may throw on VS2012! +#define MOODYCAMEL_NOEXCEPT _NOEXCEPT +#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference::value && std::is_move_constructible::value ? std::is_trivially_move_constructible::value : std::is_trivially_copy_constructible::value) +#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference::value && std::is_move_assignable::value ? std::is_trivially_move_assignable::value || std::is_nothrow_move_assignable::value : std::is_trivially_copy_assignable::value || std::is_nothrow_copy_assignable::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr)) +#elif defined(_MSC_VER) && defined(_NOEXCEPT) && _MSC_VER < 1900 +#define MOODYCAMEL_NOEXCEPT _NOEXCEPT +#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) (std::is_rvalue_reference::value && std::is_move_constructible::value ? std::is_trivially_move_constructible::value || std::is_nothrow_move_constructible::value : std::is_trivially_copy_constructible::value || std::is_nothrow_copy_constructible::value) +#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) ((std::is_rvalue_reference::value && std::is_move_assignable::value ? std::is_trivially_move_assignable::value || std::is_nothrow_move_assignable::value : std::is_trivially_copy_assignable::value || std::is_nothrow_copy_assignable::value) && MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr)) +#else +#define MOODYCAMEL_NOEXCEPT noexcept +#define MOODYCAMEL_NOEXCEPT_CTOR(type, valueType, expr) noexcept(expr) +#define MOODYCAMEL_NOEXCEPT_ASSIGN(type, valueType, expr) noexcept(expr) +#endif +#endif + +#ifndef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED +#ifdef MCDBGQ_USE_RELACY +#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED +#else +// VS2013 doesn't support `thread_local`, and MinGW-w64 w/ POSIX threading has a crippling bug: http://sourceforge.net/p/mingw-w64/bugs/445 +// g++ <=4.7 doesn't support thread_local either. +// Finally, iOS/ARM doesn't have support for it either, and g++/ARM allows it to compile but it's unconfirmed to actually work +#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && (!defined(__MINGW32__) && !defined(__MINGW64__) || !defined(__WINPTHREADS_VERSION)) && (!defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && (!defined(__APPLE__) || !TARGET_OS_IPHONE) && !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) +// Assume `thread_local` is fully supported in all other C++11 compilers/platforms +//#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED // always disabled for now since several users report having problems with it on +#endif +#endif +#endif + +// VS2012 doesn't support deleted functions. +// In this case, we declare the function normally but don't define it. A link error will be generated if the function is called. +#ifndef MOODYCAMEL_DELETE_FUNCTION +#if defined(_MSC_VER) && _MSC_VER < 1800 +#define MOODYCAMEL_DELETE_FUNCTION +#else +#define MOODYCAMEL_DELETE_FUNCTION = delete +#endif +#endif + +// Compiler-specific likely/unlikely hints +namespace moodycamel { namespace details { +#if defined(__GNUC__) + static inline bool (likely)(bool x) { return __builtin_expect((x), true); } + static inline bool (unlikely)(bool x) { return __builtin_expect((x), false); } +#else + static inline bool (likely)(bool x) { return x; } + static inline bool (unlikely)(bool x) { return x; } +#endif +} } + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG +#include "internal/concurrentqueue_internal_debug.h" +#endif + +namespace moodycamel { +namespace details { + template + struct const_numeric_max { + static_assert(std::is_integral::value, "const_numeric_max can only be used with integers"); + static const T value = std::numeric_limits::is_signed + ? (static_cast(1) << (sizeof(T) * CHAR_BIT - 1)) - static_cast(1) + : static_cast(-1); + }; + +#if defined(__GLIBCXX__) + typedef ::max_align_t std_max_align_t; // libstdc++ forgot to add it to std:: for a while +#else + typedef std::max_align_t std_max_align_t; // Others (e.g. MSVC) insist it can *only* be accessed via std:: +#endif + + // Some platforms have incorrectly set max_align_t to a type with <8 bytes alignment even while supporting + // 8-byte aligned scalar values (*cough* 32-bit iOS). Work around this with our own union. See issue #64. + typedef union { + std_max_align_t x; + long long y; + void* z; + } max_align_t; +} + +// Default traits for the ConcurrentQueue. To change some of the +// traits without re-implementing all of them, inherit from this +// struct and shadow the declarations you wish to be different; +// since the traits are used as a template type parameter, the +// shadowed declarations will be used where defined, and the defaults +// otherwise. +struct ConcurrentQueueDefaultTraits +{ + // General-purpose size type. std::size_t is strongly recommended. + typedef std::size_t size_t; + + // The type used for the enqueue and dequeue indices. Must be at least as + // large as size_t. Should be significantly larger than the number of elements + // you expect to hold at once, especially if you have a high turnover rate; + // for example, on 32-bit x86, if you expect to have over a hundred million + // elements or pump several million elements through your queue in a very + // short space of time, using a 32-bit type *may* trigger a race condition. + // A 64-bit int type is recommended in that case, and in practice will + // prevent a race condition no matter the usage of the queue. Note that + // whether the queue is lock-free with a 64-int type depends on the whether + // std::atomic is lock-free, which is platform-specific. + typedef std::size_t index_t; + + // Internally, all elements are enqueued and dequeued from multi-element + // blocks; this is the smallest controllable unit. If you expect few elements + // but many producers, a smaller block size should be favoured. For few producers + // and/or many elements, a larger block size is preferred. A sane default + // is provided. Must be a power of 2. + static const size_t BLOCK_SIZE = 32; + + // For explicit producers (i.e. when using a producer token), the block is + // checked for being empty by iterating through a list of flags, one per element. + // For large block sizes, this is too inefficient, and switching to an atomic + // counter-based approach is faster. The switch is made for block sizes strictly + // larger than this threshold. + static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = 32; + + // How many full blocks can be expected for a single explicit producer? This should + // reflect that number's maximum for optimal performance. Must be a power of 2. + static const size_t EXPLICIT_INITIAL_INDEX_SIZE = 32; + + // How many full blocks can be expected for a single implicit producer? This should + // reflect that number's maximum for optimal performance. Must be a power of 2. + static const size_t IMPLICIT_INITIAL_INDEX_SIZE = 32; + + // The initial size of the hash table mapping thread IDs to implicit producers. + // Note that the hash is resized every time it becomes half full. + // Must be a power of two, and either 0 or at least 1. If 0, implicit production + // (using the enqueue methods without an explicit producer token) is disabled. + static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = 32; + + // Controls the number of items that an explicit consumer (i.e. one with a token) + // must consume before it causes all consumers to rotate and move on to the next + // internal queue. + static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = 256; + + // The maximum number of elements (inclusive) that can be enqueued to a sub-queue. + // Enqueue operations that would cause this limit to be surpassed will fail. Note + // that this limit is enforced at the block level (for performance reasons), i.e. + // it's rounded up to the nearest block size. + static const size_t MAX_SUBQUEUE_SIZE = details::const_numeric_max::value; + + +#ifndef MCDBGQ_USE_RELACY + // Memory allocation can be customized if needed. + // malloc should return nullptr on failure, and handle alignment like std::malloc. +#if defined(malloc) || defined(free) + // Gah, this is 2015, stop defining macros that break standard code already! + // Work around malloc/free being special macros: + static inline void* WORKAROUND_malloc(size_t size) { return malloc(size); } + static inline void WORKAROUND_free(void* ptr) { return free(ptr); } + static inline void* (malloc)(size_t size) { return WORKAROUND_malloc(size); } + static inline void (free)(void* ptr) { return WORKAROUND_free(ptr); } +#else + static inline void* malloc(size_t size) { return std::malloc(size); } + static inline void free(void* ptr) { return std::free(ptr); } +#endif +#else + // Debug versions when running under the Relacy race detector (ignore + // these in user code) + static inline void* malloc(size_t size) { return rl::rl_malloc(size, $); } + static inline void free(void* ptr) { return rl::rl_free(ptr, $); } +#endif +}; + + +// When producing or consuming many elements, the most efficient way is to: +// 1) Use one of the bulk-operation methods of the queue with a token +// 2) Failing that, use the bulk-operation methods without a token +// 3) Failing that, create a token and use that with the single-item methods +// 4) Failing that, use the single-parameter methods of the queue +// Having said that, don't create tokens willy-nilly -- ideally there should be +// a maximum of one token per thread (of each kind). +struct ProducerToken; +struct ConsumerToken; + +template class ConcurrentQueue; +template class BlockingConcurrentQueue; +class ConcurrentQueueTests; + + +namespace details +{ + struct ConcurrentQueueProducerTypelessBase + { + ConcurrentQueueProducerTypelessBase* next; + std::atomic inactive; + ProducerToken* token; + + ConcurrentQueueProducerTypelessBase() + : next(nullptr), inactive(false), token(nullptr) + { + } + }; + + template struct _hash_32_or_64 { + static inline std::uint32_t hash(std::uint32_t h) + { + // MurmurHash3 finalizer -- see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp + // Since the thread ID is already unique, all we really want to do is propagate that + // uniqueness evenly across all the bits, so that we can use a subset of the bits while + // reducing collisions significantly + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + return h ^ (h >> 16); + } + }; + template<> struct _hash_32_or_64<1> { + static inline std::uint64_t hash(std::uint64_t h) + { + h ^= h >> 33; + h *= 0xff51afd7ed558ccd; + h ^= h >> 33; + h *= 0xc4ceb9fe1a85ec53; + return h ^ (h >> 33); + } + }; + template struct hash_32_or_64 : public _hash_32_or_64<(size > 4)> { }; + + static inline size_t hash_thread_id(thread_id_t id) + { + static_assert(sizeof(thread_id_t) <= 8, "Expected a platform where thread IDs are at most 64-bit values"); + return static_cast(hash_32_or_64::thread_id_hash_t)>::hash( + thread_id_converter::prehash(id))); + } + + template + static inline bool circular_less_than(T a, T b) + { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4554) +#endif + static_assert(std::is_integral::value && !std::numeric_limits::is_signed, "circular_less_than is intended to be used only with unsigned integer types"); + return static_cast(a - b) > static_cast(static_cast(1) << static_cast(sizeof(T) * CHAR_BIT - 1)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } + + template + static inline char* align_for(char* ptr) + { + const std::size_t alignment = std::alignment_of::value; + return ptr + (alignment - (reinterpret_cast(ptr) % alignment)) % alignment; + } + + template + static inline T ceil_to_pow_2(T x) + { + static_assert(std::is_integral::value && !std::numeric_limits::is_signed, "ceil_to_pow_2 is intended to be used only with unsigned integer types"); + + // Adapted from http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + for (std::size_t i = 1; i < sizeof(T); i <<= 1) { + x |= x >> (i << 3); + } + ++x; + return x; + } + + template + static inline void swap_relaxed(std::atomic& left, std::atomic& right) + { + T temp = std::move(left.load(std::memory_order_relaxed)); + left.store(std::move(right.load(std::memory_order_relaxed)), std::memory_order_relaxed); + right.store(std::move(temp), std::memory_order_relaxed); + } + + template + static inline T const& nomove(T const& x) + { + return x; + } + + template + struct nomove_if + { + template + static inline T const& eval(T const& x) + { + return x; + } + }; + + template<> + struct nomove_if + { + template + static inline auto eval(U&& x) + -> decltype(std::forward(x)) + { + return std::forward(x); + } + }; + + template + static inline auto deref_noexcept(It& it) MOODYCAMEL_NOEXCEPT -> decltype(*it) + { + return *it; + } + +#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + template struct is_trivially_destructible : std::is_trivially_destructible { }; +#else + template struct is_trivially_destructible : std::has_trivial_destructor { }; +#endif + +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED +#ifdef MCDBGQ_USE_RELACY + typedef RelacyThreadExitListener ThreadExitListener; + typedef RelacyThreadExitNotifier ThreadExitNotifier; +#else + struct ThreadExitListener + { + typedef void (*callback_t)(void*); + callback_t callback; + void* userData; + + ThreadExitListener* next; // reserved for use by the ThreadExitNotifier + }; + + + class ThreadExitNotifier + { + public: + static void subscribe(ThreadExitListener* listener) + { + auto& tlsInst = instance(); + listener->next = tlsInst.tail; + tlsInst.tail = listener; + } + + static void unsubscribe(ThreadExitListener* listener) + { + auto& tlsInst = instance(); + ThreadExitListener** prev = &tlsInst.tail; + for (auto ptr = tlsInst.tail; ptr != nullptr; ptr = ptr->next) { + if (ptr == listener) { + *prev = ptr->next; + break; + } + prev = &ptr->next; + } + } + + private: + ThreadExitNotifier() : tail(nullptr) { } + ThreadExitNotifier(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION; + ThreadExitNotifier& operator=(ThreadExitNotifier const&) MOODYCAMEL_DELETE_FUNCTION; + + ~ThreadExitNotifier() + { + // This thread is about to exit, let everyone know! + assert(this == &instance() && "If this assert fails, you likely have a buggy compiler! Change the preprocessor conditions such that MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is no longer defined."); + for (auto ptr = tail; ptr != nullptr; ptr = ptr->next) { + ptr->callback(ptr->userData); + } + } + + // Thread-local + static inline ThreadExitNotifier& instance() + { + static thread_local ThreadExitNotifier notifier; + return notifier; + } + + private: + ThreadExitListener* tail; + }; +#endif +#endif + + template struct static_is_lock_free_num { enum { value = 0 }; }; + template<> struct static_is_lock_free_num { enum { value = ATOMIC_CHAR_LOCK_FREE }; }; + template<> struct static_is_lock_free_num { enum { value = ATOMIC_SHORT_LOCK_FREE }; }; + template<> struct static_is_lock_free_num { enum { value = ATOMIC_INT_LOCK_FREE }; }; + template<> struct static_is_lock_free_num { enum { value = ATOMIC_LONG_LOCK_FREE }; }; + template<> struct static_is_lock_free_num { enum { value = ATOMIC_LLONG_LOCK_FREE }; }; + template struct static_is_lock_free : static_is_lock_free_num::type> { }; + template<> struct static_is_lock_free { enum { value = ATOMIC_BOOL_LOCK_FREE }; }; + template struct static_is_lock_free { enum { value = ATOMIC_POINTER_LOCK_FREE }; }; +} + + +struct ProducerToken +{ + template + explicit ProducerToken(ConcurrentQueue& queue); + + template + explicit ProducerToken(BlockingConcurrentQueue& queue); + + ProducerToken(ProducerToken&& other) MOODYCAMEL_NOEXCEPT + : producer(other.producer) + { + other.producer = nullptr; + if (producer != nullptr) { + producer->token = this; + } + } + + inline ProducerToken& operator=(ProducerToken&& other) MOODYCAMEL_NOEXCEPT + { + swap(other); + return *this; + } + + void swap(ProducerToken& other) MOODYCAMEL_NOEXCEPT + { + std::swap(producer, other.producer); + if (producer != nullptr) { + producer->token = this; + } + if (other.producer != nullptr) { + other.producer->token = &other; + } + } + + // A token is always valid unless: + // 1) Memory allocation failed during construction + // 2) It was moved via the move constructor + // (Note: assignment does a swap, leaving both potentially valid) + // 3) The associated queue was destroyed + // Note that if valid() returns true, that only indicates + // that the token is valid for use with a specific queue, + // but not which one; that's up to the user to track. + inline bool valid() const { return producer != nullptr; } + + ~ProducerToken() + { + if (producer != nullptr) { + producer->token = nullptr; + producer->inactive.store(true, std::memory_order_release); + } + } + + // Disable copying and assignment + ProducerToken(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION; + ProducerToken& operator=(ProducerToken const&) MOODYCAMEL_DELETE_FUNCTION; + +private: + template friend class ConcurrentQueue; + friend class ConcurrentQueueTests; + +protected: + details::ConcurrentQueueProducerTypelessBase* producer; +}; + + +struct ConsumerToken +{ + template + explicit ConsumerToken(ConcurrentQueue& q); + + template + explicit ConsumerToken(BlockingConcurrentQueue& q); + + ConsumerToken(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT + : initialOffset(other.initialOffset), lastKnownGlobalOffset(other.lastKnownGlobalOffset), itemsConsumedFromCurrent(other.itemsConsumedFromCurrent), currentProducer(other.currentProducer), desiredProducer(other.desiredProducer) + { + } + + inline ConsumerToken& operator=(ConsumerToken&& other) MOODYCAMEL_NOEXCEPT + { + swap(other); + return *this; + } + + void swap(ConsumerToken& other) MOODYCAMEL_NOEXCEPT + { + std::swap(initialOffset, other.initialOffset); + std::swap(lastKnownGlobalOffset, other.lastKnownGlobalOffset); + std::swap(itemsConsumedFromCurrent, other.itemsConsumedFromCurrent); + std::swap(currentProducer, other.currentProducer); + std::swap(desiredProducer, other.desiredProducer); + } + + // Disable copying and assignment + ConsumerToken(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION; + ConsumerToken& operator=(ConsumerToken const&) MOODYCAMEL_DELETE_FUNCTION; + +private: + template friend class ConcurrentQueue; + friend class ConcurrentQueueTests; + +private: // but shared with ConcurrentQueue + std::uint32_t initialOffset; + std::uint32_t lastKnownGlobalOffset; + std::uint32_t itemsConsumedFromCurrent; + details::ConcurrentQueueProducerTypelessBase* currentProducer; + details::ConcurrentQueueProducerTypelessBase* desiredProducer; +}; + +// Need to forward-declare this swap because it's in a namespace. +// See http://stackoverflow.com/questions/4492062/why-does-a-c-friend-class-need-a-forward-declaration-only-in-other-namespaces +template +inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, typename ConcurrentQueue::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT; + + +template +class ConcurrentQueue +{ +public: + typedef ::moodycamel::ProducerToken producer_token_t; + typedef ::moodycamel::ConsumerToken consumer_token_t; + + typedef typename Traits::index_t index_t; + typedef typename Traits::size_t size_t; + + static const size_t BLOCK_SIZE = static_cast(Traits::BLOCK_SIZE); + static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = static_cast(Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD); + static const size_t EXPLICIT_INITIAL_INDEX_SIZE = static_cast(Traits::EXPLICIT_INITIAL_INDEX_SIZE); + static const size_t IMPLICIT_INITIAL_INDEX_SIZE = static_cast(Traits::IMPLICIT_INITIAL_INDEX_SIZE); + static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = static_cast(Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE); + static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = static_cast(Traits::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4307) // + integral constant overflow (that's what the ternary expression is for!) +#pragma warning(disable: 4309) // static_cast: Truncation of constant value +#endif + static const size_t MAX_SUBQUEUE_SIZE = (details::const_numeric_max::value - static_cast(Traits::MAX_SUBQUEUE_SIZE) < BLOCK_SIZE) ? details::const_numeric_max::value : ((static_cast(Traits::MAX_SUBQUEUE_SIZE) + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + static_assert(!std::numeric_limits::is_signed && std::is_integral::value, "Traits::size_t must be an unsigned integral type"); + static_assert(!std::numeric_limits::is_signed && std::is_integral::value, "Traits::index_t must be an unsigned integral type"); + static_assert(sizeof(index_t) >= sizeof(size_t), "Traits::index_t must be at least as wide as Traits::size_t"); + static_assert((BLOCK_SIZE > 1) && !(BLOCK_SIZE & (BLOCK_SIZE - 1)), "Traits::BLOCK_SIZE must be a power of 2 (and at least 2)"); + static_assert((EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD > 1) && !(EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD & (EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD - 1)), "Traits::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD must be a power of 2 (and greater than 1)"); + static_assert((EXPLICIT_INITIAL_INDEX_SIZE > 1) && !(EXPLICIT_INITIAL_INDEX_SIZE & (EXPLICIT_INITIAL_INDEX_SIZE - 1)), "Traits::EXPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)"); + static_assert((IMPLICIT_INITIAL_INDEX_SIZE > 1) && !(IMPLICIT_INITIAL_INDEX_SIZE & (IMPLICIT_INITIAL_INDEX_SIZE - 1)), "Traits::IMPLICIT_INITIAL_INDEX_SIZE must be a power of 2 (and greater than 1)"); + static_assert((INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) || !(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE & (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE - 1)), "Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be a power of 2"); + static_assert(INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0 || INITIAL_IMPLICIT_PRODUCER_HASH_SIZE >= 1, "Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE must be at least 1 (or 0 to disable implicit enqueueing)"); + +public: + // Creates a queue with at least `capacity` element slots; note that the + // actual number of elements that can be inserted without additional memory + // allocation depends on the number of producers and the block size (e.g. if + // the block size is equal to `capacity`, only a single block will be allocated + // up-front, which means only a single producer will be able to enqueue elements + // without an extra allocation -- blocks aren't shared between producers). + // This method is not thread safe -- it is up to the user to ensure that the + // queue is fully constructed before it starts being used by other threads (this + // includes making the memory effects of construction visible, possibly with a + // memory barrier). + explicit ConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE) + : producerListTail(nullptr), + producerCount(0), + initialBlockPoolIndex(0), + nextExplicitConsumerId(0), + globalExplicitConsumerOffset(0) + { + implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); + populate_initial_implicit_producer_hash(); + populate_initial_block_list(capacity / BLOCK_SIZE + ((capacity & (BLOCK_SIZE - 1)) == 0 ? 0 : 1)); + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + // Track all the producers using a fully-resolved typed list for + // each kind; this makes it possible to debug them starting from + // the root queue object (otherwise wacky casts are needed that + // don't compile in the debugger's expression evaluator). + explicitProducers.store(nullptr, std::memory_order_relaxed); + implicitProducers.store(nullptr, std::memory_order_relaxed); +#endif + } + + // Computes the correct amount of pre-allocated blocks for you based + // on the minimum number of elements you want available at any given + // time, and the maximum concurrent number of each type of producer. + ConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers) + : producerListTail(nullptr), + producerCount(0), + initialBlockPoolIndex(0), + nextExplicitConsumerId(0), + globalExplicitConsumerOffset(0) + { + implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); + populate_initial_implicit_producer_hash(); + size_t blocks = (((minCapacity + BLOCK_SIZE - 1) / BLOCK_SIZE) - 1) * (maxExplicitProducers + 1) + 2 * (maxExplicitProducers + maxImplicitProducers); + populate_initial_block_list(blocks); + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + explicitProducers.store(nullptr, std::memory_order_relaxed); + implicitProducers.store(nullptr, std::memory_order_relaxed); +#endif + } + + // Note: The queue should not be accessed concurrently while it's + // being deleted. It's up to the user to synchronize this. + // This method is not thread safe. + ~ConcurrentQueue() + { + // Destroy producers + auto ptr = producerListTail.load(std::memory_order_relaxed); + while (ptr != nullptr) { + auto next = ptr->next_prod(); + if (ptr->token != nullptr) { + ptr->token->producer = nullptr; + } + destroy(ptr); + ptr = next; + } + + // Destroy implicit producer hash tables + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE != 0) { + auto hash = implicitProducerHash.load(std::memory_order_relaxed); + while (hash != nullptr) { + auto prev = hash->prev; + if (prev != nullptr) { // The last hash is part of this object and was not allocated dynamically + for (size_t i = 0; i != hash->capacity; ++i) { + hash->entries[i].~ImplicitProducerKVP(); + } + hash->~ImplicitProducerHash(); + (Traits::free)(hash); + } + hash = prev; + } + } + + // Destroy global free list + auto block = freeList.head_unsafe(); + while (block != nullptr) { + auto next = block->freeListNext.load(std::memory_order_relaxed); + if (block->dynamicallyAllocated) { + destroy(block); + } + block = next; + } + + // Destroy initial free list + destroy_array(initialBlockPool, initialBlockPoolSize); + } + + // Disable copying and copy assignment + ConcurrentQueue(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION; + ConcurrentQueue& operator=(ConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION; + + // Moving is supported, but note that it is *not* a thread-safe operation. + // Nobody can use the queue while it's being moved, and the memory effects + // of that move must be propagated to other threads before they can use it. + // Note: When a queue is moved, its tokens are still valid but can only be + // used with the destination queue (i.e. semantically they are moved along + // with the queue itself). + ConcurrentQueue(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT + : producerListTail(other.producerListTail.load(std::memory_order_relaxed)), + producerCount(other.producerCount.load(std::memory_order_relaxed)), + initialBlockPoolIndex(other.initialBlockPoolIndex.load(std::memory_order_relaxed)), + initialBlockPool(other.initialBlockPool), + initialBlockPoolSize(other.initialBlockPoolSize), + freeList(std::move(other.freeList)), + nextExplicitConsumerId(other.nextExplicitConsumerId.load(std::memory_order_relaxed)), + globalExplicitConsumerOffset(other.globalExplicitConsumerOffset.load(std::memory_order_relaxed)) + { + // Move the other one into this, and leave the other one as an empty queue + implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); + populate_initial_implicit_producer_hash(); + swap_implicit_producer_hashes(other); + + other.producerListTail.store(nullptr, std::memory_order_relaxed); + other.producerCount.store(0, std::memory_order_relaxed); + other.nextExplicitConsumerId.store(0, std::memory_order_relaxed); + other.globalExplicitConsumerOffset.store(0, std::memory_order_relaxed); + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + explicitProducers.store(other.explicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed); + other.explicitProducers.store(nullptr, std::memory_order_relaxed); + implicitProducers.store(other.implicitProducers.load(std::memory_order_relaxed), std::memory_order_relaxed); + other.implicitProducers.store(nullptr, std::memory_order_relaxed); +#endif + + other.initialBlockPoolIndex.store(0, std::memory_order_relaxed); + other.initialBlockPoolSize = 0; + other.initialBlockPool = nullptr; + + reown_producers(); + } + + inline ConcurrentQueue& operator=(ConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT + { + return swap_internal(other); + } + + // Swaps this queue's state with the other's. Not thread-safe. + // Swapping two queues does not invalidate their tokens, however + // the tokens that were created for one queue must be used with + // only the swapped queue (i.e. the tokens are tied to the + // queue's movable state, not the object itself). + inline void swap(ConcurrentQueue& other) MOODYCAMEL_NOEXCEPT + { + swap_internal(other); + } + +private: + ConcurrentQueue& swap_internal(ConcurrentQueue& other) + { + if (this == &other) { + return *this; + } + + details::swap_relaxed(producerListTail, other.producerListTail); + details::swap_relaxed(producerCount, other.producerCount); + details::swap_relaxed(initialBlockPoolIndex, other.initialBlockPoolIndex); + std::swap(initialBlockPool, other.initialBlockPool); + std::swap(initialBlockPoolSize, other.initialBlockPoolSize); + freeList.swap(other.freeList); + details::swap_relaxed(nextExplicitConsumerId, other.nextExplicitConsumerId); + details::swap_relaxed(globalExplicitConsumerOffset, other.globalExplicitConsumerOffset); + + swap_implicit_producer_hashes(other); + + reown_producers(); + other.reown_producers(); + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + details::swap_relaxed(explicitProducers, other.explicitProducers); + details::swap_relaxed(implicitProducers, other.implicitProducers); +#endif + + return *this; + } + +public: + // Enqueues a single item (by copying it). + // Allocates memory if required. Only fails if memory allocation fails (or implicit + // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0, + // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Thread-safe. + inline bool enqueue(T const& item) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue(item); + } + + // Enqueues a single item (by moving it, if possible). + // Allocates memory if required. Only fails if memory allocation fails (or implicit + // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0, + // or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Thread-safe. + inline bool enqueue(T&& item) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue(std::move(item)); + } + + // Enqueues a single item (by copying it) using an explicit producer token. + // Allocates memory if required. Only fails if memory allocation fails (or + // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Thread-safe. + inline bool enqueue(producer_token_t const& token, T const& item) + { + return inner_enqueue(token, item); + } + + // Enqueues a single item (by moving it, if possible) using an explicit producer token. + // Allocates memory if required. Only fails if memory allocation fails (or + // Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Thread-safe. + inline bool enqueue(producer_token_t const& token, T&& item) + { + return inner_enqueue(token, std::move(item)); + } + + // Enqueues several items. + // Allocates memory if required. Only fails if memory allocation fails (or + // implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE + // is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Note: Use std::make_move_iterator if the elements should be moved instead of copied. + // Thread-safe. + template + bool enqueue_bulk(It itemFirst, size_t count) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue_bulk(itemFirst, count); + } + + // Enqueues several items using an explicit producer token. + // Allocates memory if required. Only fails if memory allocation fails + // (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed). + // Note: Use std::make_move_iterator if the elements should be moved + // instead of copied. + // Thread-safe. + template + bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) + { + return inner_enqueue_bulk(token, itemFirst, count); + } + + // Enqueues a single item (by copying it). + // Does not allocate memory. Fails if not enough room to enqueue (or implicit + // production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE + // is 0). + // Thread-safe. + inline bool try_enqueue(T const& item) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue(item); + } + + // Enqueues a single item (by moving it, if possible). + // Does not allocate memory (except for one-time implicit producer). + // Fails if not enough room to enqueue (or implicit production is + // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0). + // Thread-safe. + inline bool try_enqueue(T&& item) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue(std::move(item)); + } + + // Enqueues a single item (by copying it) using an explicit producer token. + // Does not allocate memory. Fails if not enough room to enqueue. + // Thread-safe. + inline bool try_enqueue(producer_token_t const& token, T const& item) + { + return inner_enqueue(token, item); + } + + // Enqueues a single item (by moving it, if possible) using an explicit producer token. + // Does not allocate memory. Fails if not enough room to enqueue. + // Thread-safe. + inline bool try_enqueue(producer_token_t const& token, T&& item) + { + return inner_enqueue(token, std::move(item)); + } + + // Enqueues several items. + // Does not allocate memory (except for one-time implicit producer). + // Fails if not enough room to enqueue (or implicit production is + // disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0). + // Note: Use std::make_move_iterator if the elements should be moved + // instead of copied. + // Thread-safe. + template + bool try_enqueue_bulk(It itemFirst, size_t count) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return false; + return inner_enqueue_bulk(itemFirst, count); + } + + // Enqueues several items using an explicit producer token. + // Does not allocate memory. Fails if not enough room to enqueue. + // Note: Use std::make_move_iterator if the elements should be moved + // instead of copied. + // Thread-safe. + template + bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) + { + return inner_enqueue_bulk(token, itemFirst, count); + } + + + + // Attempts to dequeue from the queue. + // Returns false if all producer streams appeared empty at the time they + // were checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + bool try_dequeue(U& item) + { + // Instead of simply trying each producer in turn (which could cause needless contention on the first + // producer), we score them heuristically. + size_t nonEmptyCount = 0; + ProducerBase* best = nullptr; + size_t bestSize = 0; + for (auto ptr = producerListTail.load(std::memory_order_acquire); nonEmptyCount < 3 && ptr != nullptr; ptr = ptr->next_prod()) { + auto size = ptr->size_approx(); + if (size > 0) { + if (size > bestSize) { + bestSize = size; + best = ptr; + } + ++nonEmptyCount; + } + } + + // If there was at least one non-empty queue but it appears empty at the time + // we try to dequeue from it, we need to make sure every queue's been tried + if (nonEmptyCount > 0) { + if ((details::likely)(best->dequeue(item))) { + return true; + } + for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + if (ptr != best && ptr->dequeue(item)) { + return true; + } + } + } + return false; + } + + // Attempts to dequeue from the queue. + // Returns false if all producer streams appeared empty at the time they + // were checked (so, the queue is likely but not guaranteed to be empty). + // This differs from the try_dequeue(item) method in that this one does + // not attempt to reduce contention by interleaving the order that producer + // streams are dequeued from. So, using this method can reduce overall throughput + // under contention, but will give more predictable results in single-threaded + // consumer scenarios. This is mostly only useful for internal unit tests. + // Never allocates. Thread-safe. + template + bool try_dequeue_non_interleaved(U& item) + { + for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + if (ptr->dequeue(item)) { + return true; + } + } + return false; + } + + // Attempts to dequeue from the queue using an explicit consumer token. + // Returns false if all producer streams appeared empty at the time they + // were checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + bool try_dequeue(consumer_token_t& token, U& item) + { + // The idea is roughly as follows: + // Every 256 items from one producer, make everyone rotate (increase the global offset) -> this means the highest efficiency consumer dictates the rotation speed of everyone else, more or less + // If you see that the global offset has changed, you must reset your consumption counter and move to your designated place + // If there's no items where you're supposed to be, keep moving until you find a producer with some items + // If the global offset has not changed but you've run out of items to consume, move over from your current position until you find an producer with something in it + + if (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) { + if (!update_current_producer_after_rotation(token)) { + return false; + } + } + + // If there was at least one non-empty queue but it appears empty at the time + // we try to dequeue from it, we need to make sure every queue's been tried + if (static_cast(token.currentProducer)->dequeue(item)) { + if (++token.itemsConsumedFromCurrent == EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) { + globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed); + } + return true; + } + + auto tail = producerListTail.load(std::memory_order_acquire); + auto ptr = static_cast(token.currentProducer)->next_prod(); + if (ptr == nullptr) { + ptr = tail; + } + while (ptr != static_cast(token.currentProducer)) { + if (ptr->dequeue(item)) { + token.currentProducer = ptr; + token.itemsConsumedFromCurrent = 1; + return true; + } + ptr = ptr->next_prod(); + if (ptr == nullptr) { + ptr = tail; + } + } + return false; + } + + // Attempts to dequeue several elements from the queue. + // Returns the number of items actually dequeued. + // Returns 0 if all producer streams appeared empty at the time they + // were checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + size_t try_dequeue_bulk(It itemFirst, size_t max) + { + size_t count = 0; + for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + count += ptr->dequeue_bulk(itemFirst, max - count); + if (count == max) { + break; + } + } + return count; + } + + // Attempts to dequeue several elements from the queue using an explicit consumer token. + // Returns the number of items actually dequeued. + // Returns 0 if all producer streams appeared empty at the time they + // were checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max) + { + if (token.desiredProducer == nullptr || token.lastKnownGlobalOffset != globalExplicitConsumerOffset.load(std::memory_order_relaxed)) { + if (!update_current_producer_after_rotation(token)) { + return 0; + } + } + + size_t count = static_cast(token.currentProducer)->dequeue_bulk(itemFirst, max); + if (count == max) { + if ((token.itemsConsumedFromCurrent += static_cast(max)) >= EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE) { + globalExplicitConsumerOffset.fetch_add(1, std::memory_order_relaxed); + } + return max; + } + token.itemsConsumedFromCurrent += static_cast(count); + max -= count; + + auto tail = producerListTail.load(std::memory_order_acquire); + auto ptr = static_cast(token.currentProducer)->next_prod(); + if (ptr == nullptr) { + ptr = tail; + } + while (ptr != static_cast(token.currentProducer)) { + auto dequeued = ptr->dequeue_bulk(itemFirst, max); + count += dequeued; + if (dequeued != 0) { + token.currentProducer = ptr; + token.itemsConsumedFromCurrent = static_cast(dequeued); + } + if (dequeued == max) { + break; + } + max -= dequeued; + ptr = ptr->next_prod(); + if (ptr == nullptr) { + ptr = tail; + } + } + return count; + } + + + + // Attempts to dequeue from a specific producer's inner queue. + // If you happen to know which producer you want to dequeue from, this + // is significantly faster than using the general-case try_dequeue methods. + // Returns false if the producer's queue appeared empty at the time it + // was checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + inline bool try_dequeue_from_producer(producer_token_t const& producer, U& item) + { + return static_cast(producer.producer)->dequeue(item); + } + + // Attempts to dequeue several elements from a specific producer's inner queue. + // Returns the number of items actually dequeued. + // If you happen to know which producer you want to dequeue from, this + // is significantly faster than using the general-case try_dequeue methods. + // Returns 0 if the producer's queue appeared empty at the time it + // was checked (so, the queue is likely but not guaranteed to be empty). + // Never allocates. Thread-safe. + template + inline size_t try_dequeue_bulk_from_producer(producer_token_t const& producer, It itemFirst, size_t max) + { + return static_cast(producer.producer)->dequeue_bulk(itemFirst, max); + } + + + // Returns an estimate of the total number of elements currently in the queue. This + // estimate is only accurate if the queue has completely stabilized before it is called + // (i.e. all enqueue and dequeue operations have completed and their memory effects are + // visible on the calling thread, and no further operations start while this method is + // being called). + // Thread-safe. + size_t size_approx() const + { + size_t size = 0; + for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + size += ptr->size_approx(); + } + return size; + } + + + // Returns true if the underlying atomic variables used by + // the queue are lock-free (they should be on most platforms). + // Thread-safe. + static bool is_lock_free() + { + return + details::static_is_lock_free::value == 2 && + details::static_is_lock_free::value == 2 && + details::static_is_lock_free::value == 2 && + details::static_is_lock_free::value == 2 && + details::static_is_lock_free::value == 2 && + details::static_is_lock_free::thread_id_numeric_size_t>::value == 2; + } + + +private: + friend struct ProducerToken; + friend struct ConsumerToken; + struct ExplicitProducer; + friend struct ExplicitProducer; + struct ImplicitProducer; + friend struct ImplicitProducer; + friend class ConcurrentQueueTests; + + enum AllocationMode { CanAlloc, CannotAlloc }; + + + /////////////////////////////// + // Queue methods + /////////////////////////////// + + template + inline bool inner_enqueue(producer_token_t const& token, U&& element) + { + return static_cast(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue(std::forward(element)); + } + + template + inline bool inner_enqueue(U&& element) + { + auto producer = get_or_add_implicit_producer(); + return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue(std::forward(element)); + } + + template + inline bool inner_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count) + { + return static_cast(token.producer)->ConcurrentQueue::ExplicitProducer::template enqueue_bulk(itemFirst, count); + } + + template + inline bool inner_enqueue_bulk(It itemFirst, size_t count) + { + auto producer = get_or_add_implicit_producer(); + return producer == nullptr ? false : producer->ConcurrentQueue::ImplicitProducer::template enqueue_bulk(itemFirst, count); + } + + inline bool update_current_producer_after_rotation(consumer_token_t& token) + { + // Ah, there's been a rotation, figure out where we should be! + auto tail = producerListTail.load(std::memory_order_acquire); + if (token.desiredProducer == nullptr && tail == nullptr) { + return false; + } + auto prodCount = producerCount.load(std::memory_order_relaxed); + auto globalOffset = globalExplicitConsumerOffset.load(std::memory_order_relaxed); + if ((details::unlikely)(token.desiredProducer == nullptr)) { + // Aha, first time we're dequeueing anything. + // Figure out our local position + // Note: offset is from start, not end, but we're traversing from end -- subtract from count first + std::uint32_t offset = prodCount - 1 - (token.initialOffset % prodCount); + token.desiredProducer = tail; + for (std::uint32_t i = 0; i != offset; ++i) { + token.desiredProducer = static_cast(token.desiredProducer)->next_prod(); + if (token.desiredProducer == nullptr) { + token.desiredProducer = tail; + } + } + } + + std::uint32_t delta = globalOffset - token.lastKnownGlobalOffset; + if (delta >= prodCount) { + delta = delta % prodCount; + } + for (std::uint32_t i = 0; i != delta; ++i) { + token.desiredProducer = static_cast(token.desiredProducer)->next_prod(); + if (token.desiredProducer == nullptr) { + token.desiredProducer = tail; + } + } + + token.lastKnownGlobalOffset = globalOffset; + token.currentProducer = token.desiredProducer; + token.itemsConsumedFromCurrent = 0; + return true; + } + + + /////////////////////////// + // Free list + /////////////////////////// + + template + struct FreeListNode + { + FreeListNode() : freeListRefs(0), freeListNext(nullptr) { } + + std::atomic freeListRefs; + std::atomic freeListNext; + }; + + // A simple CAS-based lock-free free list. Not the fastest thing in the world under heavy contention, but + // simple and correct (assuming nodes are never freed until after the free list is destroyed), and fairly + // speedy under low contention. + template // N must inherit FreeListNode or have the same fields (and initialization of them) + struct FreeList + { + FreeList() : freeListHead(nullptr) { } + FreeList(FreeList&& other) : freeListHead(other.freeListHead.load(std::memory_order_relaxed)) { other.freeListHead.store(nullptr, std::memory_order_relaxed); } + void swap(FreeList& other) { details::swap_relaxed(freeListHead, other.freeListHead); } + + FreeList(FreeList const&) MOODYCAMEL_DELETE_FUNCTION; + FreeList& operator=(FreeList const&) MOODYCAMEL_DELETE_FUNCTION; + + inline void add(N* node) + { +#if MCDBGQ_NOLOCKFREE_FREELIST + debug::DebugLock lock(mutex); +#endif + // We know that the should-be-on-freelist bit is 0 at this point, so it's safe to + // set it using a fetch_add + if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST, std::memory_order_acq_rel) == 0) { + // Oh look! We were the last ones referencing this node, and we know + // we want to add it to the free list, so let's do it! + add_knowing_refcount_is_zero(node); + } + } + + inline N* try_get() + { +#if MCDBGQ_NOLOCKFREE_FREELIST + debug::DebugLock lock(mutex); +#endif + auto head = freeListHead.load(std::memory_order_acquire); + while (head != nullptr) { + auto prevHead = head; + auto refs = head->freeListRefs.load(std::memory_order_relaxed); + if ((refs & REFS_MASK) == 0 || !head->freeListRefs.compare_exchange_strong(refs, refs + 1, std::memory_order_acquire, std::memory_order_relaxed)) { + head = freeListHead.load(std::memory_order_acquire); + continue; + } + + // Good, reference count has been incremented (it wasn't at zero), which means we can read the + // next and not worry about it changing between now and the time we do the CAS + auto next = head->freeListNext.load(std::memory_order_relaxed); + if (freeListHead.compare_exchange_strong(head, next, std::memory_order_acquire, std::memory_order_relaxed)) { + // Yay, got the node. This means it was on the list, which means shouldBeOnFreeList must be false no + // matter the refcount (because nobody else knows it's been taken off yet, it can't have been put back on). + assert((head->freeListRefs.load(std::memory_order_relaxed) & SHOULD_BE_ON_FREELIST) == 0); + + // Decrease refcount twice, once for our ref, and once for the list's ref + head->freeListRefs.fetch_sub(2, std::memory_order_release); + return head; + } + + // OK, the head must have changed on us, but we still need to decrease the refcount we increased. + // Note that we don't need to release any memory effects, but we do need to ensure that the reference + // count decrement happens-after the CAS on the head. + refs = prevHead->freeListRefs.fetch_sub(1, std::memory_order_acq_rel); + if (refs == SHOULD_BE_ON_FREELIST + 1) { + add_knowing_refcount_is_zero(prevHead); + } + } + + return nullptr; + } + + // Useful for traversing the list when there's no contention (e.g. to destroy remaining nodes) + N* head_unsafe() const { return freeListHead.load(std::memory_order_relaxed); } + + private: + inline void add_knowing_refcount_is_zero(N* node) + { + // Since the refcount is zero, and nobody can increase it once it's zero (except us, and we run + // only one copy of this method per node at a time, i.e. the single thread case), then we know + // we can safely change the next pointer of the node; however, once the refcount is back above + // zero, then other threads could increase it (happens under heavy contention, when the refcount + // goes to zero in between a load and a refcount increment of a node in try_get, then back up to + // something non-zero, then the refcount increment is done by the other thread) -- so, if the CAS + // to add the node to the actual list fails, decrease the refcount and leave the add operation to + // the next thread who puts the refcount back at zero (which could be us, hence the loop). + auto head = freeListHead.load(std::memory_order_relaxed); + while (true) { + node->freeListNext.store(head, std::memory_order_relaxed); + node->freeListRefs.store(1, std::memory_order_release); + if (!freeListHead.compare_exchange_strong(head, node, std::memory_order_release, std::memory_order_relaxed)) { + // Hmm, the add failed, but we can only try again when the refcount goes back to zero + if (node->freeListRefs.fetch_add(SHOULD_BE_ON_FREELIST - 1, std::memory_order_release) == 1) { + continue; + } + } + return; + } + } + + private: + // Implemented like a stack, but where node order doesn't matter (nodes are inserted out of order under contention) + std::atomic freeListHead; + + static const std::uint32_t REFS_MASK = 0x7FFFFFFF; + static const std::uint32_t SHOULD_BE_ON_FREELIST = 0x80000000; + +#if MCDBGQ_NOLOCKFREE_FREELIST + debug::DebugMutex mutex; +#endif + }; + + + /////////////////////////// + // Block + /////////////////////////// + + enum InnerQueueContext { implicit_context = 0, explicit_context = 1 }; + + struct Block + { + Block() + : next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), shouldBeOnFreeList(false), dynamicallyAllocated(true) + { +#if MCDBGQ_TRACKMEM + owner = nullptr; +#endif + } + + template + inline bool is_empty() const + { + if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { + // Check flags + for (size_t i = 0; i < BLOCK_SIZE; ++i) { + if (!emptyFlags[i].load(std::memory_order_relaxed)) { + return false; + } + } + + // Aha, empty; make sure we have all other memory effects that happened before the empty flags were set + std::atomic_thread_fence(std::memory_order_acquire); + return true; + } + else { + // Check counter + if (elementsCompletelyDequeued.load(std::memory_order_relaxed) == BLOCK_SIZE) { + std::atomic_thread_fence(std::memory_order_acquire); + return true; + } + assert(elementsCompletelyDequeued.load(std::memory_order_relaxed) <= BLOCK_SIZE); + return false; + } + } + + // Returns true if the block is now empty (does not apply in explicit context) + template + inline bool set_empty(index_t i) + { + if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { + // Set flag + assert(!emptyFlags[BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1))].load(std::memory_order_relaxed)); + emptyFlags[BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1))].store(true, std::memory_order_release); + return false; + } + else { + // Increment counter + auto prevVal = elementsCompletelyDequeued.fetch_add(1, std::memory_order_release); + assert(prevVal < BLOCK_SIZE); + return prevVal == BLOCK_SIZE - 1; + } + } + + // Sets multiple contiguous item statuses to 'empty' (assumes no wrapping and count > 0). + // Returns true if the block is now empty (does not apply in explicit context). + template + inline bool set_many_empty(index_t i, size_t count) + { + if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { + // Set flags + std::atomic_thread_fence(std::memory_order_release); + i = BLOCK_SIZE - 1 - static_cast(i & static_cast(BLOCK_SIZE - 1)) - count + 1; + for (size_t j = 0; j != count; ++j) { + assert(!emptyFlags[i + j].load(std::memory_order_relaxed)); + emptyFlags[i + j].store(true, std::memory_order_relaxed); + } + return false; + } + else { + // Increment counter + auto prevVal = elementsCompletelyDequeued.fetch_add(count, std::memory_order_release); + assert(prevVal + count <= BLOCK_SIZE); + return prevVal + count == BLOCK_SIZE; + } + } + + template + inline void set_all_empty() + { + if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { + // Set all flags + for (size_t i = 0; i != BLOCK_SIZE; ++i) { + emptyFlags[i].store(true, std::memory_order_relaxed); + } + } + else { + // Reset counter + elementsCompletelyDequeued.store(BLOCK_SIZE, std::memory_order_relaxed); + } + } + + template + inline void reset_empty() + { + if (context == explicit_context && BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD) { + // Reset flags + for (size_t i = 0; i != BLOCK_SIZE; ++i) { + emptyFlags[i].store(false, std::memory_order_relaxed); + } + } + else { + // Reset counter + elementsCompletelyDequeued.store(0, std::memory_order_relaxed); + } + } + + inline T* operator[](index_t idx) MOODYCAMEL_NOEXCEPT { return static_cast(static_cast(elements)) + static_cast(idx & static_cast(BLOCK_SIZE - 1)); } + inline T const* operator[](index_t idx) const MOODYCAMEL_NOEXCEPT { return static_cast(static_cast(elements)) + static_cast(idx & static_cast(BLOCK_SIZE - 1)); } + + private: + // IMPORTANT: This must be the first member in Block, so that if T depends on the alignment of + // addresses returned by malloc, that alignment will be preserved. Apparently clang actually + // generates code that uses this assumption for AVX instructions in some cases. Ideally, we + // should also align Block to the alignment of T in case it's higher than malloc's 16-byte + // alignment, but this is hard to do in a cross-platform way. Assert for this case: + static_assert(std::alignment_of::value <= std::alignment_of::value, "The queue does not support super-aligned types at this time"); + // Additionally, we need the alignment of Block itself to be a multiple of max_align_t since + // otherwise the appropriate padding will not be added at the end of Block in order to make + // arrays of Blocks all be properly aligned (not just the first one). We use a union to force + // this. + union { + char elements[sizeof(T) * BLOCK_SIZE]; + details::max_align_t dummy; + }; + public: + Block* next; + std::atomic elementsCompletelyDequeued; + std::atomic emptyFlags[BLOCK_SIZE <= EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD ? BLOCK_SIZE : 1]; + public: + std::atomic freeListRefs; + std::atomic freeListNext; + std::atomic shouldBeOnFreeList; + bool dynamicallyAllocated; // Perhaps a better name for this would be 'isNotPartOfInitialBlockPool' + +#if MCDBGQ_TRACKMEM + void* owner; +#endif + }; + static_assert(std::alignment_of::value >= std::alignment_of::value, "Internal error: Blocks must be at least as aligned as the type they are wrapping"); + + +#if MCDBGQ_TRACKMEM +public: + struct MemStats; +private: +#endif + + /////////////////////////// + // Producer base + /////////////////////////// + + struct ProducerBase : public details::ConcurrentQueueProducerTypelessBase + { + ProducerBase(ConcurrentQueue* parent_, bool isExplicit_) : + tailIndex(0), + headIndex(0), + dequeueOptimisticCount(0), + dequeueOvercommit(0), + tailBlock(nullptr), + isExplicit(isExplicit_), + parent(parent_) + { + } + + virtual ~ProducerBase() { }; + + template + inline bool dequeue(U& element) + { + if (isExplicit) { + return static_cast(this)->dequeue(element); + } + else { + return static_cast(this)->dequeue(element); + } + } + + template + inline size_t dequeue_bulk(It& itemFirst, size_t max) + { + if (isExplicit) { + return static_cast(this)->dequeue_bulk(itemFirst, max); + } + else { + return static_cast(this)->dequeue_bulk(itemFirst, max); + } + } + + inline ProducerBase* next_prod() const { return static_cast(next); } + + inline size_t size_approx() const + { + auto tail = tailIndex.load(std::memory_order_relaxed); + auto head = headIndex.load(std::memory_order_relaxed); + return details::circular_less_than(head, tail) ? static_cast(tail - head) : 0; + } + + inline index_t getTail() const { return tailIndex.load(std::memory_order_relaxed); } + protected: + std::atomic tailIndex; // Where to enqueue to next + std::atomic headIndex; // Where to dequeue from next + + std::atomic dequeueOptimisticCount; + std::atomic dequeueOvercommit; + + Block* tailBlock; + + public: + bool isExplicit; + ConcurrentQueue* parent; + + protected: +#if MCDBGQ_TRACKMEM + friend struct MemStats; +#endif + }; + + + /////////////////////////// + // Explicit queue + /////////////////////////// + + struct ExplicitProducer : public ProducerBase + { + explicit ExplicitProducer(ConcurrentQueue* parent) : + ProducerBase(parent, true), + blockIndex(nullptr), + pr_blockIndexSlotsUsed(0), + pr_blockIndexSize(EXPLICIT_INITIAL_INDEX_SIZE >> 1), + pr_blockIndexFront(0), + pr_blockIndexEntries(nullptr), + pr_blockIndexRaw(nullptr) + { + size_t poolBasedIndexSize = details::ceil_to_pow_2(parent->initialBlockPoolSize) >> 1; + if (poolBasedIndexSize > pr_blockIndexSize) { + pr_blockIndexSize = poolBasedIndexSize; + } + + new_block_index(0); // This creates an index with double the number of current entries, i.e. EXPLICIT_INITIAL_INDEX_SIZE + } + + ~ExplicitProducer() + { + // Destruct any elements not yet dequeued. + // Since we're in the destructor, we can assume all elements + // are either completely dequeued or completely not (no halfways). + if (this->tailBlock != nullptr) { // Note this means there must be a block index too + // First find the block that's partially dequeued, if any + Block* halfDequeuedBlock = nullptr; + if ((this->headIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)) != 0) { + // The head's not on a block boundary, meaning a block somewhere is partially dequeued + // (or the head block is the tail block and was fully dequeued, but the head/tail are still not on a boundary) + size_t i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & (pr_blockIndexSize - 1); + while (details::circular_less_than(pr_blockIndexEntries[i].base + BLOCK_SIZE, this->headIndex.load(std::memory_order_relaxed))) { + i = (i + 1) & (pr_blockIndexSize - 1); + } + assert(details::circular_less_than(pr_blockIndexEntries[i].base, this->headIndex.load(std::memory_order_relaxed))); + halfDequeuedBlock = pr_blockIndexEntries[i].block; + } + + // Start at the head block (note the first line in the loop gives us the head from the tail on the first iteration) + auto block = this->tailBlock; + do { + block = block->next; + if (block->ConcurrentQueue::Block::template is_empty()) { + continue; + } + + size_t i = 0; // Offset into block + if (block == halfDequeuedBlock) { + i = static_cast(this->headIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)); + } + + // Walk through all the items in the block; if this is the tail block, we need to stop when we reach the tail index + auto lastValidIndex = (this->tailIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)) == 0 ? BLOCK_SIZE : static_cast(this->tailIndex.load(std::memory_order_relaxed) & static_cast(BLOCK_SIZE - 1)); + while (i != BLOCK_SIZE && (block != this->tailBlock || i != lastValidIndex)) { + (*block)[i++]->~T(); + } + } while (block != this->tailBlock); + } + + // Destroy all blocks that we own + if (this->tailBlock != nullptr) { + auto block = this->tailBlock; + do { + auto nextBlock = block->next; + if (block->dynamicallyAllocated) { + destroy(block); + } + else { + this->parent->add_block_to_free_list(block); + } + block = nextBlock; + } while (block != this->tailBlock); + } + + // Destroy the block indices + auto header = static_cast(pr_blockIndexRaw); + while (header != nullptr) { + auto prev = static_cast(header->prev); + header->~BlockIndexHeader(); + (Traits::free)(header); + header = prev; + } + } + + template + inline bool enqueue(U&& element) + { + index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed); + index_t newTailIndex = 1 + currentTailIndex; + if ((currentTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { + // We reached the end of a block, start a new one + auto startBlock = this->tailBlock; + auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed; + if (this->tailBlock != nullptr && this->tailBlock->next->ConcurrentQueue::Block::template is_empty()) { + // We can re-use the block ahead of us, it's empty! + this->tailBlock = this->tailBlock->next; + this->tailBlock->ConcurrentQueue::Block::template reset_empty(); + + // We'll put the block on the block index (guaranteed to be room since we're conceptually removing the + // last block from it first -- except instead of removing then adding, we can just overwrite). + // Note that there must be a valid block index here, since even if allocation failed in the ctor, + // it would have been re-attempted when adding the first block to the queue; since there is such + // a block, a block index must have been successfully allocated. + } + else { + // Whatever head value we see here is >= the last value we saw here (relatively), + // and <= its current value. Since we have the most recent tail, the head must be + // <= to it. + auto head = this->headIndex.load(std::memory_order_relaxed); + assert(!details::circular_less_than(currentTailIndex, head)); + if (!details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) + || (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) { + // We can't enqueue in another block because there's not enough leeway -- the + // tail could surpass the head by the time the block fills up! (Or we'll exceed + // the size limit, if the second part of the condition was true.) + return false; + } + // We're going to need a new block; check that the block index has room + if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize) { + // Hmm, the circular block index is already full -- we'll need + // to allocate a new index. Note pr_blockIndexRaw can only be nullptr if + // the initial allocation failed in the constructor. + + if (allocMode == CannotAlloc || !new_block_index(pr_blockIndexSlotsUsed)) { + return false; + } + } + + // Insert a new block in the circular linked list + auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); + if (newBlock == nullptr) { + return false; + } +#if MCDBGQ_TRACKMEM + newBlock->owner = this; +#endif + newBlock->ConcurrentQueue::Block::template reset_empty(); + if (this->tailBlock == nullptr) { + newBlock->next = newBlock; + } + else { + newBlock->next = this->tailBlock->next; + this->tailBlock->next = newBlock; + } + this->tailBlock = newBlock; + ++pr_blockIndexSlotsUsed; + } + + if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward(element)))) { + // The constructor may throw. We want the element not to appear in the queue in + // that case (without corrupting the queue): + MOODYCAMEL_TRY { + new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); + } + MOODYCAMEL_CATCH (...) { + // Revert change to the current block, but leave the new block available + // for next time + pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; + this->tailBlock = startBlock == nullptr ? this->tailBlock : startBlock; + MOODYCAMEL_RETHROW; + } + } + else { + (void)startBlock; + (void)originalBlockIndexSlotsUsed; + } + + // Add block to block index + auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; + entry.base = currentTailIndex; + entry.block = this->tailBlock; + blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release); + pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); + + if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward(element)))) { + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + } + + // Enqueue + new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); + + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + + template + bool dequeue(U& element) + { + auto tail = this->tailIndex.load(std::memory_order_relaxed); + auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); + if (details::circular_less_than(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) { + // Might be something to dequeue, let's give it a try + + // Note that this if is purely for performance purposes in the common case when the queue is + // empty and the values are eventually consistent -- we may enter here spuriously. + + // Note that whatever the values of overcommit and tail are, they are not going to change (unless we + // change them) and must be the same value at this point (inside the if) as when the if condition was + // evaluated. + + // We insert an acquire fence here to synchronize-with the release upon incrementing dequeueOvercommit below. + // This ensures that whatever the value we got loaded into overcommit, the load of dequeueOptisticCount in + // the fetch_add below will result in a value at least as recent as that (and therefore at least as large). + // Note that I believe a compiler (signal) fence here would be sufficient due to the nature of fetch_add (all + // read-modify-write operations are guaranteed to work on the latest value in the modification order), but + // unfortunately that can't be shown to be correct using only the C++11 standard. + // See http://stackoverflow.com/questions/18223161/what-are-the-c11-memory-ordering-guarantees-in-this-corner-case + std::atomic_thread_fence(std::memory_order_acquire); + + // Increment optimistic counter, then check if it went over the boundary + auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed); + + // Note that since dequeueOvercommit must be <= dequeueOptimisticCount (because dequeueOvercommit is only ever + // incremented after dequeueOptimisticCount -- this is enforced in the `else` block below), and since we now + // have a version of dequeueOptimisticCount that is at least as recent as overcommit (due to the release upon + // incrementing dequeueOvercommit and the acquire above that synchronizes with it), overcommit <= myDequeueCount. + // However, we can't assert this since both dequeueOptimisticCount and dequeueOvercommit may (independently) + // overflow; in such a case, though, the logic still holds since the difference between the two is maintained. + + // Note that we reload tail here in case it changed; it will be the same value as before or greater, since + // this load is sequenced after (happens after) the earlier load above. This is supported by read-read + // coherency (as defined in the standard), explained here: http://en.cppreference.com/w/cpp/atomic/memory_order + tail = this->tailIndex.load(std::memory_order_acquire); + if ((details::likely)(details::circular_less_than(myDequeueCount - overcommit, tail))) { + // Guaranteed to be at least one element to dequeue! + + // Get the index. Note that since there's guaranteed to be at least one element, this + // will never exceed tail. We need to do an acquire-release fence here since it's possible + // that whatever condition got us to this point was for an earlier enqueued element (that + // we already see the memory effects for), but that by the time we increment somebody else + // has incremented it, and we need to see the memory effects for *that* element, which is + // in such a case is necessarily visible on the thread that incremented it in the first + // place with the more current condition (they must have acquired a tail that is at least + // as recent). + auto index = this->headIndex.fetch_add(1, std::memory_order_acq_rel); + + + // Determine which block the element is in + + auto localBlockIndex = blockIndex.load(std::memory_order_acquire); + auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire); + + // We need to be careful here about subtracting and dividing because of index wrap-around. + // When an index wraps, we need to preserve the sign of the offset when dividing it by the + // block size (in order to get a correct signed block count offset in all cases): + auto headBase = localBlockIndex->entries[localBlockIndexHead].base; + auto blockBaseIndex = index & ~static_cast(BLOCK_SIZE - 1); + auto offset = static_cast(static_cast::type>(blockBaseIndex - headBase) / BLOCK_SIZE); + auto block = localBlockIndex->entries[(localBlockIndexHead + offset) & (localBlockIndex->size - 1)].block; + + // Dequeue + auto& el = *((*block)[index]); + if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) { + // Make sure the element is still fully dequeued and destroyed even if the assignment + // throws + struct Guard { + Block* block; + index_t index; + + ~Guard() + { + (*block)[index]->~T(); + block->ConcurrentQueue::Block::template set_empty(index); + } + } guard = { block, index }; + + element = std::move(el); + } + else { + element = std::move(el); + el.~T(); + block->ConcurrentQueue::Block::template set_empty(index); + } + + return true; + } + else { + // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent + this->dequeueOvercommit.fetch_add(1, std::memory_order_release); // Release so that the fetch_add on dequeueOptimisticCount is guaranteed to happen before this write + } + } + + return false; + } + + template + bool enqueue_bulk(It itemFirst, size_t count) + { + // First, we need to make sure we have enough room to enqueue all of the elements; + // this means pre-allocating blocks and putting them in the block index (but only if + // all the allocations succeeded). + index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed); + auto startBlock = this->tailBlock; + auto originalBlockIndexFront = pr_blockIndexFront; + auto originalBlockIndexSlotsUsed = pr_blockIndexSlotsUsed; + + Block* firstAllocatedBlock = nullptr; + + // Figure out how many blocks we'll need to allocate, and do so + size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1)); + index_t currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); + if (blockBaseDiff > 0) { + // Allocate as many blocks as possible from ahead + while (blockBaseDiff > 0 && this->tailBlock != nullptr && this->tailBlock->next != firstAllocatedBlock && this->tailBlock->next->ConcurrentQueue::Block::template is_empty()) { + blockBaseDiff -= static_cast(BLOCK_SIZE); + currentTailIndex += static_cast(BLOCK_SIZE); + + this->tailBlock = this->tailBlock->next; + firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock; + + auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; + entry.base = currentTailIndex; + entry.block = this->tailBlock; + pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); + } + + // Now allocate as many blocks as necessary from the block pool + while (blockBaseDiff > 0) { + blockBaseDiff -= static_cast(BLOCK_SIZE); + currentTailIndex += static_cast(BLOCK_SIZE); + + auto head = this->headIndex.load(std::memory_order_relaxed); + assert(!details::circular_less_than(currentTailIndex, head)); + bool full = !details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head)); + if (pr_blockIndexRaw == nullptr || pr_blockIndexSlotsUsed == pr_blockIndexSize || full) { + if (allocMode == CannotAlloc || full || !new_block_index(originalBlockIndexSlotsUsed)) { + // Failed to allocate, undo changes (but keep injected blocks) + pr_blockIndexFront = originalBlockIndexFront; + pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; + this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; + return false; + } + + // pr_blockIndexFront is updated inside new_block_index, so we need to + // update our fallback value too (since we keep the new index even if we + // later fail) + originalBlockIndexFront = originalBlockIndexSlotsUsed; + } + + // Insert a new block in the circular linked list + auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); + if (newBlock == nullptr) { + pr_blockIndexFront = originalBlockIndexFront; + pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; + this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; + return false; + } + +#if MCDBGQ_TRACKMEM + newBlock->owner = this; +#endif + newBlock->ConcurrentQueue::Block::template set_all_empty(); + if (this->tailBlock == nullptr) { + newBlock->next = newBlock; + } + else { + newBlock->next = this->tailBlock->next; + this->tailBlock->next = newBlock; + } + this->tailBlock = newBlock; + firstAllocatedBlock = firstAllocatedBlock == nullptr ? this->tailBlock : firstAllocatedBlock; + + ++pr_blockIndexSlotsUsed; + + auto& entry = blockIndex.load(std::memory_order_relaxed)->entries[pr_blockIndexFront]; + entry.base = currentTailIndex; + entry.block = this->tailBlock; + pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); + } + + // Excellent, all allocations succeeded. Reset each block's emptiness before we fill them up, and + // publish the new block index front + auto block = firstAllocatedBlock; + while (true) { + block->ConcurrentQueue::Block::template reset_empty(); + if (block == this->tailBlock) { + break; + } + block = block->next; + } + + if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) { + blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); + } + } + + // Enqueue, one block at a time + index_t newTailIndex = startTailIndex + static_cast(count); + currentTailIndex = startTailIndex; + auto endBlock = this->tailBlock; + this->tailBlock = startBlock; + assert((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0); + if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) { + this->tailBlock = firstAllocatedBlock; + } + while (true) { + auto stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + if (details::circular_less_than(newTailIndex, stopIndex)) { + stopIndex = newTailIndex; + } + if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) { + while (currentTailIndex != stopIndex) { + new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); + } + } + else { + MOODYCAMEL_TRY { + while (currentTailIndex != stopIndex) { + // Must use copy constructor even if move constructor is available + // because we may have to revert if there's an exception. + // Sorry about the horrible templated next line, but it was the only way + // to disable moving *at compile time*, which is important because a type + // may only define a (noexcept) move constructor, and so calls to the + // cctor will not compile, even if they are in an if branch that will never + // be executed + new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); + ++currentTailIndex; + ++itemFirst; + } + } + MOODYCAMEL_CATCH (...) { + // Oh dear, an exception's been thrown -- destroy the elements that + // were enqueued so far and revert the entire bulk operation (we'll keep + // any allocated blocks in our linked list for later, though). + auto constructedStopIndex = currentTailIndex; + auto lastBlockEnqueued = this->tailBlock; + + pr_blockIndexFront = originalBlockIndexFront; + pr_blockIndexSlotsUsed = originalBlockIndexSlotsUsed; + this->tailBlock = startBlock == nullptr ? firstAllocatedBlock : startBlock; + + if (!details::is_trivially_destructible::value) { + auto block = startBlock; + if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { + block = firstAllocatedBlock; + } + currentTailIndex = startTailIndex; + while (true) { + stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + if (details::circular_less_than(constructedStopIndex, stopIndex)) { + stopIndex = constructedStopIndex; + } + while (currentTailIndex != stopIndex) { + (*block)[currentTailIndex++]->~T(); + } + if (block == lastBlockEnqueued) { + break; + } + block = block->next; + } + } + MOODYCAMEL_RETHROW; + } + } + + if (this->tailBlock == endBlock) { + assert(currentTailIndex == newTailIndex); + break; + } + this->tailBlock = this->tailBlock->next; + } + + if (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst))) && firstAllocatedBlock != nullptr) { + blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); + } + + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + + template + size_t dequeue_bulk(It& itemFirst, size_t max) + { + auto tail = this->tailIndex.load(std::memory_order_relaxed); + auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); + auto desiredCount = static_cast(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit)); + if (details::circular_less_than(0, desiredCount)) { + desiredCount = desiredCount < max ? desiredCount : max; + std::atomic_thread_fence(std::memory_order_acquire); + + auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);; + + tail = this->tailIndex.load(std::memory_order_acquire); + auto actualCount = static_cast(tail - (myDequeueCount - overcommit)); + if (details::circular_less_than(0, actualCount)) { + actualCount = desiredCount < actualCount ? desiredCount : actualCount; + if (actualCount < desiredCount) { + this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release); + } + + // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this + // will never exceed tail. + auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel); + + // Determine which block the first element is in + auto localBlockIndex = blockIndex.load(std::memory_order_acquire); + auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire); + + auto headBase = localBlockIndex->entries[localBlockIndexHead].base; + auto firstBlockBaseIndex = firstIndex & ~static_cast(BLOCK_SIZE - 1); + auto offset = static_cast(static_cast::type>(firstBlockBaseIndex - headBase) / BLOCK_SIZE); + auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1); + + // Iterate the blocks and dequeue + auto index = firstIndex; + do { + auto firstIndexInBlock = index; + auto endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) ? firstIndex + static_cast(actualCount) : endIndex; + auto block = localBlockIndex->entries[indexIndex].block; + if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) { + while (index != endIndex) { + auto& el = *((*block)[index]); + *itemFirst++ = std::move(el); + el.~T(); + ++index; + } + } + else { + MOODYCAMEL_TRY { + while (index != endIndex) { + auto& el = *((*block)[index]); + *itemFirst = std::move(el); + ++itemFirst; + el.~T(); + ++index; + } + } + MOODYCAMEL_CATCH (...) { + // It's too late to revert the dequeue, but we can make sure that all + // the dequeued objects are properly destroyed and the block index + // (and empty count) are properly updated before we propagate the exception + do { + block = localBlockIndex->entries[indexIndex].block; + while (index != endIndex) { + (*block)[index++]->~T(); + } + block->ConcurrentQueue::Block::template set_many_empty(firstIndexInBlock, static_cast(endIndex - firstIndexInBlock)); + indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1); + + firstIndexInBlock = index; + endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) ? firstIndex + static_cast(actualCount) : endIndex; + } while (index != firstIndex + actualCount); + + MOODYCAMEL_RETHROW; + } + } + block->ConcurrentQueue::Block::template set_many_empty(firstIndexInBlock, static_cast(endIndex - firstIndexInBlock)); + indexIndex = (indexIndex + 1) & (localBlockIndex->size - 1); + } while (index != firstIndex + actualCount); + + return actualCount; + } + else { + // Wasn't anything to dequeue after all; make the effective dequeue count eventually consistent + this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release); + } + } + + return 0; + } + + private: + struct BlockIndexEntry + { + index_t base; + Block* block; + }; + + struct BlockIndexHeader + { + size_t size; + std::atomic front; // Current slot (not next, like pr_blockIndexFront) + BlockIndexEntry* entries; + void* prev; + }; + + + bool new_block_index(size_t numberOfFilledSlotsToExpose) + { + auto prevBlockSizeMask = pr_blockIndexSize - 1; + + // Create the new block + pr_blockIndexSize <<= 1; + auto newRawPtr = static_cast((Traits::malloc)(sizeof(BlockIndexHeader) + std::alignment_of::value - 1 + sizeof(BlockIndexEntry) * pr_blockIndexSize)); + if (newRawPtr == nullptr) { + pr_blockIndexSize >>= 1; // Reset to allow graceful retry + return false; + } + + auto newBlockIndexEntries = reinterpret_cast(details::align_for(newRawPtr + sizeof(BlockIndexHeader))); + + // Copy in all the old indices, if any + size_t j = 0; + if (pr_blockIndexSlotsUsed != 0) { + auto i = (pr_blockIndexFront - pr_blockIndexSlotsUsed) & prevBlockSizeMask; + do { + newBlockIndexEntries[j++] = pr_blockIndexEntries[i]; + i = (i + 1) & prevBlockSizeMask; + } while (i != pr_blockIndexFront); + } + + // Update everything + auto header = new (newRawPtr) BlockIndexHeader; + header->size = pr_blockIndexSize; + header->front.store(numberOfFilledSlotsToExpose - 1, std::memory_order_relaxed); + header->entries = newBlockIndexEntries; + header->prev = pr_blockIndexRaw; // we link the new block to the old one so we can free it later + + pr_blockIndexFront = j; + pr_blockIndexEntries = newBlockIndexEntries; + pr_blockIndexRaw = newRawPtr; + blockIndex.store(header, std::memory_order_release); + + return true; + } + + private: + std::atomic blockIndex; + + // To be used by producer only -- consumer must use the ones in referenced by blockIndex + size_t pr_blockIndexSlotsUsed; + size_t pr_blockIndexSize; + size_t pr_blockIndexFront; // Next slot (not current) + BlockIndexEntry* pr_blockIndexEntries; + void* pr_blockIndexRaw; + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + public: + ExplicitProducer* nextExplicitProducer; + private: +#endif + +#if MCDBGQ_TRACKMEM + friend struct MemStats; +#endif + }; + + + ////////////////////////////////// + // Implicit queue + ////////////////////////////////// + + struct ImplicitProducer : public ProducerBase + { + ImplicitProducer(ConcurrentQueue* parent) : + ProducerBase(parent, false), + nextBlockIndexCapacity(IMPLICIT_INITIAL_INDEX_SIZE), + blockIndex(nullptr) + { + new_block_index(); + } + + ~ImplicitProducer() + { + // Note that since we're in the destructor we can assume that all enqueue/dequeue operations + // completed already; this means that all undequeued elements are placed contiguously across + // contiguous blocks, and that only the first and last remaining blocks can be only partially + // empty (all other remaining blocks must be completely full). + +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + // Unregister ourselves for thread termination notification + if (!this->inactive.load(std::memory_order_relaxed)) { + details::ThreadExitNotifier::unsubscribe(&threadExitListener); + } +#endif + + // Destroy all remaining elements! + auto tail = this->tailIndex.load(std::memory_order_relaxed); + auto index = this->headIndex.load(std::memory_order_relaxed); + Block* block = nullptr; + assert(index == tail || details::circular_less_than(index, tail)); + bool forceFreeLastBlock = index != tail; // If we enter the loop, then the last (tail) block will not be freed + while (index != tail) { + if ((index & static_cast(BLOCK_SIZE - 1)) == 0 || block == nullptr) { + if (block != nullptr) { + // Free the old block + this->parent->add_block_to_free_list(block); + } + + block = get_block_index_entry_for_index(index)->value.load(std::memory_order_relaxed); + } + + ((*block)[index])->~T(); + ++index; + } + // Even if the queue is empty, there's still one block that's not on the free list + // (unless the head index reached the end of it, in which case the tail will be poised + // to create a new block). + if (this->tailBlock != nullptr && (forceFreeLastBlock || (tail & static_cast(BLOCK_SIZE - 1)) != 0)) { + this->parent->add_block_to_free_list(this->tailBlock); + } + + // Destroy block index + auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); + if (localBlockIndex != nullptr) { + for (size_t i = 0; i != localBlockIndex->capacity; ++i) { + localBlockIndex->index[i]->~BlockIndexEntry(); + } + do { + auto prev = localBlockIndex->prev; + localBlockIndex->~BlockIndexHeader(); + (Traits::free)(localBlockIndex); + localBlockIndex = prev; + } while (localBlockIndex != nullptr); + } + } + + template + inline bool enqueue(U&& element) + { + index_t currentTailIndex = this->tailIndex.load(std::memory_order_relaxed); + index_t newTailIndex = 1 + currentTailIndex; + if ((currentTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { + // We reached the end of a block, start a new one + auto head = this->headIndex.load(std::memory_order_relaxed); + assert(!details::circular_less_than(currentTailIndex, head)); + if (!details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head))) { + return false; + } +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + // Find out where we'll be inserting this block in the block index + BlockIndexEntry* idxEntry; + if (!insert_block_index_entry(idxEntry, currentTailIndex)) { + return false; + } + + // Get ahold of a new block + auto newBlock = this->parent->ConcurrentQueue::template requisition_block(); + if (newBlock == nullptr) { + rewind_block_index_tail(); + idxEntry->value.store(nullptr, std::memory_order_relaxed); + return false; + } +#if MCDBGQ_TRACKMEM + newBlock->owner = this; +#endif + newBlock->ConcurrentQueue::Block::template reset_empty(); + + if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward(element)))) { + // May throw, try to insert now before we publish the fact that we have this new block + MOODYCAMEL_TRY { + new ((*newBlock)[currentTailIndex]) T(std::forward(element)); + } + MOODYCAMEL_CATCH (...) { + rewind_block_index_tail(); + idxEntry->value.store(nullptr, std::memory_order_relaxed); + this->parent->add_block_to_free_list(newBlock); + MOODYCAMEL_RETHROW; + } + } + + // Insert the new block into the index + idxEntry->value.store(newBlock, std::memory_order_relaxed); + + this->tailBlock = newBlock; + + if (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (nullptr) T(std::forward(element)))) { + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + } + + // Enqueue + new ((*this->tailBlock)[currentTailIndex]) T(std::forward(element)); + + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + + template + bool dequeue(U& element) + { + // See ExplicitProducer::dequeue for rationale and explanation + index_t tail = this->tailIndex.load(std::memory_order_relaxed); + index_t overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); + if (details::circular_less_than(this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) { + std::atomic_thread_fence(std::memory_order_acquire); + + index_t myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed); + tail = this->tailIndex.load(std::memory_order_acquire); + if ((details::likely)(details::circular_less_than(myDequeueCount - overcommit, tail))) { + index_t index = this->headIndex.fetch_add(1, std::memory_order_acq_rel); + + // Determine which block the element is in + auto entry = get_block_index_entry_for_index(index); + + // Dequeue + auto block = entry->value.load(std::memory_order_relaxed); + auto& el = *((*block)[index]); + + if (!MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, element = std::move(el))) { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + // Note: Acquiring the mutex with every dequeue instead of only when a block + // is released is very sub-optimal, but it is, after all, purely debug code. + debug::DebugLock lock(producer->mutex); +#endif + struct Guard { + Block* block; + index_t index; + BlockIndexEntry* entry; + ConcurrentQueue* parent; + + ~Guard() + { + (*block)[index]->~T(); + if (block->ConcurrentQueue::Block::template set_empty(index)) { + entry->value.store(nullptr, std::memory_order_relaxed); + parent->add_block_to_free_list(block); + } + } + } guard = { block, index, entry, this->parent }; + + element = std::move(el); + } + else { + element = std::move(el); + el.~T(); + + if (block->ConcurrentQueue::Block::template set_empty(index)) { + { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + // Add the block back into the global free pool (and remove from block index) + entry->value.store(nullptr, std::memory_order_relaxed); + } + this->parent->add_block_to_free_list(block); // releases the above store + } + } + + return true; + } + else { + this->dequeueOvercommit.fetch_add(1, std::memory_order_release); + } + } + + return false; + } + + template + bool enqueue_bulk(It itemFirst, size_t count) + { + // First, we need to make sure we have enough room to enqueue all of the elements; + // this means pre-allocating blocks and putting them in the block index (but only if + // all the allocations succeeded). + + // Note that the tailBlock we start off with may not be owned by us any more; + // this happens if it was filled up exactly to the top (setting tailIndex to + // the first index of the next block which is not yet allocated), then dequeued + // completely (putting it on the free list) before we enqueue again. + + index_t startTailIndex = this->tailIndex.load(std::memory_order_relaxed); + auto startBlock = this->tailBlock; + Block* firstAllocatedBlock = nullptr; + auto endBlock = this->tailBlock; + + // Figure out how many blocks we'll need to allocate, and do so + size_t blockBaseDiff = ((startTailIndex + count - 1) & ~static_cast(BLOCK_SIZE - 1)) - ((startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1)); + index_t currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); + if (blockBaseDiff > 0) { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + do { + blockBaseDiff -= static_cast(BLOCK_SIZE); + currentTailIndex += static_cast(BLOCK_SIZE); + + // Find out where we'll be inserting this block in the block index + BlockIndexEntry* idxEntry = nullptr; // initialization here unnecessary but compiler can't always tell + Block* newBlock; + bool indexInserted = false; + auto head = this->headIndex.load(std::memory_order_relaxed); + assert(!details::circular_less_than(currentTailIndex, head)); + bool full = !details::circular_less_than(head, currentTailIndex + BLOCK_SIZE) || (MAX_SUBQUEUE_SIZE != details::const_numeric_max::value && (MAX_SUBQUEUE_SIZE == 0 || MAX_SUBQUEUE_SIZE - BLOCK_SIZE < currentTailIndex - head)); + if (full || !(indexInserted = insert_block_index_entry(idxEntry, currentTailIndex)) || (newBlock = this->parent->ConcurrentQueue::template requisition_block()) == nullptr) { + // Index allocation or block allocation failed; revert any other allocations + // and index insertions done so far for this operation + if (indexInserted) { + rewind_block_index_tail(); + idxEntry->value.store(nullptr, std::memory_order_relaxed); + } + currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); + for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) { + currentTailIndex += static_cast(BLOCK_SIZE); + idxEntry = get_block_index_entry_for_index(currentTailIndex); + idxEntry->value.store(nullptr, std::memory_order_relaxed); + rewind_block_index_tail(); + } + this->parent->add_blocks_to_free_list(firstAllocatedBlock); + this->tailBlock = startBlock; + + return false; + } + +#if MCDBGQ_TRACKMEM + newBlock->owner = this; +#endif + newBlock->ConcurrentQueue::Block::template reset_empty(); + newBlock->next = nullptr; + + // Insert the new block into the index + idxEntry->value.store(newBlock, std::memory_order_relaxed); + + // Store the chain of blocks so that we can undo if later allocations fail, + // and so that we can find the blocks when we do the actual enqueueing + if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr) { + assert(this->tailBlock != nullptr); + this->tailBlock->next = newBlock; + } + this->tailBlock = newBlock; + endBlock = newBlock; + firstAllocatedBlock = firstAllocatedBlock == nullptr ? newBlock : firstAllocatedBlock; + } while (blockBaseDiff > 0); + } + + // Enqueue, one block at a time + index_t newTailIndex = startTailIndex + static_cast(count); + currentTailIndex = startTailIndex; + this->tailBlock = startBlock; + assert((startTailIndex & static_cast(BLOCK_SIZE - 1)) != 0 || firstAllocatedBlock != nullptr || count == 0); + if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0 && firstAllocatedBlock != nullptr) { + this->tailBlock = firstAllocatedBlock; + } + while (true) { + auto stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + if (details::circular_less_than(newTailIndex, stopIndex)) { + stopIndex = newTailIndex; + } + if (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))) { + while (currentTailIndex != stopIndex) { + new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); + } + } + else { + MOODYCAMEL_TRY { + while (currentTailIndex != stopIndex) { + new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); + ++currentTailIndex; + ++itemFirst; + } + } + MOODYCAMEL_CATCH (...) { + auto constructedStopIndex = currentTailIndex; + auto lastBlockEnqueued = this->tailBlock; + + if (!details::is_trivially_destructible::value) { + auto block = startBlock; + if ((startTailIndex & static_cast(BLOCK_SIZE - 1)) == 0) { + block = firstAllocatedBlock; + } + currentTailIndex = startTailIndex; + while (true) { + stopIndex = (currentTailIndex & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + if (details::circular_less_than(constructedStopIndex, stopIndex)) { + stopIndex = constructedStopIndex; + } + while (currentTailIndex != stopIndex) { + (*block)[currentTailIndex++]->~T(); + } + if (block == lastBlockEnqueued) { + break; + } + block = block->next; + } + } + + currentTailIndex = (startTailIndex - 1) & ~static_cast(BLOCK_SIZE - 1); + for (auto block = firstAllocatedBlock; block != nullptr; block = block->next) { + currentTailIndex += static_cast(BLOCK_SIZE); + auto idxEntry = get_block_index_entry_for_index(currentTailIndex); + idxEntry->value.store(nullptr, std::memory_order_relaxed); + rewind_block_index_tail(); + } + this->parent->add_blocks_to_free_list(firstAllocatedBlock); + this->tailBlock = startBlock; + MOODYCAMEL_RETHROW; + } + } + + if (this->tailBlock == endBlock) { + assert(currentTailIndex == newTailIndex); + break; + } + this->tailBlock = this->tailBlock->next; + } + this->tailIndex.store(newTailIndex, std::memory_order_release); + return true; + } + + template + size_t dequeue_bulk(It& itemFirst, size_t max) + { + auto tail = this->tailIndex.load(std::memory_order_relaxed); + auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); + auto desiredCount = static_cast(tail - (this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit)); + if (details::circular_less_than(0, desiredCount)) { + desiredCount = desiredCount < max ? desiredCount : max; + std::atomic_thread_fence(std::memory_order_acquire); + + auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed); + + tail = this->tailIndex.load(std::memory_order_acquire); + auto actualCount = static_cast(tail - (myDequeueCount - overcommit)); + if (details::circular_less_than(0, actualCount)) { + actualCount = desiredCount < actualCount ? desiredCount : actualCount; + if (actualCount < desiredCount) { + this->dequeueOvercommit.fetch_add(desiredCount - actualCount, std::memory_order_release); + } + + // Get the first index. Note that since there's guaranteed to be at least actualCount elements, this + // will never exceed tail. + auto firstIndex = this->headIndex.fetch_add(actualCount, std::memory_order_acq_rel); + + // Iterate the blocks and dequeue + auto index = firstIndex; + BlockIndexHeader* localBlockIndex; + auto indexIndex = get_block_index_index_for_index(index, localBlockIndex); + do { + auto blockStartIndex = index; + auto endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) ? firstIndex + static_cast(actualCount) : endIndex; + + auto entry = localBlockIndex->index[indexIndex]; + auto block = entry->value.load(std::memory_order_relaxed); + if (MOODYCAMEL_NOEXCEPT_ASSIGN(T, T&&, details::deref_noexcept(itemFirst) = std::move((*(*block)[index])))) { + while (index != endIndex) { + auto& el = *((*block)[index]); + *itemFirst++ = std::move(el); + el.~T(); + ++index; + } + } + else { + MOODYCAMEL_TRY { + while (index != endIndex) { + auto& el = *((*block)[index]); + *itemFirst = std::move(el); + ++itemFirst; + el.~T(); + ++index; + } + } + MOODYCAMEL_CATCH (...) { + do { + entry = localBlockIndex->index[indexIndex]; + block = entry->value.load(std::memory_order_relaxed); + while (index != endIndex) { + (*block)[index++]->~T(); + } + + if (block->ConcurrentQueue::Block::template set_many_empty(blockStartIndex, static_cast(endIndex - blockStartIndex))) { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + entry->value.store(nullptr, std::memory_order_relaxed); + this->parent->add_block_to_free_list(block); + } + indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1); + + blockStartIndex = index; + endIndex = (index & ~static_cast(BLOCK_SIZE - 1)) + static_cast(BLOCK_SIZE); + endIndex = details::circular_less_than(firstIndex + static_cast(actualCount), endIndex) ? firstIndex + static_cast(actualCount) : endIndex; + } while (index != firstIndex + actualCount); + + MOODYCAMEL_RETHROW; + } + } + if (block->ConcurrentQueue::Block::template set_many_empty(blockStartIndex, static_cast(endIndex - blockStartIndex))) { + { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + // Note that the set_many_empty above did a release, meaning that anybody who acquires the block + // we're about to free can use it safely since our writes (and reads!) will have happened-before then. + entry->value.store(nullptr, std::memory_order_relaxed); + } + this->parent->add_block_to_free_list(block); // releases the above store + } + indexIndex = (indexIndex + 1) & (localBlockIndex->capacity - 1); + } while (index != firstIndex + actualCount); + + return actualCount; + } + else { + this->dequeueOvercommit.fetch_add(desiredCount, std::memory_order_release); + } + } + + return 0; + } + + private: + // The block size must be > 1, so any number with the low bit set is an invalid block base index + static const index_t INVALID_BLOCK_BASE = 1; + + struct BlockIndexEntry + { + std::atomic key; + std::atomic value; + }; + + struct BlockIndexHeader + { + size_t capacity; + std::atomic tail; + BlockIndexEntry* entries; + BlockIndexEntry** index; + BlockIndexHeader* prev; + }; + + template + inline bool insert_block_index_entry(BlockIndexEntry*& idxEntry, index_t blockStartIndex) + { + auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); // We're the only writer thread, relaxed is OK + if (localBlockIndex == nullptr) { + return false; // this can happen if new_block_index failed in the constructor + } + auto newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); + idxEntry = localBlockIndex->index[newTail]; + if (idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE || + idxEntry->value.load(std::memory_order_relaxed) == nullptr) { + + idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); + localBlockIndex->tail.store(newTail, std::memory_order_release); + return true; + } + + // No room in the old block index, try to allocate another one! + if (allocMode == CannotAlloc || !new_block_index()) { + return false; + } + localBlockIndex = blockIndex.load(std::memory_order_relaxed); + newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); + idxEntry = localBlockIndex->index[newTail]; + assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE); + idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); + localBlockIndex->tail.store(newTail, std::memory_order_release); + return true; + } + + inline void rewind_block_index_tail() + { + auto localBlockIndex = blockIndex.load(std::memory_order_relaxed); + localBlockIndex->tail.store((localBlockIndex->tail.load(std::memory_order_relaxed) - 1) & (localBlockIndex->capacity - 1), std::memory_order_relaxed); + } + + inline BlockIndexEntry* get_block_index_entry_for_index(index_t index) const + { + BlockIndexHeader* localBlockIndex; + auto idx = get_block_index_index_for_index(index, localBlockIndex); + return localBlockIndex->index[idx]; + } + + inline size_t get_block_index_index_for_index(index_t index, BlockIndexHeader*& localBlockIndex) const + { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + debug::DebugLock lock(mutex); +#endif + index &= ~static_cast(BLOCK_SIZE - 1); + localBlockIndex = blockIndex.load(std::memory_order_acquire); + auto tail = localBlockIndex->tail.load(std::memory_order_acquire); + auto tailBase = localBlockIndex->index[tail]->key.load(std::memory_order_relaxed); + assert(tailBase != INVALID_BLOCK_BASE); + // Note: Must use division instead of shift because the index may wrap around, causing a negative + // offset, whose negativity we want to preserve + auto offset = static_cast(static_cast::type>(index - tailBase) / BLOCK_SIZE); + size_t idx = (tail + offset) & (localBlockIndex->capacity - 1); + assert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr); + return idx; + } + + bool new_block_index() + { + auto prev = blockIndex.load(std::memory_order_relaxed); + size_t prevCapacity = prev == nullptr ? 0 : prev->capacity; + auto entryCount = prev == nullptr ? nextBlockIndexCapacity : prevCapacity; + auto raw = static_cast((Traits::malloc)( + sizeof(BlockIndexHeader) + + std::alignment_of::value - 1 + sizeof(BlockIndexEntry) * entryCount + + std::alignment_of::value - 1 + sizeof(BlockIndexEntry*) * nextBlockIndexCapacity)); + if (raw == nullptr) { + return false; + } + + auto header = new (raw) BlockIndexHeader; + auto entries = reinterpret_cast(details::align_for(raw + sizeof(BlockIndexHeader))); + auto index = reinterpret_cast(details::align_for(reinterpret_cast(entries) + sizeof(BlockIndexEntry) * entryCount)); + if (prev != nullptr) { + auto prevTail = prev->tail.load(std::memory_order_relaxed); + auto prevPos = prevTail; + size_t i = 0; + do { + prevPos = (prevPos + 1) & (prev->capacity - 1); + index[i++] = prev->index[prevPos]; + } while (prevPos != prevTail); + assert(i == prevCapacity); + } + for (size_t i = 0; i != entryCount; ++i) { + new (entries + i) BlockIndexEntry; + entries[i].key.store(INVALID_BLOCK_BASE, std::memory_order_relaxed); + index[prevCapacity + i] = entries + i; + } + header->prev = prev; + header->entries = entries; + header->index = index; + header->capacity = nextBlockIndexCapacity; + header->tail.store((prevCapacity - 1) & (nextBlockIndexCapacity - 1), std::memory_order_relaxed); + + blockIndex.store(header, std::memory_order_release); + + nextBlockIndexCapacity <<= 1; + + return true; + } + + private: + size_t nextBlockIndexCapacity; + std::atomic blockIndex; + +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + public: + details::ThreadExitListener threadExitListener; + private: +#endif + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + public: + ImplicitProducer* nextImplicitProducer; + private: +#endif + +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODBLOCKINDEX + mutable debug::DebugMutex mutex; +#endif +#if MCDBGQ_TRACKMEM + friend struct MemStats; +#endif + }; + + + ////////////////////////////////// + // Block pool manipulation + ////////////////////////////////// + + void populate_initial_block_list(size_t blockCount) + { + initialBlockPoolSize = blockCount; + if (initialBlockPoolSize == 0) { + initialBlockPool = nullptr; + return; + } + + initialBlockPool = create_array(blockCount); + if (initialBlockPool == nullptr) { + initialBlockPoolSize = 0; + } + for (size_t i = 0; i < initialBlockPoolSize; ++i) { + initialBlockPool[i].dynamicallyAllocated = false; + } + } + + inline Block* try_get_block_from_initial_pool() + { + if (initialBlockPoolIndex.load(std::memory_order_relaxed) >= initialBlockPoolSize) { + return nullptr; + } + + auto index = initialBlockPoolIndex.fetch_add(1, std::memory_order_relaxed); + + return index < initialBlockPoolSize ? (initialBlockPool + index) : nullptr; + } + + inline void add_block_to_free_list(Block* block) + { +#if MCDBGQ_TRACKMEM + block->owner = nullptr; +#endif + freeList.add(block); + } + + inline void add_blocks_to_free_list(Block* block) + { + while (block != nullptr) { + auto next = block->next; + add_block_to_free_list(block); + block = next; + } + } + + inline Block* try_get_block_from_free_list() + { + return freeList.try_get(); + } + + // Gets a free block from one of the memory pools, or allocates a new one (if applicable) + template + Block* requisition_block() + { + auto block = try_get_block_from_initial_pool(); + if (block != nullptr) { + return block; + } + + block = try_get_block_from_free_list(); + if (block != nullptr) { + return block; + } + + if (canAlloc == CanAlloc) { + return create(); + } + + return nullptr; + } + + +#if MCDBGQ_TRACKMEM + public: + struct MemStats { + size_t allocatedBlocks; + size_t usedBlocks; + size_t freeBlocks; + size_t ownedBlocksExplicit; + size_t ownedBlocksImplicit; + size_t implicitProducers; + size_t explicitProducers; + size_t elementsEnqueued; + size_t blockClassBytes; + size_t queueClassBytes; + size_t implicitBlockIndexBytes; + size_t explicitBlockIndexBytes; + + friend class ConcurrentQueue; + + private: + static MemStats getFor(ConcurrentQueue* q) + { + MemStats stats = { 0 }; + + stats.elementsEnqueued = q->size_approx(); + + auto block = q->freeList.head_unsafe(); + while (block != nullptr) { + ++stats.allocatedBlocks; + ++stats.freeBlocks; + block = block->freeListNext.load(std::memory_order_relaxed); + } + + for (auto ptr = q->producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + bool implicit = dynamic_cast(ptr) != nullptr; + stats.implicitProducers += implicit ? 1 : 0; + stats.explicitProducers += implicit ? 0 : 1; + + if (implicit) { + auto prod = static_cast(ptr); + stats.queueClassBytes += sizeof(ImplicitProducer); + auto head = prod->headIndex.load(std::memory_order_relaxed); + auto tail = prod->tailIndex.load(std::memory_order_relaxed); + auto hash = prod->blockIndex.load(std::memory_order_relaxed); + if (hash != nullptr) { + for (size_t i = 0; i != hash->capacity; ++i) { + if (hash->index[i]->key.load(std::memory_order_relaxed) != ImplicitProducer::INVALID_BLOCK_BASE && hash->index[i]->value.load(std::memory_order_relaxed) != nullptr) { + ++stats.allocatedBlocks; + ++stats.ownedBlocksImplicit; + } + } + stats.implicitBlockIndexBytes += hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry); + for (; hash != nullptr; hash = hash->prev) { + stats.implicitBlockIndexBytes += sizeof(typename ImplicitProducer::BlockIndexHeader) + hash->capacity * sizeof(typename ImplicitProducer::BlockIndexEntry*); + } + } + for (; details::circular_less_than(head, tail); head += BLOCK_SIZE) { + //auto block = prod->get_block_index_entry_for_index(head); + ++stats.usedBlocks; + } + } + else { + auto prod = static_cast(ptr); + stats.queueClassBytes += sizeof(ExplicitProducer); + auto tailBlock = prod->tailBlock; + bool wasNonEmpty = false; + if (tailBlock != nullptr) { + auto block = tailBlock; + do { + ++stats.allocatedBlocks; + if (!block->ConcurrentQueue::Block::template is_empty() || wasNonEmpty) { + ++stats.usedBlocks; + wasNonEmpty = wasNonEmpty || block != tailBlock; + } + ++stats.ownedBlocksExplicit; + block = block->next; + } while (block != tailBlock); + } + auto index = prod->blockIndex.load(std::memory_order_relaxed); + while (index != nullptr) { + stats.explicitBlockIndexBytes += sizeof(typename ExplicitProducer::BlockIndexHeader) + index->size * sizeof(typename ExplicitProducer::BlockIndexEntry); + index = static_cast(index->prev); + } + } + } + + auto freeOnInitialPool = q->initialBlockPoolIndex.load(std::memory_order_relaxed) >= q->initialBlockPoolSize ? 0 : q->initialBlockPoolSize - q->initialBlockPoolIndex.load(std::memory_order_relaxed); + stats.allocatedBlocks += freeOnInitialPool; + stats.freeBlocks += freeOnInitialPool; + + stats.blockClassBytes = sizeof(Block) * stats.allocatedBlocks; + stats.queueClassBytes += sizeof(ConcurrentQueue); + + return stats; + } + }; + + // For debugging only. Not thread-safe. + MemStats getMemStats() + { + return MemStats::getFor(this); + } + private: + friend struct MemStats; +#endif + + + ////////////////////////////////// + // Producer list manipulation + ////////////////////////////////// + + ProducerBase* recycle_or_create_producer(bool isExplicit) + { + bool recycled; + return recycle_or_create_producer(isExplicit, recycled); + } + + ProducerBase* recycle_or_create_producer(bool isExplicit, bool& recycled) + { +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH + debug::DebugLock lock(implicitProdMutex); +#endif + // Try to re-use one first + for (auto ptr = producerListTail.load(std::memory_order_acquire); ptr != nullptr; ptr = ptr->next_prod()) { + if (ptr->inactive.load(std::memory_order_relaxed) && ptr->isExplicit == isExplicit) { + bool expected = true; + if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) { + // We caught one! It's been marked as activated, the caller can have it + recycled = true; + return ptr; + } + } + } + + recycled = false; + return add_producer(isExplicit ? static_cast(create(this)) : create(this)); + } + + ProducerBase* add_producer(ProducerBase* producer) + { + // Handle failed memory allocation + if (producer == nullptr) { + return nullptr; + } + + producerCount.fetch_add(1, std::memory_order_relaxed); + + // Add it to the lock-free list + auto prevTail = producerListTail.load(std::memory_order_relaxed); + do { + producer->next = prevTail; + } while (!producerListTail.compare_exchange_weak(prevTail, producer, std::memory_order_release, std::memory_order_relaxed)); + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + if (producer->isExplicit) { + auto prevTailExplicit = explicitProducers.load(std::memory_order_relaxed); + do { + static_cast(producer)->nextExplicitProducer = prevTailExplicit; + } while (!explicitProducers.compare_exchange_weak(prevTailExplicit, static_cast(producer), std::memory_order_release, std::memory_order_relaxed)); + } + else { + auto prevTailImplicit = implicitProducers.load(std::memory_order_relaxed); + do { + static_cast(producer)->nextImplicitProducer = prevTailImplicit; + } while (!implicitProducers.compare_exchange_weak(prevTailImplicit, static_cast(producer), std::memory_order_release, std::memory_order_relaxed)); + } +#endif + + return producer; + } + + void reown_producers() + { + // After another instance is moved-into/swapped-with this one, all the + // producers we stole still think their parents are the other queue. + // So fix them up! + for (auto ptr = producerListTail.load(std::memory_order_relaxed); ptr != nullptr; ptr = ptr->next_prod()) { + ptr->parent = this; + } + } + + + ////////////////////////////////// + // Implicit producer hash + ////////////////////////////////// + + struct ImplicitProducerKVP + { + std::atomic key; + ImplicitProducer* value; // No need for atomicity since it's only read by the thread that sets it in the first place + + ImplicitProducerKVP() : value(nullptr) { } + + ImplicitProducerKVP(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT + { + key.store(other.key.load(std::memory_order_relaxed), std::memory_order_relaxed); + value = other.value; + } + + inline ImplicitProducerKVP& operator=(ImplicitProducerKVP&& other) MOODYCAMEL_NOEXCEPT + { + swap(other); + return *this; + } + + inline void swap(ImplicitProducerKVP& other) MOODYCAMEL_NOEXCEPT + { + if (this != &other) { + details::swap_relaxed(key, other.key); + std::swap(value, other.value); + } + } + }; + + template + friend void moodycamel::swap(typename ConcurrentQueue::ImplicitProducerKVP&, typename ConcurrentQueue::ImplicitProducerKVP&) MOODYCAMEL_NOEXCEPT; + + struct ImplicitProducerHash + { + size_t capacity; + ImplicitProducerKVP* entries; + ImplicitProducerHash* prev; + }; + + inline void populate_initial_implicit_producer_hash() + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return; + + implicitProducerHashCount.store(0, std::memory_order_relaxed); + auto hash = &initialImplicitProducerHash; + hash->capacity = INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; + hash->entries = &initialImplicitProducerHashEntries[0]; + for (size_t i = 0; i != INITIAL_IMPLICIT_PRODUCER_HASH_SIZE; ++i) { + initialImplicitProducerHashEntries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed); + } + hash->prev = nullptr; + implicitProducerHash.store(hash, std::memory_order_relaxed); + } + + void swap_implicit_producer_hashes(ConcurrentQueue& other) + { + if (INITIAL_IMPLICIT_PRODUCER_HASH_SIZE == 0) return; + + // Swap (assumes our implicit producer hash is initialized) + initialImplicitProducerHashEntries.swap(other.initialImplicitProducerHashEntries); + initialImplicitProducerHash.entries = &initialImplicitProducerHashEntries[0]; + other.initialImplicitProducerHash.entries = &other.initialImplicitProducerHashEntries[0]; + + details::swap_relaxed(implicitProducerHashCount, other.implicitProducerHashCount); + + details::swap_relaxed(implicitProducerHash, other.implicitProducerHash); + if (implicitProducerHash.load(std::memory_order_relaxed) == &other.initialImplicitProducerHash) { + implicitProducerHash.store(&initialImplicitProducerHash, std::memory_order_relaxed); + } + else { + ImplicitProducerHash* hash; + for (hash = implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &other.initialImplicitProducerHash; hash = hash->prev) { + continue; + } + hash->prev = &initialImplicitProducerHash; + } + if (other.implicitProducerHash.load(std::memory_order_relaxed) == &initialImplicitProducerHash) { + other.implicitProducerHash.store(&other.initialImplicitProducerHash, std::memory_order_relaxed); + } + else { + ImplicitProducerHash* hash; + for (hash = other.implicitProducerHash.load(std::memory_order_relaxed); hash->prev != &initialImplicitProducerHash; hash = hash->prev) { + continue; + } + hash->prev = &other.initialImplicitProducerHash; + } + } + + // Only fails (returns nullptr) if memory allocation fails + ImplicitProducer* get_or_add_implicit_producer() + { + // Note that since the data is essentially thread-local (key is thread ID), + // there's a reduced need for fences (memory ordering is already consistent + // for any individual thread), except for the current table itself. + + // Start by looking for the thread ID in the current and all previous hash tables. + // If it's not found, it must not be in there yet, since this same thread would + // have added it previously to one of the tables that we traversed. + + // Code and algorithm adapted from http://preshing.com/20130605/the-worlds-simplest-lock-free-hash-table + +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH + debug::DebugLock lock(implicitProdMutex); +#endif + + auto id = details::thread_id(); + auto hashedId = details::hash_thread_id(id); + + auto mainHash = implicitProducerHash.load(std::memory_order_acquire); + for (auto hash = mainHash; hash != nullptr; hash = hash->prev) { + // Look for the id in this hash + auto index = hashedId; + while (true) { // Not an infinite loop because at least one slot is free in the hash table + index &= hash->capacity - 1; + + auto probedKey = hash->entries[index].key.load(std::memory_order_relaxed); + if (probedKey == id) { + // Found it! If we had to search several hashes deep, though, we should lazily add it + // to the current main hash table to avoid the extended search next time. + // Note there's guaranteed to be room in the current hash table since every subsequent + // table implicitly reserves space for all previous tables (there's only one + // implicitProducerHashCount). + auto value = hash->entries[index].value; + if (hash != mainHash) { + index = hashedId; + while (true) { + index &= mainHash->capacity - 1; + probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); + auto empty = details::invalid_thread_id; +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + auto reusable = details::invalid_thread_id2; + if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || + (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { +#else + if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { +#endif + mainHash->entries[index].value = value; + break; + } + ++index; + } + } + + return value; + } + if (probedKey == details::invalid_thread_id) { + break; // Not in this hash table + } + ++index; + } + } + + // Insert! + auto newCount = 1 + implicitProducerHashCount.fetch_add(1, std::memory_order_relaxed); + while (true) { + if (newCount >= (mainHash->capacity >> 1) && !implicitProducerHashResizeInProgress.test_and_set(std::memory_order_acquire)) { + // We've acquired the resize lock, try to allocate a bigger hash table. + // Note the acquire fence synchronizes with the release fence at the end of this block, and hence when + // we reload implicitProducerHash it must be the most recent version (it only gets changed within this + // locked block). + mainHash = implicitProducerHash.load(std::memory_order_acquire); + if (newCount >= (mainHash->capacity >> 1)) { + auto newCapacity = mainHash->capacity << 1; + while (newCount >= (newCapacity >> 1)) { + newCapacity <<= 1; + } + auto raw = static_cast((Traits::malloc)(sizeof(ImplicitProducerHash) + std::alignment_of::value - 1 + sizeof(ImplicitProducerKVP) * newCapacity)); + if (raw == nullptr) { + // Allocation failed + implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); + implicitProducerHashResizeInProgress.clear(std::memory_order_relaxed); + return nullptr; + } + + auto newHash = new (raw) ImplicitProducerHash; + newHash->capacity = newCapacity; + newHash->entries = reinterpret_cast(details::align_for(raw + sizeof(ImplicitProducerHash))); + for (size_t i = 0; i != newCapacity; ++i) { + new (newHash->entries + i) ImplicitProducerKVP; + newHash->entries[i].key.store(details::invalid_thread_id, std::memory_order_relaxed); + } + newHash->prev = mainHash; + implicitProducerHash.store(newHash, std::memory_order_release); + implicitProducerHashResizeInProgress.clear(std::memory_order_release); + mainHash = newHash; + } + else { + implicitProducerHashResizeInProgress.clear(std::memory_order_release); + } + } + + // If it's < three-quarters full, add to the old one anyway so that we don't have to wait for the next table + // to finish being allocated by another thread (and if we just finished allocating above, the condition will + // always be true) + if (newCount < (mainHash->capacity >> 1) + (mainHash->capacity >> 2)) { + bool recycled; + auto producer = static_cast(recycle_or_create_producer(false, recycled)); + if (producer == nullptr) { + implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); + return nullptr; + } + if (recycled) { + implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); + } + +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + producer->threadExitListener.callback = &ConcurrentQueue::implicit_producer_thread_exited_callback; + producer->threadExitListener.userData = producer; + details::ThreadExitNotifier::subscribe(&producer->threadExitListener); +#endif + + auto index = hashedId; + while (true) { + index &= mainHash->capacity - 1; + auto probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); + + auto empty = details::invalid_thread_id; +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + auto reusable = details::invalid_thread_id2; + if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || + (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { +#else + if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { +#endif + mainHash->entries[index].value = producer; + break; + } + ++index; + } + return producer; + } + + // Hmm, the old hash is quite full and somebody else is busy allocating a new one. + // We need to wait for the allocating thread to finish (if it succeeds, we add, if not, + // we try to allocate ourselves). + mainHash = implicitProducerHash.load(std::memory_order_acquire); + } + } + +#ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED + void implicit_producer_thread_exited(ImplicitProducer* producer) + { + // Remove from thread exit listeners + details::ThreadExitNotifier::unsubscribe(&producer->threadExitListener); + + // Remove from hash +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH + debug::DebugLock lock(implicitProdMutex); +#endif + auto hash = implicitProducerHash.load(std::memory_order_acquire); + assert(hash != nullptr); // The thread exit listener is only registered if we were added to a hash in the first place + auto id = details::thread_id(); + auto hashedId = details::hash_thread_id(id); + details::thread_id_t probedKey; + + // We need to traverse all the hashes just in case other threads aren't on the current one yet and are + // trying to add an entry thinking there's a free slot (because they reused a producer) + for (; hash != nullptr; hash = hash->prev) { + auto index = hashedId; + do { + index &= hash->capacity - 1; + probedKey = hash->entries[index].key.load(std::memory_order_relaxed); + if (probedKey == id) { + hash->entries[index].key.store(details::invalid_thread_id2, std::memory_order_release); + break; + } + ++index; + } while (probedKey != details::invalid_thread_id); // Can happen if the hash has changed but we weren't put back in it yet, or if we weren't added to this hash in the first place + } + + // Mark the queue as being recyclable + producer->inactive.store(true, std::memory_order_release); + } + + static void implicit_producer_thread_exited_callback(void* userData) + { + auto producer = static_cast(userData); + auto queue = producer->parent; + queue->implicit_producer_thread_exited(producer); + } +#endif + + ////////////////////////////////// + // Utility functions + ////////////////////////////////// + + template + static inline U* create_array(size_t count) + { + assert(count > 0); + auto p = static_cast((Traits::malloc)(sizeof(U) * count)); + if (p == nullptr) { + return nullptr; + } + + for (size_t i = 0; i != count; ++i) { + new (p + i) U(); + } + return p; + } + + template + static inline void destroy_array(U* p, size_t count) + { + if (p != nullptr) { + assert(count > 0); + for (size_t i = count; i != 0; ) { + (p + --i)->~U(); + } + (Traits::free)(p); + } + } + + template + static inline U* create() + { + auto p = (Traits::malloc)(sizeof(U)); + return p != nullptr ? new (p) U : nullptr; + } + + template + static inline U* create(A1&& a1) + { + auto p = (Traits::malloc)(sizeof(U)); + return p != nullptr ? new (p) U(std::forward(a1)) : nullptr; + } + + template + static inline void destroy(U* p) + { + if (p != nullptr) { + p->~U(); + } + (Traits::free)(p); + } + +private: + std::atomic producerListTail; + std::atomic producerCount; + + std::atomic initialBlockPoolIndex; + Block* initialBlockPool; + size_t initialBlockPoolSize; + +#if !MCDBGQ_USEDEBUGFREELIST + FreeList freeList; +#else + debug::DebugFreeList freeList; +#endif + + std::atomic implicitProducerHash; + std::atomic implicitProducerHashCount; // Number of slots logically used + ImplicitProducerHash initialImplicitProducerHash; + std::array initialImplicitProducerHashEntries; + std::atomic_flag implicitProducerHashResizeInProgress; + + std::atomic nextExplicitConsumerId; + std::atomic globalExplicitConsumerOffset; + +#if MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH + debug::DebugMutex implicitProdMutex; +#endif + +#ifdef MOODYCAMEL_QUEUE_INTERNAL_DEBUG + std::atomic explicitProducers; + std::atomic implicitProducers; +#endif +}; + + +template +ProducerToken::ProducerToken(ConcurrentQueue& queue) + : producer(queue.recycle_or_create_producer(true)) +{ + if (producer != nullptr) { + producer->token = this; + } +} + +template +ProducerToken::ProducerToken(BlockingConcurrentQueue& queue) + : producer(reinterpret_cast*>(&queue)->recycle_or_create_producer(true)) +{ + if (producer != nullptr) { + producer->token = this; + } +} + +template +ConsumerToken::ConsumerToken(ConcurrentQueue& queue) + : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) +{ + initialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release); + lastKnownGlobalOffset = -1; +} + +template +ConsumerToken::ConsumerToken(BlockingConcurrentQueue& queue) + : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) +{ + initialOffset = reinterpret_cast*>(&queue)->nextExplicitConsumerId.fetch_add(1, std::memory_order_release); + lastKnownGlobalOffset = -1; +} + +template +inline void swap(ConcurrentQueue& a, ConcurrentQueue& b) MOODYCAMEL_NOEXCEPT +{ + a.swap(b); +} + +inline void swap(ProducerToken& a, ProducerToken& b) MOODYCAMEL_NOEXCEPT +{ + a.swap(b); +} + +inline void swap(ConsumerToken& a, ConsumerToken& b) MOODYCAMEL_NOEXCEPT +{ + a.swap(b); +} + +template +inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, typename ConcurrentQueue::ImplicitProducerKVP& b) MOODYCAMEL_NOEXCEPT +{ + a.swap(b); +} + +} + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif diff --git a/ext/lwip-contrib.patch b/ext/lwip-contrib.patch deleted file mode 100644 index 8d80f11..0000000 --- a/ext/lwip-contrib.patch +++ /dev/null @@ -1,32 +0,0 @@ -diff --git a/ports/unix/port/include/arch/cc.h b/ports/unix/port/include/arch/cc.h -index 80b37d8..ae46d76 100644 ---- a/ports/unix/port/include/arch/cc.h -+++ b/ports/unix/port/include/arch/cc.h -@@ -32,6 +32,8 @@ - #ifndef LWIP_ARCH_CC_H - #define LWIP_ARCH_CC_H - -+#include "include/Debug.hpp" // libzt -+ - /* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */ - #if defined __ANDROID__ - #define LWIP_UNIX_ANDROID -@@ -65,7 +67,7 @@ - #endif - - #if defined(LWIP_UNIX_ANDROID) && defined(FD_SET) --typedef __kernel_fd_set fd_set; -+//typedef __kernel_fd_set fd_set; - #endif - - #if defined(LWIP_UNIX_MACH) -@@ -81,6 +83,9 @@ typedef struct sio_status_s sio_status_t; - #define sio_fd_t sio_status_t* - #define __sio_fd_t_defined - -+// Comment out the following line to use lwIP's default diagnostic printing routine -+#define LWIP_PLATFORM_DIAG(x) do {DEBUG_INFO x;} while(0) -+ - typedef unsigned int sys_prot_t; - - #endif /* LWIP_ARCH_CC_H */ diff --git a/ext/lwipopts.h b/ext/lwipopts.h deleted file mode 100644 index b018998..0000000 --- a/ext/lwipopts.h +++ /dev/null @@ -1,2 +0,0 @@ -// Refers to the actual lwIP stack driver location -#include "../include/lwipopts.h" \ No newline at end of file diff --git a/include/Constants.hpp b/include/Constants.hpp deleted file mode 100644 index f511004..0000000 --- a/include/Constants.hpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Useful constants - */ - -#ifndef LIBZT_CONSTANTS_HPP -#define LIBZT_CONSTANTS_HPP - -////////////////////////////////////////////////////////////////////////////// -// Callbacks // -////////////////////////////////////////////////////////////////////////////// - -#define ZTS_NODE_CALLBACKS 1 -#define ZTS_NETWORK_CALLBACKS 1 -#define ZTS_NETIF_CALLBACKS 1 -#define ZTS_PEER_CALLBACKS 1 - -#define ZTS_CALLBACK_PROCESSING_INTERVAL ZTS_WRAPPER_CHECK_INTERVAL // 100 // ms -#define ZTS_CALLBACK_MSG_QUEUE_LEN 256 - -////////////////////////////////////////////////////////////////////////////// -// Error codes returned by ZeroTier and the libzt API // -// See ext/ZeroTierOne/include/ZeroTierOne.h // -////////////////////////////////////////////////////////////////////////////// - -typedef int zts_err_t; - -#define ZTS_ERR_OK 0 // Everything is ok -#define ZTS_ERR_INVALID_ARG -1 // A parameter provided by the user application is invalid (e.g. our of range, NULL, etc) -#define ZTS_ERR_SERVICE -2 // The service isn't initialized or is for some other reason currently unavailable -#define ZTS_ERR_INVALID_OP -3 // For some reason this API operation is not permitted (perhaps the service is still starting?) - -#define ZTS_EVENT_NONE 0x00000000 -// Node-specific events -#define ZTS_EVENT_NODE_ONLINE 0x00000001 // Node is online -#define ZTS_EVENT_NODE_OFFLINE 0x00000002 // Node is offline -#define ZTS_EVENT_NODE_DOWN 0x00000004 // Node is shutting down -#define ZTS_EVENT_NODE_IDENTITY_COLLISION 0x00000008 // Identity collision - check for duplicate instances -#define ZTS_EVENT_NODE_UNRECOVERABLE_ERROR 0x00000010 // Something is seriously wrong -#define ZTS_EVENT_NODE_NORMAL_TERMINATION 0x00000020 // Service thread has stopped -// Network-specific events -#define ZTS_EVENT_NETWORK_NOT_FOUND 0x00000080 -#define ZTS_EVENT_NETWORK_CLIENT_TOO_OLD 0x00000100 -#define ZTS_EVENT_NETWORK_REQUESTING_CONFIG 0x00000200 -#define ZTS_EVENT_NETWORK_OK 0x00000400 -#define ZTS_EVENT_NETWORK_ACCESS_DENIED 0x00000800 -#define ZTS_EVENT_NETWORK_READY_IP4 0x00001000 -#define ZTS_EVENT_NETWORK_READY_IP6 0x00002000 -#define ZTS_EVENT_NETWORK_DOWN 0x00004000 -#define ZTS_EVENT_NETWORK_STATUS_CHANGE ZTS_EVENT_NETWORK_NOT_FOUND | ZTS_EVENT_NETWORK_CLIENT_TOO_OLD | ZTS_EVENT_NETWORK_REQUESTING_CONFIG | ZTS_EVENT_NETWORK_OK | ZTS_EVENT_NETWORK_ACCESS_DENIED -// lwIP netif events -#define ZTS_EVENT_NETIF_UP_IP4 0x00100000 -#define ZTS_EVENT_NETIF_UP_IP6 0x00200000 -#define ZTS_EVENT_NETIF_DOWN_IP4 0x00400000 -#define ZTS_EVENT_NETIF_DOWN_IP6 0x00800000 -#define ZTS_EVENT_NETIF_REMOVED 0x01000000 -#define ZTS_EVENT_NETIF_LINK_UP 0x02000000 -#define ZTS_EVENT_NETIF_LINK_DOWN 0x04000000 -#define ZTS_EVENT_NETIF_NEW_ADDRESS 0x08000000 -#define ZTS_EVENT_NETIF_STATUS_CHANGE ZTS_EVENT_NETIF_UP_IP4 | ZTS_EVENT_NETIF_UP_IP6 | ZTS_EVENT_NETIF_DOWN_IP4 | ZTS_EVENT_NETIF_DOWN_IP6 | ZTS_EVENT_NETIF_LINK_UP | ZTS_EVENT_NETIF_LINK_DOWN -// -#define ZTS_EVENT_GENERIC_DOWN ZTS_EVENT_NETWORK_DOWN | ZTS_EVENT_NETIF_DOWN_IP4 | ZTS_EVENT_NETIF_DOWN_IP6 | ZTS_EVENT_NETIF_LINK_DOWN -// Peer events -#define ZTS_EVENT_PEER_P2P 0x20000000 -#define ZTS_EVENT_PEER_RELAY 0x40000000 -#define ZTS_EVENT_PEER_UNREACHABLE 0x80000000 // Not yet supported - -////////////////////////////////////////////////////////////////////////////// -// libzt config // -////////////////////////////////////////////////////////////////////////////// - -/** - * Default port that libzt will use to support all virtual communication - */ -#define ZTS_DEFAULT_PORT 9994 - -/** - * Maximum port number allowed - */ -#define ZTS_MAX_PORT 65535 - -/** - * For layer-2 only (this will omit all user-space network stack code) - */ -#define ZTS_NO_STACK 0 - -/** - * How fast service states are re-checked (in milliseconds) - */ -#define ZTS_WRAPPER_CHECK_INTERVAL 50 - -/** - * By how much thread I/O and callback loop delays are multiplied (unitless) - */ -#define ZTS_HIBERNATION_MULTIPLIER 50 - -/** - * Maximum allowed number of networks joined to concurrently - */ -#define ZTS_MAX_JOINED_NETWORKS 64 - -/** - * Maximum address assignments per network - */ -#define ZTS_MAX_ASSIGNED_ADDRESSES 16 - -/** - * Maximum routes per network - */ -#define ZTS_MAX_NETWORK_ROUTES 32 - -/** - * Length of buffer required to hold a ztAddress/nodeID - */ -#define ZTS_ID_LEN 16 - -/** - * Polling interval (in ms) for file descriptors wrapped in the Phy I/O loop (for raw drivers only) - */ -#define ZTS_PHY_POLL_INTERVAL 1 - -/** - * Maximum length of libzt/ZeroTier home path (where keys, and config files are stored) - */ -#define ZTS_HOME_PATH_MAX_LEN 256 - -/** - * Length of human-readable MAC address string - */ -#define ZTS_MAC_ADDRSTRLEN 18 - -/** - * Interval (in ms) for performing background tasks - */ -#define ZTS_HOUSEKEEPING_INTERVAL 1000 - -/** - * Name of the service thread (for debug purposes only) - */ -#define ZTS_SERVICE_THREAD_NAME "ZeroTierServiceThread" - -/** - * Name of the callback monitor thread (for debug purposes only) - */ -#define ZTS_EVENT_CALLBACK_THREAD_NAME "ZeroTierEventCallbackThread" - -////////////////////////////////////////////////////////////////////////////// -// lwIP driver config // -// For more LWIP configuration options see: include/lwipopts.h // -////////////////////////////////////////////////////////////////////////////// - -/* - * The following three quantities are related and govern how incoming frames are fed into the - * network stack's core: - - * Every LWIP_GUARDED_BUF_CHECK_INTERVAL milliseconds, a callback will be called from the core and - * will input a maximum of LWIP_FRAMES_HANDLED_PER_CORE_CALL frames before returning control back - * to the core. Meanwhile, incoming frames from the ZeroTier wire will be allocated and their - * pointers will be cached in the receive frame buffer of the size LWIP_MAX_GUARDED_RX_BUF_SZ to - * await the next callback from the core - */ - -#define LWIP_GUARDED_BUF_CHECK_INTERVAL 5 // in ms -#define LWIP_MAX_GUARDED_RX_BUF_SZ 1024 // number of frame pointers that can be cached waiting for receipt into core -#define LWIP_FRAMES_HANDLED_PER_CORE_CALL 16 // How many frames are handled per call from core - -typedef signed char err_t; - -#define ND6_DISCOVERY_INTERVAL 1000 -#define ARP_DISCOVERY_INTERVAL ARP_TMR_INTERVAL - -////////////////////////////////////////////////////////////////////////////// -// Subset of: ZeroTierOne.h and Constants.hpp // -// We redefine a few ZT structures here so that we don't need to drag the // -// entire ZeroTierOne.h file into the user application // -////////////////////////////////////////////////////////////////////////////// - -/** - * Maximum MTU size for ZeroTier - */ -#define ZT_MAX_MTU 10000 - -/** - * Maximum number of direct network paths to a given peer - */ -#define ZT_MAX_PEER_NETWORK_PATHS 16 - -// -// This include file also auto-detects and canonicalizes some environment -// information defines: -// -// __LINUX__ -// __APPLE__ -// __BSD__ (OSX also defines this) -// __UNIX_LIKE__ (Linux, BSD, etc.) -// __WINDOWS__ -// -// Also makes sure __BYTE_ORDER is defined reasonably. -// - -// Hack: make sure __GCC__ is defined on old GCC compilers -#ifndef __GCC__ -#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) -#define __GCC__ -#endif -#endif - -#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) -#ifndef __LINUX__ -#define __LINUX__ -#endif -#ifndef __UNIX_LIKE__ -#define __UNIX_LIKE__ -#endif -#include -#endif - -#ifdef __APPLE__ -#define likely(x) __builtin_expect((x),1) -#define unlikely(x) __builtin_expect((x),0) -#include -#ifndef __UNIX_LIKE__ -#define __UNIX_LIKE__ -#endif -#ifndef __BSD__ -#define __BSD__ -#endif -#include -#endif - -// Defined this macro to disable "type punning" on a number of targets that -// have issues with unaligned memory access. -#if defined(__arm__) || defined(__ARMEL__) || (defined(__APPLE__) && ( (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0)) || (defined(TARGET_OS_WATCH) && (TARGET_OS_WATCH != 0)) || (defined(TARGET_IPHONE_SIMULATOR) && (TARGET_IPHONE_SIMULATOR != 0)) ) ) -#ifndef ZT_NO_TYPE_PUNNING -#define ZT_NO_TYPE_PUNNING -#endif -#endif - -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) -#ifndef __UNIX_LIKE__ -#define __UNIX_LIKE__ -#endif -#ifndef __BSD__ -#define __BSD__ -#endif -#include -#ifndef __BYTE_ORDER -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#endif -#endif - -#if defined(_WIN32) || defined(_WIN64) -#ifndef __WINDOWS__ -#define __WINDOWS__ -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#pragma warning(disable : 4290) -#pragma warning(disable : 4996) -#pragma warning(disable : 4101) -#undef __UNIX_LIKE__ -#undef __BSD__ -#define ZT_PATH_SEPARATOR '\\' -#define ZT_PATH_SEPARATOR_S "\\" -#define ZT_EOL_S "\r\n" -#include -#include -#endif - -// Assume little endian if not defined -#if (defined(__APPLE__) || defined(__WINDOWS__)) && (!defined(__BYTE_ORDER)) -#undef __BYTE_ORDER -#undef __LITTLE_ENDIAN -#undef __BIG_ENDIAN -#define __BIG_ENDIAN 4321 -#define __LITTLE_ENDIAN 1234 -#define __BYTE_ORDER 1234 -#endif - -#ifdef __UNIX_LIKE__ -#define ZT_PATH_SEPARATOR '/' -#define ZT_PATH_SEPARATOR_S "/" -#define ZT_EOL_S "\n" -#endif - -#ifndef __BYTE_ORDER -#include -#endif - -#ifdef __NetBSD__ -#define RTF_MULTICAST 0x20000000 -#endif - -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) -#ifndef likely -#define likely(x) __builtin_expect((x),1) -#endif -#ifndef unlikely -#define unlikely(x) __builtin_expect((x),0) -#endif -#else -#ifndef likely -#define likely(x) (x) -#endif -#ifndef unlikely -#define unlikely(x) (x) -#endif -#endif - -#ifdef __WINDOWS__ -#define ZT_PACKED_STRUCT(D) __pragma(pack(push,1)) D __pragma(pack(pop)) -#else -#define ZT_PACKED_STRUCT(D) D __attribute__((packed)) -#endif - -#endif // _H \ No newline at end of file diff --git a/include/Defs.hpp b/include/Defs.hpp deleted file mode 100644 index 39a8162..0000000 --- a/include/Defs.hpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Management of virtual tap interfaces - */ - -#ifndef LIBZT_DEFS_HPP -#define LIBZT_DEFS_HPP - -#include "Constants.hpp" - -#ifndef _USING_LWIP_DEFINITIONS_ -#include -#endif - -namespace ZeroTier { - -////////////////////////////////////////////////////////////////////////////// -// Subset of: ZeroTierOne.h // -// We redefine a few ZT structures here so that we don't need to drag the // -// entire ZeroTierOne.h file into the user application // -////////////////////////////////////////////////////////////////////////////// - -/** - * What trust hierarchy role does this peer have? - */ -enum zts_peer_role -{ - ZTS_PEER_ROLE_LEAF = 0, // ordinary node - ZTS_PEER_ROLE_MOON = 1, // moon root - ZTS_PEER_ROLE_PLANET = 2 // planetary root -}; - -/** - * A structure used to represent a virtual network route - */ -struct zts_virtual_network_route -{ - /** - * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default - */ - struct sockaddr_storage target; - - /** - * Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway) - */ - struct sockaddr_storage via; - - /** - * Route flags - */ - uint16_t flags; - - /** - * Route metric (not currently used) - */ - uint16_t metric; -}; - -/** - * A structure used to convey network-specific details to the user application - */ -struct zts_network_details -{ - /** - * Network ID - */ - uint64_t nwid; - - /** - * Maximum Transmission Unit size for this network - */ - int mtu; - - /** - * Number of addresses (actually) assigned to the node on this network - */ - short num_addresses; - - /** - * Array of IPv4 and IPv6 addresses assigned to the node on this network - */ - struct sockaddr_storage addr[ZTS_MAX_ASSIGNED_ADDRESSES]; - - /** - * Number of routes - */ - unsigned int num_routes; - - /** - * Array of IPv4 and IPv6 addresses assigned to the node on this network - */ - struct zts_virtual_network_route routes[ZTS_MAX_NETWORK_ROUTES]; -}; - -/** - * Physical network path to a peer - */ -struct zts_physical_path -{ - /** - * Address of endpoint - */ - struct sockaddr_storage address; - - /** - * Time of last send in milliseconds or 0 for never - */ - uint64_t lastSend; - - /** - * Time of last receive in milliseconds or 0 for never - */ - uint64_t lastReceive; - - /** - * Is this a trusted path? If so this will be its nonzero ID. - */ - uint64_t trustedPathId; - - /** - * Is path expired? - */ - int expired; - - /** - * Is path preferred? - */ - int preferred; -}; - -/** - * Peer status result buffer - */ -struct zts_peer_details -{ - /** - * ZeroTier address (40 bits) - */ - uint64_t address; - - /** - * Remote major version or -1 if not known - */ - int versionMajor; - - /** - * Remote minor version or -1 if not known - */ - int versionMinor; - - /** - * Remote revision or -1 if not known - */ - int versionRev; - - /** - * Last measured latency in milliseconds or -1 if unknown - */ - int latency; - - /** - * What trust hierarchy role does this device have? - */ - enum zts_peer_role role; - - /** - * Number of paths (size of paths[]) - */ - unsigned int pathCount; - - /** - * Known network paths to peer - */ - zts_physical_path paths[ZT_MAX_PEER_NETWORK_PATHS]; -}; - -/** - * List of peers - */ -struct zts_peer_list -{ - zts_peer_details *peers; - unsigned long peerCount; -}; - -} // namespace ZeroTier - -#endif // _H \ No newline at end of file diff --git a/include/RingBuffer.h b/include/RingBuffer.h deleted file mode 100644 index e143584..0000000 --- a/include/RingBuffer.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Ring buffer implementation for network stack drivers - */ - -#ifndef ZT_RINGBUFFER_H -#define ZT_RINGBUFFER_H - -#include -#include - -typedef char bufElementType; - -class RingBuffer -{ -private: - bufElementType * buf; - size_t size; - size_t begin; - size_t end; - bool wrap; - -public: - /** - * create a RingBuffer with space for up to size elements. - */ - explicit RingBuffer(size_t size) - : size(size), - begin(0), - end(0), - wrap(false) - { - buf = new bufElementType[size]; - } -/* - RingBuffer(const RingBuffer & ring) - { - this(ring.size); - begin = ring.begin; - end = ring.end; - memcpy(buf, ring.buf, sizeof(T) * size); - } -*/ - ~RingBuffer() - { - delete[] buf; - } - - // get a reference to the underlying buffer - bufElementType* get_buf(); - - // adjust buffer index pointer as if we copied data in - size_t produce(size_t n); - - // merely reset the buffer pointer, doesn't erase contents - void reset(); - - // adjust buffer index pointer as if we copied data out - size_t consume(size_t n); - - size_t write(const bufElementType * data, size_t n); - - size_t read(bufElementType * dest, size_t n); - - size_t count(); - - size_t getFree(); -}; - -#endif // _H diff --git a/include/ServiceControls.hpp b/include/ServiceControls.hpp deleted file mode 100644 index 9ceca6c..0000000 --- a/include/ServiceControls.hpp +++ /dev/null @@ -1,393 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Header for ZeroTier service controls - */ - -#ifndef LIBZT_SERVICE_CONTROLS_HPP -#define LIBZT_SERVICE_CONTROLS_HPP - -#include "Constants.hpp" - -namespace ZeroTier { - -#ifdef _WIN32 - #ifdef ADD_EXPORTS - #define ZT_SOCKET_API __declspec(dllexport) - #else - #define ZT_SOCKET_API __declspec(dllimport) - #endif - #define ZTCALL __cdecl -#else - #define ZT_SOCKET_API - #define ZTCALL -#endif - -////////////////////////////////////////////////////////////////////////////// -// ZeroTier Service Controls // -////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief (optional) Sets the port for the background libzt service. If this function is called - * with a port number between 1-65535 it will attempt to bind to that port. If it is called with - * a port number of 0 it will attempt to randomly search for an available port. If this function - * is never called, the service will try to bind on LIBZT_DEFAULT_PORT which is 9994. - * - * @usage Should be called at the beginning of your application before `zts_startjoin()` - * @param portno Port number - * @return 0 if successful; or -1 if failed - */ -ZT_SOCKET_API int ZTCALL zts_set_service_port(int portno); - -/** - * @brief (optional) Returns the port number used by the ZeroTier service - * @usage Can be called if a port number was previously assigned - * @return the port number used by the ZeroTier service - */ -ZT_SOCKET_API int ZTCALL zts_get_service_port(); - -/** - * @brief Starts the ZeroTier service - * - * @usage Should be called at the beginning of your application. Will blocks until all of the following conditions are met: - * - ZeroTier core service has been initialized - * - Cryptographic identity has been generated or loaded from directory specified by `path` - * - Virtual network is successfully joined - * - IP address is assigned by network controller service - * @param path path directory where cryptographic identities and network configuration files are stored and retrieved - * (`identity.public`, `identity.secret`) - * @param blocking whether or not this call will block until the entire service is up and running - * @return 0 if successful; or 1 if failed - */ -ZT_SOCKET_API int ZTCALL zts_start(const char *path, int blocking); - -/** - * @brief Starts the ZeroTier service and notifies user application of events via callback - * - * @usage Should be called at the beginning of your application. Will blocks until all of the following conditions are met: - * - ZeroTier core service has been initialized - * - Cryptographic identity has been generated or loaded from directory specified by `path` - * - Virtual network is successfully joined - * - IP address is assigned by network controller service - * @param path path directory where cryptographic identities and network configuration files are stored and retrieved - * (`identity.public`, `identity.secret`) - * @param userCallbackFunc User-specified callback for ZeroTier events - * @param blocking whether or not this call will block until the entire service is up and running - * @return 0 if successful; or 1 if failed - */ -ZT_SOCKET_API int ZTCALL zts_start_with_callback(const char *path, void (*userCallbackFunc)(uint64_t, int), int blocking); - -/** - * @brief Starts the ZeroTier service - * - * @usage Should be called at the beginning of your application. Will blocks until all of the following conditions are met: - * - ZeroTier core service has been initialized - * - Cryptographic identity has been generated or loaded from directory specified by `path` - * - Virtual network is successfully joined - * - IP address is assigned by network controller service - * @param path path directory where cryptographic identities and network configuration files are stored and retrieved - * (`identity.public`, `identity.secret`) - * @param nwid A 16-digit hexidecimal network identifier (e.g. Earth: `8056c2e21c000001`) - * @return 0 if successful; or 1 if failed - */ -ZT_SOCKET_API int ZTCALL zts_startjoin(const char *path, const uint64_t nwid); - -/** - * @brief Stops the ZeroTier service, brings down all virtual interfaces in order to stop all traffic processing. - * - * @usage This should be called when the application anticipates not needing any sort of traffic processing for a - * prolonged period of time. The stack driver (with associated timers) will remain active in case future traffic - * processing is required. Note that the application must tolerate a multi-second startup time if zts_start() - * zts_startjoin() is called again. To stop this background thread and free all resources use zts_free() instead. - * @param blocking whether or not this call will block until the entire service is torn down - * @return Returns 0 on success, -1 on failure - */ -ZT_SOCKET_API int ZTCALL zts_stop(int blocking = 1); - -/** - * @brief Stops all background services, brings down all interfaces, frees all resources. After calling this function - * an application restart will be required before the library can be used again. This is a blocking call. - * - * @usage This should be called at the end of your program or when you do not anticipate communicating over ZeroTier - * @return Returns 0 on success, -1 on failure - */ -ZT_SOCKET_API int ZTCALL zts_free(); - -/** - * @brief Return whether the ZeroTier service is currently running - * - * @usage Call this after zts_start() - * @return 1 if running, 0 if not running - */ -ZT_SOCKET_API int ZTCALL zts_core_running(); - -/** - * @brief Return whether libzt is ready to handle socket API calls. Alternatively you could - * have just called zts_startjoin(path, nwid) - * - * @usage Call this after zts_start() - * @return 1 if running, 0 if not running - */ -ZT_SOCKET_API int ZTCALL zts_ready(); - -/** - * @brief Return the number of networks currently joined by this node - * - * @usage Call this after zts_start(), zts_startjoin() and/or zts_join() - * @return Number of networks joined by this node - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_get_num_joined_networks(); - -/** - * @brief Populates a structure with details for a given network - * - * @usage Call this from the application thread any time after the node has joined a network - * @param nwid A 16-digit hexidecimal virtual network ID - * @param nd Pointer to a zts_network_details structure to populate - * @return ZTS_ERR_SERVICE if failed, 0 if otherwise - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_get_network_details(uint64_t nwid, struct zts_network_details *nd); - -/** - * @brief Populates an array of structures with details for any given number of networks - * - * @usage Call this from the application thread any time after the node has joined a network - * @param nds Pointer to an array of zts_network_details structures to populate - * @param num Number of zts_network_details structures available to copy data into, will be updated - * to reflect number of structures that were actually populated - * @return ZTS_ERR_SERVICE if failed, 0 if otherwise - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_get_all_network_details(struct zts_network_details *nds, int *num); - -/** - * @brief Join a network - * - * @usage Call this from application thread. Only after zts_start() has succeeded - * @param nwid A 16-digit hexidecimal virtual network ID - * @return 0 if successful, -1 for any failure - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_join(const uint64_t nwid, int blocking = 1); - -/** - * @brief Leave a network - * - * @usage Call this from application thread. Only after zts_start() has succeeded - * @param nwid A 16-digit hexidecimal virtual network ID - * @return 0 if successful, -1 for any failure - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_leave(const uint64_t nwid, int blocking = 1); - - -/** - * @brief Leaves all networks - * - * @usage Call this from application thread. Only after zts_start() has succeeded - * @param nwid A 16-digit hexidecimal virtual network ID - * @return 0 if successful, -1 for any failure - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_leave_all(int blocking = 1); - -/** - * @brief Orbits a given moon (user-defined root server) - * - * @usage Call this from application thread. Only after zts_start() has succeeded - * @param moonWorldId A 16-digit hexidecimal world ID - * @param moonSeed A 16-digit hexidecimal seed ID - * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE, ZTS_ERR_INVALID_ARG, ZTS_ERR_INVALID_OP if otherwise - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_orbit(uint64_t moonWorldId, uint64_t moonSeed); - -/** - * @brief De-orbits a given moon (user-defined root server) - * - * @usage Call this from application thread. Only after zts_start() has succeeded - * @param moonWorldId A 16-digit hexidecimal world ID - * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE, ZTS_ERR_INVALID_ARG, ZTS_ERR_INVALID_OP if otherwise - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_deorbit(uint64_t moonWorldId); - -/** - * @brief Copies the configuration path used by ZeroTier into the provided buffer - * - * @usage Use this to determine where ZeroTier is storing identity files - * @param homePath Path to ZeroTier configuration files - * @param len Length of destination buffer - * @return 0 if no error, -1 if invalid argument was supplied - */ -ZT_SOCKET_API zts_err_t ZTCALL zts_get_path(char *homePath, size_t *len); - -/** - * @brief Returns the node ID of this instance - * - * @usage Call this after zts_start() and/or when zts_running() returns true - * @return - */ -ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id(); - -/** - * @brief Returns whether any address has been assigned to the SockTap for this network - * - * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack - * @param nwid Network ID - * @return - */ -ZT_SOCKET_API int ZTCALL zts_has_address(const uint64_t nwid); - - -/** - * @brief Returns the number of addresses assigned to this node for the given nwid - * - * @param nwid Network ID - * @return The number of addresses assigned - */ -ZT_SOCKET_API int ZTCALL zts_get_num_assigned_addresses(const uint64_t nwid); - -/** - * @brief Returns the assigned address located at the given index - * - * @usage The indices of each assigned address are not guaranteed and should only - * be used for iterative purposes. - * @param nwid Network ID - * @param index location of assigned address - * @return The number of addresses assigned - */ -ZT_SOCKET_API int ZTCALL zts_get_address_at_index( - const uint64_t nwid, const int index, struct sockaddr *addr, socklen_t *addrlen); - -/** - * @brief Get IP address for this device on a given network - * - * @usage FIXME: Only returns first address found, good enough for most cases - * @param nwid Network ID - * @param addr Destination structure for address - * @param addrlen size of destination address buffer, will be changed to size of returned address - * @return 0 if an address was successfully found, -1 if failure - */ -ZT_SOCKET_API int ZTCALL zts_get_address( - const uint64_t nwid, struct sockaddr_storage *addr, const int address_family); - -/** - * @brief Computes a 6PLANE IPv6 address for the given Network ID and Node ID - * - * @usage Can call any time - * @param addr Destination structure for address - * @param nwid Network ID - * @param nodeId Node ID - * @return - */ -ZT_SOCKET_API void ZTCALL zts_get_6plane_addr( - struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); - -/** - * @brief Computes a RFC4193 IPv6 address for the given Network ID and Node ID - * - * @usage Can call any time - * @param addr Destination structure for address - * @param nwid Network ID - * @param nodeId Node ID - * @return - */ -ZT_SOCKET_API void ZTCALL zts_get_rfc4193_addr( - struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); - -/** - * @brief Return the number of peers - * - * @usage Call this after zts_start() has succeeded - * @return - */ -ZT_SOCKET_API zts_err_t zts_get_peer_count(); - -ZT_SOCKET_API zts_err_t zts_get_peers(struct zts_peer_details *pds, int *num); - -/** - * @brief Enables the HTTP backplane management system - * - * @usage Call this after zts_start() has succeeded - * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE if otherwise - */ -ZT_SOCKET_API zts_err_t zts_enable_http_backplane_mgmt(); - -/** - * @brief Disables the HTTP backplane management system - * - * @usage Call this after zts_start() has succeeded - * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE, ZTS_ERR_INVALID_OP if otherwise - */ -ZT_SOCKET_API zts_err_t zts_disable_http_backplane_mgmt(); - - -/** - * @brief Starts a ZeroTier service in the background - * - * @usage For internal use only. - * @param - * @return - */ -#if defined(_WIN32) -DWORD WINAPI _zts_start_service(LPVOID thread_id); -#else -void *_zts_start_service(void *thread_id); -#endif - -/** - * @brief [Should not be called from user application] This function must be surrounded by - * ZT service locks. It will determine if it is currently safe and allowed to operate on - * the service. - * @usage Can be called at any time - * @return 1 or 0 - */ -int _zts_can_perform_service_operation(); - -/** - * @brief [Should not be called from user application] Returns whether or not the node is - * online. - * @usage Can be called at any time - * @return 1 or 0 - */ -int _zts_node_online(); - -/** - * @brief [Should not be called from user application] Adjusts the delay multiplier for the - * network stack driver thread. - * @usage Can be called at any time - */ -void _hibernate_if_needed(); - -#ifdef __cplusplus -} -#endif - -} // namespace ZeroTier - -#endif // _H \ No newline at end of file diff --git a/include/libzt.h b/include/libzt.h index 2f75735..950ce60 100644 --- a/include/libzt.h +++ b/include/libzt.h @@ -63,22 +63,86 @@ typedef int socklen_t; #include #endif +/* #ifdef _USING_LWIP_DEFINITIONS_ #include "lwip/sockets.h" #endif - -#include "Constants.hpp" -#include "Defs.hpp" -#include "ServiceControls.hpp" - -class InetAddress; -class VirtualTap; +*/ #if defined(_MSC_VER) #include typedef SSIZE_T ssize_t; #endif +namespace ZeroTier { + +#ifdef __cplusplus +extern "C" { +#endif + +// Custom errno to prevent conflicts with platform's own errno +extern int zts_errno; +typedef int zts_err_t; + +#ifdef __cplusplus +} +#endif + +/** + * The system port upon which ZT traffic is sent and received + */ +#define ZTS_DEFAULT_PORT 9994 + +////////////////////////////////////////////////////////////////////////////// +// Control API error codes // +////////////////////////////////////////////////////////////////////////////// + +#define ZTS_ERR_OK 0 // Everything is ok +#define ZTS_ERR_INVALID_ARG -1 // A parameter provided by the user application is invalid (e.g. our of range, NULL, etc) +#define ZTS_ERR_SERVICE -2 // The service isn't initialized or is for some other reason currently unavailable +#define ZTS_ERR_INVALID_OP -3 // For some reason this API operation is not permitted (perhaps the service is still starting?) + +////////////////////////////////////////////////////////////////////////////// +// Control API event codes // +////////////////////////////////////////////////////////////////////////////// + +#define ZTS_EVENT_NONE -1 +#define ZTS_EVENT_NODE_UP 0 +// Standard node events +#define ZTS_EVENT_NODE_OFFLINE 1 +#define ZTS_EVENT_NODE_ONLINE 2 +#define ZTS_EVENT_NODE_DOWN 3 +#define ZTS_EVENT_NODE_IDENTITY_COLLISION 4 +// libzt node events +#define ZTS_EVENT_NODE_UNRECOVERABLE_ERROR 16 +#define ZTS_EVENT_NODE_NORMAL_TERMINATION 17 +// Network-specific events +#define ZTS_EVENT_NETWORK_NOT_FOUND 32 +#define ZTS_EVENT_NETWORK_CLIENT_TOO_OLD 33 +#define ZTS_EVENT_NETWORK_REQUESTING_CONFIG 34 +#define ZTS_EVENT_NETWORK_OK 35 +#define ZTS_EVENT_NETWORK_ACCESS_DENIED 36 +#define ZTS_EVENT_NETWORK_READY_IP4 37 +#define ZTS_EVENT_NETWORK_READY_IP6 38 +#define ZTS_EVENT_NETWORK_DOWN 39 +// +#define ZTS_EVENT_NETWORK_STACK_UP 48 +#define ZTS_EVENT_NETWORK_STACK_DOWN 49 + +// lwIP netif events +#define ZTS_EVENT_NETIF_UP_IP4 64 +#define ZTS_EVENT_NETIF_UP_IP6 65 +#define ZTS_EVENT_NETIF_DOWN_IP4 66 +#define ZTS_EVENT_NETIF_DOWN_IP6 67 +#define ZTS_EVENT_NETIF_REMOVED 68 +#define ZTS_EVENT_NETIF_LINK_UP 69 +#define ZTS_EVENT_NETIF_LINK_DOWN 70 +#define ZTS_EVENT_NETIF_NEW_ADDRESS 71 +// Peer events +#define ZTS_EVENT_PEER_P2P 96 +#define ZTS_EVENT_PEER_RELAY 97 +#define ZTS_EVENT_PEER_UNREACHABLE 98 + ////////////////////////////////////////////////////////////////////////////// // Common definitions and structures for interacting with the ZT socket API // // This is a subset of lwip/sockets.h, lwip/arch.h, and lwip/inet.h // @@ -196,7 +260,7 @@ typedef SSIZE_T ssize_t; #error "external ZTS_FD_SETSIZE too small for number of sockets" #endif // FD_SET -#if !defined(_USING_LWIP_DEFINITIONS_) +#if defined(_USING_LWIP_DEFINITIONS_) #ifdef __cplusplus extern "C" { @@ -322,15 +386,454 @@ struct sockaddr_ll { #endif ////////////////////////////////////////////////////////////////////////////// -// Socket API // +// Subset of: ZeroTierOne.h // +// We redefine a few ZT structures here so that we don't need to drag the // +// entire ZeroTierOne.h file into the user application // +////////////////////////////////////////////////////////////////////////////// + +/** + * Maximum address assignments per network + */ +#define ZTS_MAX_ASSIGNED_ADDRESSES 16 + +/** + * Maximum routes per network + */ +#define ZTS_MAX_NETWORK_ROUTES 32 + +/** + * Maximum number of direct network paths to a given peer + */ +#define ZT_MAX_PEER_NETWORK_PATHS 16 + +/** + * What trust hierarchy role does this peer have? + */ +enum zts_peer_role +{ + ZTS_PEER_ROLE_LEAF = 0, // ordinary node + ZTS_PEER_ROLE_MOON = 1, // moon root + ZTS_PEER_ROLE_PLANET = 2 // planetary root +}; + +/** + * A structure used to represent a virtual network route + */ +struct zts_virtual_network_route +{ + /** + * Target network / netmask bits (in port field) or NULL or 0.0.0.0/0 for default + */ + struct sockaddr_storage target; + + /** + * Gateway IP address (port ignored) or NULL (family == 0) for LAN-local (no gateway) + */ + struct sockaddr_storage via; + + /** + * Route flags + */ + uint16_t flags; + + /** + * Route metric (not currently used) + */ + uint16_t metric; +}; + +/** + * A structure used to convey network-specific details to the user application + */ +struct zts_network_details +{ + /** + * Network ID + */ + uint64_t nwid; + + /** + * Maximum Transmission Unit size for this network + */ + int mtu; + + /** + * Number of addresses (actually) assigned to the node on this network + */ + short num_addresses; + + /** + * Array of IPv4 and IPv6 addresses assigned to the node on this network + */ + struct sockaddr_storage addr[ZTS_MAX_ASSIGNED_ADDRESSES]; + + /** + * Number of routes + */ + unsigned int num_routes; + + /** + * Array of IPv4 and IPv6 addresses assigned to the node on this network + */ + struct zts_virtual_network_route routes[ZTS_MAX_NETWORK_ROUTES]; +}; + +/** + * Physical network path to a peer + */ +struct zts_physical_path +{ + /** + * Address of endpoint + */ + struct sockaddr_storage address; + + /** + * Time of last send in milliseconds or 0 for never + */ + uint64_t lastSend; + + /** + * Time of last receive in milliseconds or 0 for never + */ + uint64_t lastReceive; + + /** + * Is this a trusted path? If so this will be its nonzero ID. + */ + uint64_t trustedPathId; + + /** + * Is path expired? + */ + int expired; + + /** + * Is path preferred? + */ + int preferred; +}; + +/** + * Peer status result buffer + */ +struct zts_peer_details +{ + /** + * ZeroTier address (40 bits) + */ + uint64_t address; + + /** + * Remote major version or -1 if not known + */ + int versionMajor; + + /** + * Remote minor version or -1 if not known + */ + int versionMinor; + + /** + * Remote revision or -1 if not known + */ + int versionRev; + + /** + * Last measured latency in milliseconds or -1 if unknown + */ + int latency; + + /** + * What trust hierarchy role does this device have? + */ + enum zts_peer_role role; + + /** + * Number of paths (size of paths[]) + */ + unsigned int pathCount; + + /** + * Known network paths to peer + */ + zts_physical_path paths[ZT_MAX_PEER_NETWORK_PATHS]; +}; + +/** + * List of peers + */ +struct zts_peer_list +{ + zts_peer_details *peers; + unsigned long peerCount; +}; + +////////////////////////////////////////////////////////////////////////////// +// ZeroTier Service Controls // ////////////////////////////////////////////////////////////////////////////// #ifdef __cplusplus extern "C" { #endif -// Custom errno to prevent conflicts with platform's own errno -extern int zts_errno; +/** + * @brief Starts the ZeroTier service and notifies user application of events via callback + * + * @usage Should be called at the beginning of your application. Will blocks until all of the following conditions are met: + * - ZeroTier core service has been initialized + * - Cryptographic identity has been generated or loaded from directory specified by `path` + * - Virtual network is successfully joined + * - IP address is assigned by network controller service + * @param path path directory where cryptographic identities and network configuration files are stored and retrieved + * (`identity.public`, `identity.secret`) + * @param userCallbackFunc User-specified callback for ZeroTier events + * @return 0 if successful; or 1 if failed + */ +ZT_SOCKET_API int ZTCALL zts_start(const char *path, void (*userCallbackFunc)(uint64_t, int), int port = ZTS_DEFAULT_PORT); + +/** + * @brief Stops the ZeroTier service, brings down all virtual interfaces in order to stop all traffic processing. + * + * @usage This should be called when the application anticipates not needing any sort of traffic processing for a + * prolonged period of time. The stack driver (with associated timers) will remain active in case future traffic + * processing is required. Note that the application must tolerate a multi-second startup time if zts_start() + * zts_startjoin() is called again. To stop this background thread and free all resources use zts_free() instead. + * @return Returns 0 on success, -1 on failure + */ +ZT_SOCKET_API int ZTCALL zts_stop(); + +/** + * @brief Stops all background services, brings down all interfaces, frees all resources. After calling this function + * an application restart will be required before the library can be used again. This is a blocking call. + * + * @usage This should be called at the end of your program or when you do not anticipate communicating over ZeroTier + * @return Returns 0 on success, -1 on failure + */ +ZT_SOCKET_API int ZTCALL zts_free(); + +/** + * @brief Return whether the ZeroTier service is currently running + * + * @usage Call this after zts_start() + * @return 1 if running, 0 if not running + */ +ZT_SOCKET_API int ZTCALL zts_core_running(); + +/** + * @brief Return the number of networks currently joined by this node + * + * @usage Call this after zts_start(), zts_startjoin() and/or zts_join() + * @return Number of networks joined by this node + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_get_num_joined_networks(); + +/** + * @brief Populates a structure with details for a given network + * + * @usage Call this from the application thread any time after the node has joined a network + * @param nwid A 16-digit hexidecimal virtual network ID + * @param nd Pointer to a zts_network_details structure to populate + * @return ZTS_ERR_SERVICE if failed, 0 if otherwise + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_get_network_details(uint64_t nwid, struct zts_network_details *nd); + +/** + * @brief Populates an array of structures with details for any given number of networks + * + * @usage Call this from the application thread any time after the node has joined a network + * @param nds Pointer to an array of zts_network_details structures to populate + * @param num Number of zts_network_details structures available to copy data into, will be updated + * to reflect number of structures that were actually populated + * @return ZTS_ERR_SERVICE if failed, 0 if otherwise + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_get_all_network_details(struct zts_network_details *nds, int *num); + +/** + * @brief Join a network + * + * @usage Call this from application thread. Only after zts_start() has succeeded + * @param nwid A 16-digit hexidecimal virtual network ID + * @return 0 if successful, -1 for any failure + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_join(const uint64_t nwid); + +/** + * @brief Leave a network + * + * @usage Call this from application thread. Only after zts_start() has succeeded + * @param nwid A 16-digit hexidecimal virtual network ID + * @return 0 if successful, -1 for any failure + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_leave(const uint64_t nwid); + + +/** + * @brief Leaves all networks + * + * @usage Call this from application thread. Only after zts_start() has succeeded + * @return 0 if successful, -1 for any failure + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_leave_all(); + +/** + * @brief Orbits a given moon (user-defined root server) + * + * @usage Call this from application thread. Only after zts_start() has succeeded + * @param moonWorldId A 16-digit hexidecimal world ID + * @param moonSeed A 16-digit hexidecimal seed ID + * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE, ZTS_ERR_INVALID_ARG, ZTS_ERR_INVALID_OP if otherwise + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_orbit(uint64_t moonWorldId, uint64_t moonSeed); + +/** + * @brief De-orbits a given moon (user-defined root server) + * + * @usage Call this from application thread. Only after zts_start() has succeeded + * @param moonWorldId A 16-digit hexidecimal world ID + * @return ZTS_ERR_OK if successful, ZTS_ERR_SERVICE, ZTS_ERR_INVALID_ARG, ZTS_ERR_INVALID_OP if otherwise + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_deorbit(uint64_t moonWorldId); + +/** + * @brief Copies the configuration path used by ZeroTier into the provided buffer + * + * @usage Use this to determine where ZeroTier is storing identity files + * @param homePath Path to ZeroTier configuration files + * @param len Length of destination buffer + * @return 0 if no error, -1 if invalid argument was supplied + */ +ZT_SOCKET_API zts_err_t ZTCALL zts_get_path(char *homePath, size_t *len); + +/** + * @brief Returns the node ID of this instance + * + * @usage Call this after zts_start() and/or when zts_running() returns true + * @return + */ +ZT_SOCKET_API uint64_t ZTCALL zts_get_node_id(); + +/** + * @brief Returns whether any address has been assigned to the SockTap for this network + * + * @usage This is used as an indicator of readiness for service for the ZeroTier core and stack + * @param nwid Network ID + * @return + */ +ZT_SOCKET_API int ZTCALL zts_has_address(const uint64_t nwid); + + +/** + * @brief Returns the number of addresses assigned to this node for the given nwid + * + * @param nwid Network ID + * @return The number of addresses assigned + */ +ZT_SOCKET_API int ZTCALL zts_get_num_assigned_addresses(const uint64_t nwid); + +/** + * @brief Returns the assigned address located at the given index + * + * @usage The indices of each assigned address are not guaranteed and should only + * be used for iterative purposes. + * @param nwid Network ID + * @param index location of assigned address + * @return The number of addresses assigned + */ +ZT_SOCKET_API int ZTCALL zts_get_address_at_index( + const uint64_t nwid, const int index, struct sockaddr *addr, socklen_t *addrlen); + +/** + * @brief Get IP address for this device on a given network + * + * @usage FIXME: Only returns first address found, good enough for most cases + * @param nwid Network ID + * @param addr Destination structure for address + * @param addrlen size of destination address buffer, will be changed to size of returned address + * @return 0 if an address was successfully found, -1 if failure + */ +ZT_SOCKET_API int ZTCALL zts_get_address( + const uint64_t nwid, struct sockaddr_storage *addr, const int address_family); + +/** + * @brief Computes a 6PLANE IPv6 address for the given Network ID and Node ID + * + * @usage Can call any time + * @param addr Destination structure for address + * @param nwid Network ID + * @param nodeId Node ID + * @return + */ +ZT_SOCKET_API void ZTCALL zts_get_6plane_addr( + struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); + +/** + * @brief Computes a RFC4193 IPv6 address for the given Network ID and Node ID + * + * @usage Can call any time + * @param addr Destination structure for address + * @param nwid Network ID + * @param nodeId Node ID + * @return + */ +ZT_SOCKET_API void ZTCALL zts_get_rfc4193_addr( + struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); + +/** + * @brief Return the number of peers + * + * @usage Call this after zts_start() has succeeded + * @return + */ +ZT_SOCKET_API zts_err_t zts_get_peer_count(); + +ZT_SOCKET_API zts_err_t zts_get_peers(struct zts_peer_details *pds, int *num); + +/** + * @brief Determines whether a peer is reachable via a P2P connection + * or is being relayed via roots. + * + * @usage + * @param nodeId The ID of the peer to check + * @return The status of a peer + */ +ZT_SOCKET_API zts_err_t zts_get_peer_status(uint64_t nodeId); + +/** + * @brief Starts a ZeroTier service in the background + * + * @usage For internal use only. + * @param + * @return + */ +#if defined(_WIN32) +DWORD WINAPI _zts_start_service(LPVOID thread_id); +#else +void *_zts_start_service(void *thread_id); +#endif + +/** + * @brief [Should not be called from user application] This function must be surrounded by + * ZT service locks. It will determine if it is currently safe and allowed to operate on + * the service. + * @usage Can be called at any time + * @return 1 or 0 + */ +int _zts_can_perform_service_operation(); + +/** + * @brief [Should not be called from user application] Returns whether or not the node is + * online. + * @usage Can be called at any time + * @return 1 or 0 + */ +int _zts_node_online(); + +int zts_ready(); + +////////////////////////////////////////////////////////////////////////////// +// Socket API // +////////////////////////////////////////////////////////////////////////////// /** * @brief Create a socket @@ -679,4 +1182,6 @@ ZT_SOCKET_API zts_err_t ZTCALL zts_del_dns_nameserver(struct sockaddr *addr); } // extern "C" #endif +} // namespace ZeroTier + #endif // _H diff --git a/packages/PyPI/bdist.bat b/packages/PyPI/bdist.bat deleted file mode 100644 index 28fb8cb..0000000 --- a/packages/PyPI/bdist.bat +++ /dev/null @@ -1,7 +0,0 @@ -cd ../../ -cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=DEBUG -cmake --build build -copy bin\lib\Debug\*.lib packages\pypi -cd packages\pypi -pip3 install wheel twine -py setup.py bdist_wheel \ No newline at end of file diff --git a/packages/README.md b/packages/README.md deleted file mode 100644 index 8a2d93b..0000000 --- a/packages/README.md +++ /dev/null @@ -1,25 +0,0 @@ -### Projects and scripts for building various packages - -Pre-built binaries [here](https://download.zerotier.com/RELEASES/) - -*** - -### To build entire distribution package: - -Step 1: On a Windows host, run `make dist`. Outputs will be copied to `prebuilt/(debug|release)/(win32/win64)` -Step 2: On a Linux host, run `make dist`. Outputs will be copied to `prebuilt/linux-$ARCH` -Step 3: On a macOS host, run `make dist`. Outputs will be copied to `prebuilt/macos-$ARCH` -Step 4: Perform any necessary modifications to the generated projects (such as Xcode projects) -Step 5: Re-run `make dist` -Step 6: On a Unix-like host, run `make package`. This will zip everything up into a pair of `tar.gz` files in `products` - -*** - -### iOS - - - In `packages/xcode_ios`, change SDK from `macOS` to `iOS` - - Build - -### Android - -This project is not currently generated by CMake, but does utilize the `CMakeLists.txt` and generates a `.aar` Android Archive which can be imported into an Android Studio project as a library. An example of this library's usage can be found in [examples/android](examples/android). Further examples of the libzt JNI API can be seen in [examples/java](examples/java). diff --git a/packages/android/.gitignore b/packages/android/.gitignore deleted file mode 100644 index 5edb4ee..0000000 --- a/packages/android/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -.DS_Store -/build -/captures -.externalNativeBuild diff --git a/packages/android/.project b/packages/android/.project new file mode 100644 index 0000000..3964dd3 --- /dev/null +++ b/packages/android/.project @@ -0,0 +1,17 @@ + + + android + Project android created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/packages/android/app/.gitignore b/packages/android/app/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/packages/android/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/packages/android/app/build.gradle b/packages/android/app/build.gradle deleted file mode 100644 index b52d99b..0000000 --- a/packages/android/app/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 28 - defaultConfig { - minSdkVersion 21 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - externalNativeBuild { - cmake { - cppFlags "" - } - } - ndk { - // Tells Gradle to build outputs for the following ABIs and package - // them into your APK. - abiFilters 'armeabi-v7a' - } - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - externalNativeBuild { - cmake { - path "../../../CMakeLists.txt" - } - } -} - -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' - 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/packages/android/app/proguard-rules.pro b/packages/android/app/proguard-rules.pro deleted file mode 100644 index f1b4245..0000000 --- a/packages/android/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/packages/android/app/src/androidTest/java/com/example/zerotier/ExampleInstrumentedTest.java b/packages/android/app/src/androidTest/java/com/example/zerotier/ExampleInstrumentedTest.java deleted file mode 100644 index fe8e36c..0000000 --- a/packages/android/app/src/androidTest/java/com/example/zerotier/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.zerotier; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.example.zerotier", appContext.getPackageName()); - } -} diff --git a/packages/android/app/src/main/AndroidManifest.xml b/packages/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 42365c2..0000000 --- a/packages/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/packages/android/app/src/main/java/ZTFDSet.java b/packages/android/app/src/main/java/ZTFDSet.java deleted file mode 100644 index cf5bd7b..0000000 --- a/packages/android/app/src/main/java/ZTFDSet.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -public class ZTFDSet -{ - byte[] fds_bits = new byte[1024]; - - public void CLR(int fd) - { - fds_bits[fd] = 0x00; - } - - public boolean ISSET(int fd) - { - return fds_bits[fd] == 0x01; - } - - public void SET(int fd) - { - fds_bits[fd] = 0x01; - } - - public void ZERO() - { - for (int i=0; i<1024; i++) { - fds_bits[i] = 0x00; - } - } -} \ No newline at end of file diff --git a/packages/android/app/src/main/java/ZTSocketAddress.java b/packages/android/app/src/main/java/ZTSocketAddress.java deleted file mode 100644 index b86a985..0000000 --- a/packages/android/app/src/main/java/ZTSocketAddress.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import com.zerotier.libzt.ZeroTier; - -import java.net.InetAddress; - -// Designed to transport address information across the JNI boundary -public class ZTSocketAddress -{ - public byte[] _ip6 = new byte[16]; - public byte[] _ip4 = new byte[4]; - - public int _family; - public int _port; // Also reused for netmask or prefix - - public ZTSocketAddress() {} - - public ZTSocketAddress(String ipStr, int port) - { - if(ipStr.contains(":")) { - _family = ZeroTier.AF_INET6; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip6 = ip.getAddress(); - } - catch (Exception e) { } - } - else if(ipStr.contains(".")) { - _family = ZeroTier.AF_INET; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip4 = ip.getAddress(); - } - catch (Exception e) { } - } - _port = port; - } - - public int getPort() { return _port; } - public int getNetmask() { return _port; } - public int getPrefix() { return _port; } - - private String ipString() - { - if (_family == ZeroTier.AF_INET) { - try { - InetAddress inet = InetAddress.getByAddress(_ip4); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - if (_family == ZeroTier.AF_INET6) { - try { - InetAddress inet = InetAddress.getByAddress(_ip6); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - return ""; - } - - public String toString() { return ipString() + ":" + _port; } - public String toCIDR() { return ipString() + "/" + _port; } -} diff --git a/packages/android/app/src/main/java/ZeroTier.java b/packages/android/app/src/main/java/ZeroTier.java deleted file mode 100644 index 26e337b..0000000 --- a/packages/android/app/src/main/java/ZeroTier.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import java.net.*; - -public class ZeroTier { - - public static int AF_INET = 2; - public static int AF_INET6 = 30; - public static int SOCK_STREAM = 1; - public static int SOCK_DGRAM = 2; - public static int O_APPEND = 1024; - public static int O_NONBLOCK = 2048; - public static int O_ASYNC = 8192; - public static int O_DIRECT = 65536; - public static int O_NOATIME = 262144; - public static int F_GETFL = 3; - public static int F_SETFL = 4; - - public native void start(String homePath, boolean blocking); - public native void startjoin(String homePath, long nwid); - public native void stop(); - public native boolean core_running(); - public native boolean stack_running(); - public native boolean ready(); - public native int join(long nwid); - public native int leave(long nwid); - public native String get_path(); - public native long get_node_id(); - public native int get_num_assigned_addresses(long nwid); - public native boolean get_address_at_index(long nwid, int index, ZTSocketAddress addr); - public native boolean has_address(long nwid); - public native boolean get_address(long nwid, int address_family, ZTSocketAddress addr); - public native void get_6plane_addr(long nwid, long nodeId, ZTSocketAddress addr); - public native void get_rfc4193_addr(long nwid, long nodeId, ZTSocketAddress addr); - - public native int socket(int family, int type, int protocol); - public native int connect(int fd, ZTSocketAddress addr); - public native int bind(int fd, ZTSocketAddress addr); - public native int listen(int fd, int backlog); - public native int accept(int fd, ZTSocketAddress addr); - public native int accept4(int fd, String addr, int port); - public native int close(int fd); - public native int setsockopt(int fd, int level, int optname, int optval, int optlen); - public native int getsockopt(int fd, int level, int optname, int optval, int optlen); - public native int sendto(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int send(int fd, byte[] buf, int flags); - public native int recv(int fd, byte[] buf, int flags); - public native int recvfrom(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int read(int fd, byte[] buf); - public native int write(int fd, byte[] buf); - public native int shutdown(int fd, int how); - public native boolean getsockname(int fd, ZTSocketAddress addr); - public native int getpeername(int fd, ZTSocketAddress addr); - public native int fcntl(int sock, int cmd, int flag); - public native int select(int nfds, ZTFDSet readfds, ZTFDSet writefds, ZTFDSet exceptfds, int timeout_sec, int timeout_usec); -} \ No newline at end of file diff --git a/packages/android/app/src/main/java/com/example/zerotier/MainActivity.java b/packages/android/app/src/main/java/com/example/zerotier/MainActivity.java deleted file mode 100644 index 66ee81b..0000000 --- a/packages/android/app/src/main/java/com/example/zerotier/MainActivity.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.example.zerotier; - -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; -import android.widget.TextView; - -import com.zerotier.libzt.ZeroTier; -import com.zerotier.libzt.ZTSocketAddress; -import com.zerotier.libzt.ZTFDSet; - -public class MainActivity extends AppCompatActivity { - - // Used to load the 'native-lib' library on application startup. - static { - System.loadLibrary("zt"); - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - - final ZeroTier libzt = new ZeroTier(); - - new Thread(new Runnable() { - public void run() { - final String path = getApplicationContext().getFilesDir() + "/zerotier"; - long nwid = 0xac9afb023544b071L; - - // Test modes - boolean blocking_start_call = true; - boolean client_mode = false; - boolean tcp = false; - boolean loop = true; - - int fd = -1, client_fd = -1, err, r, w, length = 0, flags = 0; - byte[] rxBuffer; - byte[] txBuffer = "welcome to the machine".getBytes(); - String remoteAddrStr = "11.7.7.224"; - String localAddrStr = "1.2.3.4"; - int portNo = 4040; - - ZTSocketAddress remoteAddr, localAddr; - ZTSocketAddress sockname = new ZTSocketAddress(); - ZTSocketAddress addr = new ZTSocketAddress(); - - // METHOD 1 (easy) - // Blocking call that waits for all components of the service to start - System.out.println("Starting ZT service..."); - if (blocking_start_call) { - libzt.startjoin(path, nwid); - } - System.out.println("ZT service ready."); - - // Device/Node address info - System.out.println("path=" + libzt.get_path()); - long nodeId = libzt.get_node_id(); - System.out.println("nodeId=" + Long.toHexString(nodeId)); - int numAddresses = libzt.get_num_assigned_addresses(nwid); - System.out.println("this node has (" + numAddresses + ") assigned addresses on network " + Long.toHexString(nwid)); - for (int i=0; i - - - - - - - - - - diff --git a/packages/android/app/src/main/res/drawable/ic_launcher_background.xml b/packages/android/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index d5fccc5..0000000 --- a/packages/android/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/android/app/src/main/res/layout/activity_main.xml b/packages/android/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 7d8d24e..0000000 --- a/packages/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cf..0000000 --- a/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cf..0000000 --- a/packages/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f5908..0000000 Binary files a/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b52399..0000000 Binary files a/packages/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd..0000000 Binary files a/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c7..0000000 Binary files a/packages/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd8..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca60..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b41..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebd..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13..0000000 Binary files a/packages/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/packages/android/app/src/main/res/values/colors.xml b/packages/android/app/src/main/res/values/colors.xml deleted file mode 100644 index 3ab3e9c..0000000 --- a/packages/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/packages/android/app/src/main/res/values/strings.xml b/packages/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 87c6cc8..0000000 --- a/packages/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - ZeroTier - diff --git a/packages/android/app/src/main/res/values/styles.xml b/packages/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 5885930..0000000 --- a/packages/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/packages/android/app/src/test/java/com/example/zerotier/ExampleUnitTest.java b/packages/android/app/src/test/java/com/example/zerotier/ExampleUnitTest.java deleted file mode 100644 index f0aee30..0000000 --- a/packages/android/app/src/test/java/com/example/zerotier/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.zerotier; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/packages/android/build.gradle b/packages/android/build.gradle deleted file mode 100644 index 43c0708..0000000 --- a/packages/android/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - - repositories { - google() - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' - - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/packages/android/gradle.properties b/packages/android/gradle.properties deleted file mode 100644 index b2b3bb2..0000000 --- a/packages/android/gradle.properties +++ /dev/null @@ -1,13 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file diff --git a/packages/android/gradle/wrapper/gradle-wrapper.jar b/packages/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7a3265e..0000000 Binary files a/packages/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/packages/android/gradle/wrapper/gradle-wrapper.properties b/packages/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 3705bc5..0000000 --- a/packages/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Wed Jul 18 09:57:38 PDT 2018 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/packages/android/gradlew b/packages/android/gradlew deleted file mode 100755 index cccdd3d..0000000 --- a/packages/android/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/packages/android/gradlew.bat b/packages/android/gradlew.bat deleted file mode 100644 index e95643d..0000000 --- a/packages/android/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/packages/android/settings.gradle b/packages/android/settings.gradle deleted file mode 100644 index e7b4def..0000000 --- a/packages/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/packages/clean.bat b/packages/clean.bat deleted file mode 100644 index 6e337a8..0000000 --- a/packages/clean.bat +++ /dev/null @@ -1,4 +0,0 @@ -rd /S /Q bin -rd /S /Q build -rd /S /Q WinBuild32 -rd /S /Q WinBuild64 \ No newline at end of file diff --git a/packages/clean.sh b/packages/clean.sh deleted file mode 100755 index 65e8421..0000000 --- a/packages/clean.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -rm -rf bin build products tmp -rm -f *.o *.s *.exp *.lib .depend* *.core core -rm -rf .depend -find . -type f \( -name '*.o' -o -name '*.o.d' -o -name \ - '*.out' -o -name '*.log' -o -name '*.dSYM' -o -name '*.class' \) -delete diff --git a/packages/dist.bat b/packages/dist.bat deleted file mode 100644 index b82f883..0000000 --- a/packages/dist.bat +++ /dev/null @@ -1,88 +0,0 @@ -REM Build all target configurations and copy results into "prebuilt" - -set PrebuiltDebugWin32Dir=staging\debug\win32 -set PrebuiltDebugWin64Dir=staging\debug\win64 -set PrebuiltReleaseWin32Dir=staging\release\win32 -set PrebuiltReleaseWin64Dir=staging\release\win64 - -mkdir %PrebuiltDebugWin32Dir% -mkdir %PrebuiltDebugWin64Dir% -mkdir %PrebuiltReleaseWin32Dir% -mkdir %PrebuiltReleaseWin64Dir% - -set DebugWinBuildDir=bin\lib\Debug -set ReleaseWinBuildDir=bin\lib\Release - -mkdir WinBuild32 & pushd WinBuild32 -cmake -G "Visual Studio 15 2017" ../ -popd -mkdir WinBuild64 & pushd WinBuild64 -cmake -G "Visual Studio 15 2017 Win64" ../ -popd - -cmake --build WinBuild32 --config Release -cmake --build WinBuild32 --config Debug - -copy %DebugWinBuildDir%\zt-static.lib %PrebuiltDebugWin32Dir%\zt.lib -copy %DebugWinBuildDir%\zt-shared.dll %PrebuiltDebugWin32Dir%\zt.dll -copy %ReleaseWinBuildDir%\zt-static.lib %PrebuiltReleaseWin32Dir%\zt.lib -copy %ReleaseWinBuildDir%\zt-shared.dll %PrebuiltReleaseWin32Dir%\zt.dll - -cmake --build WinBuild64 --config Release -cmake --build WinBuild64 --config Debug - -copy %DebugWinBuildDir%\zt-static.lib %PrebuiltDebugWin64Dir%\zt.lib -copy %DebugWinBuildDir%\zt-shared.dll %PrebuiltDebugWin64Dir%\zt.dll -copy %ReleaseWinBuildDir%\zt-static.lib %PrebuiltReleaseWin64Dir%\zt.lib -copy %ReleaseWinBuildDir%\zt-shared.dll %PrebuiltReleaseWin64Dir%\zt.dll - -rd /S /Q bin - -# Build with JNI - -mkdir WinBuild32 & pushd WinBuild32 -cmake -D JNI:BOOL=ON -G "Visual Studio 15 2017" ../ -popd -mkdir WinBuild64 & pushd WinBuild64 -cmake -D JNI:BOOL=ON -G "Visual Studio 15 2017 Win64" ../ -popd - -cmake --build WinBuild32 --config Release -cmake --build WinBuild32 --config Debug - -REM Build JAR file -REM release variant -cd packages\java -del com/zerotier/libzt/*.class -move ..\..\%ReleaseWinBuildDir%\zt-shared.dll zt.dll -javac com/zerotier/libzt/*.java -jar cf zt.jar zt.dll com/zerotier/libzt/*.class -move zt.jar ..\..\%PrebuiltReleaseWin32Dir% -REM debug variant -del com/zerotier/libzt/*.class -move ..\..\%DebugWinBuildDir%\zt-shared.dll zt.dll -javac com/zerotier/libzt/*.java -jar cf zt.jar zt.dll com/zerotier/libzt/*.class -move zt.jar ..\..\%PrebuiltDebugWin32Dir% -popd -popd - -cmake --build WinBuild64 --config Release -cmake --build WinBuild64 --config Debug - -REM Build JAR file -REM release variant -cd packages\java -del com/zerotier/libzt/*.class -move ..\..\%ReleaseWinBuildDir%\zt-shared.dll zt.dll -javac com/zerotier/libzt/*.java -jar cf zt.jar zt.dll com/zerotier/libzt/*.class -move zt.jar ..\..\%PrebuiltReleaseWin64Dir% -REM debug variant -del com/zerotier/libzt/*.class -move ..\..\%DebugWinBuildDir%\zt-shared.dll zt.dll -javac com/zerotier/libzt/*.java -jar cf zt.jar zt.dll com/zerotier/libzt/*.class -move zt.jar ..\..\%PrebuiltDebugWin64Dir% -popd -popd \ No newline at end of file diff --git a/packages/dist.sh b/packages/dist.sh deleted file mode 100755 index 1afb6ec..0000000 --- a/packages/dist.sh +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash - -# Call this script from the root project directory via `make dist` -# - submodules will be recursively initialized and updated -# - patches will be applied to submodules if needed -# - this script will call CMake to generate library-building packages if necessary -# - once projects have been generated, this script will use their tooling to build the libraries/packages -# - when all products have been built and moved to `tmp`, they will be compressed and moved to `products` - -OSNAME=$(uname | tr '[A-Z]' '[a-z]') -BUILD_CONCURRENCY=4 -PROJROOT=$(pwd) -BUILD_PRODUCTS_DIR=$(pwd)/bin -LIB_PRODUCTS_DIR=$BUILD_PRODUCTS_DIR/lib -FINISHED_PRODUCTS_DIR=$(pwd)/products -STAGING_DIR=$(pwd)/staging -# Windows (previously built) -WIN_PREBUILT_DIR=$PROJROOT/staging/win -WIN_RELEASE_PRODUCTS_DIR=$WIN_PREBUILT_DIR/release -WIN_DEBUG_PRODUCTS_DIR=$WIN_PREBUILT_DIR/debug -WIN32_RELEASE_PRODUCTS_DIR=$WIN_RELEASE_PRODUCTS_DIR/win32 -WIN64_RELEASE_PRODUCTS_DIR=$WIN_RELEASE_PRODUCTS_DIR/win64 -WIN32_DEBUG_PRODUCTS_DIR=$WIN_DEBUG_PRODUCTS_DIR/win32 -WIN64_DEBUG_PRODUCTS_DIR=$WIN_DEBUG_PRODUCTS_DIR/win64 -# Linux -LINUX_PROD_DIR=$PROJROOT/staging/linux -# macOS -MACOS_PROD_DIR=$PROJROOT/staging/macos -MACOS_RELEASE_PROD_DIR=$MACOS_PROD_DIR/release -MACOS_DEBUG_PROD_DIR=$MACOS_PROD_DIR/debug -# iOS -IOS_PROD_DIR=$PROJROOT/staging/ios -# Android -ANDROID_PROJ_DIR=$(pwd)/"packages/android" -ANDROID_ARCHIVE_FILENAME="zt.aar" -# Xcode -XCODE_IOS_PROJ_DIR=$(pwd)/"packages/xcode_ios" -XCODE_MACOS_PROJ_DIR=$(pwd)/"packages/xcode_macos" - -mkdir $FINISHED_PRODUCTS_DIR -mkdir $STAGING_DIR - -# Check that projects exist, generate them and exit if they don't exist -generate_projects_if_necessary() -{ - if [[ $OSNAME = *"darwin"* ]]; then - # iOS - if [ ! -d "$XCODE_IOS_PROJ_DIR" ]; then - echo "BUILDING: iOS project" - should_exit=1 - mkdir -p $XCODE_IOS_PROJ_DIR - cd $XCODE_IOS_PROJ_DIR - cmake -G Xcode ../../ - # Bug in CMake requires us to manually replace architecture strings in project file - sed -i '' 's/x86_64/$(CURRENT_ARCH)/g' $PROJNAME.xcodeproj/project.pbxproj - cd - - fi - # macOS - if [ ! -d "$XCODE_MACOS_PROJ_DIR" ]; then - echo "BUILDING: macOS project" - should_exit=1 - mkdir -p $XCODE_MACOS_PROJ_DIR - cd $XCODE_MACOS_PROJ_DIR - cmake -G Xcode ../../ - cd - - fi - # android? - if [[ $should_exit = 1 ]]; then - echo "Generated projects. Perform necessary modifications and then re-run this script" - echo "Please place previously built windows binaries in $WIN_PREBUILT_DIR before running again." - exit 0 - else - echo "Projects detected, going to build stage next" - fi - fi -} - -build_all_products() -{ - CONFIG=$1 - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - - # Targets to build on and for darwin - if [[ $OSNAME = *"darwin"* ]]; then - # Xcode Frameworks --- Builds targets from a CMake-generated Xcode project - if true; then - if [[ $2 != *"JNI"* ]]; then - CURR_BUILD_PRODUCTS_DIR=$LIB_PRODUCTS_DIR/$UPPERCASE_CONFIG - # (iOS) - echo "BUILDING: iOS" - cd $XCODE_IOS_PROJ_DIR - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "iphoneos" - xcodebuild -target zt-static -configuration "$UPPERCASE_CONFIG" -sdk "iphoneos" - cd - - CURR_ARCH="arm64" # spoof this architecture since HOSTTYPE is likely x86_64 - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/ios-$CURR_ARCH - mkdir -p $CURR_TMP_PRODUCT_DIR - mv $CURR_BUILD_PRODUCTS_DIR/*.framework $CURR_TMP_PRODUCT_DIR - mv $CURR_BUILD_PRODUCTS_DIR/libzt.* $CURR_TMP_PRODUCT_DIR - - # (macOS) - echo "BUILDING: macOS" - cd $XCODE_MACOS_PROJ_DIR - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "macosx" - xcodebuild -target zt-static -configuration "$UPPERCASE_CONFIG" -sdk "macosx" - xcodebuild -target zt-shared -configuration "$UPPERCASE_CONFIG" -sdk "macosx" - cd - - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/macos-$(uname -m) - mkdir -p $CURR_TMP_PRODUCT_DIR - mv $CURR_BUILD_PRODUCTS_DIR/*.framework $CURR_TMP_PRODUCT_DIR - mv $CURR_BUILD_PRODUCTS_DIR/libzt.* $CURR_TMP_PRODUCT_DIR - fi - fi - # Android Archive (AAR) --- Executes a Gradle task - if true; then - CMAKE_FLAGS=$CMAKE_FLAGS" -DJNI=1" - CURR_ARCH="armeabi-v7a" # spoof this architecture since HOSTTYPE is likely x86_64 - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/android-$CURR_ARCH - mkdir -p $CURR_TMP_PRODUCT_DIR - echo "BUILDING: AAR" - cd $ANDROID_PROJ_DIR - ./gradlew assemble$UPPERCASE_CONFIG # e.g. assembleRelease - mv $ANDROID_PROJ_DIR/app/build/outputs/aar/app-$CONFIG.aar $CURR_TMP_PRODUCT_DIR/$ANDROID_ARCHIVE_FILENAME - cd - - fi - # Java Archive (JAR) - if true; then - CURR_BUILD_PRODUCTS_DIR=$LIB_PRODUCTS_DIR - CMAKE_FLAGS=$CMAKE_FLAGS" -DJNI=1" - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/macos-$(uname -m) - mkdir -p $CURR_TMP_PRODUCT_DIR - echo "BUILDING: JAR" - rm -rf $LIB_PRODUCTS_DIR # clean-lite - cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=$CONFIG "-DJNI=1 -DBUILD_TESTS=0" - cmake --build build - cd $PROJROOT/packages/java - cp $CURR_BUILD_PRODUCTS_DIR/libzt.dylib . - javac com/zerotier/libzt/*.java - jar cf zt.jar libzt.dylib com/zerotier/libzt/*.class - rm libzt.dylib - mv zt.jar $CURR_TMP_PRODUCT_DIR - cd - - fi - fi - # Linux targets - if [[ $OSNAME = *"linux"* ]]; then - CURR_BUILD_PRODUCTS_DIR=$LIB_PRODUCTS_DIR - # Ordinary libraries - if true; then - rm -rf $LIB_PRODUCTS_DIR - cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=$CONFIG "-DBUILD_TESTS=0" - cmake --build build - # -j $BUILD_CONCURRENCY - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/linux-$(uname -m) - mkdir -p $CURR_TMP_PRODUCT_DIR - mv $CURR_BUILD_PRODUCTS_DIR/libzt.* $CURR_TMP_PRODUCT_DIR - fi - # Java JAR file - if true; then - rm -rf $LIB_PRODUCTS_DIR - cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=$CONFIG "-DJNI=1 -DBUILD_TESTS=0" - cmake --build build - # -j $BUILD_CONCURRENCY - CURR_TMP_PRODUCT_DIR=$STAGING_DIR/$CONFIG/linux-$(uname -m) - mkdir -p $CURR_TMP_PRODUCT_DIR - cd $PROJROOT/packages/java - cp $CURR_BUILD_PRODUCTS_DIR/libzt.so . - javac com/zerotier/libzt/*.java - jar cf zt.jar libzt.dylib com/zerotier/libzt/*.class - rm libzt.dylib - mv zt.jar $CURR_TMP_PRODUCT_DIR - cd - - fi - fi -} - -main() -{ - generate_projects_if_necessary - build_all_products "release" - build_all_products "debug" -} - -main "$@" \ No newline at end of file diff --git a/packages/java/com/zerotier/libzt/ZTFDSet.java b/packages/java/com/zerotier/libzt/ZTFDSet.java deleted file mode 100644 index cf5bd7b..0000000 --- a/packages/java/com/zerotier/libzt/ZTFDSet.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -public class ZTFDSet -{ - byte[] fds_bits = new byte[1024]; - - public void CLR(int fd) - { - fds_bits[fd] = 0x00; - } - - public boolean ISSET(int fd) - { - return fds_bits[fd] == 0x01; - } - - public void SET(int fd) - { - fds_bits[fd] = 0x01; - } - - public void ZERO() - { - for (int i=0; i<1024; i++) { - fds_bits[i] = 0x00; - } - } -} \ No newline at end of file diff --git a/packages/java/com/zerotier/libzt/ZTSocketAddress.java b/packages/java/com/zerotier/libzt/ZTSocketAddress.java deleted file mode 100644 index c922251..0000000 --- a/packages/java/com/zerotier/libzt/ZTSocketAddress.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import com.zerotier.libzt.ZeroTier; - -import java.net.InetAddress; - -// Designed to transport address information across the JNI boundary -public class ZTSocketAddress -{ - public byte[] _ip6 = new byte[16]; - public byte[] _ip4 = new byte[4]; - - public int _family; - public int _port; // Also reused for netmask or prefix - - public ZTSocketAddress() {} - - public ZTSocketAddress(String ipStr, int port) - { - if(ipStr.contains(":")) { - _family = ZeroTier.AF_INET6; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip6 = ip.getAddress(); - } - catch (Exception e) { } - } - else if(ipStr.contains(".")) { - _family = ZeroTier.AF_INET; - try { - InetAddress ip = InetAddress.getByName(ipStr); - _ip4 = ip.getAddress(); - } - catch (Exception e) { } - } - _port = port; - } - - public int getPort() { return _port; } - public int getNetmask() { return _port; } - public int getPrefix() { return _port; } - - private String ipString() - { - if (_family == ZeroTier.AF_INET) { - try { - InetAddress inet = InetAddress.getByAddress(_ip4); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - if (_family == ZeroTier.AF_INET6) { - try { - InetAddress inet = InetAddress.getByAddress(_ip6); - return "" + inet.getHostAddress(); - } catch (Exception e) { - System.out.println(e); - } - } - return ""; - } - - public String toString() { return ipString() + ":" + _port; } - public String toCIDR() { return ipString() + "/" + _port; } -} diff --git a/packages/java/com/zerotier/libzt/ZeroTier.java b/packages/java/com/zerotier/libzt/ZeroTier.java deleted file mode 100644 index 26e337b..0000000 --- a/packages/java/com/zerotier/libzt/ZeroTier.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -package com.zerotier.libzt; - -import java.net.*; - -public class ZeroTier { - - public static int AF_INET = 2; - public static int AF_INET6 = 30; - public static int SOCK_STREAM = 1; - public static int SOCK_DGRAM = 2; - public static int O_APPEND = 1024; - public static int O_NONBLOCK = 2048; - public static int O_ASYNC = 8192; - public static int O_DIRECT = 65536; - public static int O_NOATIME = 262144; - public static int F_GETFL = 3; - public static int F_SETFL = 4; - - public native void start(String homePath, boolean blocking); - public native void startjoin(String homePath, long nwid); - public native void stop(); - public native boolean core_running(); - public native boolean stack_running(); - public native boolean ready(); - public native int join(long nwid); - public native int leave(long nwid); - public native String get_path(); - public native long get_node_id(); - public native int get_num_assigned_addresses(long nwid); - public native boolean get_address_at_index(long nwid, int index, ZTSocketAddress addr); - public native boolean has_address(long nwid); - public native boolean get_address(long nwid, int address_family, ZTSocketAddress addr); - public native void get_6plane_addr(long nwid, long nodeId, ZTSocketAddress addr); - public native void get_rfc4193_addr(long nwid, long nodeId, ZTSocketAddress addr); - - public native int socket(int family, int type, int protocol); - public native int connect(int fd, ZTSocketAddress addr); - public native int bind(int fd, ZTSocketAddress addr); - public native int listen(int fd, int backlog); - public native int accept(int fd, ZTSocketAddress addr); - public native int accept4(int fd, String addr, int port); - public native int close(int fd); - public native int setsockopt(int fd, int level, int optname, int optval, int optlen); - public native int getsockopt(int fd, int level, int optname, int optval, int optlen); - public native int sendto(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int send(int fd, byte[] buf, int flags); - public native int recv(int fd, byte[] buf, int flags); - public native int recvfrom(int fd, byte[] buf, int flags, ZTSocketAddress addr); - public native int read(int fd, byte[] buf); - public native int write(int fd, byte[] buf); - public native int shutdown(int fd, int how); - public native boolean getsockname(int fd, ZTSocketAddress addr); - public native int getpeername(int fd, ZTSocketAddress addr); - public native int fcntl(int sock, int cmd, int flag); - public native int select(int nfds, ZTFDSet readfds, ZTFDSet writefds, ZTFDSet exceptfds, int timeout_sec, int timeout_usec); -} \ No newline at end of file diff --git a/packages/module.modulemap b/packages/module.modulemap deleted file mode 100644 index 2fd95d7..0000000 --- a/packages/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module zt { - umbrella header "Xcode-Bridging-Header.h" - - export * - module * { export * } -} diff --git a/packages/package.sh b/packages/package.sh deleted file mode 100755 index 011c29b..0000000 --- a/packages/package.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -PROJNAME="zt" -LIBNAME="lib"$PROJNAME -LIBZT_VERSION="1.2.0" -LIBZT_REVISION="1" -ZT_CORE_VERSION="1.2.12" -FILENAME_PREFIX=${LIBNAME} - -STAGING_DIR=$(pwd)/staging -STAGING_DEBUG_DIR=$(pwd)/staging/debug -STAGING_RELEASE_DIR=$(pwd)/staging/release -FINISHED_PRODUCTS_DIR=$(pwd)/products - -# Clean before zipping -find . -type f \( -name '*.DS_Store' -o -name 'thumbs.db' \) -delete - -# Emit a README file -echo $'* libzt version: '${LIBZT_VERSION}$'r'${LIBZT_REVISION}$'\n* Core ZeroTier version: '${ZT_CORE_VERSION}$'\n* Date: '$(date)$'\n\nZeroTier Manual: https://www.zerotier.com/manual.shtml\n -Other Downloads: https://www.zerotier.com/download.shtml -\nlibzt Repo: https://github.com/zerotier/libzt\n\nFor more assistance, visit https://my.zerotier.com and ask your question in our Community section' > ${STAGING_DIR}/README.md - -cp ${STAGING_DIR}/README.md ${STAGING_DIR}/debug/README.md -cp ${STAGING_DIR}/README.md ${STAGING_DIR}/release/README.md - -# Package everything together -# (debug) -PRODUCT_FILENAME=${FILENAME_PREFIX}-debug.tar.gz -echo "Making: " ${FINISHED_PRODUCTS_DIR}/${PRODUCT_FILENAME} -cd ${STAGING_DEBUG_DIR} -tar --exclude=${PRODUCT_FILENAME} -zcvf ${PRODUCT_FILENAME} . -md5 $PRODUCT_FILENAME -mv *.tar.gz ${FINISHED_PRODUCTS_DIR} -cd - - -# (release) -PRODUCT_FILENAME=${FILENAME_PREFIX}-release.tar.gz -echo "Making: " ${FINISHED_PRODUCTS_DIR}/${PRODUCT_FILENAME} -cd ${STAGING_RELEASE_DIR} -tar --exclude=${PRODUCT_FILENAME} -zcvf ${PRODUCT_FILENAME} . -md5 $PRODUCT_FILENAME -mv *.tar.gz ${FINISHED_PRODUCTS_DIR} -cd - \ No newline at end of file diff --git a/packages/pypi/LICENSE.txt b/packages/pypi/LICENSE.txt deleted file mode 100644 index 94a9ed0..0000000 --- a/packages/pypi/LICENSE.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/packages/pypi/MANIFEST.in b/packages/pypi/MANIFEST.in deleted file mode 100644 index e246643..0000000 --- a/packages/pypi/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -# file GENERATED by distutils, do NOT edit -README.rst -setup.cfg -setup.py -#recursive-include ../../src *.c -recursive-include ../../src *.cpp -recursive-include ../../include *.h -#recursive-include ../../include *.hpp -include libhttp.a -include liblwip.a -include http.lib -include lwip.lib \ No newline at end of file diff --git a/packages/pypi/Makefile b/packages/pypi/Makefile deleted file mode 100644 index 5276ded..0000000 --- a/packages/pypi/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# generate a new wrapper *.cxx from the *.i interface file -wrapper: - swig -c++ -python libzt.i - -# build and package a binary distribution -bdist: - cd ../../; cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=DEBUG - cd ../../; cmake --build build - cp ../../bin/lib/*.a . - python3 setup.py bdist_wheel - -# upload to PyPI -upload: - twine upload dist/* - -clean: - rm -rf *.a - rm -rf build - rm -rf dist - rm -rf libzt.egg-info diff --git a/packages/pypi/README.md b/packages/pypi/README.md deleted file mode 100644 index 3044a33..0000000 --- a/packages/pypi/README.md +++ /dev/null @@ -1,67 +0,0 @@ -## libzt PyPI Package -[pypi/libzt](https://pypi.python.org/pypi/libzt) -*** - -## Getting started - -`pip3 install libzt` - -``` -import libzt -import time - -print('joining virtual network...') -libzt.zts_startjoin('whatev_config', 0x123456789ABCDEF1) -print('fd = ' + str(libzt.zts_socket(1,2,3))) - -print('looping forever, ping me') -while True: - time.sleep(1) -``` - -## Building - - - install SWIG - - `make wrapper` - -### macOS, Linux - -Binary distribution: - -make bdist - -Alternatively, source Distribution: - -make sdist - -Upload to PyPI: - -make upload - -Cleanup: - -make clean - -### Windows - -Binary distribution: - -bdist.bat - -Source distribution: - -sdist.bat - -Upload to PyPI: - -upload.bat - -Cleanup: - -clean.bat - -## Installing from a locally-built package/wheel - - - `pip3 install dist/.whl` - -*Note: As there appears to be no way to differentiate C and C++ code (and thus pass correct build args to each type) in a setuptools script we must separately build the `lwip` and `http_parser` libraries, copy them here, and then build the binary. See the top-level [README.md](../../README.md) for instructions on how to do that* diff --git a/packages/pypi/README.rst b/packages/pypi/README.rst deleted file mode 100644 index 6af85d2..0000000 --- a/packages/pypi/README.rst +++ /dev/null @@ -1,8 +0,0 @@ -# libzt -*ZeroTier: Encrypted P2P communication between apps and services* -*** - -A library version of [ZeroTier](https://github.com/zerotier/ZeroTierOne), **libzt** makes it easy to securely connect devices, servers, cloud VMs, containers, and apps everywhere and manage them at scale. Now you can bake this ability directly into your app or service using your preferred language. We provide a POSIX-like socket API supporting `SOCK_STREAM`, `SOCK_DGRAM`, and `SOCK_RAW` to make the integration simple. There's no need for system-wide virtual interfaces. This connection is exclusive to your app and fully encrypted via the [Salsa20](https://en.wikipedia.org/wiki/Salsa20) cipher. For a more in-depth discussion on the technical side of ZeroTier, check out our [Manual](https://www.zerotier.com/manual.shtml?pk_campaign=github_libzt) - -### Commercial License - - To be released from GPLv3, contact us directly via `contact@zerotier.com` for commercial licensing. diff --git a/packages/pypi/libzt.i b/packages/pypi/libzt.i deleted file mode 100644 index ab6efe4..0000000 --- a/packages/pypi/libzt.i +++ /dev/null @@ -1,136 +0,0 @@ - /* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -%module libzt - -%include "stdint.i" - -%{ -#define SWIG_FILE_WITH_INIT -#include "../../include/libzt.h" -%} - -int zts_start(const char *path, bool blocking); - -int zts_startjoin(const char *path, const uint64_t nwid); - -void zts_stop(); - -int zts_core_running(); - -int zts_stack_running(); - -int zts_ready(); - -int zts_join(const uint64_t nwid); - -int zts_leave(const uint64_t nwid); - -void zts_get_path(char *homePath, const size_t len); - -uint64_t zts_get_node_id(); - -uint64_t zts_get_node_id_from_file(const char *filepath); - -int zts_has_address(const uint64_t nwid); - -int zts_get_num_assigned_addresses(const uint64_t nwid); - -int zts_get_address_at_index( - const uint64_t nwid, const int index, struct sockaddr_storage *addr); - -int zts_get_address( - const uint64_t nwid, struct sockaddr_storage *addr, const int address_family); - -void zts_get_6plane_addr( - struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); - -void zts_get_rfc4193_addr( - struct sockaddr_storage *addr, const uint64_t nwid, const uint64_t nodeId); - -unsigned long zts_get_peer_count(); - -int zts_get_peer_address(char *peer, const uint64_t nodeId); - -int zts_socket(int socket_family, int socket_type, int protocol); - -int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); - -int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); - -int zts_listen(int fd, int backlog); - -int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen); - -int zts_setsockopt( - int fd, int level, int optname, const void *optval, socklen_t optlen); - -int zts_getsockopt( - int fd, int level, int optname, void *optval, socklen_t *optlen); - -int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); - -int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); - -int zts_gethostname(char *name, size_t len); - -int zts_sethostname(const char *name, size_t len); - -struct hostent *zts_gethostbyname(const char *name); - -int zts_close(int fd); - -int zts_select( - int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); - -int zts_fcntl(int fd, int cmd, int flags); - -int zts_ioctl(int fd, unsigned long request, void *argp); - -ssize_t zts_send(int fd, const void *buf, size_t len, int flags); - -ssize_t zts_sendto( - int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen); - -ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags); - -ssize_t zts_recv(int fd, void *buf, size_t len, int flags); - -ssize_t zts_recvfrom( - int fd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen); - -ssize_t zts_recvmsg(int fd, struct msghdr *msg,int flags); - -int zts_read(int fd, void *buf, size_t len); - -int zts_write(int fd, const void *buf, size_t len); - -int zts_shutdown(int fd, int how); - -int zts_add_dns_nameserver(struct sockaddr *addr); - -int zts_del_dns_nameserver(struct sockaddr *addr); - diff --git a/packages/pypi/libzt.py b/packages/pypi/libzt.py deleted file mode 100644 index 267f62b..0000000 --- a/packages/pypi/libzt.py +++ /dev/null @@ -1,380 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 3.0.12 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - -from sys import version_info as _swig_python_version_info -if _swig_python_version_info >= (2, 7, 0): - def swig_import_helper(): - import importlib - pkg = __name__.rpartition('.')[0] - mname = '.'.join((pkg, '_libzt')).lstrip('.') - try: - return importlib.import_module(mname) - except ImportError: - return importlib.import_module('_libzt') - _libzt = swig_import_helper() - del swig_import_helper -elif _swig_python_version_info >= (2, 6, 0): - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_libzt', [dirname(__file__)]) - except ImportError: - import _libzt - return _libzt - try: - _mod = imp.load_module('_libzt', fp, pathname, description) - finally: - if fp is not None: - fp.close() - return _mod - _libzt = swig_import_helper() - del swig_import_helper -else: - import _libzt -del _swig_python_version_info - -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. - -try: - import builtins as __builtin__ -except ImportError: - import __builtin__ - -def _swig_setattr_nondynamic(self, class_type, name, value, static=1): - if (name == "thisown"): - return self.this.own(value) - if (name == "this"): - if type(value).__name__ == 'SwigPyObject': - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name, None) - if method: - return method(self, value) - if (not static): - if _newclass: - object.__setattr__(self, name, value) - else: - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - - -def _swig_setattr(self, class_type, name, value): - return _swig_setattr_nondynamic(self, class_type, name, value, 0) - - -def _swig_getattr(self, class_type, name): - if (name == "thisown"): - return self.this.own() - method = class_type.__swig_getmethods__.get(name, None) - if method: - return method(self) - raise AttributeError("'%s' object has no attribute '%s'" % (class_type.__name__, name)) - - -def _swig_repr(self): - try: - strthis = "proxy of " + self.this.__repr__() - except __builtin__.Exception: - strthis = "" - return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) - -try: - _object = object - _newclass = 1 -except __builtin__.Exception: - class _object: - pass - _newclass = 0 - - - - - -class libztSocket: - def __init__(self, _fd, _family, _type, _proto): - self.fd = _fd - self.family = _family - self.type = _type - self.proto = _proto - - # object-centric wrpper for calls so we can have a more "pythonic" experience - def connect(self, address): - addrlen = 0 - return _libzt.zts_connect(self.fd, address, addrlen) - - def connect(self, address): - return - - def connect_ex(self, address): - return - - def getpeername(): - return - - def getsockname(): - return - - def getsockopt(level, optname, buflen): - return - - def fcntl(fd, cmd, flags): - return _libzt.zts_fcntl(self.fd, cmd, flags) - - def ioctl(control, option): - return - - def listen(): - return _libzt.zts_listen(fd, backlog) - - def accept(): - return - - def bind(address): - return - - def close(self): - zts_close(self.fd) - - def recvfrom(bufsz, flags): - return - - def recv(bufsz, flags): - return - - def recvmsg(bufsz, ancillarybufsz, flags): - return - - def send(bytes, flags): - return - - def sendall(bytes, flags): - return - - def sendto(bytes, address): - return - - def sendto(bytes, flags, address): - return - - def sendmsg(buffers, ancdata, flags, address): - return - - def setblocking(flag): - return - - def setsockopt(level, optname, int): - return - - def setsockopt(level, optname, buffer): - return - - def shutdown(how): - return _libzt.zts_shutdown(self.fd, how) - - -def zts_socket(socket_family, socket_type, socket_protocol): - fd = _libzt.zts_socket(socket_family, socket_type, socket_protocol) - return libztSocket(fd, socket_family, socket_type, socket_protocol) - - - -""" ZeroTier Control API """ - -def zts_start(path, blocking): - return _libzt.zts_start(path, blocking) -zts_start = _libzt.zts_start - -def zts_startjoin(path, nwid): - return _libzt.zts_startjoin(path, nwid) -zts_startjoin = _libzt.zts_startjoin - -def zts_stop(): - return _libzt.zts_stop() -zts_stop = _libzt.zts_stop - -def zts_core_running(): - return _libzt.zts_core_running() -zts_core_running = _libzt.zts_core_running - -def zts_stack_running(): - return _libzt.zts_stack_running() -zts_stack_running = _libzt.zts_stack_running - -def zts_ready(): - return _libzt.zts_ready() -zts_ready = _libzt.zts_ready - -def zts_join(nwid): - return _libzt.zts_join(nwid) -zts_join = _libzt.zts_join - -def zts_leave(nwid): - return _libzt.zts_leave(nwid) -zts_leave = _libzt.zts_leave - -def zts_get_path(homePath, len): - return _libzt.zts_get_path(homePath, len) -zts_get_path = _libzt.zts_get_path - -def zts_get_node_id(): - return _libzt.zts_get_node_id() -zts_get_node_id = _libzt.zts_get_node_id - -def zts_get_node_id_from_file(filepath): - return _libzt.zts_get_node_id_from_file(filepath) -zts_get_node_id_from_file = _libzt.zts_get_node_id_from_file - -def zts_has_address(nwid): - return _libzt.zts_has_address(nwid) -zts_has_address = _libzt.zts_has_address - -def zts_get_num_assigned_addresses(nwid): - return _libzt.zts_get_num_assigned_addresses(nwid) -zts_get_num_assigned_addresses = _libzt.zts_get_num_assigned_addresses - -def zts_get_address_at_index(nwid, index, addr): - return _libzt.zts_get_address_at_index(nwid, index, addr) -zts_get_address_at_index = _libzt.zts_get_address_at_index - -def zts_get_address(nwid, addr, address_family): - return _libzt.zts_get_address(nwid, addr, address_family) -zts_get_address = _libzt.zts_get_address - -def zts_get_6plane_addr(addr, nwid, nodeId): - return _libzt.zts_get_6plane_addr(addr, nwid, nodeId) -zts_get_6plane_addr = _libzt.zts_get_6plane_addr - -def zts_get_rfc4193_addr(addr, nwid, nodeId): - return _libzt.zts_get_rfc4193_addr(addr, nwid, nodeId) -zts_get_rfc4193_addr = _libzt.zts_get_rfc4193_addr - -def zts_get_peer_count(): - return _libzt.zts_get_peer_count() -zts_get_peer_count = _libzt.zts_get_peer_count - -def zts_get_peer_address(peer, nodeId): - return _libzt.zts_get_peer_address(peer, nodeId) -zts_get_peer_address = _libzt.zts_get_peer_address - - -""" Socket-Layer Control API """ - -#def zts_socket(socket_family, socket_type, protocol): -# return _libzt.zts_socket(socket_family, socket_type, protocol) -#zts_socket = _libzt.zts_socket - -def zts_connect(fd, addr, addrlen): - return _libzt.zts_connect(fd, addr, addrlen) -zts_connect = _libzt.zts_connect - -def zts_bind(fd, addr, addrlen): - return _libzt.zts_bind(fd, addr, addrlen) -zts_bind = _libzt.zts_bind - -#def zts_listen(fd, backlog): -# return _libzt.zts_listen(fd, backlog) -#zts_listen = _libzt.zts_listen - -def zts_accept(fd, addr, addrlen): - return _libzt.zts_accept(fd, addr, addrlen) -zts_accept = _libzt.zts_accept - -def zts_setsockopt(fd, level, optname, optval, optlen): - return _libzt.zts_setsockopt(fd, level, optname, optval, optlen) -zts_setsockopt = _libzt.zts_setsockopt - -def zts_getsockopt(fd, level, optname, optval, optlen): - return _libzt.zts_getsockopt(fd, level, optname, optval, optlen) -zts_getsockopt = _libzt.zts_getsockopt - -def zts_getsockname(fd, addr, addrlen): - return _libzt.zts_getsockname(fd, addr, addrlen) -zts_getsockname = _libzt.zts_getsockname - -def zts_getpeername(fd, addr, addrlen): - return _libzt.zts_getpeername(fd, addr, addrlen) -zts_getpeername = _libzt.zts_getpeername - -def zts_gethostname(name, len): - return _libzt.zts_gethostname(name, len) -zts_gethostname = _libzt.zts_gethostname - -def zts_sethostname(name, len): - return _libzt.zts_sethostname(name, len) -zts_sethostname = _libzt.zts_sethostname - -def zts_gethostbyname(name): - return _libzt.zts_gethostbyname(name) -zts_gethostbyname = _libzt.zts_gethostbyname - -#def zts_close(fd): -# return _libzt.zts_close(fd) -#zts_close = _libzt.zts_close - -def zts_select(nfds, readfds, writefds, exceptfds, timeout): - return _libzt.zts_select(nfds, readfds, writefds, exceptfds, timeout) -zts_select = _libzt.zts_select - -#def zts_fcntl(fd, cmd, flags): -# return _libzt.zts_fcntl(fd, cmd, flags) -#zts_fcntl = _libzt.zts_fcntl - -def zts_ioctl(fd, request, argp): - return _libzt.zts_ioctl(fd, request, argp) -zts_ioctl = _libzt.zts_ioctl - -def zts_send(fd, buf, len, flags): - return _libzt.zts_send(fd, buf, len, flags) -zts_send = _libzt.zts_send - -def zts_sendto(fd, buf, len, flags, addr, addrlen): - return _libzt.zts_sendto(fd, buf, len, flags, addr, addrlen) -zts_sendto = _libzt.zts_sendto - -def zts_sendmsg(fd, msg, flags): - return _libzt.zts_sendmsg(fd, msg, flags) -zts_sendmsg = _libzt.zts_sendmsg - -def zts_recv(fd, buf, len, flags): - return _libzt.zts_recv(fd, buf, len, flags) -zts_recv = _libzt.zts_recv - -def zts_recvfrom(fd, buf, len, flags, addr, addrlen): - return _libzt.zts_recvfrom(fd, buf, len, flags, addr, addrlen) -zts_recvfrom = _libzt.zts_recvfrom - -def zts_recvmsg(fd, msg, flags): - return _libzt.zts_recvmsg(fd, msg, flags) -zts_recvmsg = _libzt.zts_recvmsg - -def zts_read(fd, buf, len): - return _libzt.zts_read(fd, buf, len) -zts_read = _libzt.zts_read - -def zts_write(fd, buf, len): - return _libzt.zts_write(fd, buf, len) -zts_write = _libzt.zts_write - -#def zts_shutdown(fd, how): -# return _libzt.zts_shutdown(fd, how) -#zts_shutdown = _libzt.zts_shutdown - -def zts_add_dns_nameserver(addr): - return _libzt.zts_add_dns_nameserver(addr) -zts_add_dns_nameserver = _libzt.zts_add_dns_nameserver - -def zts_del_dns_nameserver(addr): - return _libzt.zts_del_dns_nameserver(addr) -zts_del_dns_nameserver = _libzt.zts_del_dns_nameserver -# This file is compatible with both classic and new-style classes. - - diff --git a/packages/pypi/libzt/.gitignore b/packages/pypi/libzt/.gitignore deleted file mode 100644 index 5e7d273..0000000 --- a/packages/pypi/libzt/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/packages/pypi/libzt_wrap.cxx b/packages/pypi/libzt_wrap.cxx deleted file mode 100644 index d537c89..0000000 --- a/packages/pypi/libzt_wrap.cxx +++ /dev/null @@ -1,6003 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.12 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - - -#ifndef SWIGPYTHON -#define SWIGPYTHON -#endif - -#define SWIG_PYTHON_DIRECTOR_NO_VTABLE - - -#ifdef __cplusplus -/* SwigValueWrapper is described in swig.swg */ -template class SwigValueWrapper { - struct SwigMovePointer { - T *ptr; - SwigMovePointer(T *p) : ptr(p) { } - ~SwigMovePointer() { delete ptr; } - SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } - } pointer; - SwigValueWrapper& operator=(const SwigValueWrapper& rhs); - SwigValueWrapper(const SwigValueWrapper& rhs); -public: - SwigValueWrapper() : pointer(0) { } - SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } - operator T&() const { return *pointer.ptr; } - T *operator&() { return pointer.ptr; } -}; - -template T SwigValueInit() { - return T(); -} -#endif - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if defined(__GNUC__) -# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - -/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ -#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) -# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 -#endif - -/* Intel's compiler complains if a variable which was never initialised is - * cast to void, which is a common idiom which we use to indicate that we - * are aware a variable isn't used. So we just silence that warning. - * See: https://github.com/swig/swig/issues/192 for more discussion. - */ -#ifdef __INTEL_COMPILER -# pragma warning disable 592 -#endif - - -#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) -/* Use debug wrappers with the Python release dll */ -# undef _DEBUG -# include -# define _DEBUG -#else -# include -#endif - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return an integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast(r) (r) -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCmp(const char *nb, const char *tb) { - int equiv = 1; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (equiv != 0 && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = SWIG_TypeNameComp(nb, ne, tb, te); - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; -} - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - size_t l = 0; - size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - const unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - char d = *(c++); - unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = (unsigned char)((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = (unsigned char)((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (unsigned char)(d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (unsigned char)(d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) -#define PyString_Check(name) PyBytes_Check(name) -#define PyString_FromString(x) PyUnicode_FromString(x) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) -#define PyString_AsString(str) PyBytes_AsString(str) -#define PyString_Size(str) PyBytes_Size(str) -#define PyString_InternFromString(key) PyUnicode_InternFromString(key) -#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE -#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) -#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intintargfunc ssizessizeargfunc; -typedef intobjargproc ssizeobjargproc; -typedef intintobjargproc ssizessizeobjargproc; -typedef getreadbufferproc readbufferproc; -typedef getwritebufferproc writebufferproc; -typedef getsegcountproc segcountproc; -typedef getcharbufferproc charbufferproc; -static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) -{ - long result = 0; - PyObject *i = PyNumber_Int(x); - if (i) { - result = PyInt_AsLong(i); - Py_DECREF(i); - } - return result; -} -#endif - -#if PY_VERSION_HEX < 0x02050000 -#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) -#endif - -#if PY_VERSION_HEX < 0x02040000 -#define Py_VISIT(op) \ - do { \ - if (op) { \ - int vret = visit((op), arg); \ - if (vret) \ - return vret; \ - } \ - } while (0) -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef struct { - PyTypeObject type; - PyNumberMethods as_number; - PyMappingMethods as_mapping; - PySequenceMethods as_sequence; - PyBufferProcs as_buffer; - PyObject *name, *slots; -} PyHeapTypeObject; -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef destructor freefunc; -#endif - -#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ - (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ - (PY_MAJOR_VERSION > 3)) -# define SWIGPY_USE_CAPSULE -# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) -#endif - -#if PY_VERSION_HEX < 0x03020000 -#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) -#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) -#define Py_hash_t long -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -#if PY_VERSION_HEX >= 0x03000000 -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) -{ - return PyInstanceMethod_New(func); -} -#else -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) -{ - return NULL; -} -#endif - -#ifdef __cplusplus -} -#endif - - -/* ----------------------------------------------------------------------------- - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) - -#ifdef SWIGPYTHON_BUILTIN -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) -#else -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) -#endif - -#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) - -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -#if defined(SWIGPYTHON_BUILTIN) - -SWIGINTERN void -SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { - PyObject *s = PyString_InternFromString(key); - PyList_Append(seq, s); - Py_DECREF(s); -} - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); - if (public_interface) - SwigPyBuiltin_AddPublicSymbol(public_interface, name); -} - -#else - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); -} - -#endif - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN Py_ssize_t -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - if (min <= 1 && max >= 1) { - Py_ssize_t i; - objs[0] = args; - for (i = 1; i < max; ++i) { - objs[i] = 0; - } - return 2; - } - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - Py_ssize_t i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) -#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) - -#ifdef __cplusplus -extern "C" { -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; - PyTypeObject *pytype; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - data->pytype = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData *data) { - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -#ifdef SWIGPYTHON_BUILTIN - PyObject *dict; -#endif -} SwigPyObject; - - -#ifdef SWIGPYTHON_BUILTIN - -SWIGRUNTIME PyObject * -SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) -{ - SwigPyObject *sobj = (SwigPyObject *)v; - - if (!sobj->dict) - sobj->dict = PyDict_New(); - - Py_INCREF(sobj->dict); - return sobj->dict; -} - -#endif - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); - if (v->next) { -# ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -# else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -# endif -# if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -# else - PyString_ConcatAndDel(&repr,nrep); -# endif - } - return repr; -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); - return res; -} - - -SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); - -#ifdef SWIGPYTHON_BUILTIN -static swig_type_info *SwigPyObject_stype = 0; -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - SwigPyClientData *cd; - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - assert(cd); - assert(cd->pytype); - return cd->pytype; -} -#else -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); - return type; -} -#endif - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { -#ifdef SWIGPYTHON_BUILTIN - PyTypeObject *target_tp = SwigPyObject_type(); - if (PyType_IsSubtype(op->ob_type, target_tp)) - return 1; - return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); -#else - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -#endif -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - - /* PyObject_CallFunction() has the potential to silently drop - the active active exception. In cases of unnamed temporary - variable or where we just finished iterating over a generator - StopIteration will be active right now, and this needs to - remain true upon return from SwigPyObject_dealloc. So save - and restore. */ - - PyObject *val = NULL, *type = NULL, *tb = NULL; - PyErr_Fetch(&val, &type, &tb); - - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - if (!res) - PyErr_WriteUnraisable(destroy); - - PyErr_Restore(val, type, tb); - - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#elif (PY_VERSION_HEX < 0x02050000) - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#else - if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -SwigPyObject_TypeOnce(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ -#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpyobject_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpyobject_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpyobject_type) < 0) - return NULL; -#endif - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == SwigPyPacked_TypeOnce()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_TypeOnce(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpypacked_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpypacked_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpypacked_type) < 0) - return NULL; -#endif - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -static PyObject *swig_this = NULL; - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - if (swig_this == NULL) - swig_this = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - PyObject *obj; - - if (SwigPyObject_Check(pyobj)) - return (SwigPyObject *) pyobj; - -#ifdef SWIGPYTHON_BUILTIN - (void)obj; -# ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - pyobj = PyWeakref_GET_OBJECT(pyobj); - if (pyobj && SwigPyObject_Check(pyobj)) - return (SwigPyObject*) pyobj; - } -# endif - return NULL; -#else - - obj = 0; - -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; -#endif -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - int res; - SwigPyObject *sobj; - int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; - - if (!obj) - return SWIG_ERROR; - if (obj == Py_None && !implicit_conv) { - if (ptr) - *ptr = 0; - return SWIG_OK; - } - - res = SWIG_ERROR; - - sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - res = SWIG_OK; - } else { - if (implicit_conv) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - if (!SWIG_IsOK(res) && obj == Py_None) { - if (ptr) - *ptr = 0; - if (PyErr_Occurred()) - PyErr_Clear(); - res = SWIG_OK; - } - } - return res; -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - if (inst) { - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; - } -#else - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst = 0; - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { - SwigPyClientData *clientdata; - PyObject * robj; - int own; - - if (!ptr) - return SWIG_Py_Void(); - - clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - if (clientdata && clientdata->pytype) { - SwigPyObject *newobj; - if (flags & SWIG_BUILTIN_TP_INIT) { - newobj = (SwigPyObject*) self; - if (newobj->ptr) { - PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); - while (newobj->next) - newobj = (SwigPyObject *) newobj->next; - newobj->next = next_self; - newobj = (SwigPyObject *)next_self; -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - } else { - newobj = PyObject_New(SwigPyObject, clientdata->pytype); -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - if (newobj) { - newobj->ptr = ptr; - newobj->ty = type; - newobj->own = own; - newobj->next = 0; - return (PyObject*) newobj; - } - return SWIG_Py_Void(); - } - - assert(!(flags & SWIG_BUILTIN_TP_INIT)); - - robj = SwigPyObject_New(ptr, type, own); - if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - Py_DECREF(robj); - robj = inst; - } - return robj; -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else -# ifdef SWIGPY_USE_CAPSULE - type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); -# else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); -# endif - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -#ifdef SWIGPY_USE_CAPSULE -SWIG_Python_DestroyModule(PyObject *obj) -#else -SWIG_Python_DestroyModule(void *vptr) -#endif -{ -#ifdef SWIGPY_USE_CAPSULE - swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); -#else - swig_module_info *swig_module = (swig_module_info *) vptr; -#endif - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); - swig_this = NULL; -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { -#if PY_VERSION_HEX >= 0x03000000 - /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); -#endif -#ifdef SWIGPY_USE_CAPSULE - PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#else - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#endif -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { -#ifdef SWIGPY_USE_CAPSULE - descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); -#else - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); -#endif - } else { - swig_module_info *swig_module = SWIG_GetModule(0); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { -#ifdef SWIGPY_USE_CAPSULE - obj = PyCapsule_New((void*) descriptor, NULL, NULL); -#else - obj = PyCObject_FromVoidPtr(descriptor, NULL); -#endif - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : ""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - -#ifdef SWIGPYTHON_BUILTIN -SWIGRUNTIME int -SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { - PyTypeObject *tp = obj->ob_type; - PyObject *descr; - PyObject *encoded_name; - descrsetfunc f; - int res = -1; - -# ifdef Py_USING_UNICODE - if (PyString_Check(name)) { - name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); - if (!name) - return -1; - } else if (!PyUnicode_Check(name)) -# else - if (!PyString_Check(name)) -# endif - { - PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); - return -1; - } else { - Py_INCREF(name); - } - - if (!tp->tp_dict) { - if (PyType_Ready(tp) < 0) - goto done; - } - - descr = _PyType_Lookup(tp, name); - f = NULL; - if (descr != NULL) - f = descr->ob_type->tp_descr_set; - if (!f) { - if (PyString_Check(name)) { - encoded_name = name; - Py_INCREF(name); - } else { - encoded_name = PyUnicode_AsUTF8String(name); - } - PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); - Py_DECREF(encoded_name); - } else { - res = f(descr, obj, value); - } - - done: - Py_DECREF(name); - return res; -} -#endif - - -#ifdef __cplusplus -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p_char swig_types[0] -#define SWIGTYPE_p_fd_set swig_types[1] -#define SWIGTYPE_p_hostent swig_types[2] -#define SWIGTYPE_p_int swig_types[3] -#define SWIGTYPE_p_long_long swig_types[4] -#define SWIGTYPE_p_msghdr swig_types[5] -#define SWIGTYPE_p_short swig_types[6] -#define SWIGTYPE_p_signed_char swig_types[7] -#define SWIGTYPE_p_sockaddr swig_types[8] -#define SWIGTYPE_p_sockaddr_storage swig_types[9] -#define SWIGTYPE_p_socklen_t swig_types[10] -#define SWIGTYPE_p_ssize_t swig_types[11] -#define SWIGTYPE_p_timeval swig_types[12] -#define SWIGTYPE_p_unsigned_char swig_types[13] -#define SWIGTYPE_p_unsigned_int swig_types[14] -#define SWIGTYPE_p_unsigned_long_long swig_types[15] -#define SWIGTYPE_p_unsigned_short swig_types[16] -static swig_type_info *swig_types[18]; -static swig_module_info swig_module = {swig_types, 17, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif - -/*----------------------------------------------- - @(target):= _libzt.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__libzt - -#else -# define SWIG_init init_libzt - -#endif -#define SWIG_name "libzt" - -#define SWIGVERSION 0x030012 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) - - -#include - - -namespace swig { - class SwigPtr_PyObject { - protected: - PyObject *_obj; - - public: - SwigPtr_PyObject() :_obj(0) - { - } - - SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj) - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - - SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj) - { - if (initial_ref) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - } - - SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(item._obj); - Py_XDECREF(_obj); - _obj = item._obj; - SWIG_PYTHON_THREAD_END_BLOCK; - return *this; - } - - ~SwigPtr_PyObject() - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XDECREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - - operator PyObject *() const - { - return _obj; - } - - PyObject *operator->() const - { - return _obj; - } - }; -} - - -namespace swig { - struct SwigVar_PyObject : SwigPtr_PyObject { - SwigVar_PyObject(PyObject* obj = 0) : SwigPtr_PyObject(obj, false) { } - - SwigVar_PyObject & operator = (PyObject* obj) - { - Py_XDECREF(_obj); - _obj = obj; - return *this; - } - }; -} - - -#include // Use the C99 official header - - -#define SWIG_FILE_WITH_INIT -#include "../../include/libzt.h" - - -SWIGINTERN swig_type_info* -SWIG_pchar_descriptor(void) -{ - static int init = 0; - static swig_type_info* info = 0; - if (!init) { - info = SWIG_TypeQuery("_p_char"); - init = 1; - } - return info; -} - - -SWIGINTERN int -SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) -{ -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (PyBytes_Check(obj)) -#else - if (PyUnicode_Check(obj)) -#endif -#else - if (PyString_Check(obj)) -#endif - { - char *cstr; Py_ssize_t len; -#if PY_VERSION_HEX>=0x03000000 -#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (!alloc && cptr) { - /* We can't allow converting without allocation, since the internal - representation of string in Python 3 is UCS-2/UCS-4 but we require - a UTF-8 representation. - TODO(bhy) More detailed explanation */ - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if(alloc) *alloc = SWIG_NEWOBJ; -#endif - PyBytes_AsStringAndSize(obj, &cstr, &len); -#else - PyString_AsStringAndSize(obj, &cstr, &len); -#endif - if (cptr) { - if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -#else - if (*alloc == SWIG_NEWOBJ) -#endif - { - *cptr = reinterpret_cast< char* >(memcpy(new char[len + 1], cstr, sizeof(char)*(len + 1))); - *alloc = SWIG_NEWOBJ; - } else { - *cptr = cstr; - *alloc = SWIG_OLDOBJ; - } - } else { -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - *cptr = PyBytes_AsString(obj); -#else - assert(0); /* Should never reach here with Unicode strings in Python 3 */ -#endif -#else - *cptr = SWIG_Python_str_AsChar(obj); -#endif - } - } - if (psize) *psize = len + 1; -#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - Py_XDECREF(obj); -#endif - return SWIG_OK; - } else { -#if defined(SWIG_PYTHON_2_UNICODE) -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) -#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once" -#endif -#if PY_VERSION_HEX<0x03000000 - if (PyUnicode_Check(obj)) { - char *cstr; Py_ssize_t len; - if (!alloc && cptr) { - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { - if (cptr) { - if (alloc) *alloc = SWIG_NEWOBJ; - *cptr = reinterpret_cast< char* >(memcpy(new char[len + 1], cstr, sizeof(char)*(len + 1))); - } - if (psize) *psize = len + 1; - - Py_XDECREF(obj); - return SWIG_OK; - } else { - Py_XDECREF(obj); - } - } -#endif -#endif - - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { - void* vptr = 0; - if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { - if (cptr) *cptr = (char *) vptr; - if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; - if (alloc) *alloc = SWIG_OLDOBJ; - return SWIG_OK; - } - } - } - return SWIG_TypeError; -} - - - - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; -#if PY_VERSION_HEX < 0x03000000 - } else if (PyInt_Check(obj)) { - if (val) *val = (double) PyInt_AsLong(obj); - return SWIG_OK; -#endif - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_long (PyObject *obj, long* val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else -#endif - if (PyLong_Check(obj)) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - long v = PyInt_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { - if (val) *val = (long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_bool (PyObject *obj, bool *val) -{ - int r; - if (!PyBool_Check(obj)) - return SWIG_ERROR; - r = PyObject_IsTrue(obj); - if (r == -1) - return SWIG_ERROR; - if (val) *val = r ? true : false; - return SWIG_OK; -} - - -SWIGINTERNINLINE PyObject* - SWIG_From_int (int value) -{ - return PyInt_FromLong((long) value); -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else -#endif - if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -#if defined(LLONG_MAX) && !defined(SWIG_LONG_LONG_AVAILABLE) -# define SWIG_LONG_LONG_AVAILABLE -#endif - - -#ifdef SWIG_LONG_LONG_AVAILABLE -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) -{ - int res = SWIG_TypeError; - if (PyLong_Check(obj)) { - unsigned long long v = PyLong_AsUnsignedLongLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - res = SWIG_OverflowError; - } - } else { - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj,&v); - if (SWIG_IsOK(res)) { - if (val) *val = v; - return res; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - const double mant_max = 1LL << DBL_MANT_DIG; - double d; - res = SWIG_AsVal_double (obj,&d); - if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max)) - return SWIG_OverflowError; - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { - if (val) *val = (unsigned long long)(d); - return SWIG_AddCast(res); - } - res = SWIG_TypeError; - } -#endif - return res; -} -#endif - - -SWIGINTERNINLINE int -SWIG_AsVal_size_t (PyObject * obj, size_t *val) -{ - int res = SWIG_TypeError; -#ifdef SWIG_LONG_LONG_AVAILABLE - if (sizeof(size_t) <= sizeof(unsigned long)) { -#endif - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v); -#ifdef SWIG_LONG_LONG_AVAILABLE - } else if (sizeof(size_t) <= sizeof(unsigned long long)) { - unsigned long long v; - res = SWIG_AsVal_unsigned_SS_long_SS_long (obj, val ? &v : 0); - if (SWIG_IsOK(res) && val) *val = static_cast< size_t >(v); - } -#endif - return res; -} - - -#ifdef SWIG_LONG_LONG_AVAILABLE -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long_SS_long (unsigned long long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLongLong(value) : PyInt_FromLong(static_cast< long >(value)); -} -#endif - - -SWIGINTERN int -SWIG_AsVal_int (PyObject * obj, int *val) -{ - long v; - int res = SWIG_AsVal_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v < INT_MIN || v > INT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = static_cast< int >(v); - } - } - return res; -} - - - #define SWIG_From_long PyInt_FromLong - - -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long (unsigned long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLong(value) : PyInt_FromLong(static_cast< long >(value)); -} - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_zts_start(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - bool arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - bool val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_start",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_start" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_bool(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_start" "', argument " "2"" of type '" "bool""'"); - } - arg2 = static_cast< bool >(val2); - result = (int)zts_start((char const *)arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_startjoin(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - uint64_t arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - unsigned long long val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_startjoin",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_startjoin" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_startjoin" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - result = (int)zts_startjoin((char const *)arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_stop(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - - if (!PyArg_ParseTuple(args,(char *)":zts_stop")) SWIG_fail; - zts_stop(); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_core_running(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":zts_core_running")) SWIG_fail; - result = (int)zts_core_running(); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_stack_running(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":zts_stack_running")) SWIG_fail; - result = (int)zts_stack_running(); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_ready(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int result; - - if (!PyArg_ParseTuple(args,(char *)":zts_ready")) SWIG_fail; - result = (int)zts_ready(); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_join(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - unsigned long long val1 ; - int ecode1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_join",&obj0)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_join" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - result = (int)zts_join(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_leave(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - unsigned long long val1 ; - int ecode1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_leave",&obj0)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_leave" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - result = (int)zts_leave(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_path(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - size_t arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_get_path",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_get_path" "', argument " "1"" of type '" "char *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_size_t(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_get_path" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = static_cast< size_t >(val2); - zts_get_path(arg1,arg2); - resultobj = SWIG_Py_Void(); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_node_id(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t result; - - if (!PyArg_ParseTuple(args,(char *)":zts_get_node_id")) SWIG_fail; - result = (uint64_t)zts_get_node_id(); - resultobj = SWIG_From_unsigned_SS_long_SS_long(static_cast< unsigned long long >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_node_id_from_file(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject * obj0 = 0 ; - uint64_t result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_get_node_id_from_file",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_get_node_id_from_file" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - result = (uint64_t)zts_get_node_id_from_file((char const *)arg1); - resultobj = SWIG_From_unsigned_SS_long_SS_long(static_cast< unsigned long long >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_has_address(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - unsigned long long val1 ; - int ecode1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_has_address",&obj0)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_has_address" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - result = (int)zts_has_address(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_num_assigned_addresses(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - unsigned long long val1 ; - int ecode1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_get_num_assigned_addresses",&obj0)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_get_num_assigned_addresses" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - result = (int)zts_get_num_assigned_addresses(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_address_at_index(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - int arg2 ; - sockaddr_storage *arg3 = (sockaddr_storage *) 0 ; - unsigned long long val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_get_address_at_index",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_get_address_at_index" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_get_address_at_index" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_sockaddr_storage, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_get_address_at_index" "', argument " "3"" of type '" "sockaddr_storage *""'"); - } - arg3 = reinterpret_cast< sockaddr_storage * >(argp3); - result = (int)zts_get_address_at_index(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_address(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - uint64_t arg1 ; - sockaddr_storage *arg2 = (sockaddr_storage *) 0 ; - int arg3 ; - unsigned long long val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_get_address",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_get_address" "', argument " "1"" of type '" "uint64_t""'"); - } - arg1 = static_cast< uint64_t >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr_storage, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_get_address" "', argument " "2"" of type '" "sockaddr_storage *""'"); - } - arg2 = reinterpret_cast< sockaddr_storage * >(argp2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_get_address" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - result = (int)zts_get_address(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_6plane_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - sockaddr_storage *arg1 = (sockaddr_storage *) 0 ; - uint64_t arg2 ; - uint64_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned long long val2 ; - int ecode2 = 0 ; - unsigned long long val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_get_6plane_addr",&obj0,&obj1,&obj2)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_sockaddr_storage, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_get_6plane_addr" "', argument " "1"" of type '" "sockaddr_storage *""'"); - } - arg1 = reinterpret_cast< sockaddr_storage * >(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_get_6plane_addr" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - ecode3 = SWIG_AsVal_unsigned_SS_long_SS_long(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_get_6plane_addr" "', argument " "3"" of type '" "uint64_t""'"); - } - arg3 = static_cast< uint64_t >(val3); - zts_get_6plane_addr(arg1,arg2,arg3); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_rfc4193_addr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - sockaddr_storage *arg1 = (sockaddr_storage *) 0 ; - uint64_t arg2 ; - uint64_t arg3 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned long long val2 ; - int ecode2 = 0 ; - unsigned long long val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_get_rfc4193_addr",&obj0,&obj1,&obj2)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_sockaddr_storage, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_get_rfc4193_addr" "', argument " "1"" of type '" "sockaddr_storage *""'"); - } - arg1 = reinterpret_cast< sockaddr_storage * >(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_get_rfc4193_addr" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - ecode3 = SWIG_AsVal_unsigned_SS_long_SS_long(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_get_rfc4193_addr" "', argument " "3"" of type '" "uint64_t""'"); - } - arg3 = static_cast< uint64_t >(val3); - zts_get_rfc4193_addr(arg1,arg2,arg3); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_peer_count(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - unsigned long result; - - if (!PyArg_ParseTuple(args,(char *)":zts_get_peer_count")) SWIG_fail; - result = (unsigned long)zts_get_peer_count(); - resultobj = SWIG_From_unsigned_SS_long(static_cast< unsigned long >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_get_peer_address(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - uint64_t arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - unsigned long long val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_get_peer_address",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_get_peer_address" "', argument " "1"" of type '" "char *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_get_peer_address" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - result = (int)zts_get_peer_address(arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_socket(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int arg3 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_socket",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_socket" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_socket" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_socket" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - result = (int)zts_socket(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_connect(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - sockaddr *arg2 = (sockaddr *) 0 ; - socklen_t arg3 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_connect",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_connect" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_connect" "', argument " "2"" of type '" "sockaddr const *""'"); - } - arg2 = reinterpret_cast< sockaddr * >(argp2); - { - res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_socklen_t, 0 | 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_connect" "', argument " "3"" of type '" "socklen_t""'"); - } - if (!argp3) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "zts_connect" "', argument " "3"" of type '" "socklen_t""'"); - } else { - socklen_t * temp = reinterpret_cast< socklen_t * >(argp3); - arg3 = *temp; - if (SWIG_IsNewObj(res3)) delete temp; - } - } - result = (int)zts_connect(arg1,(sockaddr const *)arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_bind(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - sockaddr *arg2 = (sockaddr *) 0 ; - socklen_t arg3 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_bind",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_bind" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_bind" "', argument " "2"" of type '" "sockaddr const *""'"); - } - arg2 = reinterpret_cast< sockaddr * >(argp2); - { - res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_socklen_t, 0 | 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_bind" "', argument " "3"" of type '" "socklen_t""'"); - } - if (!argp3) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "zts_bind" "', argument " "3"" of type '" "socklen_t""'"); - } else { - socklen_t * temp = reinterpret_cast< socklen_t * >(argp3); - arg3 = *temp; - if (SWIG_IsNewObj(res3)) delete temp; - } - } - result = (int)zts_bind(arg1,(sockaddr const *)arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_listen(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_listen",&obj0,&obj1)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_listen" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_listen" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - result = (int)zts_listen(arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_accept(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - sockaddr *arg2 = (sockaddr *) 0 ; - socklen_t *arg3 = (socklen_t *) 0 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_accept",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_accept" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_accept" "', argument " "2"" of type '" "sockaddr *""'"); - } - arg2 = reinterpret_cast< sockaddr * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_accept" "', argument " "3"" of type '" "socklen_t *""'"); - } - arg3 = reinterpret_cast< socklen_t * >(argp3); - result = (int)zts_accept(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_setsockopt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int arg3 ; - void *arg4 = (void *) 0 ; - socklen_t arg5 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int res4 ; - void *argp5 ; - int res5 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOO:zts_setsockopt",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_setsockopt" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_setsockopt" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_setsockopt" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - res4 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "zts_setsockopt" "', argument " "4"" of type '" "void const *""'"); - } - { - res5 = SWIG_ConvertPtr(obj4, &argp5, SWIGTYPE_p_socklen_t, 0 | 0); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "zts_setsockopt" "', argument " "5"" of type '" "socklen_t""'"); - } - if (!argp5) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "zts_setsockopt" "', argument " "5"" of type '" "socklen_t""'"); - } else { - socklen_t * temp = reinterpret_cast< socklen_t * >(argp5); - arg5 = *temp; - if (SWIG_IsNewObj(res5)) delete temp; - } - } - result = (int)zts_setsockopt(arg1,arg2,arg3,(void const *)arg4,arg5); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_getsockopt(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int arg3 ; - void *arg4 = (void *) 0 ; - socklen_t *arg5 = (socklen_t *) 0 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - int res4 ; - void *argp5 = 0 ; - int res5 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOO:zts_getsockopt",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_getsockopt" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_getsockopt" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_getsockopt" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - res4 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg4), 0, 0); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "zts_getsockopt" "', argument " "4"" of type '" "void *""'"); - } - res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "zts_getsockopt" "', argument " "5"" of type '" "socklen_t *""'"); - } - arg5 = reinterpret_cast< socklen_t * >(argp5); - result = (int)zts_getsockopt(arg1,arg2,arg3,arg4,arg5); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_getsockname(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - sockaddr *arg2 = (sockaddr *) 0 ; - socklen_t *arg3 = (socklen_t *) 0 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_getsockname",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_getsockname" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_getsockname" "', argument " "2"" of type '" "sockaddr *""'"); - } - arg2 = reinterpret_cast< sockaddr * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_getsockname" "', argument " "3"" of type '" "socklen_t *""'"); - } - arg3 = reinterpret_cast< socklen_t * >(argp3); - result = (int)zts_getsockname(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_getpeername(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - sockaddr *arg2 = (sockaddr *) 0 ; - socklen_t *arg3 = (socklen_t *) 0 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_getpeername",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_getpeername" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_getpeername" "', argument " "2"" of type '" "sockaddr *""'"); - } - arg2 = reinterpret_cast< sockaddr * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_getpeername" "', argument " "3"" of type '" "socklen_t *""'"); - } - arg3 = reinterpret_cast< socklen_t * >(argp3); - result = (int)zts_getpeername(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_gethostname(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - size_t arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_gethostname",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_gethostname" "', argument " "1"" of type '" "char *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_size_t(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_gethostname" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = static_cast< size_t >(val2); - result = (int)zts_gethostname(arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_sethostname(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - size_t arg2 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - size_t val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_sethostname",&obj0,&obj1)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_sethostname" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - ecode2 = SWIG_AsVal_size_t(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_sethostname" "', argument " "2"" of type '" "size_t""'"); - } - arg2 = static_cast< size_t >(val2); - result = (int)zts_sethostname((char const *)arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_gethostbyname(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - char *arg1 = (char *) 0 ; - int res1 ; - char *buf1 = 0 ; - int alloc1 = 0 ; - PyObject * obj0 = 0 ; - hostent *result = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_gethostbyname",&obj0)) SWIG_fail; - res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_gethostbyname" "', argument " "1"" of type '" "char const *""'"); - } - arg1 = reinterpret_cast< char * >(buf1); - result = (hostent *)zts_gethostbyname((char const *)arg1); - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_hostent, 0 | 0 ); - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return resultobj; -fail: - if (alloc1 == SWIG_NEWOBJ) delete[] buf1; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_close(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int val1 ; - int ecode1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_close",&obj0)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_close" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - result = (int)zts_close(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_select(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - fd_set *arg2 = (fd_set *) 0 ; - fd_set *arg3 = (fd_set *) 0 ; - fd_set *arg4 = (fd_set *) 0 ; - timeval *arg5 = (timeval *) 0 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - void *argp3 = 0 ; - int res3 = 0 ; - void *argp4 = 0 ; - int res4 = 0 ; - void *argp5 = 0 ; - int res5 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOO:zts_select",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_select" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_fd_set, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_select" "', argument " "2"" of type '" "fd_set *""'"); - } - arg2 = reinterpret_cast< fd_set * >(argp2); - res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_fd_set, 0 | 0 ); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_select" "', argument " "3"" of type '" "fd_set *""'"); - } - arg3 = reinterpret_cast< fd_set * >(argp3); - res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_fd_set, 0 | 0 ); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "zts_select" "', argument " "4"" of type '" "fd_set *""'"); - } - arg4 = reinterpret_cast< fd_set * >(argp4); - res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_timeval, 0 | 0 ); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "zts_select" "', argument " "5"" of type '" "timeval *""'"); - } - arg5 = reinterpret_cast< timeval * >(argp5); - result = (int)zts_select(arg1,arg2,arg3,arg4,arg5); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_fcntl(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int arg3 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_fcntl",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_fcntl" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_fcntl" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_fcntl" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - result = (int)zts_fcntl(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_ioctl(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - unsigned long arg2 ; - void *arg3 = (void *) 0 ; - int val1 ; - int ecode1 = 0 ; - unsigned long val2 ; - int ecode2 = 0 ; - int res3 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_ioctl",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_ioctl" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_unsigned_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_ioctl" "', argument " "2"" of type '" "unsigned long""'"); - } - arg2 = static_cast< unsigned long >(val2); - res3 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg3), 0, 0); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "zts_ioctl" "', argument " "3"" of type '" "void *""'"); - } - result = (int)zts_ioctl(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_send(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int arg4 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:zts_send",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_send" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_send" "', argument " "2"" of type '" "void const *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_send" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "zts_send" "', argument " "4"" of type '" "int""'"); - } - arg4 = static_cast< int >(val4); - result = zts_send(arg1,(void const *)arg2,arg3,arg4); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_sendto(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int arg4 ; - sockaddr *arg5 = (sockaddr *) 0 ; - socklen_t arg6 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - void *argp5 = 0 ; - int res5 = 0 ; - void *argp6 ; - int res6 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:zts_sendto",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_sendto" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_sendto" "', argument " "2"" of type '" "void const *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_sendto" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "zts_sendto" "', argument " "4"" of type '" "int""'"); - } - arg4 = static_cast< int >(val4); - res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "zts_sendto" "', argument " "5"" of type '" "sockaddr const *""'"); - } - arg5 = reinterpret_cast< sockaddr * >(argp5); - { - res6 = SWIG_ConvertPtr(obj5, &argp6, SWIGTYPE_p_socklen_t, 0 | 0); - if (!SWIG_IsOK(res6)) { - SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "zts_sendto" "', argument " "6"" of type '" "socklen_t""'"); - } - if (!argp6) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "zts_sendto" "', argument " "6"" of type '" "socklen_t""'"); - } else { - socklen_t * temp = reinterpret_cast< socklen_t * >(argp6); - arg6 = *temp; - if (SWIG_IsNewObj(res6)) delete temp; - } - } - result = zts_sendto(arg1,(void const *)arg2,arg3,arg4,(sockaddr const *)arg5,arg6); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_sendmsg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - msghdr *arg2 = (msghdr *) 0 ; - int arg3 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_sendmsg",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_sendmsg" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_msghdr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_sendmsg" "', argument " "2"" of type '" "msghdr const *""'"); - } - arg2 = reinterpret_cast< msghdr * >(argp2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_sendmsg" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - result = zts_sendmsg(arg1,(msghdr const *)arg2,arg3); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_recv(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int arg4 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:zts_recv",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_recv" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_recv" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_recv" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "zts_recv" "', argument " "4"" of type '" "int""'"); - } - arg4 = static_cast< int >(val4); - result = zts_recv(arg1,arg2,arg3,arg4); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_recvfrom(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int arg4 ; - sockaddr *arg5 = (sockaddr *) 0 ; - socklen_t *arg6 = (socklen_t *) 0 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - void *argp5 = 0 ; - int res5 = 0 ; - void *argp6 = 0 ; - int res6 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOOO:zts_recvfrom",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_recvfrom" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_recvfrom" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_recvfrom" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "zts_recvfrom" "', argument " "4"" of type '" "int""'"); - } - arg4 = static_cast< int >(val4); - res5 = SWIG_ConvertPtr(obj4, &argp5,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res5)) { - SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "zts_recvfrom" "', argument " "5"" of type '" "sockaddr *""'"); - } - arg5 = reinterpret_cast< sockaddr * >(argp5); - res6 = SWIG_ConvertPtr(obj5, &argp6,SWIGTYPE_p_socklen_t, 0 | 0 ); - if (!SWIG_IsOK(res6)) { - SWIG_exception_fail(SWIG_ArgError(res6), "in method '" "zts_recvfrom" "', argument " "6"" of type '" "socklen_t *""'"); - } - arg6 = reinterpret_cast< socklen_t * >(argp6); - result = zts_recvfrom(arg1,arg2,arg3,arg4,arg5,arg6); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_recvmsg(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - msghdr *arg2 = (msghdr *) 0 ; - int arg3 ; - int val1 ; - int ecode1 = 0 ; - void *argp2 = 0 ; - int res2 = 0 ; - int val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - ssize_t result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_recvmsg",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_recvmsg" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_msghdr, 0 | 0 ); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_recvmsg" "', argument " "2"" of type '" "msghdr *""'"); - } - arg2 = reinterpret_cast< msghdr * >(argp2); - ecode3 = SWIG_AsVal_int(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_recvmsg" "', argument " "3"" of type '" "int""'"); - } - arg3 = static_cast< int >(val3); - result = zts_recvmsg(arg1,arg2,arg3); - resultobj = SWIG_NewPointerObj((new ssize_t(static_cast< const ssize_t& >(result))), SWIGTYPE_p_ssize_t, SWIG_POINTER_OWN | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_read(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_read",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_read" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_read" "', argument " "2"" of type '" "void *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_read" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - result = (int)zts_read(arg1,arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_write(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - void *arg2 = (void *) 0 ; - size_t arg3 ; - int val1 ; - int ecode1 = 0 ; - int res2 ; - size_t val3 ; - int ecode3 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OOO:zts_write",&obj0,&obj1,&obj2)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_write" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - res2 = SWIG_ConvertPtr(obj1,SWIG_as_voidptrptr(&arg2), 0, 0); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "zts_write" "', argument " "2"" of type '" "void const *""'"); - } - ecode3 = SWIG_AsVal_size_t(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "zts_write" "', argument " "3"" of type '" "size_t""'"); - } - arg3 = static_cast< size_t >(val3); - result = (int)zts_write(arg1,(void const *)arg2,arg3); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_shutdown(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - int arg1 ; - int arg2 ; - int val1 ; - int ecode1 = 0 ; - int val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"OO:zts_shutdown",&obj0,&obj1)) SWIG_fail; - ecode1 = SWIG_AsVal_int(obj0, &val1); - if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "zts_shutdown" "', argument " "1"" of type '" "int""'"); - } - arg1 = static_cast< int >(val1); - ecode2 = SWIG_AsVal_int(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "zts_shutdown" "', argument " "2"" of type '" "int""'"); - } - arg2 = static_cast< int >(val2); - result = (int)zts_shutdown(arg1,arg2); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_add_dns_nameserver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - sockaddr *arg1 = (sockaddr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_add_dns_nameserver",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_add_dns_nameserver" "', argument " "1"" of type '" "sockaddr *""'"); - } - arg1 = reinterpret_cast< sockaddr * >(argp1); - result = (int)zts_add_dns_nameserver(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_zts_del_dns_nameserver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - sockaddr *arg1 = (sockaddr *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - int result; - - if (!PyArg_ParseTuple(args,(char *)"O:zts_del_dns_nameserver",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_sockaddr, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "zts_del_dns_nameserver" "', argument " "1"" of type '" "sockaddr *""'"); - } - arg1 = reinterpret_cast< sockaddr * >(argp1); - result = (int)zts_del_dns_nameserver(arg1); - resultobj = SWIG_From_int(static_cast< int >(result)); - return resultobj; -fail: - return NULL; -} - - -static PyMethodDef SwigMethods[] = { - { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, - { (char *)"zts_start", _wrap_zts_start, METH_VARARGS, NULL}, - { (char *)"zts_startjoin", _wrap_zts_startjoin, METH_VARARGS, NULL}, - { (char *)"zts_stop", _wrap_zts_stop, METH_VARARGS, NULL}, - { (char *)"zts_core_running", _wrap_zts_core_running, METH_VARARGS, NULL}, - { (char *)"zts_stack_running", _wrap_zts_stack_running, METH_VARARGS, NULL}, - { (char *)"zts_ready", _wrap_zts_ready, METH_VARARGS, NULL}, - { (char *)"zts_join", _wrap_zts_join, METH_VARARGS, NULL}, - { (char *)"zts_leave", _wrap_zts_leave, METH_VARARGS, NULL}, - { (char *)"zts_get_path", _wrap_zts_get_path, METH_VARARGS, NULL}, - { (char *)"zts_get_node_id", _wrap_zts_get_node_id, METH_VARARGS, NULL}, - { (char *)"zts_get_node_id_from_file", _wrap_zts_get_node_id_from_file, METH_VARARGS, NULL}, - { (char *)"zts_has_address", _wrap_zts_has_address, METH_VARARGS, NULL}, - { (char *)"zts_get_num_assigned_addresses", _wrap_zts_get_num_assigned_addresses, METH_VARARGS, NULL}, - { (char *)"zts_get_address_at_index", _wrap_zts_get_address_at_index, METH_VARARGS, NULL}, - { (char *)"zts_get_address", _wrap_zts_get_address, METH_VARARGS, NULL}, - { (char *)"zts_get_6plane_addr", _wrap_zts_get_6plane_addr, METH_VARARGS, NULL}, - { (char *)"zts_get_rfc4193_addr", _wrap_zts_get_rfc4193_addr, METH_VARARGS, NULL}, - { (char *)"zts_get_peer_count", _wrap_zts_get_peer_count, METH_VARARGS, NULL}, - { (char *)"zts_get_peer_address", _wrap_zts_get_peer_address, METH_VARARGS, NULL}, - { (char *)"zts_socket", _wrap_zts_socket, METH_VARARGS, NULL}, - { (char *)"zts_connect", _wrap_zts_connect, METH_VARARGS, NULL}, - { (char *)"zts_bind", _wrap_zts_bind, METH_VARARGS, NULL}, - { (char *)"zts_listen", _wrap_zts_listen, METH_VARARGS, NULL}, - { (char *)"zts_accept", _wrap_zts_accept, METH_VARARGS, NULL}, - { (char *)"zts_setsockopt", _wrap_zts_setsockopt, METH_VARARGS, NULL}, - { (char *)"zts_getsockopt", _wrap_zts_getsockopt, METH_VARARGS, NULL}, - { (char *)"zts_getsockname", _wrap_zts_getsockname, METH_VARARGS, NULL}, - { (char *)"zts_getpeername", _wrap_zts_getpeername, METH_VARARGS, NULL}, - { (char *)"zts_gethostname", _wrap_zts_gethostname, METH_VARARGS, NULL}, - { (char *)"zts_sethostname", _wrap_zts_sethostname, METH_VARARGS, NULL}, - { (char *)"zts_gethostbyname", _wrap_zts_gethostbyname, METH_VARARGS, NULL}, - { (char *)"zts_close", _wrap_zts_close, METH_VARARGS, NULL}, - { (char *)"zts_select", _wrap_zts_select, METH_VARARGS, NULL}, - { (char *)"zts_fcntl", _wrap_zts_fcntl, METH_VARARGS, NULL}, - { (char *)"zts_ioctl", _wrap_zts_ioctl, METH_VARARGS, NULL}, - { (char *)"zts_send", _wrap_zts_send, METH_VARARGS, NULL}, - { (char *)"zts_sendto", _wrap_zts_sendto, METH_VARARGS, NULL}, - { (char *)"zts_sendmsg", _wrap_zts_sendmsg, METH_VARARGS, NULL}, - { (char *)"zts_recv", _wrap_zts_recv, METH_VARARGS, NULL}, - { (char *)"zts_recvfrom", _wrap_zts_recvfrom, METH_VARARGS, NULL}, - { (char *)"zts_recvmsg", _wrap_zts_recvmsg, METH_VARARGS, NULL}, - { (char *)"zts_read", _wrap_zts_read, METH_VARARGS, NULL}, - { (char *)"zts_write", _wrap_zts_write, METH_VARARGS, NULL}, - { (char *)"zts_shutdown", _wrap_zts_shutdown, METH_VARARGS, NULL}, - { (char *)"zts_add_dns_nameserver", _wrap_zts_add_dns_nameserver, METH_VARARGS, NULL}, - { (char *)"zts_del_dns_nameserver", _wrap_zts_del_dns_nameserver, METH_VARARGS, NULL}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_fd_set = {"_p_fd_set", "fd_set *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_hostent = {"_p_hostent", "hostent *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_msghdr = {"_p_msghdr", "msghdr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_sockaddr = {"_p_sockaddr", "sockaddr *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_sockaddr_storage = {"_p_sockaddr_storage", "sockaddr_storage *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_socklen_t = {"_p_socklen_t", "socklen_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_ssize_t = {"_p_ssize_t", "ssize_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_timeval = {"_p_timeval", "timeval *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p_char, - &_swigt__p_fd_set, - &_swigt__p_hostent, - &_swigt__p_int, - &_swigt__p_long_long, - &_swigt__p_msghdr, - &_swigt__p_short, - &_swigt__p_signed_char, - &_swigt__p_sockaddr, - &_swigt__p_sockaddr_storage, - &_swigt__p_socklen_t, - &_swigt__p_ssize_t, - &_swigt__p_timeval, - &_swigt__p_unsigned_char, - &_swigt__p_unsigned_int, - &_swigt__p_unsigned_long_long, - &_swigt__p_unsigned_short, -}; - -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_fd_set[] = { {&_swigt__p_fd_set, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_hostent[] = { {&_swigt__p_hostent, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_msghdr[] = { {&_swigt__p_msghdr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_sockaddr[] = { {&_swigt__p_sockaddr, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_sockaddr_storage[] = { {&_swigt__p_sockaddr_storage, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_socklen_t[] = { {&_swigt__p_socklen_t, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_ssize_t[] = { {&_swigt__p_ssize_t, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_timeval[] = { {&_swigt__p_timeval, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p_char, - _swigc__p_fd_set, - _swigc__p_hostent, - _swigc__p_int, - _swigc__p_long_long, - _swigc__p_msghdr, - _swigc__p_short, - _swigc__p_signed_char, - _swigc__p_sockaddr, - _swigc__p_sockaddr_storage, - _swigc__p_socklen_t, - _swigc__p_ssize_t, - _swigc__p_timeval, - _swigc__p_unsigned_char, - _swigc__p_unsigned_int, - _swigc__p_unsigned_long_long, - _swigc__p_unsigned_short, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned statically to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int init; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - iter=module_head; - do { - if (iter==&swig_module) { - /* Our module is already in the list, so there's nothing more to do. */ - return; - } - iter=iter->next; - } while (iter!= module_head); - - /* otherwise we must add our module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpreters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"swigvarlink", /* tp_name */ - sizeof(swig_varlinkobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) swig_varlink_dealloc, /* tp_dealloc */ - (printfunc) swig_varlink_print, /* tp_print */ - (getattrfunc) swig_varlink_getattr, /* tp_getattr */ - (setattrfunc) swig_varlink_setattr, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - varlink_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - varlink_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&varlink_type) < 0) - return NULL; -#endif - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (!c) continue; - c = strstr(c, "swig_ptr: "); - if (c) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d, *md; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { -# if PY_VERSION_HEX >= 0x03020000 - PyModuleDef_HEAD_INIT, -# else - { - PyObject_HEAD_INIT(NULL) - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, -# endif - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - -#if defined(SWIGPYTHON_BUILTIN) - static SwigPyClientData SwigPyObject_clientdata = { - 0, 0, 0, 0, 0, 0, 0 - }; - static PyGetSetDef this_getset_def = { - (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL - }; - static SwigPyGetSet thisown_getset_closure = { - (PyCFunction) SwigPyObject_own, - (PyCFunction) SwigPyObject_own - }; - static PyGetSetDef thisown_getset_def = { - (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure - }; - PyTypeObject *builtin_pytype; - int builtin_base_count; - swig_type_info *builtin_basetype; - PyObject *tuple; - PyGetSetDescrObject *static_getset; - PyTypeObject *metatype; - PyTypeObject *swigpyobject; - SwigPyClientData *cd; - PyObject *public_interface, *public_symbol; - PyObject *this_descr; - PyObject *thisown_descr; - PyObject *self = 0; - int i; - - (void)builtin_pytype; - (void)builtin_base_count; - (void)builtin_basetype; - (void)tuple; - (void)static_getset; - (void)self; - - /* Metaclass is used to implement static member variables */ - metatype = SwigPyObjectType(); - assert(metatype); -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - - md = d = PyModule_GetDict(m); - (void)md; - - SWIG_InitializeModule(0); - -#ifdef SWIGPYTHON_BUILTIN - swigpyobject = SwigPyObject_TypeOnce(); - - SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - if (!cd) { - SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; - SwigPyObject_clientdata.pytype = swigpyobject; - } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { - PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); -# if PY_VERSION_HEX >= 0x03000000 - return NULL; -# else - return; -# endif - } - - /* All objects have a 'this' attribute */ - this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); - (void)this_descr; - - /* All objects have a 'thisown' attribute */ - thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); - (void)thisown_descr; - - public_interface = PyList_New(0); - public_symbol = 0; - (void)public_symbol; - - PyDict_SetItemString(md, "__all__", public_interface); - Py_DECREF(public_interface); - for (i = 0; SwigMethods[i].ml_name != NULL; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); - for (i = 0; swig_const_table[i].name != 0; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); -#endif - - SWIG_InstallConstants(d,swig_const_table); - -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - diff --git a/packages/pypi/setup.cfg b/packages/pypi/setup.cfg deleted file mode 100644 index 5aef279..0000000 --- a/packages/pypi/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description-file = README.rst diff --git a/packages/pypi/setup.py b/packages/pypi/setup.py deleted file mode 100644 index 52fa43c..0000000 --- a/packages/pypi/setup.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python - -from setuptools import setup, Extension, Command, Distribution -import glob -import os - -class BinaryDistribution(Distribution): - def is_pure(self): - return False - -# WINDOWS -if os.name == 'nt': - projDir='..\\..' - source_list = ['libzt_wrap.cxx'] - source_list.extend(list(glob.glob(projDir+'\\src\\*.cpp'))) - source_list.extend(list(glob.glob(projDir+'\\zto\\node\\*.cpp'))) - source_list.extend(list(glob.glob(projDir+'\\zto\\osdep\\*.cpp'))) - source_list.extend(list(glob.glob(projDir+'\\zto\\service\\*.cpp'))) - source_list.extend(list(glob.glob(projDir+'\\zto\\controller\\*.cpp'))) - - source_list = list(set(source_list)-set( - [ - projDir+'\\zto\\osdep\\LinuxEthernetTap.cpp', - projDir+'\\zto\\osdep\\BSDEthernetTap.cpp', - projDir+'\\zto\\osdep\\OSXEthernetTap.cpp', - projDir+'\\zto\\osdep\\WindowsEthernetTap.cpp' - ])) - - libzt_module = Extension('_libzt', - extra_compile_args=['/std:c++14', '-DNOMINMAX=1', '-DZT_SDK', '-DSDK', '-DZT_SOFTWARE_UPDATE_DEFAULT=\"disable\"'], - extra_link_args=['/LIBPATH:.', 'WS2_32.Lib', 'ShLwApi.Lib', 'iphlpapi.Lib','lwip.lib','http.lib'], - sources=source_list, - include_dirs=[projDir+'\\include', - projDir+'\\ext\\lwip\\src\\include', - projDir+'\\ext\\lwip-contrib\\ports\\win32\\include', - projDir+'\\zto\\include', - projDir+'\\zto\\node', - projDir+'\\zto\\service', - projDir+'\\zto\\osdep', - projDir+'\\zto\\controller'] - ) -# EVERYTHING ELSE -else: - projDir='../..' - source_list = ['libzt_wrap.cxx'] - source_list.extend(list(glob.glob(projDir+'/src/*.cpp'))) - source_list.extend(list(glob.glob(projDir+'/zto/node/*.cpp'))) - source_list.extend(list(glob.glob(projDir+'/zto/osdep/*.cpp'))) - source_list.extend(list(glob.glob(projDir+'/zto/service/*.cpp'))) - source_list.extend(list(glob.glob(projDir+'/zto/controller/*.cpp'))) - - source_list = list(set(source_list)-set( - [ - projDir+'/zto/osdep/LinuxEthernetTap.cpp', - projDir+'/zto/osdep/BSDEthernetTap.cpp', - projDir+'/zto/osdep/OSXEthernetTap.cpp', - projDir+'/zto/osdep/WindowsEthernetTap.cpp' - ])) - - libzt_module = Extension('_libzt', - extra_compile_args=['-std=c++11', '-DZT_SDK', '-DZT_SOFTWARE_UPDATE_DEFAULT=\"disable\"'], - extra_link_args=['-L.','-llwip','-lhttp'], - sources=source_list, - include_dirs=[projDir+'/include', - projDir+'/ext/lwip/src/include', - projDir+'/ext/lwip-contrib/ports/unix/include', - projDir+'/zto/include', - projDir+'/zto/node', - projDir+'/zto/service', - projDir+'/zto/osdep', - projDir+'/zto/controller'] - ) - -setup( - include_package_data=True, - distclass=BinaryDistribution, - ext_modules = [libzt_module], - py_modules = ['libzt'], - name = 'libzt', - packages = ['libzt'], - version = '1.1.6a0', - description = 'ZeroTier', - long_description = 'Encrypted P2P communication between apps and services', - author = 'ZeroTier, Inc.', - author_email = 'josep@zerotier.com', - url = 'https://github.com/zerotier/libzt', - license='GPLv3', - download_url = 'https://github.com/zerotier/libzt/archive/1.1.6.tar.gz', - keywords = 'zerotier sdwan sdn virtual network socket p2p peer-to-peer', - classifiers = ['Development Status :: 3 - Alpha', - 'Environment :: MacOS X', - 'Environment :: Win32 (MS Windows)', - 'Intended Audience :: Information Technology', - 'Intended Audience :: Science/Research', - 'Intended Audience :: System Administrators', - 'Intended Audience :: Telecommunications Industry', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'License :: Free for non-commercial use', - 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', - 'Operating System :: iOS', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX :: BSD', - 'Operating System :: Unix', - 'Programming Language :: C++', - 'Programming Language :: C', - 'Programming Language :: Python', - 'Topic :: Internet', - 'Topic :: Security :: Cryptography', - 'Topic :: System :: Networking' - ], -) \ No newline at end of file diff --git a/packages/pypi/test.py b/packages/pypi/test.py deleted file mode 100644 index 53e8c71..0000000 --- a/packages/pypi/test.py +++ /dev/null @@ -1,23 +0,0 @@ -import libzt -import time - -nwid = 0x1234567890ABCDEF - -# Authorization required via my.zerotier.com if this is a private network). -print('Joining virtual network...') -libzt.zts_startjoin('whatev_config', nwid) - -fd = libzt.zts_socket(AF_INET,SOCK_STREAM,0) -if fd < 0: - print('error creating socket') -print('fd = ' + str(fd)) - -# Display info about this node -print('I am ' + str(hex(libzt.zts_get_node_id()))) -address = None -libzt.zts_get_address(nwid, address, AF_INET) -print('assigned address = ' + str(address)) - -print('Looping forever, ping me or something') -while True: - time.sleep(1) \ No newline at end of file diff --git a/src/Controls.cpp b/src/Controls.cpp new file mode 100644 index 0000000..b41375a --- /dev/null +++ b/src/Controls.cpp @@ -0,0 +1,760 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * ZeroTier service controls + */ + +#include + +#include "Service.hpp" +#include "Node.hpp" +#include "ZeroTierOne.h" + +#include "OSUtils.hpp" +#include "VirtualTap.hpp" +#include "Debug.hpp" +#include "concurrentqueue.h" + +#include "libzt.h" + +#if defined(_WIN32) +WSADATA wsaData; +#include +#endif + +#ifdef SDK_JNI +#include +#endif + +namespace ZeroTier { + +#ifdef __cplusplus +extern "C" { +#endif +// Custom errno to prevent conflicts with platform's own errno +int zts_errno; +#ifdef __cplusplus +} +#endif + +struct serviceParameters +{ + int port; + std::string path; +}; + +int _port; +std::string _path; + +/* + * A lock used to protect any call which relies on the presence of a valid pointer + * to the ZeroTier service. + */ +Mutex _service_lock; + +/* + * A lock which protects flags and state variables used during the startup and + * shutdown phase. + */ +Mutex _startup_lock; + +/* + * A lock used to protect callback method pointers. With a coarser-grained lock it + * would be possible for one thread to alter the callback method pointer causing + * undefined behaviour. + */ +Mutex _callback_lock; + +bool _freeHasBeenCalled = false; +bool _run_service = false; +bool _run_callbacks = false; +bool _run_lwip_tcpip = false; + +//bool _startupError = false; + +pthread_t service_thread; +pthread_t callback_thread; + +// Global reference to ZeroTier service +OneService *service; + +// User-provided callback for ZeroTier events +#ifdef SDK_JNI + // Global references to JNI objects and VM kept for future callbacks + static JavaVM *jvm = NULL; + static jobject objRef = NULL; + static jmethodID _userCallbackMethodRef = NULL; +#endif + +void (*_userEventCallbackFunc)(uint64_t, int); + +extern moodycamel::ConcurrentQueue*> _callbackMsgQueue; + +////////////////////////////////////////////////////////////////////////////// +// Internal ZeroTier Service Controls (user application shall not use these)// +////////////////////////////////////////////////////////////////////////////// + +void postEvent(uint64_t id, int eventCode) +{ + // Queue callback event messages from other threads (such as lwIP driver) + _callbackMsgQueue.enqueue(new std::pair(id, eventCode)); +} + +void _process_callback_event_helper(uint64_t nwid, int eventCode) +{ +#ifdef SDK_JNI + if(_userCallbackMethodRef) { + JNIEnv *env; + jint rs = jvm->AttachCurrentThread(&env, NULL); + assert (rs == JNI_OK); + env->CallVoidMethod(objRef, _userCallbackMethodRef, nwid, eventCode); + } +#else + if (_userEventCallbackFunc) { + _userEventCallbackFunc(nwid, eventCode); + } +#endif +} + +void _process_callback_event(uint64_t nwid, int eventCode) +{ + _callback_lock.lock(); + _process_callback_event_helper(nwid, eventCode); + _callback_lock.unlock(); +} + +bool _is_callback_registered() +{ + _callback_lock.lock(); + bool retval = false; +#ifdef SDK_JNI + retval = (jvm && objRef && _userCallbackMethodRef); +#else + retval = _userEventCallbackFunc; +#endif + _callback_lock.unlock(); + return retval; +} + +void _clear_registered_callback() +{ + _callback_lock.lock(); +#ifdef SDK_JNI + objRef = NULL; + _userCallbackMethodRef = NULL; +#else + _userEventCallbackFunc = NULL; +#endif + _callback_lock.unlock(); +} + +int __zts_node_online() +{ + return service && service->getNode() && service->getNode()->online(); +} + +int __zts_can_perform_service_operation() +{ + return service + && service->isRunning() + && service->getNode() + && service->getNode()->online() + && !_freeHasBeenCalled; +} + +void _api_sleep(int interval_ms) +{ +#if defined(_WIN32) + Sleep(interval_ms); +#else + struct timespec sleepValue = {0}; + sleepValue.tv_nsec = interval_ms * 500000; + nanosleep(&sleepValue, NULL); +#endif +} + +////////////////////////////////////////////////////////////////////////////// +// Callback thread // +////////////////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) +DWORD WINAPI _zts_run_callbacks(LPVOID thread_id) +#else +void *_zts_run_callbacks(void *thread_id) +#endif +{ +#if defined(__APPLE__) + pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); +#endif + while (_run_callbacks || _callbackMsgQueue.size_approx() > 0) + { + std::pair *msg; + for (int j = 0; j != 32; j++) { // TODO: Check size of queue + if (_callbackMsgQueue.try_dequeue(msg)) { + // DEBUG_INFO("deqeueuing front: %llx,%d", msg->first, msg->second); + _process_callback_event(msg->first, msg->second); + delete msg; + } + } + _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL); + } + pthread_exit(0); +} + +////////////////////////////////////////////////////////////////////////////// +// Service thread // +////////////////////////////////////////////////////////////////////////////// + +// Starts a ZeroTier service in the background +#if defined(_WIN32) +DWORD WINAPI _zts_run_service(LPVOID arg) +#else +void *_zts_run_service(void *arg) +#endif +{ +#if defined(__APPLE__) + pthread_setname_np(ZTS_SERVICE_THREAD_NAME); +#endif + //struct serviceParameters *params = arg; + //DEBUG_INFO("path=%s", params->path.c_str()); + int err; + + try { + std::vector hpsp(OSUtils::split(_path.c_str(), ZT_PATH_SEPARATOR_S,"","")); + std::string ptmp; + if (_path[0] == ZT_PATH_SEPARATOR) { + ptmp.push_back(ZT_PATH_SEPARATOR); + } + for (std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { + if (ptmp.length() > 0) { + ptmp.push_back(ZT_PATH_SEPARATOR); + } + ptmp.append(*pi); + if ((*pi != ".")&&(*pi != "..")) { + if (OSUtils::mkdir(ptmp) == false) { + DEBUG_ERROR("home path does not exist, and could not create"); + err = true; + perror("error\n"); + } + } + } + for(;;) { + _service_lock.lock(); + service = OneService::newInstance(_path.c_str(),_port); + _service_lock.unlock(); + switch(service->run()) { + case OneService::ONE_STILL_RUNNING: + case OneService::ONE_NORMAL_TERMINATION: + postEvent((uint64_t)0, ZTS_EVENT_NODE_NORMAL_TERMINATION); + break; + case OneService::ONE_UNRECOVERABLE_ERROR: + DEBUG_ERROR("fatal error: %s", service->fatalErrorMessage().c_str()); + err = true; + postEvent((uint64_t)0, ZTS_EVENT_NODE_UNRECOVERABLE_ERROR); + break; + case OneService::ONE_IDENTITY_COLLISION: { + err = true; + delete service; + service = (OneService *)0; + std::string oldid; + OSUtils::readFile((_path + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); + if (oldid.length()) { + OSUtils::writeFile((_path + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); + OSUtils::rm((_path + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); + OSUtils::rm((_path + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); + } + postEvent((uint64_t)0, ZTS_EVENT_NODE_IDENTITY_COLLISION); + } continue; // restart! + } + break; // terminate loop -- normally we don't keep restarting + } + _service_lock.lock(); + _run_service = false; + delete service; + service = (OneService *)0; + _service_lock.unlock(); + postEvent((uint64_t)0, ZTS_EVENT_NODE_DOWN); + } catch ( ... ) { + DEBUG_ERROR("unexpected exception starting ZeroTier instance"); + } + //delete params; + // TODO: Find a more elegant solution + _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL*2); + _run_callbacks = false; + pthread_exit(0); +} + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////////// +// ZeroTier Service Controls // +////////////////////////////////////////////////////////////////////////////// + +#ifdef SDK_JNI +/* + * 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 void JNICALL Java_com_zerotier_libzt_ZeroTier_init(JNIEnv *env, jobject thisObj) +{ + jint rs = env->GetJavaVM(&jvm); + assert (rs == JNI_OK); +} +#endif + +zts_err_t zts_join(const uint64_t nwid) +{ + Mutex::Lock _l(_service_lock); + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + else { + service->join(nwid); + } + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join( + JNIEnv *env, jobject thisObj, jlong nwid) +{ + return zts_join((uint64_t)nwid); +} +#endif + +zts_err_t zts_leave(const uint64_t nwid) +{ + Mutex::Lock _l(_service_lock); + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + else { + service->leave(nwid); + } + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave( + JNIEnv *env, jobject thisObj, jlong nwid) +{ + return zts_leave((uint64_t)nwid); +} +#endif + +zts_err_t zts_leave_all() +{ + Mutex::Lock _l(_service_lock); + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + else { + service->leaveAll(); + } + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +#endif + +zts_err_t zts_orbit(uint64_t moonWorldId, uint64_t moonSeed) +{ + Mutex::Lock _l(_service_lock); + void *tptr = NULL; + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } else { + service->getNode()->orbit(tptr, moonWorldId, moonSeed); + } + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +#endif + +zts_err_t zts_deorbit(uint64_t moonWorldId) +{ + Mutex::Lock _l(_service_lock); + void *tptr = NULL; + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } else { + service->getNode()->deorbit(tptr, moonWorldId); + } + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +#endif + +zts_err_t zts_start(const char *path, void (*callback)(uint64_t, int), int port) +{ + Mutex::Lock _l(_service_lock); + if (service || _run_service) { + // Service is already initialized + return ZTS_ERR_INVALID_OP; + } + if (_freeHasBeenCalled) { + // Stack (presumably lwIP) has been dismantled, an application restart is required now + return ZTS_ERR_INVALID_OP; + } +#ifdef SDK_JNI + _userEventCallbackFunc = callback; +#endif + _userEventCallbackFunc = callback; + if (!_is_callback_registered()) { + // Must have a callback + return ZTS_ERR_INVALID_ARG; + } + if (!path) { + return ZTS_ERR_INVALID_ARG; + } + if (port < 0 || port > 0xFFFF) { + return ZTS_ERR_INVALID_ARG; + } + + _path = std::string(path); + _port = port; + + serviceParameters *params = new serviceParameters(); + + /* + params->port = port; + DEBUG_INFO("path=%s", path); + params->path = std::string(path); + DEBUG_INFO("path=%s", params->path.c_str()); + + if (params->path.length() == 0) { + return ZTS_ERR_INVALID_ARG; + } + */ + + int err; + int retval = ZTS_ERR_OK; + _run_callbacks = true; + _run_service = true; + + // Start the ZT service thread +#if defined(_WIN32) + // Initialize WinSock. Used in Phy for loopback pipe + WSAStartup(MAKEWORD(2, 2), &wsaData); + HANDLE serviceThread = CreateThread(NULL, 0, _zts_run_service, (void*)params, 0, NULL); + HANDLE callbackThread = CreateThread(NULL, 0, _zts_run_callbacks, NULL, 0, NULL); +#endif + if ((err = pthread_create(&service_thread, NULL, _zts_run_service, NULL)) != 0) { + retval = err; + } + if ((err = pthread_create(&callback_thread, NULL, _zts_run_callbacks, NULL)) != 0) { + retval = err; + } +#if defined(__linux__) + pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME); + pthread_setname_np(callback_thread, ZTS_EVENT_CALLBACK_THREAD_NAME); +#endif + + if (retval != ZTS_ERR_OK) { + _run_callbacks = false; + _run_service = false; + _clear_registered_callback(); + delete params; + } + return retval; +} + +#ifdef SDK_JNI +JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_start( + JNIEnv *env, jobject thisObj, jstring path, jobject callback, jint port) +{ + if (!path) { + return; + } + jclass eventListenerClass = env->GetObjectClass(callback); + if(eventListenerClass == NULL) { + DEBUG_ERROR("Couldn't find class for ZeroTierEventListener instance"); + return; + } + jmethodID eventListenerCallbackMethod = env->GetMethodID(eventListenerClass, "onZeroTierEvent", "(JI)V"); + if(eventListenerCallbackMethod == NULL) { + DEBUG_ERROR("Couldn't find onZeroTierEvent method"); + return; + } + objRef = env->NewGlobalRef(callback); // Reference used for later calls + _userCallbackMethodRef = eventListenerCallbackMethod; + const char* utf_string = env->GetStringUTFChars(path, NULL); + zts_start(utf_string, NULL, port); // using _userCallbackMethodRef + env->ReleaseStringUTFChars(path, utf_string); +} +#endif + +zts_err_t zts_stop() +{ + Mutex::Lock _l(_service_lock); + bool didStop = false; + if (__zts_can_perform_service_operation()) { + _run_service = false; + service->terminate(); + didStop = true; +#if defined(_WIN32) + WSACleanup(); +#endif + return ZTS_ERR_OK; + } + return ZTS_ERR_SERVICE; +} +#ifdef SDK_JNI +JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop( + JNIEnv *env, jobject thisObj) +{ + zts_stop(); +} +#endif + +zts_err_t zts_free() +{ + Mutex::Lock _l(_service_lock); + zts_err_t retval = 0; + if (_freeHasBeenCalled) { + return ZTS_ERR_INVALID_OP; + } + _freeHasBeenCalled = true; + return zts_stop(); + // TODO: add stack shutdown logic +} +#ifdef SDK_JNI +JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free( + JNIEnv *env, jobject thisObj) +{ + zts_free(); +} +#endif + +uint64_t zts_get_node_id() +{ + Mutex::Lock _l(_service_lock); + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + return service->getNode()->address(); +} +#ifdef SDK_JNI +JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1node_1id( + JNIEnv *env, jobject thisObj) +{ + return zts_get_node_id(); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// Peers // +////////////////////////////////////////////////////////////////////////////// + +int zts_get_peer_count() +{ + Mutex::Lock _l(_service_lock); + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + return service->getNode()->peers()->peerCount; +} +#ifdef SDK_JNI +JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1peer_1count( + JNIEnv *env, jobject thisObj) +{ + return zts_get_peer_count(); +} +#endif + +int zts_get_peers(struct zts_peer_details *pds, int *num) +{ + // TODO: Modernize + Mutex::Lock _l(_service_lock); + if (!pds || !num) { + return ZTS_ERR_INVALID_ARG; + } + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + ZT_PeerList *pl = service->getNode()->peers(); + if (pl) { + *num = pl->peerCount; + for(unsigned long i=0;ipeerCount;++i) { + memcpy(&(pds[i]), &(pl->peers[i]), sizeof(struct zts_peer_details)); + } + } + service->getNode()->freeQueryResult((void *)pl); + return ZTS_ERR_OK; +} +#ifdef SDK_JNI +#endif + +int zts_get_peer_status(uint64_t id) +{ + Mutex::Lock _l(_service_lock); + zts_err_t retval = ZTS_ERR_OK; + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + return service->getPeerStatus(id); +} +#ifdef SDK_JNI +JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1peer_1status( + JNIEnv *env, jobject thisObj, jlong id) +{ + return zts_get_peer_status(id); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// Networks // +////////////////////////////////////////////////////////////////////////////// + +zts_err_t zts_get_num_joined_networks() +{ + Mutex::Lock _l(_service_lock); + zts_err_t retval = ZTS_ERR_OK; + if (!__zts_can_perform_service_operation()) { + return ZTS_ERR_SERVICE; + } + return service->networkCount(); +} +#ifdef SDK_JNI +JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1num_1joined_1networks( + JNIEnv *env, jobject thisObj) +{ + return zts_get_num_joined_networks(); +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// Network Details // +////////////////////////////////////////////////////////////////////////////// + +void __get_network_details_helper(uint64_t nwid, struct zts_network_details *nd) +{ + /* + socklen_t addrlen; + VirtualTap *tap = vtapMap[nwid]; + nd->nwid = tap->_nwid; + nd->mtu = tap->_mtu; + // assigned addresses + nd->num_addresses = tap->_ips.size() < ZTS_MAX_ASSIGNED_ADDRESSES ? tap->_ips.size() : ZTS_MAX_ASSIGNED_ADDRESSES; + for (int j=0; jnum_addresses; j++) { + addrlen = tap->_ips[j].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); + memcpy(&(nd->addr[j]), &(tap->_ips[j]), addrlen); + } + // routes + nd->num_routes = ZTS_MAX_NETWORK_ROUTES;; + service->getRoutes(nwid, (ZT_VirtualNetworkRoute*)&(nd->routes)[0], &(nd->num_routes)); + */ +} + +void _get_network_details(uint64_t nwid, struct zts_network_details *nd) +{ + /* + _vtaps_lock.lock(); + __get_network_details_helper(nwid, nd); + _vtaps_lock.unlock(); + */ +} + +void _get_all_network_details(struct zts_network_details *nds, int *num) +{ + /* + _vtaps_lock.lock(); + *num = vtapMap.size(); + int idx = 0; + std::map::iterator it; + for (it = vtapMap.begin(); it != vtapMap.end(); it++) { + _get_network_details(it->first, &nds[idx]); + idx++; + } + _vtaps_lock.unlock(); + */ +} + +zts_err_t zts_get_network_details(uint64_t nwid, struct zts_network_details *nd) +{ + /* + _service_lock.lock(); + zts_err_t retval = ZTS_ERR_OK; + if (!nd || nwid == 0) { + retval = ZTS_ERR_INVALID_ARG; + } + if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) { + retval = ZTS_ERR_SERVICE; + } + if (retval == ZTS_ERR_OK) { + _get_network_details(nwid, nd); + } + _service_lock.unlock(); + return retval; + */ + return 0; +} +#ifdef SDK_JNI +#endif + +zts_err_t zts_get_all_network_details(struct zts_network_details *nds, int *num) +{ + /* + _service_lock.lock(); + zts_err_t retval = ZTS_ERR_OK; + if (!nds || !num) { + retval = ZTS_ERR_INVALID_ARG; + } + if (!service || _freeHasBeenCalled || _serviceIsShuttingDown) { + retval = ZTS_ERR_SERVICE; + } + if (retval == ZTS_ERR_OK) { + _get_all_network_details(nds, num); + } + _service_lock.unlock(); + return retval; + */ + return 0; +} +#ifdef SDK_JNI +#endif + +////////////////////////////////////////////////////////////////////////////// +// Multipath/QoS // +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// Misc // +////////////////////////////////////////////////////////////////////////////// + +int zts_ready() +{ + Mutex::Lock _l(_service_lock); + return _run_service && _run_lwip_tcpip; +} + +#ifdef __cplusplus +} +#endif + +} // namespace ZeroTier \ No newline at end of file diff --git a/src/Controls.hpp b/src/Controls.hpp new file mode 100644 index 0000000..a60112d --- /dev/null +++ b/src/Controls.hpp @@ -0,0 +1,91 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +/** + * @file + * + * Header for ZeroTier service controls + */ + +#ifndef LIBZT_CONTROLS_HPP +#define LIBZT_CONTROLS_HPP + +namespace ZeroTier { + +////////////////////////////////////////////////////////////////////////////// +// ZeroTier Internal Service Controls // +////////////////////////////////////////////////////////////////////////////// + +void postEvent(uint64_t id, int eventCode); + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Starts a ZeroTier service in the background + * + * @usage For internal use only. + * @param + * @return + */ +#if defined(_WIN32) +DWORD WINAPI _zts_run_service(LPVOID thread_id); +#else +void *_zts_run_service(void *thread_id); +#endif + +/** + * @brief [Should not be called from user application] This function must be surrounded by + * ZT service locks. It will determine if it is currently safe and allowed to operate on + * the service. + * @usage Can be called at any time + * @return 1 or 0 + */ +int __zts_can_perform_service_operation(); + +/** + * @brief [Should not be called from user application] Returns whether or not the node is + * online. + * @usage Can be called at any time + * @return 1 or 0 + */ +int __zts_node_online(); + +/** + * @brief [Should not be called from user application] Adjusts the delay multiplier for the + * network stack driver thread. + * @usage Can be called at any time + */ +void _hibernate_if_needed(); + +#ifdef __cplusplus +} +#endif + +} // namespace ZeroTier + +#endif // _H \ No newline at end of file diff --git a/include/Debug.hpp b/src/Debug.hpp similarity index 100% rename from include/Debug.hpp rename to src/Debug.hpp diff --git a/src/Intercept.cpp b/src/Intercept.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/Intercept.hpp b/src/Intercept.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/Options.h b/src/Options.h new file mode 100644 index 0000000..bfd7258 --- /dev/null +++ b/src/Options.h @@ -0,0 +1,59 @@ +#ifndef LIBZT_OPTIONS_H +#define LIBZT_OPTIONS_H + +////////////////////////////////////////////////////////////////////////////// +// Callbacks // +////////////////////////////////////////////////////////////////////////////// + +#define ZTS_NODE_CALLBACKS 1 +#define ZTS_NETWORK_CALLBACKS 1 +#define ZTS_NETIF_CALLBACKS 1 +#define ZTS_PEER_CALLBACKS 1 + +/** + * The maximum number of un-processed callback messages + */ +#define ZTS_CALLBACK_MSG_QUEUE_LEN 256 + +////////////////////////////////////////////////////////////////////////////// +// Timing // +////////////////////////////////////////////////////////////////////////////// + +/** + * How often callback messages are assembled and/or sent + */ +#define ZTS_CALLBACK_PROCESSING_INTERVAL 25 + +/** + * Polling interval (in ms) for file descriptors wrapped in the Phy I/O loop (for raw drivers only) + */ +#define ZTS_PHY_POLL_INTERVAL 1 + +#define ZTS_HOUSEKEEPING_INTERVAL 50 + +/** + * By how much thread I/O and callback loop delays are multiplied (unitless) + */ +#define ZTS_HIBERNATION_MULTIPLIER 50 + +////////////////////////////////////////////////////////////////////////////// +// Thread names // +////////////////////////////////////////////////////////////////////////////// + +#define ZTS_SERVICE_THREAD_NAME "ZeroTierServiceThread" + +#define ZTS_EVENT_CALLBACK_THREAD_NAME "ZeroTierEventCallbackThread" + + + + +#define LWIP_FRAMES_HANDLED_PER_CORE_CALL 16 // How many frames are handled per call from core +#define LWIP_GUARDED_BUF_CHECK_INTERVAL 5 // in ms +#define LWIP_MAX_GUARDED_RX_BUF_SZ 1024 // number of frame pointers that can be cached waiting for receipt into core + + + +#define PEER_CACHING 0 + + +#endif \ No newline at end of file diff --git a/src/RingBuffer.cpp b/src/RingBuffer.cpp deleted file mode 100644 index de3a78c..0000000 --- a/src/RingBuffer.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * Ring buffer implementation for network stack drivers - */ - -#include -#include - -#include "RingBuffer.h" - -bufElementType* RingBuffer::get_buf() -{ - return buf + begin; -} - -size_t RingBuffer::produce(size_t n) -{ - n = std::min(n, getFree()); - if (n == 0) { - return n; - } - const size_t first_chunk = std::min(n, size - end); - end = (end + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - end = (end + second_chunk) % size; - } - if (begin == end) { - wrap = true; - } - return n; -} - -void RingBuffer::reset() -{ - consume(count()); -} - -size_t RingBuffer::consume(size_t n) -{ - n = std::min(n, count()); - if (n == 0) { - return n; - } - if (wrap) { - wrap = false; - } - const size_t first_chunk = std::min(n, size - begin); - begin = (begin + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - begin = (begin + second_chunk) % size; - } - return n; -} - -size_t RingBuffer::write(const bufElementType * data, size_t n) -{ - n = std::min(n, getFree()); - - if (n == 0) { - return n; - } - const size_t first_chunk = std::min(n, size - end); - memcpy(buf + end, data, first_chunk * sizeof(bufElementType)); - end = (end + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - memcpy(buf + end, data + first_chunk, second_chunk * sizeof(bufElementType)); - end = (end + second_chunk) % size; - } - if (begin == end) { - wrap = true; - } - return n; -} - -size_t RingBuffer::read(bufElementType * dest, size_t n) -{ - n = std::min(n, count()); - - if (n == 0) { - return n; - } - if (wrap) { - wrap = false; - } - const size_t first_chunk = std::min(n, size - begin); - memcpy(dest, buf + begin, first_chunk * sizeof(bufElementType)); - begin = (begin + first_chunk) % size; - if (first_chunk < n) { - const size_t second_chunk = n - first_chunk; - memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(bufElementType)); - begin = (begin + second_chunk) % size; - } - return n; -} - -size_t RingBuffer::count() -{ - if (end == begin) { - return wrap ? size : 0; - } - else if (end > begin) { - return end - begin; - } - else { - return size + end - begin; - } -} - -size_t RingBuffer::getFree() -{ - return size - count(); -} - diff --git a/src/Service.cpp b/src/Service.cpp new file mode 100644 index 0000000..5d251f0 --- /dev/null +++ b/src/Service.cpp @@ -0,0 +1,1230 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "version.h" +#include "ZeroTierOne.h" + +#include "OSUtils.hpp" +#include "Constants.hpp" +#include "Mutex.hpp" +#include "Node.hpp" +#include "Utils.hpp" +#include "InetAddress.hpp" +#include "MAC.hpp" +#include "Identity.hpp" +#include "World.hpp" +#include "Salsa20.hpp" +#include "Poly1305.hpp" +#include "SHA512.hpp" + +#include "Phy.hpp" +#include "Thread.hpp" +#include "OSUtils.hpp" +#include "PortMapper.hpp" +#include "Binder.hpp" +#include "ManagedRoute.hpp" +#include "BlockingQueue.hpp" + +#include "Service.hpp" +#include "Debug.hpp" +#include "concurrentqueue.h" + +#include "libzt.h" +#include "lwipDriver.hpp" + +#ifdef __WINDOWS__ +#include +#include +#include +#include +#include +//#include +#define stat _stat +#else +#include +#include +#include +#include +#include +#include +#endif + +// Use the virtual netcon endpoint instead of a tun/tap port driver +#include "VirtualTap.hpp" +namespace ZeroTier { typedef VirtualTap EthernetTap; } + +// Interface metric for ZeroTier taps -- this ensures that if we are on WiFi and also +// bridged via ZeroTier to the same LAN traffic will (if the OS is sane) prefer WiFi. +#define ZT_IF_METRIC 5000 + +// How often to check for new multicast subscriptions on a tap device +#define ZT_TAP_CHECK_MULTICAST_INTERVAL 5000 + +// How often to check for local interface addresses +#define ZT_LOCAL_INTERFACE_CHECK_INTERVAL 60000 + +namespace ZeroTier { + +// Concurrent queue for callback message processing +moodycamel::ConcurrentQueue*> _callbackMsgQueue; + +namespace { + +static std::string _trimString(const std::string &s) +{ + unsigned long end = (unsigned long)s.length(); + while (end) { + char c = s[end - 1]; + if ((c == ' ')||(c == '\r')||(c == '\n')||(!c)||(c == '\t')) + --end; + else break; + } + unsigned long start = 0; + while (start < end) { + char c = s[start]; + if ((c == ' ')||(c == '\r')||(c == '\n')||(!c)||(c == '\t')) + ++start; + else break; + } + return s.substr(start,end - start); +} + +class OneServiceImpl; + +static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf); +static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData); +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len); +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen); +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl); +static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr); +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result); +static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len); + +struct OneServiceIncomingPacket +{ + uint64_t now; + int64_t sock; + struct sockaddr_storage from; + unsigned int size; + uint8_t data[ZT_MAX_MTU]; +}; + +class OneServiceImpl : public OneService +{ +public: + // begin member variables -------------------------------------------------- + + const std::string _homePath; + std::string _authToken; + const std::string _networksPath; + const std::string _moonsPath; + + Phy _phy; + Node *_node; + bool _updateAutoApply; + unsigned int _multipathMode; + unsigned int _primaryPort; + unsigned int _secondaryPort; + unsigned int _tertiaryPort; + volatile unsigned int _udpPortPickerCounter; + + // + std::map peerCache; + + // + unsigned long _incomingPacketConcurrency; + std::vector _incomingPacketMemoryPool; + BlockingQueue _incomingPacketQueue; + std::vector _incomingPacketThreads; + Mutex _incomingPacketMemoryPoolLock,_incomingPacketThreadsLock; + + // Local configuration and memo-ized information from it + Hashtable< uint64_t,std::vector > _v4Hints; + Hashtable< uint64_t,std::vector > _v6Hints; + Hashtable< uint64_t,std::vector > _v4Blacklists; + Hashtable< uint64_t,std::vector > _v6Blacklists; + std::vector< InetAddress > _globalV4Blacklist; + std::vector< InetAddress > _globalV6Blacklist; + std::vector< InetAddress > _allowManagementFrom; + std::vector< std::string > _interfacePrefixBlacklist; + Mutex _localConfig_m; + + std::vector explicitBind; + + /* + * To attempt to handle NAT/gateway craziness we use three local UDP ports: + * + * [0] is the normal/default port, usually 9993 + * [1] is a port derived from our ZeroTier address + * [2] is a port computed from the normal/default for use with uPnP/NAT-PMP mappings + * + * [2] exists because on some gateways trying to do regular NAT-t interferes + * destructively with uPnP port mapping behavior in very weird buggy ways. + * It's only used if uPnP/NAT-PMP is enabled in this build. + */ + unsigned int _ports[3]; + Binder _binder; + + // Time we last received a packet from a global address + uint64_t _lastDirectReceiveFromGlobal; + + // Last potential sleep/wake event + uint64_t _lastRestart; + + // Deadline for the next background task service function + volatile int64_t _nextBackgroundTaskDeadline; + + // Configured networks + struct NetworkState + { + NetworkState() : + tap((EthernetTap *)0) + { + // Real defaults are in network 'up' code in network event handler + settings.allowManaged = true; + settings.allowGlobal = false; + settings.allowDefault = false; + } + + EthernetTap *tap; + ZT_VirtualNetworkConfig config; // memcpy() of raw config from core + std::vector managedIps; + std::list< SharedPtr > managedRoutes; + NetworkSettings settings; + }; + std::map _nets; + Mutex _nets_m; + + // Termination status information + ReasonForTermination _termReason; + std::string _fatalErrorMessage; + Mutex _termReason_m; + + // uPnP/NAT-PMP port mapper if enabled + bool _portMappingEnabled; // local.conf settings +#ifdef ZT_USE_MINIUPNPC + PortMapper *_portMapper; +#endif + + // Set to false to force service to stop + volatile bool _run; + Mutex _run_m; + + // end member variables ---------------------------------------------------- + + OneServiceImpl(const char *hp,unsigned int port) : + _homePath((hp) ? hp : ".") + ,_phy(this,false,true) + ,_node((Node *)0) + ,_updateAutoApply(false) + ,_primaryPort(port) + ,_udpPortPickerCounter(0) + ,_lastDirectReceiveFromGlobal(0) + ,_lastRestart(0) + ,_nextBackgroundTaskDeadline(0) + ,_termReason(ONE_STILL_RUNNING) + ,_portMappingEnabled(true) +#ifdef ZT_USE_MINIUPNPC + ,_portMapper((PortMapper *)0) +#endif + ,_run(true) + { + _ports[0] = 0; + _ports[1] = 0; + _ports[2] = 0; + + _incomingPacketConcurrency = std::max((unsigned long)1,std::min((unsigned long)16,(unsigned long)std::thread::hardware_concurrency())); + char *envPool = std::getenv("INCOMING_PACKET_CONCURRENCY"); + if (envPool != NULL) { + int tmp = atoi(envPool); + if (tmp > 0) { + _incomingPacketConcurrency = tmp; + } + } + for(long t=0;t<_incomingPacketConcurrency;++t) { + _incomingPacketThreads.push_back(std::thread([this]() { + OneServiceIncomingPacket *pkt = nullptr; + for(;;) { + if (!_incomingPacketQueue.get(pkt)) + break; + if (!pkt) + break; + if (!_run) + break; + + const ZT_ResultCode rc = _node->processWirePacket(nullptr,pkt->now,pkt->sock,&(pkt->from),pkt->data,pkt->size,&_nextBackgroundTaskDeadline); + { + Mutex::Lock l(_incomingPacketMemoryPoolLock); + _incomingPacketMemoryPool.push_back(pkt); + } + 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(); + break; + } + } + })); + } + } + + virtual ~OneServiceImpl() + { + _incomingPacketQueue.stop(); + _incomingPacketThreadsLock.lock(); + for(auto t=_incomingPacketThreads.begin();t!=_incomingPacketThreads.end();++t) + t->join(); + _incomingPacketThreadsLock.unlock(); + + _binder.closeAll(_phy); + + _incomingPacketMemoryPoolLock.lock(); + while (!_incomingPacketMemoryPool.empty()) { + delete _incomingPacketMemoryPool.back(); + _incomingPacketMemoryPool.pop_back(); + } + _incomingPacketMemoryPoolLock.unlock(); + +#ifdef ZT_USE_MINIUPNPC + delete _portMapper; +#endif + } + + virtual ReasonForTermination run() + { + try { + { + const std::string authTokenPath(_homePath + ZT_PATH_SEPARATOR_S "authtoken.secret"); + if (!OSUtils::readFile(authTokenPath.c_str(),_authToken)) { + unsigned char foo[24]; + Utils::getSecureRandom(foo,sizeof(foo)); + _authToken = ""; + for(unsigned int i=0;iaddress() % 45500) : _secondaryPort; + for(int i=0;;++i) { + if (i > 1000) { + _ports[1] = 0; + break; + } else if (++_ports[1] >= 65536) { + _ports[1] = 20000; + } + if (_trialBind(_ports[1])) + break; + } + +#ifdef ZT_USE_MINIUPNPC + if (_portMappingEnabled) { + // If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't + // use the other two ports for that because some NATs do really funky + // stuff with ports that are explicitly mapped that breaks things. + if (_ports[1]) { + _ports[2] = (_tertiaryPort == 0) ? _ports[1] : _tertiaryPort; + for(int i=0;;++i) { + if (i > 1000) { + _ports[2] = 0; + break; + } else if (++_ports[2] >= 65536) { + _ports[2] = 20000; + } + if (_trialBind(_ports[2])) + break; + } + if (_ports[2]) { + char uniqueName[64]; + OSUtils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]); + _portMapper = new PortMapper(_ports[2],uniqueName); + } + } + } +#endif + // Main I/O loop + _nextBackgroundTaskDeadline = 0; + int64_t clockShouldBe = OSUtils::now(); + _lastRestart = clockShouldBe; + int64_t lastTapMulticastGroupCheck = 0; + int64_t lastBindRefresh = 0; + int64_t lastUpdateCheck = clockShouldBe; + int64_t lastMultipathModeUpdate = 0; + int64_t lastCleanedPeersDb = 0; + int64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle + int64_t lastLocalConfFileCheck = OSUtils::now(); + for(;;) { + _run_m.lock(); + if (!_run) { + _run_m.unlock(); + _termReason_m.lock(); + _termReason = ONE_NORMAL_TERMINATION; + _termReason_m.unlock(); + break; + } else { + _run_m.unlock(); + } + + const int64_t now = OSUtils::now(); + + // Attempt to detect sleep/wake events by detecting delay overruns + bool restarted = false; + if ((now > clockShouldBe)&&((now - clockShouldBe) > 10000)) { + _lastRestart = now; + restarted = true; + } + + // Refresh bindings in case device's interfaces have changed, and also sync routes to update any shadow routes (e.g. shadow default) + if (((now - lastBindRefresh) >= (_multipathMode ? ZT_BINDER_REFRESH_PERIOD / 8 : ZT_BINDER_REFRESH_PERIOD))||(restarted)) { + lastBindRefresh = now; + unsigned int p[3]; + unsigned int pc = 0; + for(int i=0;i<3;++i) { + if (_ports[i]) + p[pc++] = _ports[i]; + } + _binder.refresh(_phy,p,pc,explicitBind,*this); + } + // Update multipath mode (if needed) + if (((now - lastMultipathModeUpdate) >= ZT_BINDER_REFRESH_PERIOD / 8)||(restarted)) { + lastMultipathModeUpdate = now; + _node->setMultipathMode(_multipathMode); + } + + // + generateEventMsgs(); + + // Run background task processor in core if it's time to do so + int64_t dl = _nextBackgroundTaskDeadline; + if (dl <= now) { + _node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline); + dl = _nextBackgroundTaskDeadline; + } + + // Sync multicast group memberships + if ((now - lastTapMulticastGroupCheck) >= ZT_TAP_CHECK_MULTICAST_INTERVAL) { + lastTapMulticastGroupCheck = now; + std::vector< std::pair< uint64_t,std::pair< std::vector,std::vector > > > mgChanges; + { + Mutex::Lock _l(_nets_m); + mgChanges.reserve(_nets.size() + 1); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + mgChanges.push_back(std::pair< uint64_t,std::pair< std::vector,std::vector > >(n->first,std::pair< std::vector,std::vector >())); + n->second.tap->scanMulticastGroups(mgChanges.back().second.first,mgChanges.back().second.second); + } + } + } + for(std::vector< std::pair< uint64_t,std::pair< std::vector,std::vector > > >::iterator c(mgChanges.begin());c!=mgChanges.end();++c) { + for(std::vector::iterator m(c->second.first.begin());m!=c->second.first.end();++m) + _node->multicastSubscribe((void *)0,c->first,m->mac().toInt(),m->adi()); + for(std::vector::iterator m(c->second.second.begin());m!=c->second.second.end();++m) + _node->multicastUnsubscribe(c->first,m->mac().toInt(),m->adi()); + } + } + + // Sync information about physical network interfaces + if ((now - lastLocalInterfaceAddressCheck) >= (_multipathMode ? ZT_LOCAL_INTERFACE_CHECK_INTERVAL / 8 : ZT_LOCAL_INTERFACE_CHECK_INTERVAL)) { + lastLocalInterfaceAddressCheck = now; + + _node->clearLocalInterfaceAddresses(); + +#ifdef ZT_USE_MINIUPNPC + if (_portMapper) { + std::vector mappedAddresses(_portMapper->get()); + for(std::vector::const_iterator ext(mappedAddresses.begin());ext!=mappedAddresses.end();++ext) + _node->addLocalInterfaceAddress(reinterpret_cast(&(*ext))); + } +#endif + + std::vector boundAddrs(_binder.allBoundLocalInterfaceAddresses()); + for(std::vector::const_iterator i(boundAddrs.begin());i!=boundAddrs.end();++i) + _node->addLocalInterfaceAddress(reinterpret_cast(&(*i))); + } + + // Clean peers.d periodically + if ((now - lastCleanedPeersDb) >= 3600000) { + lastCleanedPeersDb = now; + OSUtils::cleanDirectory((_homePath + ZT_PATH_SEPARATOR_S "peers.d").c_str(),now - 2592000000LL); // delete older than 30 days + } + + const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; + clockShouldBe = now + (uint64_t)delay; + _phy.poll(delay); + } + } catch (std::exception &e) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = std::string("unexpected exception in main thread: ")+e.what(); + } catch ( ... ) { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_UNRECOVERABLE_ERROR; + _fatalErrorMessage = "unexpected exception in main thread: unknown exception"; + } + + { + Mutex::Lock _l(_nets_m); + for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) + delete n->second.tap; + _nets.clear(); + } + + delete _node; + _node = (Node *)0; + + return _termReason; + } + + virtual ReasonForTermination reasonForTermination() const + { + Mutex::Lock _l(_termReason_m); + return _termReason; + } + + virtual std::string fatalErrorMessage() const + { + Mutex::Lock _l(_termReason_m); + return _fatalErrorMessage; + } + + virtual std::string portDeviceName(uint64_t nwid) const + { + Mutex::Lock _l(_nets_m); + std::map::const_iterator n(_nets.find(nwid)); + if ((n != _nets.end())&&(n->second.tap)) + return n->second.tap->deviceName(); + else return std::string(); + } + + virtual std::string givenHomePath() + { + return _homePath; + } + + void getRoutes(uint64_t nwid, void *routeArray, unsigned int *numRoutes) + { + Mutex::Lock _l(_nets_m); + NetworkState &n = _nets[nwid]; + *numRoutes = *numRoutes < n.config.routeCount ? *numRoutes : n.config.routeCount; + for(unsigned int i=0; i<*numRoutes; i++) { + ZT_VirtualNetworkRoute *vnr = (ZT_VirtualNetworkRoute*)routeArray; + memcpy(&vnr[i], &(n.config.routes[i]), sizeof(ZT_VirtualNetworkRoute)); + } + } + + virtual Node *getNode() + { + return _node; + } + + virtual void terminate() + { + _run_m.lock(); + _run = false; + _run_m.unlock(); + _phy.whack(); + } + + virtual bool getNetworkSettings(const uint64_t nwid,NetworkSettings &settings) const + { + Mutex::Lock _l(_nets_m); + std::map::const_iterator n(_nets.find(nwid)); + if (n == _nets.end()) + return false; + settings = n->second.settings; + return true; + } + + // ========================================================================= + // Internal implementation methods for control plane, route setup, etc. + // ========================================================================= + + // Checks if a managed IP or route target is allowed + bool checkIfManagedIsAllowed(const NetworkState &n,const InetAddress &target) + { + if (!n.settings.allowManaged) + return false; + + if (n.settings.allowManagedWhitelist.size() > 0) { + bool allowed = false; + for (InetAddress addr : n.settings.allowManagedWhitelist) { + if (addr.containsAddress(target) && addr.netmaskBits() <= target.netmaskBits()) { + allowed = true; + break; + } + } + if (!allowed) return false; + } + + if (target.isDefaultRoute()) + return n.settings.allowDefault; + switch(target.ipScope()) { + case InetAddress::IP_SCOPE_NONE: + case InetAddress::IP_SCOPE_MULTICAST: + case InetAddress::IP_SCOPE_LOOPBACK: + case InetAddress::IP_SCOPE_LINK_LOCAL: + return false; + case InetAddress::IP_SCOPE_GLOBAL: + return n.settings.allowGlobal; + default: + return true; + } + } + + // Apply or update managed IPs for a configured network (be sure n.tap exists) + void syncManagedStuff(NetworkState &n,bool syncIps,bool syncRoutes) + { + char ipbuf[64]; + // assumes _nets_m is locked + if (syncIps) { + std::vector newManagedIps; + newManagedIps.reserve(n.config.assignedAddressCount); + for(unsigned int i=0;i(&(n.config.assignedAddresses[i])); + if (checkIfManagedIsAllowed(n,*ii)) + newManagedIps.push_back(*ii); + } + std::sort(newManagedIps.begin(),newManagedIps.end()); + newManagedIps.erase(std::unique(newManagedIps.begin(),newManagedIps.end()),newManagedIps.end()); + for(std::vector::iterator ip(n.managedIps.begin());ip!=n.managedIps.end();++ip) { + if (std::find(newManagedIps.begin(),newManagedIps.end(),*ip) == newManagedIps.end()) { + if (!n.tap->removeIp(*ip)) + fprintf(stderr,"ERROR: unable to remove ip address %s" ZT_EOL_S, ip->toString(ipbuf)); + } + } + for(std::vector::iterator ip(newManagedIps.begin());ip!=newManagedIps.end();++ip) { + if (std::find(n.managedIps.begin(),n.managedIps.end(),*ip) == n.managedIps.end()) { + if (!n.tap->addIp(*ip)) + fprintf(stderr,"ERROR: unable to add ip address %s" ZT_EOL_S, ip->toString(ipbuf)); + } + } + n.managedIps.swap(newManagedIps); + } + + } + + // ========================================================================= + // Handlers for Node and Phy<> callbacks + // ========================================================================= + + inline void phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *localAddr,const struct sockaddr *from,void *data,unsigned long len) + { + const uint64_t now = OSUtils::now(); + if ((len >= 16)&&(reinterpret_cast(from)->ipScope() == InetAddress::IP_SCOPE_GLOBAL)) + _lastDirectReceiveFromGlobal = now; + + OneServiceIncomingPacket *pkt; + _incomingPacketMemoryPoolLock.lock(); + if (_incomingPacketMemoryPool.empty()) { + pkt = new OneServiceIncomingPacket; + } else { + pkt = _incomingPacketMemoryPool.back(); + _incomingPacketMemoryPool.pop_back(); + } + _incomingPacketMemoryPoolLock.unlock(); + + pkt->now = now; + pkt->sock = reinterpret_cast(sock); + ZT_FAST_MEMCPY(&(pkt->from),from,sizeof(struct sockaddr_storage)); + pkt->size = (unsigned int)len; + ZT_FAST_MEMCPY(pkt->data,data,len); + + _incomingPacketQueue.postLimit(pkt,16 * _incomingPacketConcurrency); + } + + inline void phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {} + inline void phyOnTcpAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN,const struct sockaddr *from) {} + void phyOnTcpClose(PhySocket *sock,void **uptr) {} + void phyOnTcpData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} + inline void phyOnTcpWritable(PhySocket *sock,void **uptr) {} + inline void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable) {} + inline void phyOnUnixAccept(PhySocket *sockL,PhySocket *sockN,void **uptrL,void **uptrN) {} + inline void phyOnUnixClose(PhySocket *sock,void **uptr) {} + inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {} + inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {} + + inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwc) + { + Mutex::Lock _l(_nets_m); + NetworkState &n = _nets[nwid]; + + switch(op) { + + case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP: + if (!n.tap) { + char friendlyName[128]; + OSUtils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid); + + n.tap = new EthernetTap( + _homePath.c_str(), + MAC(nwc->mac), + nwc->mtu, + (unsigned int)ZT_IF_METRIC, + nwid, + friendlyName, + StapFrameHandler, + (void *)this); + *nuptr = (void *)&n; + } + // After setting up tap, fall through to CONFIG_UPDATE since we also want to do this... + + case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE: + ZT_FAST_MEMCPY(&(n.config),nwc,sizeof(ZT_VirtualNetworkConfig)); + if (n.tap) { // sanity check + syncManagedStuff(n,true,true); + n.tap->setMtu(nwc->mtu); + } else { + _nets.erase(nwid); + return -999; // tap init failed + } + break; + + case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN: + case ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY: + if (n.tap) { // sanity check + *nuptr = (void *)0; + delete n.tap; + _nets.erase(nwid); + } else { + _nets.erase(nwid); + } + break; + + } + return 0; + } + + inline void nodeEventCallback(enum ZT_Event event,const void *metaData) + { + // Feed node events into lock-free queue for later dequeuing by the callback thread + if (event <= ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION) { + _callbackMsgQueue.enqueue(new std::pair(0x0000000000, event)); + } + switch(event) { + case ZT_EVENT_FATAL_ERROR_IDENTITY_COLLISION: { + Mutex::Lock _l(_termReason_m); + _termReason = ONE_IDENTITY_COLLISION; + _fatalErrorMessage = "identity/address collision"; + this->terminate(); + } break; + + case ZT_EVENT_TRACE: { + if (metaData) { + ::fprintf(stderr,"%s" ZT_EOL_S,(const char *)metaData); + ::fflush(stderr); + } + } break; + + default: + break; + } + } + + inline void generateEventMsgs() + { + // Generate messages to be dequeued by the callback message thread +#if ZTS_NETWORK_CALLBACKS + Mutex::Lock _l(_nets_m); + for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) { + int mostRecentStatus = n->second.config.status; + VirtualTap *tap = n->second.tap; + uint64_t nwid = n->first; + if (n->second.tap->_networkStatus == mostRecentStatus) { + continue; // No state change + } + switch (mostRecentStatus) { + case ZT_NETWORK_STATUS_NOT_FOUND: + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_NOT_FOUND)); + break; + case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_CLIENT_TOO_OLD)); + break; + case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_REQUESTING_CONFIG)); + break; + case ZT_NETWORK_STATUS_OK: + if (tap->netif4 && lwip_is_netif_up(tap->netif4)) { + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_READY_IP4)); + } + if (tap->netif6 && lwip_is_netif_up(tap->netif6)) { + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_READY_IP6)); + } + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_OK)); + break; + case ZT_NETWORK_STATUS_ACCESS_DENIED: + _callbackMsgQueue.enqueue(new std::pair(nwid, ZTS_EVENT_NETWORK_ACCESS_DENIED)); + break; + default: + break; + } + n->second.tap->_networkStatus = mostRecentStatus; + } +#endif // ZTS_NETWORK_CALLBACKS +#if ZTS_PEER_CALLBACKS + // TODO: Add ZTS_EVENT_PEER_NEW + ZT_PeerList *pl = _node->peers(); + if (pl) { + for(unsigned long i=0;ipeerCount;++i) { + if (!peerCache.count(pl->peers[i].address)) { // Add first entry + if (pl->peers[i].pathCount > 0) { + _callbackMsgQueue.enqueue(new std::pair(pl->peers[i].address, ZTS_EVENT_PEER_P2P)); + } + if (pl->peers[i].pathCount == 0) { + _callbackMsgQueue.enqueue(new std::pair(pl->peers[i].address, ZTS_EVENT_PEER_RELAY)); + } + } else { + if (peerCache[pl->peers[i].address] == 0 && pl->peers[i].pathCount > 0) { + _callbackMsgQueue.enqueue(new std::pair(pl->peers[i].address, ZTS_EVENT_PEER_P2P)); + } + if (peerCache[pl->peers[i].address] > 0 && pl->peers[i].pathCount == 0) { + _callbackMsgQueue.enqueue(new std::pair(pl->peers[i].address, ZTS_EVENT_PEER_RELAY)); + } + } + peerCache[pl->peers[i].address] = pl->peers[i].pathCount; + } + } + _node->freeQueryResult((void *)pl); +#endif // ZTS_PEER_CALLBACKS + } + + inline int networkCount() + { + Mutex::Lock _l(_nets_m); + return _nets.size(); + } + + inline void join(uint64_t nwid) + { + _node->join(nwid, NULL, NULL); + } + + inline void leave(uint64_t nwid) + { + _node->leave(nwid, NULL, NULL); + } + + inline void leaveAll() + { + Mutex::Lock _l(_nets_m); + for(std::map::iterator n(_nets.begin());n!=_nets.end();++n) { + _node->leave(n->first, NULL, NULL); + } + } + + inline int getPeerStatus(uint64_t id) + { + ZT_PeerList *pl = _node->peers(); + int status = ZTS_EVENT_PEER_UNREACHABLE; + if (pl) { + for(unsigned long i=0;ipeerCount;++i) { + if (pl->peers[i].address == id) { + status = pl->peers[i].pathCount > 0 ? ZTS_EVENT_PEER_P2P : ZTS_EVENT_PEER_RELAY; + break; + } + } + } + _node->freeQueryResult((void *)pl); + return status; + } + + inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) + { + char p[1024]; + FILE *f; + bool secure = false; + char dirname[1024]; + dirname[0] = 0; + + switch(type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + secure = true; + break; + case ZT_STATE_OBJECT_PLANET: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + break; +#if PEER_CACHING + case ZT_STATE_OBJECT_PEER: + OSUtils::ztsnprintf(dirname,sizeof(dirname),"%s" ZT_PATH_SEPARATOR_S "peers.d",_homePath.c_str()); + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "%.10llx.peer",dirname,(unsigned long long)id[0]); + break; +#endif + default: + return; + } + + if (len >= 0) { + // Check to see if we've already written this first. This reduces + // redundant writes and I/O overhead on most platforms and has + // little effect on others. + f = fopen(p,"rb"); + if (f) { + char buf[65535]; + long l = (long)fread(buf,1,sizeof(buf),f); + fclose(f); + if ((l == (long)len)&&(memcmp(data,buf,l) == 0)) + return; + } + + f = fopen(p,"wb"); + if ((!f)&&(dirname[0])) { // create subdirectory if it does not exist + OSUtils::mkdir(dirname); + f = fopen(p,"wb"); + } + if (f) { + if (fwrite(data,len,1,f) != 1) + fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p); + fclose(f); + if (secure) + OSUtils::lockDownFile(p,false); + } else { + fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p); + } + } else { + OSUtils::rm(p); + } + } + + inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) + { + char p[4096]; + switch(type) { + case ZT_STATE_OBJECT_IDENTITY_PUBLIC: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_IDENTITY_SECRET: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str()); + break; + case ZT_STATE_OBJECT_PLANET: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str()); + break; +#if PEER_CACHING + case ZT_STATE_OBJECT_PEER: + OSUtils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "peers.d" ZT_PATH_SEPARATOR_S "%.10llx.peer",_homePath.c_str(),(unsigned long long)id[0]); + break; +#endif + default: + return -1; + } + FILE *f = fopen(p,"rb"); + if (f) { + int n = (int)fread(data,1,maxlen,f); + fclose(f); + if (n >= 0) + return n; + } + return -1; + } + + inline int nodeWirePacketSendFunction(const int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) + { + // 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. + + if ((localSocket != -1)&&(localSocket != 0)&&(_binder.isUdpSocketValid((PhySocket *)((uintptr_t)localSocket)))) { + if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),ttl); + const bool r = _phy.udpSend((PhySocket *)((uintptr_t)localSocket),(const struct sockaddr *)addr,data,len); + if ((ttl)&&(addr->ss_family == AF_INET)) _phy.setIp4UdpTtl((PhySocket *)((uintptr_t)localSocket),255); + return ((r) ? 0 : -1); + } else { + return ((_binder.udpSendAll(_phy,addr,data,len,ttl)) ? 0 : -1); + } + } + + inline void nodeVirtualNetworkFrameFunction(uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) + { + NetworkState *n = reinterpret_cast(*nuptr); + if ((!n)||(!n->tap)) + return; + n->tap->put(MAC(sourceMac),MAC(destMac),etherType,data,len); + } + + inline int nodePathCheckFunction(uint64_t ztaddr,const int64_t localSocket,const struct sockaddr_storage *remoteAddr) + { + // Make sure we're not trying to do ZeroTier-over-ZeroTier + { + Mutex::Lock _l(_nets_m); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + std::vector ips(n->second.tap->ips()); + for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { + if (i->containsAddress(*(reinterpret_cast(remoteAddr)))) { + return 0; + } + } + } + } + } + + /* Note: I do not think we need to scan for overlap with managed routes + * because of the "route forking" and interface binding that we do. This + * ensures (we hope) that ZeroTier traffic will still take the physical + * path even if its managed routes override this for other traffic. Will + * revisit if we see recursion problems. */ + + // Check blacklists + const Hashtable< uint64_t,std::vector > *blh = (const Hashtable< uint64_t,std::vector > *)0; + const std::vector *gbl = (const std::vector *)0; + if (remoteAddr->ss_family == AF_INET) { + blh = &_v4Blacklists; + gbl = &_globalV4Blacklist; + } else if (remoteAddr->ss_family == AF_INET6) { + blh = &_v6Blacklists; + gbl = &_globalV6Blacklist; + } + if (blh) { + Mutex::Lock _l(_localConfig_m); + const std::vector *l = blh->get(ztaddr); + if (l) { + for(std::vector::const_iterator a(l->begin());a!=l->end();++a) { + if (a->containsAddress(*reinterpret_cast(remoteAddr))) + return 0; + } + } + } + if (gbl) { + for(std::vector::const_iterator a(gbl->begin());a!=gbl->end();++a) { + if (a->containsAddress(*reinterpret_cast(remoteAddr))) + return 0; + } + } + return 1; + } + + inline int nodePathLookupFunction(uint64_t ztaddr,int family,struct sockaddr_storage *result) + { + const Hashtable< uint64_t,std::vector > *lh = (const Hashtable< uint64_t,std::vector > *)0; + if (family < 0) + lh = (_node->prng() & 1) ? &_v4Hints : &_v6Hints; + else if (family == AF_INET) + lh = &_v4Hints; + else if (family == AF_INET6) + lh = &_v6Hints; + else return 0; + const std::vector *l = lh->get(ztaddr); + if ((l)&&(l->size() > 0)) { + ZT_FAST_MEMCPY(result,&((*l)[(unsigned long)_node->prng() % l->size()]),sizeof(struct sockaddr_storage)); + return 1; + } else return 0; + } + + inline void tapFrameHandler(uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) + { + _node->processVirtualNetworkFrame((void *)0,OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&_nextBackgroundTaskDeadline); + } + + bool shouldBindInterface(const char *ifname,const InetAddress &ifaddr) + { +#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) + if ((ifname[0] == 'l')&&(ifname[1] == 'o')) return false; // loopback + if ((ifname[0] == 'z')&&(ifname[1] == 't')) return false; // sanity check: zt# + if ((ifname[0] == 't')&&(ifname[1] == 'u')&&(ifname[2] == 'n')) return false; // tun# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 't')&&(ifname[1] == 'a')&&(ifname[2] == 'p')) return false; // tap# is probably an OpenVPN tunnel or similar +#endif + +#ifdef __APPLE__ + if ((ifname[0] == 'f')&&(ifname[1] == 'e')&&(ifname[2] == 't')&&(ifname[3] == 'h')) return false; // ... as is feth# + if ((ifname[0] == 'l')&&(ifname[1] == 'o')) return false; // loopback + if ((ifname[0] == 'z')&&(ifname[1] == 't')) return false; // sanity check: zt# + if ((ifname[0] == 't')&&(ifname[1] == 'u')&&(ifname[2] == 'n')) return false; // tun# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 't')&&(ifname[1] == 'a')&&(ifname[2] == 'p')) return false; // tap# is probably an OpenVPN tunnel or similar + if ((ifname[0] == 'u')&&(ifname[1] == 't')&&(ifname[2] == 'u')&&(ifname[3] == 'n')) return false; // ... as is utun# +#endif + + { + Mutex::Lock _l(_localConfig_m); + for(std::vector::const_iterator p(_interfacePrefixBlacklist.begin());p!=_interfacePrefixBlacklist.end();++p) { + if (!strncmp(p->c_str(),ifname,p->length())) + return false; + } + } + { + // Check global blacklists + const std::vector *gbl = (const std::vector *)0; + if (ifaddr.ss_family == AF_INET) { + gbl = &_globalV4Blacklist; + } else if (ifaddr.ss_family == AF_INET6) { + gbl = &_globalV6Blacklist; + } + if (gbl) { + Mutex::Lock _l(_localConfig_m); + for(std::vector::const_iterator a(gbl->begin());a!=gbl->end();++a) { + if (a->containsAddress(ifaddr)) + return false; + } + } + } + { + Mutex::Lock _l(_nets_m); + for(std::map::const_iterator n(_nets.begin());n!=_nets.end();++n) { + if (n->second.tap) { + std::vector ips(n->second.tap->ips()); + for(std::vector::const_iterator i(ips.begin());i!=ips.end();++i) { + if (i->ipsEqual(ifaddr)) + return false; + } + } + } + } + + return true; + } + + bool _trialBind(unsigned int port) + { + struct sockaddr_in in4; + struct sockaddr_in6 in6; + PhySocket *tb; + + memset(&in4,0,sizeof(in4)); + in4.sin_family = AF_INET; + in4.sin_port = Utils::hton((uint16_t)port); + tb = _phy.udpBind(reinterpret_cast(&in4),(void *)0,0); + if (tb) { + _phy.close(tb,false); + tb = _phy.tcpListen(reinterpret_cast(&in4),(void *)0); + if (tb) { + _phy.close(tb,false); + return true; + } + } + + memset(&in6,0,sizeof(in6)); + in6.sin6_family = AF_INET6; + in6.sin6_port = Utils::hton((uint16_t)port); + tb = _phy.udpBind(reinterpret_cast(&in6),(void *)0,0); + if (tb) { + _phy.close(tb,false); + tb = _phy.tcpListen(reinterpret_cast(&in6),(void *)0); + if (tb) { + _phy.close(tb,false); + return true; + } + } + + return false; + } +}; + +static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf) +{ return reinterpret_cast(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); } +static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData) +{ reinterpret_cast(uptr)->nodeEventCallback(event,metaData); } +static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len) +{ reinterpret_cast(uptr)->nodeStatePutFunction(type,id,data,len); } +static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen) +{ return reinterpret_cast(uptr)->nodeStateGetFunction(type,id,data,maxlen); } +static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,int64_t localSocket,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl) +{ return reinterpret_cast(uptr)->nodeWirePacketSendFunction(localSocket,addr,data,len,ttl); } +static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) +{ reinterpret_cast(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); } +static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int64_t localSocket,const struct sockaddr_storage *remoteAddr) +{ return reinterpret_cast(uptr)->nodePathCheckFunction(ztaddr,localSocket,remoteAddr); } +static int SnodePathLookupFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,int family,struct sockaddr_storage *result) +{ return reinterpret_cast(uptr)->nodePathLookupFunction(ztaddr,family,result); } +static void StapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) +{ reinterpret_cast(uptr)->tapFrameHandler(nwid,from,to,etherType,vlanId,data,len); } + +} // anonymous namespace + +std::string OneService::platformDefaultHomePath() +{ + return OSUtils::platformDefaultHomePath(); +} + +OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); } +OneService::~OneService() {} + +} // namespace ZeroTier diff --git a/src/Service.hpp b/src/Service.hpp new file mode 100644 index 0000000..d977c5e --- /dev/null +++ b/src/Service.hpp @@ -0,0 +1,203 @@ +/* + * ZeroTier SDK - Network Virtualization Everywhere + * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * You can be released from the requirements of the license by purchasing + * a commercial license. Buying such a license is mandatory as soon as you + * develop commercial closed-source software that incorporates or links + * directly against ZeroTier software without disclosing the source code + * of your own application. + */ + +#ifndef ZT_ONESERVICE_HPP +#define ZT_ONESERVICE_HPP + +#include +#include + +#ifdef SDK_JNI +#include +#endif + +namespace ZeroTier { + +class VirtualTap; +// Use the virtual libzt endpoint instead of a tun/tap port driver +namespace ZeroTier { typedef VirtualTap EthernetTap; } + +// Forward declaration so we can avoid dragging everything in +struct InetAddress; +class Node; + +/** + * Local service for ZeroTier One as system VPN/NFV provider + */ +class OneService +{ +public: + + /** + * Returned by node main if/when it terminates + */ + enum ReasonForTermination + { + /** + * Instance is still running + */ + ONE_STILL_RUNNING = 0, + + /** + * Normal shutdown + */ + ONE_NORMAL_TERMINATION = 1, + + /** + * A serious unrecoverable error has occurred + */ + ONE_UNRECOVERABLE_ERROR = 2, + + /** + * Your identity has collided with another + */ + ONE_IDENTITY_COLLISION = 3 + }; + + /** + * Local settings for each network + */ + struct NetworkSettings + { + /** + * Allow this network to configure IP addresses and routes? + */ + bool allowManaged; + + /** + * Whitelist of addresses that can be configured by this network. + * If empty and allowManaged is true, allow all private/pseudoprivate addresses. + */ + std::vector allowManagedWhitelist; + + /** + * Allow configuration of IPs and routes within global (Internet) IP space? + */ + bool allowGlobal; + + /** + * Allow overriding of system default routes for "full tunnel" operation? + */ + bool allowDefault; + }; + + /** + * @return Platform default home path or empty string if this platform doesn't have one + */ + static std::string platformDefaultHomePath(); + + /** + * Create a new instance of the service + * + * Once created, you must call the run() method to actually start + * processing. + * + * The port is saved to a file in the home path called zerotier-one.port, + * which is used by the CLI and can be used to see which port was chosen if + * 0 (random port) is picked. + * + * @param hp Home path + * @param port TCP and UDP port for packets and HTTP control (if 0, pick random port) + */ + static OneService *newInstance(const char *hp,unsigned int port); + + virtual ~OneService(); + + /** + * Execute the service main I/O loop until terminated + * + * The terminate() method may be called from a signal handler or another + * thread to terminate execution. Otherwise this will not return unless + * another condition terminates execution such as a fatal error. + */ + virtual ReasonForTermination run() = 0; + + /** + * @return Reason for terminating or ONE_STILL_RUNNING if running + */ + virtual ReasonForTermination reasonForTermination() const = 0; + + /** + * @return Fatal error message or empty string if none + */ + virtual std::string fatalErrorMessage() const = 0; + + /** + * @return System device name corresponding with a given ZeroTier network ID or empty string if not opened yet or network ID not found + */ + virtual std::string portDeviceName(uint64_t nwid) const = 0; + + /** + * Whether we allow access to the service via local HTTP requests (disabled by default in libzt) + */ + bool allowHttpBackplaneManagement = false; + + /** + * @return Reference to the Node + */ + virtual Node * getNode() = 0; + + /** + * Fills out a structure with network-specific route information + */ + virtual void getRoutes(uint64_t nwid, void *routeArray, unsigned int *numRoutes) = 0; + + virtual int networkCount() = 0; + virtual void leaveAll() = 0; + virtual void join(uint64_t nwid) = 0; + virtual void leave(uint64_t nwid) = 0; + virtual int getPeerStatus(uint64_t id) = 0; + + /** + * Terminate background service (can be called from other threads) + */ + virtual void terminate() = 0; + + /** + * Get local settings for a network + * + * @param nwid Network ID + * @param settings Buffer to fill with local network settings + * @return True if network was found and settings is filled + */ + virtual bool getNetworkSettings(const uint64_t nwid,NetworkSettings &settings) const = 0; + + /** + * @return True if service is still running + */ + inline bool isRunning() const { return (this->reasonForTermination() == ONE_STILL_RUNNING); } + +protected: + OneService() {} + +private: + OneService(const OneService &one) {} + inline OneService &operator=(const OneService &one) { return *this; } +}; + +} // namespace ZeroTier + +#endif diff --git a/src/ServiceControls.cpp b/src/ServiceControls.cpp deleted file mode 100644 index faf1e30..0000000 --- a/src/ServiceControls.cpp +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2019 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - -/** - * @file - * - * ZeroTier service controls - */ - -#include - -#include "OneService.hpp" -#include "Node.hpp" -#include "ZeroTierOne.h" - -#include "Constants.hpp" -#include "lwIP.h" -#include "OSUtils.hpp" -#include "ServiceControls.hpp" -#include "VirtualTap.hpp" -#include "Defs.hpp" - -#include "lwip/stats.h" - -#if defined(_WIN32) -WSADATA wsaData; -#include -#endif - -#ifdef SDK_JNI -#include -#endif - -struct zts_network_details; -struct zts_peer_details; -struct zts_network_details; - -namespace ZeroTier { - -class VirtualTap; - -/* - * A lock used to protect any call which relies on the presence of a valid pointer - * to the ZeroTier service. - */ -Mutex _service_lock; - -/* - * A lock which protects flags and state variables used during the startup and - * shutdown phase. - */ -Mutex _startup_lock; - -/* - * A lock used to protect callback method pointers. With a coarser-grained lock it - * would be possible for one thread to alter the callback method pointer causing - * undefined behaviour. - */ -Mutex _callback_lock; - -std::string homeDir; -int servicePort = ZTS_DEFAULT_PORT; -bool _freeHasBeenCalled = false; -bool _serviceIsShuttingDown = false; -bool _startupError = false; -bool _nodeIsOnlineToggle = false; - -pthread_t service_thread; -pthread_t callback_thread; - -// Collection of virtual tap interfaces -std::map vtapMap; -Mutex _vtaps_lock; - -// Global reference to ZeroTier service -OneService *zt1Service; - - -// User-provided callback for ZeroTier events -void (*_userCallbackFunc)(uint64_t, int); -#ifdef SDK_JNI -// Global references to JNI objects and VM kept for future callbacks -static JavaVM *jvm = NULL; -jobject objRef = NULL; -jmethodID _userCallbackMethodRef = NULL; -#endif - -std::map peerCache; - -////////////////////////////////////////////////////////////////////////////// -// Internal ZeroTier Service Controls (user application shall not use these)// -////////////////////////////////////////////////////////////////////////////// - -std::queue*> _callbackMsgQueue; - -void _push_callback_event(uint64_t nwid, int eventCode) -{ - _callback_lock.lock(); - if (_callbackMsgQueue.size() >= ZTS_CALLBACK_MSG_QUEUE_LEN) { - DEBUG_ERROR("too many callback messages in queue (see: ZTS_CALLBACK_MSG_QUEUE_LEN)"); - _callback_lock.unlock(); - return; - } - _callbackMsgQueue.push(new std::pair(nwid,eventCode)); - _callback_lock.unlock(); -} - -void _process_callback_event_helper(uint64_t nwid, int eventCode) -{ -#ifdef SDK_JNI - if(_userCallbackMethodRef) { - JNIEnv *env; - jint rs = jvm->AttachCurrentThread(&env, NULL); - assert (rs == JNI_OK); - env->CallVoidMethod(objRef, _userCallbackMethodRef, nwid, eventCode); - } -#else - if (_userCallbackFunc) { - _userCallbackFunc(nwid, eventCode); - } -#endif -} - -void _process_callback_event(uint64_t nwid, int eventCode) -{ - _callback_lock.lock(); - _process_callback_event_helper(nwid, eventCode); - _callback_lock.unlock(); -} - -bool _is_callback_registered() -{ - _callback_lock.lock(); - bool retval = false; -#ifdef SDK_JNI - retval = (jvm && objRef && _userCallbackMethodRef); -#else - retval = _userCallbackFunc; -#endif - _callback_lock.unlock(); - return retval; -} - -void _clear_registered_callback() -{ - _callback_lock.lock(); -#ifdef SDK_JNI - objRef = NULL; - _userCallbackMethodRef = NULL; -#else - _userCallbackFunc = NULL; -#endif - _callback_lock.unlock(); -} - -void _api_sleep(int interval_ms) -{ -#if defined(_WIN32) - Sleep(interval_ms); -#else - struct timespec sleepValue = {0}; - sleepValue.tv_nsec = interval_ms * 500000; - nanosleep(&sleepValue, NULL); -#endif -} - -int _zts_node_online() -{ - return zt1Service && zt1Service->getNode() && zt1Service->getNode()->online(); -} - -int _zts_can_perform_service_operation() -{ - return zt1Service && zt1Service->isRunning() && zt1Service->getNode() && zt1Service->getNode()->online() && !_serviceIsShuttingDown; -} - -void _hibernate_if_needed() -{ - _vtaps_lock.lock(); - if (vtapMap.size()) { - lwip_wake_driver(); - } else { - lwip_hibernate_driver(); - } - _vtaps_lock.unlock(); -} -#ifdef SDK_JNI -#endif - -/* - * Monitors the conditions required for triggering callbacks into user code. This was made - * into its own thread to prevent user application abuse of callbacks from affecting - * the timing of more sensitive aspects of the library such as polling and packet processing - */ -#if defined(_WIN32) -DWORD WINAPI _zts_monitor_callback_conditions(LPVOID thread_id) -#else -void *_zts_monitor_callback_conditions(void *thread_id) -#endif -{ -#if defined(__APPLE__) - pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); -#endif - - while (true) - { - if (_serviceIsShuttingDown) { - break; - } - _service_lock.lock(); - _callback_lock.lock(); - -#if ZTS_NODE_CALLBACKS - // ZT Node states - if (!_zts_node_online()) { - if (_nodeIsOnlineToggle) { - _nodeIsOnlineToggle = false; - _process_callback_event_helper((uint64_t)0, ZTS_EVENT_NODE_OFFLINE); - } - _service_lock.unlock(); - _callback_lock.unlock(); - _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL); - // Only process pending network callbacks if the node is online - continue; - } - if (_zts_node_online()) { - uint64_t nodeId = 0; - if (_zts_can_perform_service_operation()) { - nodeId = zt1Service->getNode()->address(); - } - if (!_nodeIsOnlineToggle) { - _nodeIsOnlineToggle = true; - _process_callback_event_helper(nodeId, ZTS_EVENT_NODE_ONLINE); - } - } -#endif - - // Handle messages placed in the message queue - while (_callbackMsgQueue.size()) { - std::pair *msg = _callbackMsgQueue.front(); - _callbackMsgQueue.pop(); -#if ZTS_NETIF_CALLBACKS - // lwIP netif - if (msg->second & (ZTS_EVENT_NETIF_STATUS_CHANGE)) { - _vtaps_lock.lock(); - if (!vtapMap.count(msg->first)) { - if (msg->second & (ZTS_EVENT_GENERIC_DOWN)) { - _process_callback_event_helper(msg->first, msg->second); - } - delete msg; - msg = NULL; - _vtaps_lock.unlock(); - continue; - } - if (msg->second == ZTS_EVENT_NETIF_UP_IP4 && vtapMap[msg->first]->_networkStatus == ZTS_EVENT_NETWORK_OK) { - _process_callback_event_helper(msg->first, ZTS_EVENT_NETWORK_READY_IP4); - } - if (msg->second == ZTS_EVENT_NETIF_UP_IP6 && vtapMap[msg->first]->_networkStatus == ZTS_EVENT_NETWORK_OK) { - _process_callback_event_helper(msg->first, ZTS_EVENT_NETWORK_READY_IP6); - } - if (msg->second & (ZTS_EVENT_NETIF_STATUS_CHANGE)) { - vtapMap[msg->first]->_netifStatus = msg->second; - } - _vtaps_lock.unlock(); - _process_callback_event_helper(msg->first, msg->second); - } -#endif // ZTS_NETIF_CALLBACKS - delete msg; - msg = NULL; - } - -#if ZTS_NETIF_CALLBACKS // Section for non-queued lwIP netif messages - // lwIP netif states - _vtaps_lock.lock(); - if (vtapMap.size()) { - std::map::iterator it; - for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - VirtualTap *vtap = (VirtualTap*)it->second; - uint64_t eventCode = vtap->recognizeLowerLevelInterfaceStateChange(vtap->netif4); - if (eventCode != ZTS_EVENT_NONE) { - _process_callback_event_helper(vtap->_nwid, eventCode); - } - eventCode = vtap->recognizeLowerLevelInterfaceStateChange(vtap->netif6); - if (eventCode != ZTS_EVENT_NONE) { - _process_callback_event_helper(vtap->_nwid, eventCode); - } - } - } - _vtaps_lock.unlock(); -#endif // ZTS_NETIF_CALLBACKS - -#if ZTS_PEER_CALLBACKS - // TODO: Add peerCache clearning mechanism - // TODO: Add ZTS_EVENT_PEER_NEW message? - ZT_PeerList *pl = zt1Service->getNode()->peers(); - if (pl) { - for(unsigned long i=0;ipeerCount;++i) { - if (!peerCache.count(pl->peers[i].address)) { // Add first entry - if (pl->peers[i].pathCount > 0) { - _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_P2P); - } - if (pl->peers[i].pathCount == 0) { - _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_RELAY); - } - } - else { - if (peerCache[pl->peers[i].address] == 0 && pl->peers[i].pathCount > 0) { - _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_P2P); - } - if (peerCache[pl->peers[i].address] > 0 && pl->peers[i].pathCount == 0) { - _process_callback_event_helper(pl->peers[i].address, ZTS_EVENT_PEER_RELAY); - } - } - peerCache[pl->peers[i].address] = pl->peers[i].pathCount; - } - } - zt1Service->getNode()->freeQueryResult((void *)pl); -#endif // ZTS_PEER_CALLBACKS - -#if ZTS_NETWORK_CALLBACKS - - _vtaps_lock.lock(); - // Second, inspect network states for changes we should report - // TODO: Use proper ZT callback mechanism - // TODO: _push_callback_event(_nwid, ZTS_EVENT_NETWORK_DOWN); - ZT_VirtualNetworkList *nl = zt1Service->getNode()->networks(); - for(unsigned long i=0;inetworkCount;++i) { - OneService::NetworkSettings localSettings; - zt1Service->getNetworkSettings(nl->networks[i].nwid,localSettings); - if (!vtapMap.count(nl->networks[i].nwid)) { - continue; - } - if (vtapMap[nl->networks[i].nwid]->_networkStatus == nl->networks[i].status) { - continue; // no state change - } - VirtualTap *vtap = vtapMap[nl->networks[i].nwid]; - uint64_t nwid = nl->networks[i].nwid; - switch (nl->networks[i].status) { - case ZT_NETWORK_STATUS_NOT_FOUND: - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_NOT_FOUND); - break; - case ZT_NETWORK_STATUS_CLIENT_TOO_OLD: - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_CLIENT_TOO_OLD); - break; - case ZT_NETWORK_STATUS_REQUESTING_CONFIGURATION: - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_REQUESTING_CONFIG); - break; - case ZT_NETWORK_STATUS_OK: - if (vtap->netif4 && lwip_is_netif_up(vtap->netif4)) { - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_READY_IP4); - } - if (vtap->netif6 && lwip_is_netif_up(vtap->netif6)) { - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_READY_IP6); - } - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_OK); - break; - case ZT_NETWORK_STATUS_ACCESS_DENIED: - _process_callback_event_helper(nwid, ZTS_EVENT_NETWORK_ACCESS_DENIED); - break; - default: - break; - } - vtapMap[nwid]->_networkStatus = nl->networks[i].status; - } - _vtaps_lock.unlock(); - zt1Service->getNode()->freeQueryResult((void *)nl); - -#endif // ZTS_NETWORK_CALLBACKS - - // Finally, check for a more useful definition of "readiness" - /* - std::map::iterator it; - for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - VirtualTap *tap = it->second; - if (tap->_lastConfigUpdateTime > 0 && !tap->_lastReadyReportTime && tap->_ips.size() > 0) { - tap->_lastReadyReportTime = tap->_lastConfigUpdateTime; - _process_callback_event(tap->_nwid, ZTS_EVENT_NETWORK_READY); - } - }*/ - _service_lock.unlock(); - _callback_lock.unlock(); - _api_sleep(ZTS_CALLBACK_PROCESSING_INTERVAL); - } - DEBUG_INFO("exited from callback processing loop"); - pthread_exit(0); -} - -// Starts a ZeroTier service in the background -#if defined(_WIN32) -DWORD WINAPI _zts_start_service(LPVOID thread_id) -#else -void *_zts_start_service(void *thread_id) -#endif -{ -#if defined(__APPLE__) - pthread_setname_np(ZTS_SERVICE_THREAD_NAME); -#endif - void *retval; - zt1Service = (OneService *)0; - - if (!homeDir.length()) { - DEBUG_ERROR("homeDir is empty, could not construct path"); - _startupError = true; - retval = NULL; - } if (zt1Service) { - DEBUG_INFO("service already started, doing nothing"); - retval = NULL; - } - try { - std::vector hpsp(OSUtils::split(homeDir.c_str(), ZT_PATH_SEPARATOR_S,"","")); - std::string ptmp; - if (homeDir[0] == ZT_PATH_SEPARATOR) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - for (std::vector::iterator pi(hpsp.begin());pi!=hpsp.end();++pi) { - if (ptmp.length() > 0) { - ptmp.push_back(ZT_PATH_SEPARATOR); - } - ptmp.append(*pi); - if ((*pi != ".")&&(*pi != "..")) { - if (OSUtils::mkdir(ptmp) == false) { - DEBUG_ERROR("home path does not exist, and could not create"); - _startupError = true; - retval = NULL; - perror("error\n"); - } - } - } - if (!_startupError) { - for(;;) { - _service_lock.lock(); - zt1Service = OneService::newInstance(homeDir.c_str(),servicePort); - _service_lock.unlock(); - switch(zt1Service->run()) { - case OneService::ONE_STILL_RUNNING: - case OneService::ONE_NORMAL_TERMINATION: - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_NORMAL_TERMINATION); - break; - case OneService::ONE_UNRECOVERABLE_ERROR: - DEBUG_ERROR("fatal error: %s", zt1Service->fatalErrorMessage().c_str()); - _startupError = true; - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_UNRECOVERABLE_ERROR); - break; - case OneService::ONE_IDENTITY_COLLISION: { - _startupError = true; - delete zt1Service; - zt1Service = (OneService *)0; - std::string oldid; - OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),oldid); - if (oldid.length()) { - OSUtils::writeFile((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret.saved_after_collision").c_str(),oldid); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.secret").c_str()); - OSUtils::rm((homeDir + ZT_PATH_SEPARATOR_S + "identity.public").c_str()); - } - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_IDENTITY_COLLISION); - } continue; // restart! - } - break; // terminate loop -- normally we don't keep restarting - } - } - - _serviceIsShuttingDown = true; - _service_lock.lock(); - delete zt1Service; - zt1Service = (OneService *)0; - _service_lock.unlock(); - _serviceIsShuttingDown = false; - _process_callback_event((uint64_t)0, ZTS_EVENT_NODE_DOWN); - DEBUG_INFO("exiting zt service thread"); - } catch ( ... ) { - DEBUG_ERROR("unexpected exception starting ZeroTier instance"); - } - pthread_exit(0); -} - -#ifdef __cplusplus -extern "C" { -#endif - -////////////////////////////////////////////////////////////////////////////// -// ZeroTier Service Controls // -////////////////////////////////////////////////////////////////////////////// - -#ifdef SDK_JNI -/* - * Called from Java, saves a reference to the VM so it can be used later to call - * a user-specified callback method from C. - */ -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_init(JNIEnv *env, jobject thisObj) -{ - jint rs = env->GetJavaVM(&jvm); - assert (rs == JNI_OK); -} -#endif - -zts_err_t zts_set_service_port(int portno) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (zt1Service) { - // Stop service before attempting to set a port - retval = ZTS_ERR_SERVICE; - } - else { - if (portno > -1 && portno < ZTS_MAX_PORT) { - // 0 is allowed, signals to ZT service to bind to a random port - servicePort = portno; - retval = ZTS_ERR_OK; - } - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_set_1service_1port( - JNIEnv *env, jobject thisObj, jint port) -{ - zts_set_service_port(port); -} -#endif - -int zts_get_service_port() -{ - return servicePort; -} -#ifdef SDK_JNI -JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1service_1port( - JNIEnv *env, jobject thisObj) -{ - return zts_get_service_port(); -} -#endif - -zts_err_t zts_join(const uint64_t nwid, int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - - _vtaps_lock.lock(); - retval = vtapMap.size() >= ZTS_MAX_JOINED_NETWORKS ? ZTS_ERR_INVALID_OP : ZTS_ERR_OK; - _vtaps_lock.unlock(); - - if (retval == ZTS_ERR_OK) { - _service_lock.lock(); - if (blocking) { - if (!zt1Service) { - retval = ZTS_ERR_SERVICE; - } else { - while (!_zts_node_online()) { - if (_serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - break; - } - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - } - } - } else { - if (!zt1Service || !_zts_node_online()) { - retval = ZTS_ERR_SERVICE; - } - } - if (retval == ZTS_ERR_OK) { - if (nwid == 0) { - retval = ZTS_ERR_INVALID_ARG; - } - if (zt1Service) { - zt1Service->getNode()->join(nwid, NULL, NULL); - } - } - _service_lock.unlock(); - } - return retval; -} -#ifdef SDK_JNI -JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_join( - JNIEnv *env, jobject thisObj, jlong nwid) -{ - return zts_join((uint64_t)nwid); -} -#endif - -zts_err_t zts_leave(const uint64_t nwid, int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (blocking) { - if (!zt1Service) { - retval = ZTS_ERR_SERVICE; - } else { - while (!_zts_node_online()) { - if (_serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - break; - } - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - } - } - } else { - if (!zt1Service || !_zts_node_online()) { - retval = ZTS_ERR_SERVICE; - } - } - if (retval == ZTS_ERR_OK) { - if (nwid == 0) { - retval = ZTS_ERR_INVALID_ARG; - } - if (zt1Service) { - zt1Service->getNode()->leave(nwid, NULL, NULL); - } - } - _vtaps_lock.lock(); - vtapMap.erase(nwid); - _vtaps_lock.unlock(); - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_leave( - JNIEnv *env, jobject thisObj, jlong nwid) -{ - return zts_leave((uint64_t)nwid); -} -#endif - -zts_err_t zts_leave_all(int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - /* - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - else { - struct zts_network_details nds[ZTS_MAX_JOINED_NETWORKS]; - int numJoined = ZTS_MAX_JOINED_NETWORKS; - zts_get_all_network_details(nds, &numJoined); - for (int i=0; igetNode()->orbit(tptr, moonWorldId, moonSeed); - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -zts_err_t zts_deorbit(uint64_t moonWorldId) -{ - zts_err_t retval = ZTS_ERR_OK; - void *tptr = NULL; - _service_lock.lock(); - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - else if (_zts_can_perform_service_operation()) { - zt1Service->getNode()->deorbit(tptr, moonWorldId); - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -int zts_core_running() -{ - _service_lock.lock(); - int retval = zt1Service == NULL ? false : zt1Service->isRunning(); - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_core_1running( - JNIEnv *env, jobject thisObj) -{ - return zts_core_running(); -} -#endif - -int zts_ready() -{ - _service_lock.lock(); - _vtaps_lock.lock(); - bool stackRunning = vtapMap.size() > 0 ? true : false; - _vtaps_lock.unlock(); - _service_lock.unlock(); - return zts_core_running() && stackRunning; -} -#ifdef SDK_JNI -JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_ready( - JNIEnv *env, jobject thisObj) -{ - return zts_ready(); -} -#endif - -zts_err_t zts_start_with_callback(const char *path, void (*callback)(uint64_t, int), int blocking) -{ - _startup_lock.lock(); - zts_err_t retval = ZTS_ERR_OK; - if (zt1Service) { - // Service is already initialized - retval = ZTS_ERR_SERVICE; - } - if (_freeHasBeenCalled) { - // Stack (presumably lwIP) has been dismantled, an application restart is required now - retval = ZTS_ERR_INVALID_OP; - } - if (!path) { - retval = ZTS_ERR_INVALID_ARG; - } - - _userCallbackFunc = callback; - - if (retval == ZTS_ERR_OK) { - homeDir = path; -#if defined(_WIN32) - // initialize WinSock. Used in Phy for loopback pipe - WSAStartup(MAKEWORD(2, 2), &wsaData); - HANDLE serviceThread = CreateThread(NULL, 0, _zts_start_service, NULL, 0, NULL); - if (_is_callback_registered()) { - HANDLE callbackThread = CreateThread(NULL, 0, _zts_monitor_callback_conditions, NULL, 0, NULL); - } - // TODO: Add thread names on Windows (optional) -#else - _startupError = false; - retval = pthread_create(&service_thread, NULL, _zts_start_service, NULL); -#if defined(__linux__) - pthread_setname_np(service_thread, ZTS_SERVICE_THREAD_NAME); -#endif - if (_is_callback_registered()) { - retval = pthread_create(&callback_thread, NULL, _zts_monitor_callback_conditions, NULL); -#if defined(__linux__) - pthread_setname_np(callback_thread, ZTS_EVENT_CALLBACK_THREAD_NAME); -#endif - } - // Wait for confirmation that the ZT service has been initialized, - // this wait condition is so brief and so rarely used that it should be - // acceptable even in a non-blocking context. - while(!zt1Service) { - if (_serviceIsShuttingDown || _startupError) { - // ZT service startup/binding might have failed for some reason - retval = ZTS_ERR_SERVICE; - break; - } - _api_sleep(10); - } -#endif - if (blocking && retval == ZTS_ERR_OK) { - // block to prevent service calls before we're ready - // waiting for zerotier service thread to start - while (zts_core_running() == false || zt1Service->getNode() == NULL) { - if (_serviceIsShuttingDown || _startupError) { - // ZT service startup/binding might have failed for some reason - retval = ZTS_ERR_SERVICE; - break; - } - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - } - if (retval == ZTS_ERR_OK) { - // waiting for node address assignment - while (zt1Service->getNode()->address() <= 0) { - if (_serviceIsShuttingDown || _startupError) { - retval = ZTS_ERR_SERVICE; - break; - } - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - } - } - if (retval == ZTS_ERR_OK) { - // Waiting for node to come online. Ensure the node is authorized to join the network - while (true) { - _service_lock.lock(); - if (_serviceIsShuttingDown || _startupError) { - retval = ZTS_ERR_SERVICE; - break; - } - if (zt1Service && zt1Service->getNode() && zt1Service->getNode()->online()) { - // Node is fully online - break; - } - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - _service_lock.unlock(); - } - _service_lock.unlock(); - } - } - } - _startup_lock.unlock(); - return retval; -} - -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_start_1with_1callback( - JNIEnv *env, jobject thisObj, jstring path, jobject userCallbackClass) -{ - jclass eventListenerClass = env->GetObjectClass(userCallbackClass); - if(eventListenerClass == NULL) { - DEBUG_ERROR("Couldn't find class for ZeroTierEventListener instance"); - return; - } - jmethodID eventListenerCallbackMethod = env->GetMethodID(eventListenerClass, "onZeroTierEvent", "(JI)V"); - if(eventListenerCallbackMethod == NULL) { - DEBUG_ERROR("Couldn't find onZeroTierEvent method"); - return; - } - objRef = env->NewGlobalRef(userCallbackClass); // Reference used for later calls - _userCallbackMethodRef = eventListenerCallbackMethod; - if (path) { - const char* utf_string = env->GetStringUTFChars(path, NULL); - zts_start_with_callback(utf_string, NULL, false); - env->ReleaseStringUTFChars(path, utf_string); - } -} -#endif - -zts_err_t zts_start(const char *path, int blocking = false) -{ - return zts_start_with_callback(path, NULL, blocking); -} -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_start( - JNIEnv *env, jobject thisObj, jstring path, jboolean blocking) -{ - if (path) { - const char* utf_string = env->GetStringUTFChars(path, NULL); - zts_start(utf_string, blocking); - env->ReleaseStringUTFChars(path, utf_string); - } -} -#endif - -zts_err_t zts_startjoin(const char *path, const uint64_t nwid) -{ - zts_err_t retval = ZTS_ERR_OK; - if ((retval = zts_start(path, true)) < 0) { - return retval; - } - while (true) { - try { - zts_join(nwid); - break; - } - catch( ... ) { - _api_sleep(ZTS_WRAPPER_CHECK_INTERVAL); - retval = ZTS_ERR_SERVICE; - } - } - return retval; -} -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_startjoin( - JNIEnv *env, jobject thisObj, jstring path, jlong nwid) -{ - if (path && nwid) { - const char* utf_string = env->GetStringUTFChars(path, NULL); - zts_startjoin(utf_string, (uint64_t)nwid); - env->ReleaseStringUTFChars(path, utf_string); - } -} -#endif - -zts_err_t zts_stop(int blocking) -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - // leave all networks - /* - _vtaps_lock.lock(); - if (vtapMap.size()) { - std::map::iterator it; - for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - VirtualTap *vtap = (VirtualTap*)it->second; - zt1Service->getNode()->leave(vtap->_nwid, NULL, NULL); - } - vtapMap.clear(); - } - _vtaps_lock.unlock(); - */ - // begin shutdown - peerCache.clear(); // TODO: Ensure this is locked correctly - bool didStop = false; - if (_zts_can_perform_service_operation()) { - _serviceIsShuttingDown = true; - zt1Service->terminate(); - didStop = true; - } - else { - // Nothing to do - retval = ZTS_ERR_SERVICE; - } -#if defined(_WIN32) - WSACleanup(); -#endif - _service_lock.unlock(); - if (blocking && retval == ZTS_ERR_OK && didStop) { - // Block until ZT service thread successfully exits - pthread_join(service_thread, NULL); - } - _clear_registered_callback(); - return retval; -} -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_stop( - JNIEnv *env, jobject thisObj) -{ - zts_stop(); -} -#endif - -zts_err_t zts_free() -{ - zts_err_t retval = 0; - _service_lock.lock(); - if (_freeHasBeenCalled) { - retval = ZTS_ERR_INVALID_OP; - _service_lock.unlock(); - } else { - _freeHasBeenCalled = true; - _service_lock.unlock(); - retval = zts_stop(); - } - // PENDING: add stack shutdown logic - return retval; -} -#ifdef SDK_JNI -JNIEXPORT void JNICALL Java_com_zerotier_libzt_ZeroTier_free( - JNIEnv *env, jobject thisObj) -{ - zts_free(); -} -#endif - -uint64_t zts_get_node_id() -{ - uint64_t nodeId = 0; - _service_lock.lock(); - if (_zts_can_perform_service_operation()) { - nodeId = zt1Service->getNode()->address(); - } - _service_lock.unlock(); - return nodeId; -} -#ifdef SDK_JNI -JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1node_1id( - JNIEnv *env, jobject thisObj) -{ - return zts_get_node_id(); -} -#endif - -int zts_get_peer_count() -{ - unsigned int peerCount = 0; - _service_lock.lock(); - if (_zts_can_perform_service_operation()) { - peerCount = zt1Service->getNode()->peers()->peerCount; - } else { - peerCount = ZTS_ERR_SERVICE; - } - _service_lock.unlock(); - return peerCount; -} -#ifdef SDK_JNI -JNIEXPORT jlong JNICALL Java_com_zerotier_libzt_ZeroTier_get_1peer_1count( - JNIEnv *env, jobject thisObj) -{ - return zts_get_peer_count(); -} -#endif - -int zts_get_peers(struct zts_peer_details *pds, int *num) -{ - zts_err_t retval = ZTS_ERR_OK; - if (!pds || !num) { - retval = ZTS_ERR_INVALID_ARG; - } - if (retval == ZTS_ERR_OK) { - _service_lock.lock(); - if (_zts_can_perform_service_operation()) { - ZT_PeerList *pl = zt1Service->getNode()->peers(); - if (pl) { - *num = pl->peerCount; - for(unsigned long i=0;ipeerCount;++i) { - memcpy(&(pds[i]), &(pl->peers[i]), sizeof(struct zts_peer_details)); - } - } - } - else { - retval = ZTS_ERR_SERVICE; - } - _service_lock.unlock(); - } - return retval; -} -#ifdef SDK_JNI -#endif - -zts_err_t zts_get_num_joined_networks() -{ - zts_err_t retval = ZTS_ERR_OK; - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - else { - _vtaps_lock.lock(); - retval = vtapMap.size(); - _vtaps_lock.unlock(); - } - return retval; -} -#ifdef SDK_JNI -JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_get_1num_1joined_1networks( - JNIEnv *env, jobject thisObj) -{ - return zts_get_num_joined_networks(); -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// Network Details // -////////////////////////////////////////////////////////////////////////////// - -void __get_network_details_helper(uint64_t nwid, struct zts_network_details *nd) -{ - socklen_t addrlen; - VirtualTap *tap = vtapMap[nwid]; - nd->nwid = tap->_nwid; - nd->mtu = tap->_mtu; - // assigned addresses - nd->num_addresses = tap->_ips.size() < ZTS_MAX_ASSIGNED_ADDRESSES ? tap->_ips.size() : ZTS_MAX_ASSIGNED_ADDRESSES; - for (int j=0; jnum_addresses; j++) { - addrlen = tap->_ips[j].isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - memcpy(&(nd->addr[j]), &(tap->_ips[j]), addrlen); - } - // routes - nd->num_routes = ZTS_MAX_NETWORK_ROUTES;; - zt1Service->getRoutes(nwid, (ZT_VirtualNetworkRoute*)&(nd->routes)[0], &(nd->num_routes)); -} - -void _get_network_details(uint64_t nwid, struct zts_network_details *nd) -{ - _vtaps_lock.lock(); - __get_network_details_helper(nwid, nd); - _vtaps_lock.unlock(); -} - -void _get_all_network_details(struct zts_network_details *nds, int *num) -{ - _vtaps_lock.lock(); - *num = vtapMap.size(); - int idx = 0; - std::map::iterator it; - for (it = vtapMap.begin(); it != vtapMap.end(); it++) { - _get_network_details(it->first, &nds[idx]); - idx++; - } - _vtaps_lock.unlock(); -} - -zts_err_t zts_get_network_details(uint64_t nwid, struct zts_network_details *nd) -{ - _service_lock.lock(); - zts_err_t retval = ZTS_ERR_OK; - if (!nd || nwid == 0) { - retval = ZTS_ERR_INVALID_ARG; - } - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - if (retval == ZTS_ERR_OK) { - _get_network_details(nwid, nd); - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -zts_err_t zts_get_all_network_details(struct zts_network_details *nds, int *num) -{ - _service_lock.lock(); - zts_err_t retval = ZTS_ERR_OK; - if (!nds || !num) { - retval = ZTS_ERR_INVALID_ARG; - } - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - if (retval == ZTS_ERR_OK) { - _get_all_network_details(nds, num); - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -////////////////////////////////////////////////////////////////////////////// -// HTTP Backplane // -////////////////////////////////////////////////////////////////////////////// - -zts_err_t zts_enable_http_backplane_mgmt() -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - else { - zt1Service->allowHttpBackplaneManagement = true; - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -zts_err_t zts_disable_http_backplane_mgmt() -{ - zts_err_t retval = ZTS_ERR_OK; - _service_lock.lock(); - if (!zt1Service || _freeHasBeenCalled || _serviceIsShuttingDown) { - retval = ZTS_ERR_SERVICE; - } - else { - zt1Service->allowHttpBackplaneManagement = false; - } - _service_lock.unlock(); - return retval; -} -#ifdef SDK_JNI -#endif - -#ifdef __cplusplus -} -#endif - -} // namespace ZeroTier \ No newline at end of file diff --git a/src/libzt.cpp b/src/Sockets.cpp similarity index 82% rename from src/libzt.cpp rename to src/Sockets.cpp index 8e1d520..f43fe21 100644 --- a/src/libzt.cpp +++ b/src/Sockets.cpp @@ -33,9 +33,12 @@ #include #include "lwip/sockets.h" -#include "Defs.hpp" +#include "lwip/def.h" + #include "libzt.h" +#include "Options.h" #include "Debug.hpp" +#include "Controls.hpp" #ifdef SDK_JNI #include @@ -45,67 +48,27 @@ //#include //#include #endif +#endif -#ifdef __cplusplus -extern "C" { - -#endif - void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); - void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); - void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set); - void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_set); -#ifdef __cplusplus -} -#endif -#endif +namespace ZeroTier { ////////////////////////////////////////////////////////////////////////////// // Socket API // ////////////////////////////////////////////////////////////////////////////// +extern bool _run_service; +extern bool _run_lwip_tcpip; + #ifdef __cplusplus extern "C" { #endif -// Custom errno to prevent conflicts with platform's own errno -int zts_errno; - -// lwIP prototypes copied from lwip/src/include/sockets.h -// Don't call these directly, call zts_* functions instead -int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_shutdown(int s, int how); -int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); -int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); -int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); - int lwip_close(int s); -int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); -int lwip_listen(int s, int backlog); -ssize_t lwip_recv(int s, void *mem, size_t len, int flags); -ssize_t lwip_read(int s, void *mem, size_t len); -ssize_t lwip_readv(int s, const struct iovec *iov, int iovcnt); -ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen); -ssize_t lwip_recvmsg(int s, struct msghdr *message, int flags); -ssize_t lwip_send(int s, const void *dataptr, size_t size, int flags); -ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); -ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen); -int lwip_socket(int domain, int type, int protocol); -ssize_t lwip_write(int s, const void *dataptr, size_t size); -ssize_t lwip_writev(int s, const struct iovec *iov, int iovcnt); -#if LWIP_SOCKET_SELECT -int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, - struct timeval *timeout); +#ifdef SDK_JNI +void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); +void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr); +void ztfdset2fdset(JNIEnv *env, int nfds, jobject src_ztfd_set, fd_set *dest_fd_set); +void fdset2ztfdset(JNIEnv *env, int nfds, fd_set *src_fd_set, jobject dest_ztfd_set); #endif -#if LWIP_SOCKET_POLL -int lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout); -#endif -int lwip_ioctl(int s, long cmd, void *argp); -int lwip_fcntl(int s, int cmd, int val); -const char *lwip_inet_ntop(int af, const void *src, char *dst, socklen_t size); -int lwip_inet_pton(int af, const char *src, void *dst); // Copied from lwip/src/include/sockets.h and renamed to prevent a name collision // with system definitions @@ -119,11 +82,11 @@ struct lwip_sockaddr { // ZeroTier Socket API // ////////////////////////////////////////////////////////////////////////////// -int zts_ready(); +extern int zts_errno; int zts_socket(int socket_family, int socket_type, int protocol) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_socket(socket_family, socket_type, protocol); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_socket(socket_family, socket_type, protocol); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_socket( @@ -142,7 +105,7 @@ int zts_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) if (addrlen > (int)sizeof(struct sockaddr_storage) || addrlen < (int)sizeof(struct sockaddr_in)) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_connect(fd, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_connect(fd, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_connect( @@ -164,7 +127,7 @@ int zts_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) if (addrlen > (int)sizeof(struct sockaddr_storage) || addrlen < (int)sizeof(struct sockaddr_in)) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_bind(fd, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_bind(fd, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_bind( @@ -180,7 +143,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_bind( int zts_listen(int fd, int backlog) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_listen(fd, backlog); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_listen(fd, backlog); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_listen( @@ -193,7 +156,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_listen( int zts_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_accept(fd, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_accept(fd, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept( @@ -210,7 +173,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_accept( #if defined(__linux__) int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - return !zts_ready() ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; } #endif #ifdef SDK_JNI @@ -229,7 +192,7 @@ int zts_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) int zts_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_setsockopt(fd, level, optname, optval, optlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_setsockopt(fd, level, optname, optval, optlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( @@ -279,7 +242,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_setsockopt( int zts_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_getsockopt(fd, level, optname, optval, optlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_getsockopt(fd, level, optname, optval, optlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getsockopt( @@ -340,7 +303,7 @@ int zts_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) if (*addrlen > (int)sizeof(struct sockaddr_storage) || *addrlen < (int)sizeof(struct sockaddr_in)) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_getsockname(fd, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_getsockname(fd, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jboolean JNICALL Java_com_zerotier_libzt_ZeroTier_getsockname(JNIEnv *env, jobject thisObj, @@ -362,7 +325,7 @@ int zts_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) if (*addrlen > (int)sizeof(struct sockaddr_storage) || *addrlen < (int)sizeof(struct sockaddr_in)) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_getpeername(fd, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_getpeername(fd, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getpeername(JNIEnv *env, jobject thisObj, @@ -377,23 +340,23 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_getpeername(JNIEnv *env, int zts_gethostname(char *name, size_t len) { - return !zts_ready() ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; // TODO + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; // TODO } #ifdef SDK_JNI #endif int zts_sethostname(const char *name, size_t len) { - return !zts_ready() ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; // TODO + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_INVALID_OP : ZTS_ERR_INVALID_OP; // TODO } #ifdef SDK_JNI #endif +/* struct hostent *zts_gethostbyname(const char *name) { - return (struct hostent *)(!zts_ready() ? NULL : NULL); + return (struct hostent *)((!_run_service || !_run_lwip_tcpip) ? NULL : NULL); // TODO: Test thread safety - /* char buf[256]; int buflen = 256; int h_err = 0; @@ -409,14 +372,14 @@ struct hostent *zts_gethostbyname(const char *name) return *result; return lwip_gethostbyname(name); - */ } #ifdef SDK_JNI #endif +*/ int zts_close(int fd) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_close(fd); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_close(fd); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_close( @@ -429,7 +392,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_close( int zts_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_select(nfds, readfds, writefds, exceptfds, timeout); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_select(nfds, readfds, writefds, exceptfds, timeout); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_select(JNIEnv *env, jobject thisObj, @@ -482,7 +445,7 @@ int zts_fcntl(int fd, int cmd, int flags) translated_flags = 1; } #endif - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_fcntl(fd, cmd, translated_flags); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_fcntl(fd, cmd, translated_flags); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_fcntl( @@ -498,7 +461,7 @@ int zts_ioctl(int fd, unsigned long request, void *argp) if (!argp) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_ioctl(fd, request, argp); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_ioctl(fd, request, argp); } #ifdef SDK_JNI JNIEXPORT int JNICALL Java_com_zerotier_libzt_ZeroTier_ioctl( @@ -532,7 +495,7 @@ ssize_t zts_send(int fd, const void *buf, size_t len, int flags) if (!buf || len <= 0) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_send(fd, buf, len, flags); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_send(fd, buf, len, flags); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_send( @@ -554,7 +517,7 @@ ssize_t zts_sendto(int fd, const void *buf, size_t len, int flags, if (addrlen > (int)sizeof(struct sockaddr_storage) || addrlen < (int)sizeof(struct sockaddr_in)) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_sendto(fd, buf, len, flags, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_sendto(fd, buf, len, flags, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_sendto( @@ -572,7 +535,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_sendto( ssize_t zts_sendmsg(int fd, const struct msghdr *msg, int flags) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_sendmsg(fd, msg, flags); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_sendmsg(fd, msg, flags); } #ifdef SDK_JNI #endif @@ -582,7 +545,7 @@ ssize_t zts_recv(int fd, void *buf, size_t len, int flags) if (!buf) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_recv(fd, buf, len, flags); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_recv(fd, buf, len, flags); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recv(JNIEnv *env, jobject thisObj, @@ -601,7 +564,7 @@ ssize_t zts_recvfrom(int fd, void *buf, size_t len, int flags, if (!buf) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_recvfrom(fd, buf, len, flags, addr, addrlen); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_recvfrom(fd, buf, len, flags, addr, addrlen); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recvfrom( @@ -619,7 +582,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_recvfrom( ssize_t zts_recvmsg(int fd, struct msghdr *msg, int flags) { - return !zts_ready() ? ZTS_ERR_SERVICE : -1; // Not currently implemented by stack + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : -1; // Not currently implemented by stack } #ifdef SDK_JNI #endif @@ -629,7 +592,7 @@ int zts_read(int fd, void *buf, size_t len) if (!buf) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_read(fd, buf, len); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_read(fd, buf, len); } int zts_read_offset(int fd, void *buf, size_t offset, size_t len) { @@ -637,7 +600,7 @@ int zts_read_offset(int fd, void *buf, size_t offset, size_t len) return ZTS_ERR_INVALID_ARG; } char *cbuf = (char*)buf; - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_read(fd, &(cbuf[offset]), len); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_read(fd, &(cbuf[offset]), len); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_read(JNIEnv *env, jobject thisObj, @@ -671,7 +634,7 @@ int zts_write(int fd, const void *buf, size_t len) if (!buf || len <= 0) { return ZTS_ERR_INVALID_ARG; } - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_write(fd, buf, len); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_write(fd, buf, len); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write__IB(JNIEnv *env, jobject thisObj, @@ -700,7 +663,7 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_write_1byte(JNIEnv *env, int zts_shutdown(int fd, int how) { - return !zts_ready() ? ZTS_ERR_SERVICE : lwip_shutdown(fd, how); + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : lwip_shutdown(fd, how); } #ifdef SDK_JNI JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_shutdown( @@ -712,14 +675,14 @@ JNIEXPORT jint JNICALL Java_com_zerotier_libzt_ZeroTier_shutdown( int zts_add_dns_nameserver(struct sockaddr *addr) { - return !zts_ready() ? ZTS_ERR_SERVICE : -1; // TODO + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : -1; // TODO } #ifdef SDK_JNI #endif int zts_del_dns_nameserver(struct sockaddr *addr) { - return !zts_ready() ? ZTS_ERR_SERVICE : -1; // TODO + return (!_run_service || !_run_lwip_tcpip) ? ZTS_ERR_SERVICE : -1; // TODO } #ifdef SDK_JNI #endif @@ -778,7 +741,7 @@ void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) { struct sockaddr_in *in4 = (struct sockaddr_in*)ss; jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, ntohs(in4->sin_port)); + (*env).SetIntField(addr, fid, lwip_ntohs(in4->sin_port)); fid = (*env).GetFieldID(c,"_family", "I"); (*env).SetIntField(addr, fid, (in4->sin_family)); fid = env->GetFieldID(c, "_ip4", "[B"); @@ -794,7 +757,7 @@ void ss2zta(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - (*env).SetIntField(addr, fid, ntohs(in6->sin6_port)); + (*env).SetIntField(addr, fid, lwip_ntohs(in6->sin6_port)); fid = (*env).GetFieldID(c,"_family", "I"); (*env).SetIntField(addr, fid, (in6->sin6_family)); fid = env->GetFieldID(c, "_ip6", "[B"); @@ -819,7 +782,7 @@ void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) { struct sockaddr_in *in4 = (struct sockaddr_in*)ss; fid = (*env).GetFieldID(c, "_port", "I"); - in4->sin_port = htons((*env).GetIntField(addr, fid)); + in4->sin_port = lwip_htons((*env).GetIntField(addr, fid)); in4->sin_family = AF_INET; fid = env->GetFieldID(c, "_ip4", "[B"); jobject ipData = (*env).GetObjectField (addr, fid); @@ -833,7 +796,7 @@ void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) { struct sockaddr_in6 *in6 = (struct sockaddr_in6*)ss; jfieldID fid = (*env).GetFieldID(c, "_port", "I"); - in6->sin6_port = htons((*env).GetIntField(addr, fid)); + in6->sin6_port = lwip_htons((*env).GetIntField(addr, fid)); fid = (*env).GetFieldID(c,"_family", "I"); in6->sin6_family = AF_INET6; fid = env->GetFieldID(c, "_ip6", "[B"); @@ -850,3 +813,5 @@ void zta2ss(JNIEnv *env, struct sockaddr_storage *ss, jobject addr) #ifdef __cplusplus } #endif + +} // namespace ZeroTier diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index 76a287d..e5c7cea 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -35,13 +35,12 @@ #include "Node.hpp" #include "OSUtils.hpp" -#include "Constants.hpp" // libzt -#include "ServiceControls.hpp" -#include "OneService.hpp" +#include "Service.hpp" extern void _push_callback_event(uint64_t nwid, int eventCode); #include "Mutex.hpp" -#include "lwIP.h" +#include "lwipDriver.hpp" +#include "libzt.h" #ifdef _MSC_VER #include "Synchapi.h" @@ -51,10 +50,7 @@ namespace ZeroTier { class VirtualTap; -extern OneService *zt1Service; -extern void (*_userCallbackFunc)(uint64_t, int); -extern std::map vtapMap; -extern Mutex _vtaps_lock; +extern OneService *service; /** * A virtual tap device. The ZeroTier core service creates one of these for each @@ -86,11 +82,6 @@ VirtualTap::VirtualTap( snprintf(vtap_full_name, sizeof(vtap_full_name), "libzt%llx", (unsigned long long)_nwid); _dev = vtap_full_name; ::pipe(_shutdownSignalPipe); - - _vtaps_lock.lock(); - vtapMap[_nwid] = this; - _vtaps_lock.unlock(); - lwip_driver_init(); // Start virtual tap thread and stack I/O loops _thread = Thread::start(this); @@ -198,10 +189,10 @@ std::string VirtualTap::deviceName() const std::string VirtualTap::nodeId() const { - if (zt1Service) { - char id[ZTS_ID_LEN]; + if (service) { + char id[16]; memset(id, 0, sizeof(id)); - sprintf(id, "%llx", (unsigned long long)((OneService *)zt1Service)->getNode()->address()); + sprintf(id, "%llx", (unsigned long long)((OneService *)service)->getNode()->address()); return std::string(id); } else { @@ -283,74 +274,9 @@ void VirtualTap::threadMain() void VirtualTap::Housekeeping() { -/* - Mutex::Lock _l(_tap_m); - OneService *service = ((OneService *)zt1Service); - if (!service) { - return; - } - nd.num_routes = ZTS_MAX_NETWORK_ROUTES; - service->getRoutes(this->_nwid, (ZT_VirtualNetworkRoute*)&(nd.routes)[0], &(nd.num_routes)); -*/ - -/* - InetAddress target_addr; - InetAddress via_addr; - InetAddress null_addr; - InetAddress nm; - null_addr.fromString(""); - bool found; - char ipbuf[INET6_ADDRSTRLEN], ipbuf2[INET6_ADDRSTRLEN], ipbuf3[INET6_ADDRSTRLEN]; - - // TODO: Rework this when we have time - // check if pushed route exists in tap (add) - /* - for (int i=0; iat(i).target; - via_addr = managed_routes->at(i).via; - nm = target_addr.netmask(); - for (size_t j=0; j", target_addr.toString(ipbuf), nm.toString(ipbuf2), via_addr.toString(ipbuf3)); - routes.push_back(std::pair(target_addr, nm)); - routeAdd(target_addr, nm, via_addr); - } - } - } - // check if route exists in tap but not in pushed routes (remove) - for (size_t i=0; iat(j).target; - via_addr = managed_routes->at(j).via; - nm = target_addr.netmask(); - if (routes[i].first.ipsEqual(target_addr) && routes[i].second.ipsEqual(nm)) { - found=true; - } - } - if (found == false) { - DEBUG_INFO("removing route to <%s,%s>", routes[i].first.toString(ipbuf), routes[i].second.toString(ipbuf2)); - routes.erase(routes.begin() + i); - routeDelete(routes[i].first, routes[i].second); - } - } -*/ + // } -////////////////////////////////////////////////////////////////////////////// -// Not used in this implementation // -////////////////////////////////////////////////////////////////////////////// - void VirtualTap::phyOnDatagram(PhySocket *sock,void **uptr,const struct sockaddr *local_address, const struct sockaddr *from,void *data,unsigned long len) {} void VirtualTap::phyOnTcpConnect(PhySocket *sock,void **uptr,bool success) {} diff --git a/include/VirtualTap.hpp b/src/VirtualTap.hpp similarity index 99% rename from include/VirtualTap.hpp rename to src/VirtualTap.hpp index 6fe509e..03eda32 100644 --- a/include/VirtualTap.hpp +++ b/src/VirtualTap.hpp @@ -43,7 +43,7 @@ extern int errno; #include "MulticastGroup.hpp" #include "Mutex.hpp" -#include "Defs.hpp" +#include "Options.h" #if defined(_WIN32) #include diff --git a/src/lwIP.cpp b/src/lwipDriver.cpp similarity index 88% rename from src/lwIP.cpp rename to src/lwipDriver.cpp index 9a776cc..faf95d0 100644 --- a/src/lwIP.cpp +++ b/src/lwipDriver.cpp @@ -30,15 +30,10 @@ * lwIP network stack driver */ -#include #include #include "MAC.hpp" - #include "Mutex.hpp" -#include "Constants.hpp" -#include "VirtualTap.hpp" -#include "Constants.hpp" // libzt #include "netif/ethernet.h" #include "lwip/netif.h" @@ -53,15 +48,23 @@ #include "lwip/ethip6.h" #include "lwip/ip_addr.h" #include "lwip/nd6.h" -#include "lwip/dns.h" #include "lwip/netifapi.h" -#include "lwIP.h" +#include "VirtualTap.hpp" +#include "lwipDriver.hpp" +#include "libzt.h" +#include "Controls.hpp" +extern void postEvent(uint64_t id, int eventCode); #if defined(_WIN32) #include #endif +/** + * Length of human-readable MAC address string + */ +#define ZTS_MAC_ADDRSTRLEN 18 + namespace ZeroTier { bool main_loop_exited = false; @@ -69,13 +72,12 @@ bool lwip_driver_initialized = false; bool has_already_been_initialized = false; int hibernationDelayMultiplier = 1; +extern bool _run_lwip_tcpip; + Mutex driver_m; std::queue rx_queue; -ZeroTier::Mutex _rx_input_lock_m; - -extern void _push_callback_event(uint64_t nwid, int eventCode); -extern void _process_callback_event_helper(uint64_t nwid, int eventCode); +Mutex _rx_input_lock_m; void lwip_hibernate_driver() { @@ -93,6 +95,8 @@ static void tcpip_init_done(void *arg) sys_sem_t *sem; sem = (sys_sem_t *)arg; lwip_driver_initialized = true; + _run_lwip_tcpip = true; + postEvent((uint64_t)0, ZTS_EVENT_NETWORK_STACK_UP); driver_m.unlock(); sys_sem_signal(sem); } @@ -157,6 +161,7 @@ static void main_lwip_driver_loop(void *arg) tcpip_callback_with_block(my_tcpip_callback, NULL, 1); } main_loop_exited = true; + _run_lwip_tcpip = false; } // Initialize the lwIP stack @@ -191,14 +196,16 @@ void lwip_driver_shutdown() while(!main_loop_exited) { usleep(LWIP_GUARDED_BUF_CHECK_INTERVAL*1000); } + /* if (tcpip_shutdown() == ERR_OK) { sys_timeouts_free(); } + */ } void lwip_dispose_of_netifs(void *tapref) { - ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)tapref; + VirtualTap *vtap = (VirtualTap*)tapref; if (vtap->netif4) { netif_remove((struct netif*)(vtap->netif4)); netif_set_down((struct netif*)(vtap->netif4)); @@ -222,7 +229,7 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) char *bufptr; int totalLength = 0; - ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap*)netif->state; + VirtualTap *tap = (VirtualTap*)netif->state; bufptr = buf; for (q = p; q != NULL; q = q->next) { memcpy(bufptr, q->payload, q->len); @@ -232,56 +239,54 @@ err_t lwip_eth_tx(struct netif *netif, struct pbuf *p) struct eth_hdr *ethhdr; ethhdr = (struct eth_hdr *)buf; - ZeroTier::MAC src_mac; - ZeroTier::MAC dest_mac; + MAC src_mac; + MAC dest_mac; src_mac.setTo(ethhdr->src.addr, 6); dest_mac.setTo(ethhdr->dest.addr, 6); char *data = buf + sizeof(struct eth_hdr); int len = totalLength - sizeof(struct eth_hdr); - int proto = ZeroTier::Utils::ntoh((uint16_t)ethhdr->type); + int proto = Utils::ntoh((uint16_t)ethhdr->type); tap->_handler(tap->_arg, NULL, tap->_nwid, src_mac, dest_mac, proto, 0, data, len); /* if (ZT_MSG_TRANSFER == true) { char flagbuf[32]; memset(&flagbuf, 0, 32); - char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[ZTS_ID_LEN]; + char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16]; snprintf(macBuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", ethhdr->dest.addr[0], ethhdr->dest.addr[1], ethhdr->dest.addr[2], ethhdr->dest.addr[3], ethhdr->dest.addr[4], ethhdr->dest.addr[5]); - ZeroTier::MAC mac; + MAC mac; mac.setTo(ethhdr->dest.addr, 6); mac.toAddress(tap->_nwid).toString(nodeBuf); DEBUG_TRANS("len=%5d dst=%s [%s TX <-- %s] proto=0x%04x %s", totalLength, macBuf, nodeBuf, tap->nodeId().c_str(), - ZeroTier::Utils::ntoh(ethhdr->type), flagbuf); + Utils::ntoh(ethhdr->type), flagbuf); } */ - - return ERR_OK; } -void lwip_eth_rx(ZeroTier::VirtualTap *tap, const ZeroTier::MAC &from, const ZeroTier::MAC &to, unsigned int etherType, +void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int etherType, const void *data, unsigned int len) { struct pbuf *p,*q; struct eth_hdr ethhdr; from.copyTo(ethhdr.src.addr, 6); to.copyTo(ethhdr.dest.addr, 6); - ethhdr.type = ZeroTier::Utils::hton((uint16_t)etherType); + ethhdr.type = Utils::hton((uint16_t)etherType); /* if (ZT_MSG_TRANSFER == true) { char flagbuf[32]; memset(&flagbuf, 0, 32); - char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[ZTS_ID_LEN]; + char macBuf[ZTS_MAC_ADDRSTRLEN], nodeBuf[16]; snprintf(macBuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", ethhdr.dest.addr[0], ethhdr.dest.addr[1], ethhdr.dest.addr[2], ethhdr.dest.addr[3], ethhdr.dest.addr[4], ethhdr.dest.addr[5]); - ZeroTier::MAC mac; + MAC mac; mac.setTo(ethhdr.src.addr, 6); mac.toAddress(tap->_nwid).toString(nodeBuf); DEBUG_TRANS("len=%5d dst=%s [%s RX --> %s] proto=0x%04x %s", len, macBuf, nodeBuf, tap->nodeId().c_str(), - ZeroTier::Utils::ntoh(ethhdr.type), flagbuf); + Utils::ntoh(ethhdr.type), flagbuf); } */ if (etherType == 0x0800 || etherType == 0x0806) { // ip4 or ARP @@ -390,23 +395,23 @@ static void netif_status_callback(struct netif *netif) if (!netif->state) { return; } - ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap *)netif->state; + VirtualTap *tap = (VirtualTap *)netif->state; if (netif->flags & NETIF_FLAG_UP) { - ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)netif->state; + VirtualTap *vtap = (VirtualTap*)netif->state; if (netif == vtap->netif6) { // DEBUG_INFO("netif=%p, vtap->netif6=%p", netif, vtap->netif6); - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_UP_IP6); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_UP_IP6); } if (netif == vtap->netif4) { // DEBUG_INFO("netif=%p, vtap->netif4=%p", netif, vtap->netif4); - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_UP_IP4); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_UP_IP4); } } if (!(netif->flags & NETIF_FLAG_UP)) { if (netif->flags & NETIF_FLAG_MLD6) { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP6); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP6); } else { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP4); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_DOWN_IP4); } } // TODO: ZTS_EVENT_NETIF_NEW_ADDRESS @@ -421,8 +426,8 @@ static void netif_remove_callback(struct netif *netif) if (!netif->state) { return; } - ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap *)netif->state; - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_REMOVED); + VirtualTap *tap = (VirtualTap *)netif->state; + postEvent(tap->_nwid, ZTS_EVENT_NETIF_REMOVED); //print_netif_info(netif); } @@ -434,12 +439,12 @@ static void netif_link_callback(struct netif *netif) if (!netif->state) { return; } - ZeroTier::VirtualTap *tap = (ZeroTier::VirtualTap *)netif->state; + VirtualTap *tap = (VirtualTap *)netif->state; if (netif->flags & NETIF_FLAG_LINK_UP) { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_LINK_UP); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_LINK_UP); } if (netif->flags & NETIF_FLAG_LINK_UP) { - _push_callback_event(tap->_nwid, ZTS_EVENT_NETIF_LINK_DOWN); + postEvent(tap->_nwid, ZTS_EVENT_NETIF_LINK_DOWN); } //print_netif_info(netif); } @@ -480,7 +485,7 @@ static err_t netif_init_6(struct netif *netif) return ERR_OK; } -void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier::InetAddress &ip) +void lwip_init_interface(void *tapref, const MAC &mac, const InetAddress &ip) { char ipbuf[INET6_ADDRSTRLEN]; char macbuf[ZTS_MAC_ADDRSTRLEN]; @@ -502,7 +507,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: macbuf, ip.toString(ipbuf), ip.netmask().toString(nmbuf)); netif_set_up(n); netif_set_link_up(n); - ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)tapref; + VirtualTap *vtap = (VirtualTap*)tapref; vtap->netif4 = (void*)n; } if (ip.isV6()) @@ -525,7 +530,7 @@ void lwip_init_interface(void *tapref, const ZeroTier::MAC &mac, const ZeroTier: n->hwaddr[3], n->hwaddr[4], n->hwaddr[5]); DEBUG_INFO("initialized netif as [mac=%s, addr=%s]", macbuf, ip.toString(ipbuf)); - ZeroTier::VirtualTap *vtap = (ZeroTier::VirtualTap*)tapref; + VirtualTap *vtap = (VirtualTap*)tapref; vtap->netif6 = (void*)n; } // Set netif callbacks, these will be used to inform decisions made diff --git a/include/lwIP.h b/src/lwipDriver.hpp similarity index 98% rename from include/lwIP.h rename to src/lwipDriver.hpp index c4d146d..e9c2fda 100644 --- a/include/lwIP.h +++ b/src/lwipDriver.hpp @@ -30,8 +30,8 @@ * lwIP network stack driver */ -#ifndef ZT_LWIP_HPP -#define ZT_LWIP_HPP +#ifndef LIBZT_LWIP_DRIVER_HPP +#define LIBZT_LWIP_DRIVER_HPP #include "Debug.hpp" #include "lwip/err.h" @@ -51,7 +51,7 @@ struct zts_sorted_packet // lwIP pbuf containing packet (originally encapsulated by ZT packet) struct pbuf *p; // ZT VirtualTap from which this packet originates - ZeroTier::VirtualTap *vtap; + VirtualTap *vtap; // lwIP netif we should accept this packet on struct netif *n; }; diff --git a/src/lwipRawDriver.cpp b/src/lwipRawDriver.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/lwipRawDriver.hpp b/src/lwipRawDriver.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/lwipopts.h b/src/lwipopts.h similarity index 99% rename from include/lwipopts.h rename to src/lwipopts.h index 8847ccb..cd0547e 100644 --- a/include/lwipopts.h +++ b/src/lwipopts.h @@ -67,7 +67,7 @@ * Don't redefine byte-order functions if they're already available */ #if __ANDROID__ -#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 0 #endif /** @@ -84,7 +84,7 @@ * Enable or disable debug, see debug ection near end of file * for more options. */ -#define LWIP_DEBUG 0 +//#define LWIP_DEBUG 0 /* flag for LWIP_DEBUGF indicating a tracing message * (to follow program flow) diff --git a/test/create_test_identities.sh b/test/create_test_identities.sh deleted file mode 100755 index 5f38015..0000000 --- a/test/create_test_identities.sh +++ /dev/null @@ -1,11 +0,0 @@ -# !/bin/bash -# Generates test identities and joins them to a test network - -NWID=$1 - -mkdir -p alice bob carol ted - -./../bin/selftest generate_id ${NWID} alice -./../bin/selftest generate_id ${NWID} bob -./../bin/selftest generate_id ${NWID} carol -./../bin/selftest generate_id ${NWID} ted diff --git a/test/echotest.cpp b/test/echotest.cpp deleted file mode 100644 index dcce325..0000000 --- a/test/echotest.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - * ZeroTier SDK - Network Virtualization Everywhere - * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * -- - * - * You can be released from the requirements of the license by purchasing - * a commercial license. Buying such a license is mandatory as soon as you - * develop commercial closed-source software that incorporates or links - * directly against ZeroTier software without disclosing the source code - * of your own application. - */ - - // Echo program to aid in the operation of selftest - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libzt.h" - -#define ECHOTEST_MODE_RX 333 -#define ECHOTEST_MODE_TX 666 - -#define MAX_RX_BUF_SZ 16384 -#define MAX_TX_BUF_SZ 16384 - -std::map testConf; - -void loadTestConfigFile(std::string filepath) -{ - std::string key, value, prefix; - std::ifstream testFile; - testFile.open(filepath.c_str()); - while (testFile >> key >> value) { - if (key == "name") { - prefix = value; - } - if (key[0] != '#' && key[0] != ';') { - testConf[prefix + "." + key] = value; // format: alice.ipv4 172.30.30.1 - //fprintf(stderr, "%s.%s = %s\n", prefix.c_str(), key.c_str(), testConf[prefix + "." + key].c_str()); - } - - } - testFile.close(); -} - -long int get_now_ts() -{ - struct timeval tp; - gettimeofday(&tp, NULL); - return tp.tv_sec * 1000 + tp.tv_usec / 1000; -} - -void start_echo_mode(std::string ipstr, int listen_port) -{ - DEBUG_TEST(); - DEBUG_TEST("listening for connections on port (%d)", listen_port); - - int backlog = 128; - int err = 0; - int sockfd, accfd; - - - struct sockaddr_in addr; - struct sockaddr_in client; - socklen_t clen = sizeof client; - addr.sin_port = htons(listen_port); - addr.sin_addr.s_addr = inet_addr(ipstr.c_str()); - addr.sin_family = AF_INET; - - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - DEBUG_ERROR("error creating socket (err=%d, errno=%s)", err, strerror(errno)); - if ((err = bind(sockfd, (struct sockaddr *)&addr, (socklen_t)sizeof(struct sockaddr_in)) < 0)) - DEBUG_ERROR("error binding to interface (err=%d, errno=%s)\n", err, strerror(errno)); - if ((err = listen(sockfd, backlog)) < 0) - DEBUG_ERROR("error placing socket in LISTENING state (err=%d, errno=%s)\n", err, strerror(errno)); - - DEBUG_TEST("accepting test connections..."); - while(true) - { - if ((accfd = accept(sockfd, (struct sockaddr *)&client, &clen)) < 0) { - DEBUG_ERROR("error accepting connection (err=%d, errno=%s)", accfd, strerror(errno)); - return; - } - DEBUG_TEST("\n\nconnection accepted! (fd=%d)", accfd); - - // Read initial test parameters from other host - int err = 0; - int mode = 0; // rx/tx - int count = 0; // of incoming byte stream, or requested outgoing - int len = sizeof mode + sizeof count; - int tot = 0; // total bytes read from remote test stream (selftest) - char pbuf[64]; // test parameter buffer - char rbuf[MAX_RX_BUF_SZ]; - - memset(pbuf, 0, sizeof pbuf); - - DEBUG_TEST("reading %d bytes (test parameters)", len); - if ((err = read(accfd, pbuf, len)) < 0) { - DEBUG_ERROR("error while reading test parameters from remote selftest host (err=%d, errno=%s)", err, strerror(errno)); - return; - } - - memcpy(&mode, pbuf, sizeof mode); - memcpy(&count, pbuf + sizeof mode, sizeof count); - - DEBUG_TEST("mode = %d, count = %d", mode, count); - - float totKB=0, totMB=0; - /* - Mode 1 (Measure performance of other host's TX): - - Receive incoming TX test config (total bytes intended) - - Prepare receiver - - Record time of first received byte - - Record time of last received byte - - Send results back to other host's selftest instance - */ - - // read 'count' bytes and send back before/after timestamps - if (mode == ECHOTEST_MODE_TX) - { - DEBUG_TEST("entering READ mode, as soon as bytes are read we will start keeping time..."); - if ((err = read(accfd, rbuf, sizeof rbuf)) < 0) { - DEBUG_ERROR("there was an error reading the test stream. aborting (err=%d, errno=%s)", err, errno); - return; - } - - tot += err; - - long int start_time = get_now_ts(); - totKB=0; - totMB=0; - DEBUG_TEST("Received first set of bytes in test stream. now keeping time"); - - while(tot < count) { - if ((err = read(accfd, rbuf, sizeof rbuf)) < 0) { - DEBUG_ERROR("there was an error reading the test stream. aborting"); - return; - } - tot += err; - totKB = (float)tot / (float)1024; - totMB = (float)tot / (float)(1024*1024); - DEBUG_TEST("read = %d, totB = %d, totKB = %3f, totMB = %3f", err, tot, totKB, totMB); - - } - DEBUG_TEST("total received = %d (%d MB)", tot); - long int end_time = get_now_ts(); - DEBUG_TEST("read last byte (tot=%d). stopping timer. sending test data back to remote selftest", tot); - - memset(pbuf, 0, sizeof pbuf); - memcpy(pbuf, &start_time, sizeof start_time); - memcpy(pbuf + sizeof start_time, &end_time, sizeof end_time); - DEBUG_TEST("copied test data, sending..."); - - if ((err = write(accfd, pbuf, sizeof start_time + sizeof end_time)) < 0) { - DEBUG_ERROR("error while sending test data to remote selftest host (err=%d, errno=%s)", err, strerror(errno)); - return; - } - DEBUG_TEST("sleeping before closing socket and accepting further selftest connections"); - sleep(3); - } - - /* - Mode 2 (Measure performance of other host's RX): - - Receive incoming RX test config (total bytes requested) - - Prepare transmitter - - Send bytes as fast as possible - */ - - // send 'count' bytes as quickly as possible - if (mode == ECHOTEST_MODE_RX) - { - totKB=0; - totMB=0; - while(tot < count) { - if ((err = write(accfd, rbuf, sizeof rbuf)) < 0) { - DEBUG_ERROR("error while sending test byte stream to echotest"); - return; - } - tot += err; - totKB = (float)tot / (float)1024; - totMB = (float)tot / (float)(1024*1024); - DEBUG_TEST("wrote = %d, totB = %d, totKB = %3f, totMB = %3f", err, tot, totKB, totMB); - } - DEBUG_TEST("sleeping before closing socket and accepting further selftest connections"); - sleep(3); - } - close(accfd); - } - close(sockfd); -} - - -int main(int argc , char *argv[]) -{ - if (argc < 5) { - fprintf(stderr, "usage: echotest to \n"); - fprintf(stderr, "e.g. : echotest test/selftest.conf bob to alice\n"); - return 1; - } - - std::string from = argv[2]; - std::string to = argv[4]; - std::string me = from; - - int start_port = 0; - int port_offset = 0; - int echo_listen_port = 0; - - std::string local_echo_ipv4; - - std::string nwid, stype, path = argv[1]; - std::string ipstr, ipstr6, local_ipstr, local_ipstr6, remote_ipstr, remote_ipstr6; - - // loaf config file - if (path.find(".conf") == std::string::npos) { - fprintf(stderr, "Possibly invalid conf file. Exiting...\n"); - exit(0); - } - loadTestConfigFile(path); - - // get echo details - local_echo_ipv4 = testConf[me + ".echo_ipv4"]; - nwid = testConf[me + ".nwid"]; - start_port = atoi(testConf[me + ".port"].c_str()); - port_offset = 100; - - // get destination details - remote_ipstr = testConf[to + ".ipv4"]; - remote_ipstr6 = testConf[to + ".ipv6"]; - - if (me == "alice" || me == "ted") { - echo_listen_port = start_port + port_offset + 1; - } - if (me == "bob" || me == "carol") { - echo_listen_port = start_port + port_offset; - } - - fprintf(stderr, "Test Parameters:\n\n"); - - fprintf(stderr, "ORIGIN:\n\n"); - fprintf(stderr, "\tlocal_ipstr = %s\n", local_ipstr.c_str()); - fprintf(stderr, "\tlocal_ipstr6 = %s\n", local_ipstr6.c_str()); - fprintf(stderr, "\tstart_port = %d\n", start_port); - fprintf(stderr, "\tnwid = %s\n", nwid.c_str()); - fprintf(stderr, "\ttype = %s\n\n", stype.c_str()); - - fprintf(stderr, "DESTINATION:\n\n"); - fprintf(stderr, "\tremote_ipstr = %s\n", remote_ipstr.c_str()); - fprintf(stderr, "\tremote_ipstr6 = %s\n", remote_ipstr6.c_str()); - - fprintf(stderr, "I am %s\n", me.c_str()); - DEBUG_TEST("Starting echo mode... %s : %d", local_echo_ipv4.c_str(), echo_listen_port); - start_echo_mode(local_echo_ipv4, echo_listen_port); - return 1; -} \ No newline at end of file