mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-17 20:46:54 +02:00
Merge branch 'dev' into redisrection
This commit is contained in:
commit
c6fc3560f2
12804 changed files with 2946788 additions and 1833 deletions
.drone.jsonnet.drone.yml.gitignoreMakefileREADME.mdRELEASE-NOTES.md
ci
controller
DB.cppDB.hppDBMirrorSet.cppDBMirrorSet.hppEmbeddedNetworkController.cppEmbeddedNetworkController.hppPostgreSQL.cpp
debian
dockerbuild
entrypoint.sh.releaseext
inja
installfiles
nlohmann
include
make-bsd.mkmake-linux.mkmake-mac.mknode
Bond.cppBond.hppConstants.hppIncomingPacket.cppIncomingPacket.hppMembership.cppMembership.hppNetwork.cppNetwork.hppNetworkConfig.hppNode.cppPath.hppPeer.cppPeer.hppRevocation.hppSalsa20.hppSelfAwareness.cppSelfAwareness.hpp
one.cpposdep
pkg
README.md
asustor
config.jsonqnap
Dockerfilebuild.shentrypoint.shqdk.conf
zerotier
68
.drone.jsonnet
Normal file
68
.drone.jsonnet
Normal file
|
@ -0,0 +1,68 @@
|
|||
|
||||
local targets = [
|
||||
//
|
||||
// Render these into .drone.yaml by running "make drone"
|
||||
//
|
||||
{ "os": "linux", "name": "el9", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "el8", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "el7", "isas": [ "amd64", "ppc64le"], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "el6", "isas": [ "amd64" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "amzn2", "isas": [ "amd64", "arm64" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "fc37", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "fc36", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "fc35", "isas": [ "amd64", "arm64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "jammy", "isas": [ "amd64", "arm64", "armv7", "riscv64", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "focal", "isas": [ "amd64", "arm64", "armv7", "riscv64", "ppc64le" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "bionic", "isas": [ "amd64", "arm64", "386", "ppc64le", "s390x" ], "events": ["tag" ] },
|
||||
{ "os": "linux", "name": "xenial", "isas": [ "amd64", "arm64", "386" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "sid", "isas": [ "386", "amd64", "arm64", "armv7", "riscv64", "mips64le", "ppc64le", "s390x" ], "events": [ "push", "tag" ] },
|
||||
{ "os": "linux", "name": "bookworm", "isas": [ "amd64", "arm64", "armv7", "386", "mips64le", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "bullseye", "isas": [ "amd64", "arm64", "armv7", "386", "mips64le", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "buster", "isas": [ "amd64", "arm64", "armv7", "386", "mips64le", "ppc64le", "s390x" ], "events": [ "tag" ] },
|
||||
{ "os": "linux", "name": "stretch", "isas": [ "amd64", "arm64", "386" ], "events": [ "tag" ] },
|
||||
// { "os": "windows", "name": "win2k19", "isas": [ "amd64" ], "events": ["push", "tag" ] }
|
||||
];
|
||||
|
||||
local Build(platform, os, isa, events) = {
|
||||
"kind": "pipeline",
|
||||
"type": "docker",
|
||||
"pull": "always",
|
||||
"name": platform + " " + isa + " " + "build",
|
||||
"clone": { "depth": 1 },
|
||||
"steps": [
|
||||
{
|
||||
"name": "build",
|
||||
"image": "registry.sean.farm/honda-builder",
|
||||
"commands": [ "./ci/scripts/build.sh " + platform + " " + isa + " " + "100.0.0+${DRONE_COMMIT_SHA:0:8}" + " " + "${DRONE_BUILD_EVENT}" ]
|
||||
},
|
||||
{
|
||||
"name": "list",
|
||||
"image": "registry.sean.farm/honda-builder",
|
||||
"commands": [ "ls -la " + platform ]
|
||||
},
|
||||
{
|
||||
"name": "notify-mattermost",
|
||||
"image": "registry.sean.farm/mattermost-notify",
|
||||
"environment": {
|
||||
"token": { "from_secret": "mattermost-token" },
|
||||
"host": { "from_secret": "mattermost-host" },
|
||||
"channel": { "from_secret": "mattermost-channel" },
|
||||
"maxRetry": 3,
|
||||
},
|
||||
"when": { "status": [ "failure" ] }
|
||||
}
|
||||
],
|
||||
"image_pull_secrets": [ "dockerconfigjson" ],
|
||||
[ if isa == "arm64" || isa == "armv7" then "platform" ]: { os: os, arch: "arm64" },
|
||||
"trigger": { "event": events }
|
||||
};
|
||||
|
||||
// puttin on the bits
|
||||
|
||||
std.flattenArrays([
|
||||
[
|
||||
Build(p.name, p.os, isa, p.events)
|
||||
for isa in p.isas
|
||||
]
|
||||
for p in targets
|
||||
])
|
2844
.drone.yml
2844
.drone.yml
File diff suppressed because it is too large
Load diff
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -6,6 +6,11 @@
|
|||
/zerotier
|
||||
/nltest
|
||||
|
||||
# IDE stuff
|
||||
/.idea
|
||||
/.nova
|
||||
/compile_commands.json
|
||||
|
||||
# OS-created garbage files from various platforms
|
||||
.DS_Store
|
||||
.Apple*
|
||||
|
@ -30,7 +35,6 @@ Thumbs.db
|
|||
/windows/WebUIWrapper/obj
|
||||
/windows/lib
|
||||
/ext/installfiles/windows/ZeroTier One-SetupFiles
|
||||
/ext/installfiles/windows/Prerequisites
|
||||
/ext/installfiles/windows/*-cache
|
||||
/ZeroTier One.msi
|
||||
*.vcxproj.backup
|
||||
|
@ -58,7 +62,6 @@ zt1-src.tar.gz
|
|||
*.opensdf
|
||||
*.user
|
||||
*.cache
|
||||
*.obj
|
||||
*.tlog
|
||||
*.pid
|
||||
*.pkg
|
||||
|
@ -103,7 +106,6 @@ windows/ZeroTierOne/Debug/
|
|||
*.swp
|
||||
*~.nib
|
||||
DerivedData/
|
||||
build/
|
||||
*.pbxuser
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
|
@ -114,7 +116,6 @@ build/
|
|||
!default.perspectivev3
|
||||
*.xccheckout
|
||||
xcuserdata/
|
||||
ext/librethinkdbxx/build
|
||||
.vscode
|
||||
__pycache__
|
||||
*~
|
||||
|
@ -123,7 +124,6 @@ attic/world/mkworld
|
|||
workspace/
|
||||
workspace2/
|
||||
zeroidc/target/
|
||||
tmp/
|
||||
|
||||
#snapcraft specifics
|
||||
/parts/
|
||||
|
|
4
Makefile
4
Makefile
|
@ -26,3 +26,7 @@ endif
|
|||
ifeq ($(OSTYPE),NetBSD)
|
||||
include make-netbsd.mk
|
||||
endif
|
||||
|
||||
drone:
|
||||
@echo "rendering .drone.yaml from .drone.jsonnet"
|
||||
drone jsonnet --format --stream
|
||||
|
|
16
README.md
16
README.md
|
@ -1,6 +1,7 @@
|
|||
ZeroTier - Global Area Networking
|
||||
======
|
||||
This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com)
|
||||
|
||||
*This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).*
|
||||
|
||||
ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region.
|
||||
|
||||
|
@ -42,24 +43,29 @@ The base path contains the ZeroTier One service main entry point (`one.cpp`), se
|
|||
- `rule-compiler/`: JavaScript rules language compiler for defining network-level rules.
|
||||
- `service/`: the ZeroTier One service, which wraps the ZeroTier core and provides VPN-like connectivity to virtual networks for desktops, laptops, servers, VMs, and containers.
|
||||
- `windows/`: Visual Studio solution files, Windows service code, and the Windows task bar app UI.
|
||||
- `zeroidc/`: OIDC implementation used by ZeroTier service to log into SSO-enabled networks. (This part is written in Rust, and more Rust will be appearing in this repository in the future.)
|
||||
|
||||
### Build and Platform Notes
|
||||
|
||||
To build on Mac and Linux just type `make`. On FreeBSD and OpenBSD `gmake` (GNU make) is required and can be installed from packages or ports. For Windows there is a Visual Studio solution in `windows/`.
|
||||
|
||||
- **Mac**
|
||||
- Xcode command line tools for OSX 10.8 or newer are required.
|
||||
- Xcode command line tools for macOS 10.13 or newer are required.
|
||||
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
|
||||
- **Linux**
|
||||
- The minimum compiler versions required are GCC/G++ 4.9.3 or CLANG/CLANG++ 3.4.2. (Install `clang` on CentOS 7 as G++ is too old.)
|
||||
- Linux makefiles automatically detect and prefer clang/clang++ if present as it produces smaller and slightly faster binaries in most cases. You can override by supplying CC and CXX variables on the make command line.
|
||||
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
|
||||
- **Windows**
|
||||
- Windows 7 or newer is supported. This *may* work on Vista but isn't officially supported there. It will not work on Windows XP.
|
||||
- We build with Visual Studio 2017. Older versions may not work. Clang or MinGW will also probably work but may require some makefile hacking.
|
||||
- Visual Studio 2022 on Windows 10 or newer.
|
||||
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
|
||||
- **FreeBSD**
|
||||
- GNU make is required. Type `gmake` to build.
|
||||
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
|
||||
- **OpenBSD**
|
||||
- There is a limit of four network memberships on OpenBSD as there are only four tap devices (`/dev/tap0` through `/dev/tap3`).
|
||||
- GNU make is required. Type `gmake` to build.
|
||||
- Rust for x86_64 and ARM64 targets *if SSO is enabled in the build*.
|
||||
|
||||
Typing `make selftest` will build a *zerotier-selftest* binary which unit tests various internals and reports on a few aspects of the build environment. It's a good idea to try this on novel platforms or architectures.
|
||||
|
||||
|
@ -82,7 +88,7 @@ Here's where home folders live (by default) on each OS:
|
|||
* **Linux**: `/var/lib/zerotier-one`
|
||||
* **FreeBSD** / **OpenBSD**: `/var/db/zerotier-one`
|
||||
* **Mac**: `/Library/Application Support/ZeroTier/One`
|
||||
* **Windows**: `\ProgramData\ZeroTier\One` (That's for Windows 7. The base 'shared app data' folder might be different on different Windows versions.)
|
||||
* **Windows**: `\ProgramData\ZeroTier\One` (That's the default. The base 'shared app data' folder might be different if Windows is installed with a non-standard drive letter assignment or layout.)
|
||||
|
||||
### Basic Troubleshooting
|
||||
|
||||
|
|
|
@ -1,11 +1,40 @@
|
|||
ZeroTier Release Notes
|
||||
======
|
||||
|
||||
# 2022-03-21 -- Version 1.8.7
|
||||
# 2022-06-07 -- Version 1.10.0
|
||||
|
||||
* Fix for dependency installations in Windows MSI package
|
||||
* Fix for privilege escalation in desktop UI when the user is not a current super-user
|
||||
* Bug fix in local OIDC / SSO support
|
||||
* Fix formatting problem in `zerotier-cli` when using SSO networks.
|
||||
* Fix a few other minor bugs in SSO signin to prepare for general availability.
|
||||
* Remove requirement for webview in desktop UI and instead just make everything available via the tray pulldown/menu. Use [libui-ng](https://github.com/libui-ng/libui-ng) for minor prompt dialogs. Saves space and eliminates installation headaches on Windows.
|
||||
* Fix SSO "spam" bug in desktop UI.
|
||||
* Use system default browser for SSO login so all your plugins, MFA devices, password managers, etc. will work as you have them configured.
|
||||
* Minor fix for bonding/multipath.
|
||||
|
||||
# 2022-05-10 -- Version 1.8.10
|
||||
|
||||
* Fixed a bug preventing SSO sign-on on Windows.
|
||||
|
||||
# 2022-04-25 -- Version 1.8.9
|
||||
|
||||
* Fixed a long-standing and strange bug that was causing sporadic "phantom" packet authentication failures. Not a security problem but could be behind spordaic reports of link failures under some conditions.
|
||||
* Fized a memory leak in SSO/OIDC support.
|
||||
* Fixed SSO/OIDC display error on CLI.
|
||||
* Fixed a bug causing nodes to sometimes fail to push certs to each other (primarily affects SSO/OIDC use cases).
|
||||
* Fixed a deadlock bug on leaving SSO/OIDC managed networks.
|
||||
* Added some new Linux distributions to the build subsystem.
|
||||
|
||||
# 2022-04-11 -- Version 1.8.8
|
||||
|
||||
* Fix a local privilege escalation bug in the Windows installer.
|
||||
* Dependency fix for some Ubuntu versions.
|
||||
* No changes for other platforms. Windows upgrade recommended, everyone else optional.
|
||||
|
||||
# 2022-03-30 -- Version 1.8.7
|
||||
|
||||
* Fix for dependency installations in Windows MSI package.
|
||||
* Fix for desktop UI setup when run by a non-super-user.
|
||||
* Bug fix in local OIDC / SSO support for auth0 and other providers.
|
||||
* Other minor fixes for e.g. old Linux distributions.
|
||||
|
||||
# 2022-03-04 -- Version 1.8.6
|
||||
|
||||
|
|
10
ci/Dockerfile.deb
Normal file
10
ci/Dockerfile.deb
Normal file
|
@ -0,0 +1,10 @@
|
|||
ARG PLATFORM
|
||||
FROM registry.sean.farm/${PLATFORM}-builder as stage
|
||||
WORKDIR /work/build
|
||||
COPY . .
|
||||
RUN make debian
|
||||
RUN ls -ls /work
|
||||
|
||||
FROM scratch AS export
|
||||
ARG PLATFORM
|
||||
COPY --from=stage /work/*.deb ./${PLATFORM}/
|
36
ci/Dockerfile.el6
Normal file
36
ci/Dockerfile.el6
Normal file
|
@ -0,0 +1,36 @@
|
|||
ARG DOCKER_ARCH
|
||||
FROM --platform=linux/${DOCKER_ARCH} alpine:edge AS builder
|
||||
|
||||
RUN apk update
|
||||
RUN apk add curl
|
||||
RUN apk add bash
|
||||
RUN apk add file
|
||||
RUN apk add rust
|
||||
RUN apk add cargo
|
||||
RUN apk add make
|
||||
RUN apk add cmake
|
||||
RUN apk add clang
|
||||
RUN apk add openssl-dev
|
||||
RUN apk add linux-headers
|
||||
RUN apk add build-base
|
||||
RUN apk add openssl-libs-static
|
||||
|
||||
COPY . .
|
||||
RUN ZT_STATIC=1 make one
|
||||
RUN ls -la
|
||||
|
||||
ARG DOCKER_ARCH
|
||||
FROM --platform=linux/${DOCKER_ARCH} centos:6 AS stage
|
||||
WORKDIR /root/rpmbuild/BUILD
|
||||
COPY . .
|
||||
COPY --from=builder zerotier-one ./
|
||||
RUN curl https://gist.githubusercontent.com/someara/b363002ba6e57b3c474dd027d4daef85/raw/4ac5534139752fc92fbe1a53599a390214f69615/el6%2520vault --output /etc/yum.repos.d/CentOS-Base.repo
|
||||
RUN uname -a
|
||||
RUN yum -y install make gcc rpm-build
|
||||
RUN pwd
|
||||
RUN ls -la
|
||||
RUN make redhat
|
||||
|
||||
FROM scratch AS export
|
||||
ARG PLATFORM
|
||||
COPY --from=stage /root/rpmbuild/RPMS/*/*.rpm ./${PLATFORM}/
|
9
ci/Dockerfile.rpm
Normal file
9
ci/Dockerfile.rpm
Normal file
|
@ -0,0 +1,9 @@
|
|||
ARG PLATFORM
|
||||
FROM registry.sean.farm/${PLATFORM}-builder as stage
|
||||
WORKDIR /root/rpmbuild/BUILD
|
||||
COPY . .
|
||||
RUN make redhat
|
||||
|
||||
FROM scratch AS export
|
||||
ARG PLATFORM
|
||||
COPY --from=stage /root/rpmbuild/RPMS/*/*.rpm ./${PLATFORM}/
|
|
@ -1,7 +0,0 @@
|
|||
FROM registry.sean.farm/sid-builder as stage
|
||||
COPY . .
|
||||
RUN /usr/bin/make -j 8
|
||||
|
||||
FROM scratch AS export
|
||||
COPY --from=stage /zerotier-one .
|
||||
COPY --from=stage /zerotier-cli .
|
|
@ -2,27 +2,115 @@
|
|||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
export GOOS=$1
|
||||
export GOARCH=$2
|
||||
export PLATFORM=$1
|
||||
export ZT_ISA=$2
|
||||
export VERSION=$3
|
||||
export DOCKER_BUILDKIT=1
|
||||
export EVENT=$4
|
||||
|
||||
echo "nproc: $(nproc)"
|
||||
|
||||
case $GOARCH in
|
||||
armv5)
|
||||
export ARCH=arm/v5
|
||||
;;
|
||||
armv7)
|
||||
export ARCH=arm/v7
|
||||
;;
|
||||
arm64)
|
||||
export ARCH=arm64/v8
|
||||
case $PLATFORM in
|
||||
el*|fc*|amzn*)
|
||||
export PKGFMT=rpm
|
||||
;;
|
||||
*)
|
||||
export ARCH=$GOARCH
|
||||
export PKGFMT=deb
|
||||
esac
|
||||
|
||||
# OSX
|
||||
# x86_64-apple-darwin
|
||||
# aarch64-apple-darwin
|
||||
|
||||
# Windows
|
||||
# x86_64-pc-windows-msvc
|
||||
# i686-pc-windows-msvc
|
||||
# aarch64-pc-windows-msvc
|
||||
|
||||
# Linux
|
||||
# i686-unknown-linux-gnu
|
||||
# x86_64-unknown-linux-gnu
|
||||
# arm-unknown-linux-gnueabi ?
|
||||
# arm-unknown-linux-gnueabihf ?
|
||||
# armv7-unknown-linux-gnueabihf
|
||||
#
|
||||
|
||||
case $ZT_ISA in
|
||||
386)
|
||||
export DOCKER_ARCH=386
|
||||
export RUST_TRIPLET=i686-unknown-linux-gnu
|
||||
;;
|
||||
amd64)
|
||||
export DOCKER_ARCH=amd64
|
||||
export RUST_TRIPLET=x86_64-unknown-linux-gnu
|
||||
;;
|
||||
armv6)
|
||||
export DOCKER_ARCH=arm/v6
|
||||
export RUST_TRIPLET=arm-unknown-linux-gnueabi
|
||||
;;
|
||||
armv7)
|
||||
export DOCKER_ARCH=arm/v7
|
||||
export RUST_TRIPLET=arm-unknown-linux-gnueabihf
|
||||
;;
|
||||
arm64)
|
||||
export DOCKER_ARCH=arm64/v8
|
||||
export RUST_TRIPLET=aarch64-unknown-linux-gnu
|
||||
;;
|
||||
riscv64)
|
||||
export DOCKER_ARCH=riscv64
|
||||
export RUST_TRIPLET=riscv64gc-unknown-linux-gnu
|
||||
;;
|
||||
ppc64le)
|
||||
export DOCKER_ARCH=ppc64le
|
||||
export RUST_TRIPLET=powerpc64le-unknown-linux-gnu
|
||||
;;
|
||||
mips64le)
|
||||
export DOCKER_ARCH=mips64le
|
||||
export RUST_TRIPLET=mips64el-unknown-linux-gnuabi64
|
||||
;;
|
||||
s390x)
|
||||
export DOCKER_ARCH=s390x
|
||||
export RUST_TRIPLET=s390x-unknown-linux-gnu
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: could not determine architecture settings. PLEASE FIX ME"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -f "ci/Dockerfile.${PLATFORM}" ]; then
|
||||
export DOCKERFILE="ci/Dockerfile.${PLATFORM}"
|
||||
else
|
||||
export DOCKERFILE="ci/Dockerfile.${PKGFMT}"
|
||||
fi
|
||||
|
||||
echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
echo "$0 variables:"
|
||||
echo "nproc: $(nproc)"
|
||||
echo "ZT_ISA: ${ZT_ISA}"
|
||||
echo "DOCKER_ARCH: ${DOCKER_ARCH}"
|
||||
echo "RUST_TRIPLET: ${RUST_TRIPLET}"
|
||||
echo "VERSION: ${VERSION}"
|
||||
echo "EVENT: ${EVENT}"
|
||||
echo "PKGFMT: ${PKGFMT}"
|
||||
echo "PWD: ${PWD}"
|
||||
echo "DOCKERFILE: ${DOCKERFILE}"
|
||||
echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
|
||||
if [ ${EVENT} == "push" ]; then
|
||||
make munge_rpm zerotier-one.spec VERSION=${VERSION}
|
||||
make munge_deb debian/changelog VERSION=${VERSION}
|
||||
fi
|
||||
|
||||
export DOCKER_BUILDKIT=1
|
||||
docker run --privileged --rm tonistiigi/binfmt --install all
|
||||
docker buildx build --platform ${GOOS}/${ARCH} -f ci/Dockerfile.sid --target export -t test . --output out/${GOOS}/${GOARCH}
|
||||
|
||||
# docker pull --platform linux/${DOCKER_ARCH} registry.sean.farm/${PLATFORM}-builder
|
||||
|
||||
docker buildx build \
|
||||
--build-arg PLATFORM="${PLATFORM}" \
|
||||
--build-arg RUST_TRIPLET="${RUST_TRIPLET}" \
|
||||
--build-arg DOCKER_ARCH="${DOCKER_ARCH}" \
|
||||
--platform linux/${DOCKER_ARCH} \
|
||||
-f ${DOCKERFILE} \
|
||||
-t build \
|
||||
. \
|
||||
--output type=local,dest=. \
|
||||
--target export
|
||||
|
|
37
ci/scripts/munge_debian_changelog.sh
Executable file
37
ci/scripts/munge_debian_changelog.sh
Executable file
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
export FILE=$1
|
||||
export VERSION=$2
|
||||
export NAME=$3
|
||||
export MESSAGE=$4
|
||||
export DATE=$(date "+%a, %d %b %Y %T %z")
|
||||
# export DATE=$(date "+%a %b %d %Y")
|
||||
|
||||
set +e
|
||||
grep --version | grep BSD &> /dev/null
|
||||
if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi
|
||||
set -e
|
||||
|
||||
# echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
# echo "$0 variables:"
|
||||
# echo "VERSION: ${VERSION}"
|
||||
# echo "NAME: ${NAME}"
|
||||
# echo "MESSAGE: ${MESSAGE}"
|
||||
# echo "DATE: ${DATE}"
|
||||
# echo "BSDGREP: ${BSDGREP}"
|
||||
# echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
# echo
|
||||
|
||||
if $BSDGREP ; then
|
||||
sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
|
||||
else
|
||||
sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
|
||||
fi
|
||||
|
||||
awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \
|
||||
'BEGIN{print "zerotier-one (" version ") unstable; urgency=medium\n\n * " message "\n\n -- " name " " date "\n" }{ print }' \
|
||||
${FILE} > ${FILE}.new
|
||||
|
||||
mv ${FILE}.new ${FILE}
|
36
ci/scripts/munge_rpm_spec.sh
Executable file
36
ci/scripts/munge_rpm_spec.sh
Executable file
|
@ -0,0 +1,36 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
export FILE=$1
|
||||
export VERSION=$2
|
||||
export NAME=$3
|
||||
export MESSAGE=$4
|
||||
export DATE=$(date "+%a %b %d %Y")
|
||||
|
||||
set +e
|
||||
grep --version | grep BSD &> /dev/null
|
||||
if [ $? == 0 ]; then BSDGREP=true ; else BSDGREP=false ; fi
|
||||
set -e
|
||||
|
||||
# echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
# echo "$0 variables:"
|
||||
# echo "VERSION: ${VERSION}"
|
||||
# echo "NAME: ${NAME}"
|
||||
# echo "MESSAGE: ${MESSAGE}"
|
||||
# echo "DATE: ${DATE}"
|
||||
# echo "BSDGREP: ${BSDGREP}"
|
||||
# echo "#~~~~~~~~~~~~~~~~~~~~"
|
||||
# echo
|
||||
|
||||
if $BSDGREP ; then
|
||||
sed -i '' s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
|
||||
else
|
||||
sed -i s/^Version:.*/"Version: ${VERSION}"/ ${FILE}
|
||||
fi
|
||||
|
||||
awk -v version=${VERSION} -v date=${DATE} -v name=${NAME} -v message=${MESSAGE} \
|
||||
'FNR==NR{ if (/%changelog/) p=NR; next} 1; FNR==p{ print "* " date " " name " - " version "\n- " message "\n" }' \
|
||||
${FILE} ${FILE} > ${FILE}.new
|
||||
|
||||
mv ${FILE}.new ${FILE}
|
|
@ -196,14 +196,6 @@ void DB::networks(std::set<uint64_t> &networks)
|
|||
networks.insert(n->first);
|
||||
}
|
||||
|
||||
void DB::networkMemberSSOHasExpired(uint64_t nwid, int64_t now) {
|
||||
std::lock_guard<std::mutex> l(_networks_l);
|
||||
auto nw = _networks.find(nwid);
|
||||
if (nw != _networks.end()) {
|
||||
nw->second->mostRecentDeauthTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
void DB::_memberChanged(nlohmann::json &old,nlohmann::json &memberConfig,bool notifyListeners)
|
||||
{
|
||||
uint64_t memberId = 0;
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "../ext/json/json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define ZT_MEMBER_AUTH_TIMEOUT_NOTIFY_BEFORE 25000
|
||||
|
||||
|
@ -135,7 +135,6 @@ public:
|
|||
virtual void nodeIsOnline(const uint64_t networkId,const uint64_t memberId,const InetAddress &physicalAddress) = 0;
|
||||
|
||||
virtual AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL) { return AuthInfo(); }
|
||||
virtual void networkMemberSSOHasExpired(uint64_t nwid, int64_t ts);
|
||||
|
||||
inline void addListener(DB::ChangeListener *const listener)
|
||||
{
|
||||
|
|
|
@ -137,14 +137,6 @@ AuthInfo DBMirrorSet::getSSOAuthInfo(const nlohmann::json &member, const std::st
|
|||
return AuthInfo();
|
||||
}
|
||||
|
||||
void DBMirrorSet::networkMemberSSOHasExpired(uint64_t nwid, int64_t ts)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_dbs_l);
|
||||
for(auto d=_dbs.begin();d!=_dbs.end();++d) {
|
||||
(*d)->networkMemberSSOHasExpired(nwid, ts);
|
||||
}
|
||||
}
|
||||
|
||||
void DBMirrorSet::networks(std::set<uint64_t> &networks)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_dbs_l);
|
||||
|
@ -248,47 +240,4 @@ void DBMirrorSet::onNetworkMemberDeauthorize(const void *db,uint64_t networkId,u
|
|||
_listener->onNetworkMemberDeauthorize(this,networkId,memberId);
|
||||
}
|
||||
|
||||
void DBMirrorSet::membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soon, std::set< std::pair<uint64_t, uint64_t> > &expired)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(_membersExpiringSoon_l);
|
||||
int64_t now = OSUtils::now();
|
||||
for(auto next=_membersExpiringSoon.begin();next!=_membersExpiringSoon.end();) {
|
||||
if (next->first > now) {
|
||||
const uint64_t nwid = next->second.first;
|
||||
const uint64_t memberId = next->second.second;
|
||||
nlohmann::json network, member;
|
||||
if (this->get(nwid, network, memberId, member)) {
|
||||
try {
|
||||
const bool authorized = member["authorized"];
|
||||
const bool ssoExempt = member["ssoExempt"];
|
||||
const int64_t authenticationExpiryTime = member["authenticationExpiryTime"];
|
||||
if ((authenticationExpiryTime == next->first)&&(authorized)&&(!ssoExempt)) {
|
||||
if ((authenticationExpiryTime - now) > ZT_MEMBER_AUTH_TIMEOUT_NOTIFY_BEFORE) {
|
||||
// Stop when we get to entries too far in the future.
|
||||
break;
|
||||
} else {
|
||||
const bool ssoEnabled = network["ssoEnabled"];
|
||||
if (ssoEnabled)
|
||||
soon.insert(std::pair<uint64_t, uint64_t>(nwid, memberId));
|
||||
}
|
||||
} else {
|
||||
// Obsolete entry, no longer authorized, or SSO exempt.
|
||||
}
|
||||
} catch ( ... ) {
|
||||
// Invalid member object, erase.
|
||||
}
|
||||
} else {
|
||||
// Not found.
|
||||
}
|
||||
}
|
||||
_membersExpiringSoon.erase(next++);
|
||||
}
|
||||
}
|
||||
|
||||
void DBMirrorSet::memberWillExpire(int64_t expTime, uint64_t nwid, uint64_t memberId)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(_membersExpiringSoon_l);
|
||||
_membersExpiringSoon.insert(std::pair< int64_t, std::pair< uint64_t, uint64_t > >(expTime, std::pair< uint64_t, uint64_t >(nwid, memberId)));
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -52,7 +52,6 @@ public:
|
|||
virtual void onNetworkMemberDeauthorize(const void *db,uint64_t networkId,uint64_t memberId);
|
||||
|
||||
AuthInfo getSSOAuthInfo(const nlohmann::json &member, const std::string &redirectURL);
|
||||
void networkMemberSSOHasExpired(uint64_t nwid, int64_t ts);
|
||||
|
||||
inline void addDB(const std::shared_ptr<DB> &db)
|
||||
{
|
||||
|
@ -61,17 +60,12 @@ public:
|
|||
_dbs.push_back(db);
|
||||
}
|
||||
|
||||
void membersExpiring(std::set< std::pair<uint64_t, uint64_t> > &soon, std::set< std::pair<uint64_t, uint64_t> > &expired);
|
||||
void memberWillExpire(int64_t expTime, uint64_t nwid, uint64_t memberId);
|
||||
|
||||
private:
|
||||
DB::ChangeListener *const _listener;
|
||||
std::atomic_bool _running;
|
||||
std::thread _syncCheckerThread;
|
||||
std::vector< std::shared_ptr< DB > > _dbs;
|
||||
mutable std::mutex _dbs_l;
|
||||
std::set< std::pair< int64_t, std::pair<uint64_t, uint64_t> > > _membersExpiringSoon;
|
||||
mutable std::mutex _membersExpiringSoon_l;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -1262,6 +1262,7 @@ void EmbeddedNetworkController::_request(
|
|||
}
|
||||
const bool newMember = ((!member.is_object())||(member.empty()));
|
||||
DB::initMember(member);
|
||||
_MemberStatusKey msk(nwid,identity.address().toInt());
|
||||
|
||||
{
|
||||
const std::string haveIdStr(OSUtils::jsonString(member["identity"],""));
|
||||
|
@ -1335,43 +1336,21 @@ void EmbeddedNetworkController::_request(
|
|||
// Should we check SSO Stuff?
|
||||
// If network is configured with SSO, and the member is not marked exempt: yes
|
||||
// Otherwise no, we use standard auth logic.
|
||||
AuthInfo info;
|
||||
int64_t authenticationExpiryTime = -1;
|
||||
bool networkSSOEnabled = OSUtils::jsonBool(network["ssoEnabled"], false);
|
||||
bool memberSSOExempt = OSUtils::jsonBool(member["ssoExempt"], false);
|
||||
AuthInfo info;
|
||||
if (networkSSOEnabled && !memberSSOExempt) {
|
||||
// TODO: Get expiry time if auth is still valid
|
||||
|
||||
// else get new auth info & stuff
|
||||
authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
|
||||
info = _db.getSSOAuthInfo(member, _ssoRedirectURL);
|
||||
assert(info.enabled == networkSSOEnabled);
|
||||
|
||||
std::string memberId = member["id"];
|
||||
//fprintf(stderr, "ssoEnabled && !ssoExempt %s-%s\n", nwids, memberId.c_str());
|
||||
uint64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
|
||||
fprintf(stderr, "authExpiryTime: %lld\n", authenticationExpiryTime);
|
||||
if (authenticationExpiryTime < now) {
|
||||
fprintf(stderr, "Handling expired member\n");
|
||||
if (authenticationExpiryTime <= now) {
|
||||
if (info.version == 0) {
|
||||
if (!info.authenticationURL.empty()) {
|
||||
_db.networkMemberSSOHasExpired(nwid, now);
|
||||
onNetworkMemberDeauthorize(&_db, nwid, identity.address().toInt());
|
||||
|
||||
Dictionary<4096> authInfo;
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, (uint64_t)0ULL);
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL, info.authenticationURL.c_str());
|
||||
//fprintf(stderr, "sending auth URL: %s\n", authenticationURL.c_str());
|
||||
|
||||
DB::cleanMember(member);
|
||||
_db.save(member,true);
|
||||
|
||||
_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (info.version == 1) {
|
||||
_db.networkMemberSSOHasExpired(nwid, now);
|
||||
onNetworkMemberDeauthorize(&_db, nwid, identity.address().toInt());
|
||||
|
||||
Dictionary<4096> authInfo;
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, (uint64_t)0ULL);
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_AUTHENTICATION_URL, info.authenticationURL.c_str());
|
||||
_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes());
|
||||
} else if (info.version == 1) {
|
||||
Dictionary<8192> authInfo;
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_VERSION, info.version);
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_ISSUER_URL, info.issuerURL.c_str());
|
||||
|
@ -1379,20 +1358,11 @@ void EmbeddedNetworkController::_request(
|
|||
authInfo.add(ZT_AUTHINFO_DICT_KEY_NONCE, info.ssoNonce.c_str());
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_STATE, info.ssoState.c_str());
|
||||
authInfo.add(ZT_AUTHINFO_DICT_KEY_CLIENT_ID, info.ssoClientID.c_str());
|
||||
|
||||
DB::cleanMember(member);
|
||||
_db.save(member, true);
|
||||
|
||||
fprintf(stderr, "Sending NC_ERROR_AUTHENTICATION_REQUIRED\n");
|
||||
_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED, authInfo.data(), authInfo.sizeBytes());
|
||||
return;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "invalid sso info.version %llu\n", info.version);
|
||||
}
|
||||
} else if (authorized) {
|
||||
fprintf(stderr, "Setting member will expire to: %lld\n", authenticationExpiryTime);
|
||||
_db.memberWillExpire(authenticationExpiryTime, nwid, identity.address().toInt());
|
||||
DB::cleanMember(member);
|
||||
_db.save(member,true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1411,8 +1381,8 @@ void EmbeddedNetworkController::_request(
|
|||
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_memberStatus_l);
|
||||
_MemberStatus &ms = _memberStatus[_MemberStatusKey(nwid,identity.address().toInt())];
|
||||
|
||||
_MemberStatus &ms = _memberStatus[msk];
|
||||
ms.authenticationExpiryTime = authenticationExpiryTime;
|
||||
ms.vMajor = (int)vMajor;
|
||||
ms.vMinor = (int)vMinor;
|
||||
ms.vRev = (int)vRev;
|
||||
|
@ -1420,9 +1390,13 @@ void EmbeddedNetworkController::_request(
|
|||
ms.lastRequestMetaData = metaData;
|
||||
ms.identity = identity;
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticationExpiryTime > 0) {
|
||||
std::lock_guard<std::mutex> l(_expiringSoon_l);
|
||||
_expiringSoon.insert(std::pair<int64_t, _MemberStatusKey>(authenticationExpiryTime, msk));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// If they are not authorized, STOP!
|
||||
DB::cleanMember(member);
|
||||
_db.save(member,true);
|
||||
|
@ -1434,18 +1408,13 @@ void EmbeddedNetworkController::_request(
|
|||
// If we made it this far, they are authorized (and authenticated).
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
|
||||
if (now > ns.mostRecentDeauthTime) {
|
||||
// If we recently de-authorized a member, shrink credential TTL/max delta to
|
||||
// be below the threshold required to exclude it. Cap this to a min/max to
|
||||
// prevent jitter or absurdly large values.
|
||||
const uint64_t deauthWindow = now - ns.mostRecentDeauthTime;
|
||||
if (deauthWindow < ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA) {
|
||||
credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA;
|
||||
} else if (deauthWindow < (ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA + 5000ULL)) {
|
||||
credentialtmd = deauthWindow - 5000ULL;
|
||||
}
|
||||
// Default timeout: 15 minutes. Maximum: two hours. Can be specified by an optional field in the network config
|
||||
// if something longer than 15 minutes is desired. Minimum is 5 minutes since shorter than that would be flaky.
|
||||
int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_DFL_MAX_DELTA;
|
||||
if (network.contains("certificateTimeoutWindowSize")) {
|
||||
credentialtmd = (int64_t)network["certificateTimeoutWindowSize"];
|
||||
}
|
||||
credentialtmd = std::max(std::min(credentialtmd, ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA), ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA);
|
||||
|
||||
std::unique_ptr<NetworkConfig> nc(new NetworkConfig());
|
||||
|
||||
|
@ -1460,7 +1429,7 @@ void EmbeddedNetworkController::_request(
|
|||
nc->mtu = std::max(std::min((unsigned int)OSUtils::jsonInt(network["mtu"],ZT_DEFAULT_MTU),(unsigned int)ZT_MAX_MTU),(unsigned int)ZT_MIN_MTU);
|
||||
nc->multicastLimit = (unsigned int)OSUtils::jsonInt(network["multicastLimit"],32ULL);
|
||||
|
||||
nc->ssoEnabled = OSUtils::jsonBool(network["ssoEnabled"], false);
|
||||
nc->ssoEnabled = networkSSOEnabled; //OSUtils::jsonBool(network["ssoEnabled"], false);
|
||||
nc->ssoVersion = info.version;
|
||||
|
||||
if (info.version == 0) {
|
||||
|
@ -1858,6 +1827,8 @@ void EmbeddedNetworkController::_startThreads()
|
|||
const long hwc = std::max((long)std::thread::hardware_concurrency(),(long)1);
|
||||
for(long t=0;t<hwc;++t) {
|
||||
_threads.emplace_back([this]() {
|
||||
std::vector<_MemberStatusKey> expired;
|
||||
nlohmann::json network, member;
|
||||
for(;;) {
|
||||
_RQEntry *qe = (_RQEntry *)0;
|
||||
auto timedWaitResult = _queue.get(qe, 1000);
|
||||
|
@ -1876,28 +1847,31 @@ void EmbeddedNetworkController::_startThreads()
|
|||
}
|
||||
}
|
||||
|
||||
std::set< std::pair<uint64_t, uint64_t> > soon;
|
||||
std::set< std::pair<uint64_t, uint64_t> > expired;
|
||||
_db.membersExpiring(soon, expired);
|
||||
|
||||
for(auto s=soon.begin();s!=soon.end();++s) {
|
||||
Identity identity;
|
||||
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastMetaData;
|
||||
{
|
||||
std::unique_lock<std::mutex> ll(_memberStatus_l);
|
||||
auto ms = _memberStatus.find(_MemberStatusKey(s->first, s->second));
|
||||
if (ms != _memberStatus.end()) {
|
||||
lastMetaData = ms->second.lastRequestMetaData;
|
||||
identity = ms->second.identity;
|
||||
expired.clear();
|
||||
int64_t now = OSUtils::now();
|
||||
{
|
||||
std::lock_guard<std::mutex> l(_expiringSoon_l);
|
||||
for(auto s=_expiringSoon.begin();s!=_expiringSoon.end();) {
|
||||
const int64_t when = s->first;
|
||||
if (when <= now) {
|
||||
// The user may have re-authorized, so we must actually look it up and check.
|
||||
network.clear();
|
||||
member.clear();
|
||||
if (_db.get(s->second.networkId, network, s->second.nodeId, member)) {
|
||||
int64_t authenticationExpiryTime = (int64_t)OSUtils::jsonInt(member["authenticationExpiryTime"], 0);
|
||||
if (authenticationExpiryTime <= now) {
|
||||
expired.push_back(s->second);
|
||||
}
|
||||
}
|
||||
_expiringSoon.erase(s++);
|
||||
} else {
|
||||
// Don't bother going further into the future than necessary.
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (identity) {
|
||||
request(s->first,InetAddress(),0,identity,lastMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto e=expired.begin();e!=expired.end();++e) {
|
||||
onNetworkMemberDeauthorize(nullptr, e->first, e->second);
|
||||
onNetworkMemberDeauthorize(nullptr, e->networkId, e->nodeId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "../osdep/Thread.hpp"
|
||||
#include "../osdep/BlockingQueue.hpp"
|
||||
|
||||
#include "../ext/json/json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "DB.hpp"
|
||||
#include "DBMirrorSet.hpp"
|
||||
|
@ -109,6 +109,7 @@ private:
|
|||
RQENTRY_TYPE_REQUEST = 0
|
||||
} type;
|
||||
};
|
||||
|
||||
struct _MemberStatusKey
|
||||
{
|
||||
_MemberStatusKey() : networkId(0),nodeId(0) {}
|
||||
|
@ -116,11 +117,13 @@ private:
|
|||
uint64_t networkId;
|
||||
uint64_t nodeId;
|
||||
inline bool operator==(const _MemberStatusKey &k) const { return ((k.networkId == networkId)&&(k.nodeId == nodeId)); }
|
||||
inline bool operator<(const _MemberStatusKey &k) const { return (k.networkId < networkId) || ((k.networkId == networkId)&&(k.nodeId < nodeId)); }
|
||||
};
|
||||
struct _MemberStatus
|
||||
{
|
||||
_MemberStatus() : lastRequestTime(0),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
|
||||
uint64_t lastRequestTime;
|
||||
_MemberStatus() : lastRequestTime(0),authenticationExpiryTime(-1),vMajor(-1),vMinor(-1),vRev(-1),vProto(-1) {}
|
||||
int64_t lastRequestTime;
|
||||
int64_t authenticationExpiryTime;
|
||||
int vMajor,vMinor,vRev,vProto;
|
||||
Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
|
||||
Identity identity;
|
||||
|
@ -152,6 +155,9 @@ private:
|
|||
std::unordered_map< _MemberStatusKey,_MemberStatus,_MemberStatusHash > _memberStatus;
|
||||
std::mutex _memberStatus_l;
|
||||
|
||||
std::set< std::pair<int64_t, _MemberStatusKey> > _expiringSoon;
|
||||
std::mutex _expiringSoon_l;
|
||||
|
||||
RedisConfig *_rc;
|
||||
std::string _ssoRedirectURL;
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <chrono>
|
||||
|
||||
|
||||
// #define ZT_TRACE 1
|
||||
// #define REDIS_TRACE 1
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
@ -783,6 +783,7 @@ void PostgreSQL::initializeMembers()
|
|||
std::string assignedAddresses = std::get<20>(row);
|
||||
|
||||
config["id"] = memberId;
|
||||
config["address"] = memberId;
|
||||
config["nwid"] = networkId;
|
||||
config["activeBridge"] = activeBridge.value_or(false);
|
||||
config["authorized"] = authorized.value_or(false);
|
||||
|
@ -942,30 +943,31 @@ void PostgreSQL::_membersWatcher_Postgres() {
|
|||
void PostgreSQL::_membersWatcher_Redis() {
|
||||
char buf[11] = {0};
|
||||
std::string key = "member-stream:{" + std::string(_myAddress.toString(buf)) + "}";
|
||||
std::string lastID = "0";
|
||||
fprintf(stderr, "Listening to member stream: %s\n", key.c_str());
|
||||
while (_run == 1) {
|
||||
try {
|
||||
json tmp;
|
||||
std::unordered_map<std::string, ItemStream> result;
|
||||
if (_rc->clusterMode) {
|
||||
_cluster->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
} else {
|
||||
_redis->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
}
|
||||
if (!result.empty()) {
|
||||
for (auto element : result) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Received notification from: %s\n", element.first.c_str());
|
||||
#endif
|
||||
for (auto rec : element.second) {
|
||||
std::string id = rec.first;
|
||||
auto attrs = rec.second;
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Record ID: %s\n", id.c_str());
|
||||
fprintf(stdout, "attrs len: %lu\n", attrs.size());
|
||||
#endif
|
||||
for (auto a : attrs) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str());
|
||||
#endif
|
||||
try {
|
||||
|
@ -987,6 +989,7 @@ void PostgreSQL::_membersWatcher_Redis() {
|
|||
} else {
|
||||
_redis->xdel(key, id);
|
||||
}
|
||||
lastID = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1029,31 +1032,31 @@ void PostgreSQL::_networksWatcher_Postgres() {
|
|||
void PostgreSQL::_networksWatcher_Redis() {
|
||||
char buf[11] = {0};
|
||||
std::string key = "network-stream:{" + std::string(_myAddress.toString(buf)) + "}";
|
||||
|
||||
std::string lastID = "0";
|
||||
while (_run == 1) {
|
||||
try {
|
||||
json tmp;
|
||||
std::unordered_map<std::string, ItemStream> result;
|
||||
if (_rc->clusterMode) {
|
||||
_cluster->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_cluster->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
} else {
|
||||
_redis->xread(key, "$", std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
_redis->xread(key, lastID, std::chrono::seconds(1), 0, std::inserter(result, result.end()));
|
||||
}
|
||||
|
||||
if (!result.empty()) {
|
||||
for (auto element : result) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Received notification from: %s\n", element.first.c_str());
|
||||
#endif
|
||||
for (auto rec : element.second) {
|
||||
std::string id = rec.first;
|
||||
auto attrs = rec.second;
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "Record ID: %s\n", id.c_str());
|
||||
fprintf(stdout, "attrs len: %lu\n", attrs.size());
|
||||
#endif
|
||||
for (auto a : attrs) {
|
||||
#ifdef ZT_TRACE
|
||||
#ifdef REDIS_TRACE
|
||||
fprintf(stdout, "key: %s\nvalue: %s\n", a.first.c_str(), a.second.c_str());
|
||||
#endif
|
||||
try {
|
||||
|
@ -1075,6 +1078,7 @@ void PostgreSQL::_networksWatcher_Redis() {
|
|||
} else {
|
||||
_redis->xdel(key, id);
|
||||
}
|
||||
lastID = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
24
debian/changelog
vendored
24
debian/changelog
vendored
|
@ -1,3 +1,27 @@
|
|||
zerotier-one (1.10.0) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Fri, 03 Jun 2022 01:00:00 -0700
|
||||
|
||||
zerotier-one (1.8.10) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Tue, 10 May 2022 01:00:00 -0700
|
||||
|
||||
zerotier-one (1.8.9) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Mon, 25 Apr 2022 01:00:00 -0700
|
||||
|
||||
zerotier-one (1.8.8) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
||||
-- Adam Ierymenko <adam.ierymenko@zerotier.com> Mon, 11 Apr 2022 01:00:00 -0700
|
||||
|
||||
zerotier-one (1.8.7) unstable; urgency=medium
|
||||
|
||||
* See RELEASE-NOTES.md for release notes.
|
||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -10,7 +10,7 @@ Homepage: https://www.zerotier.com/
|
|||
|
||||
Package: zerotier-one
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, iproute2, adduser, libstdc++6, openssl
|
||||
Depends: iproute2, adduser, libstdc++6 (>= 5), openssl
|
||||
Homepage: https://www.zerotier.com/
|
||||
Description: ZeroTier network virtualization service
|
||||
ZeroTier One lets you join ZeroTier virtual networks and
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.11.3
|
||||
FROM alpine:3.15
|
||||
|
||||
ARG go_pkg_url
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
grepzt() {
|
||||
[ -f /var/lib/zerotier-one/zerotier-one.pid -a -n "$(cat /var/lib/zerotier-one/zerotier-one.pid)" -a -d "/proc/$(cat /var/lib/zerotier-one/zerotier-one.pid)" ]
|
||||
[ -f /var/lib/zerotier-one/zerotier-one.pid -a -n "$(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null)" -a -d "/proc/$(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null)" ]
|
||||
return $?
|
||||
}
|
||||
|
||||
|
@ -33,29 +33,57 @@ fi
|
|||
mkztfile zerotier-one.port 0600 "9993"
|
||||
|
||||
killzerotier() {
|
||||
echo "Killing zerotier"
|
||||
kill $(cat /var/lib/zerotier-one/zerotier-one.pid)
|
||||
log "Killing zerotier"
|
||||
kill $(cat /var/lib/zerotier-one/zerotier-one.pid 2>/dev/null)
|
||||
exit 0
|
||||
}
|
||||
|
||||
log_header() {
|
||||
echo -n "\r=>"
|
||||
}
|
||||
|
||||
log_detail_header() {
|
||||
echo -n "\r===>"
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "$(log_header)" "$@"
|
||||
}
|
||||
|
||||
log_params() {
|
||||
title=$1
|
||||
shift
|
||||
log "$title" "[$@]"
|
||||
}
|
||||
|
||||
log_detail() {
|
||||
echo "$(log_detail_header)" "$@"
|
||||
}
|
||||
|
||||
log_detail_params() {
|
||||
title=$1
|
||||
shift
|
||||
log_detail "$title" "[$@]"
|
||||
}
|
||||
|
||||
trap killzerotier INT TERM
|
||||
|
||||
echo "Configuring networks to join"
|
||||
log "Configuring networks to join"
|
||||
mkdir -p /var/lib/zerotier-one/networks.d
|
||||
|
||||
echo "joining networks: $@"
|
||||
log_params "Joining networks:" $@
|
||||
for i in "$@"
|
||||
do
|
||||
echo "Configuring join for $i"
|
||||
log_detail_params "Configuring join:" "$i"
|
||||
touch "/var/lib/zerotier-one/networks.d/${i}.conf"
|
||||
done
|
||||
|
||||
echo "starting zerotier"
|
||||
log "Starting ZeroTier"
|
||||
nohup /usr/sbin/zerotier-one &
|
||||
|
||||
while ! grepzt
|
||||
do
|
||||
echo "zerotier hasn't started, waiting a second"
|
||||
log_detail "ZeroTier hasn't started, waiting a second"
|
||||
|
||||
if [ -f nohup.out ]
|
||||
then
|
||||
|
@ -65,7 +93,7 @@ do
|
|||
sleep 1
|
||||
done
|
||||
|
||||
echo "Writing healthcheck for networks: $@"
|
||||
log_params "Writing healthcheck for networks:" $@
|
||||
|
||||
cat >/healthcheck.sh <<EOF
|
||||
#!/bin/bash
|
||||
|
@ -77,7 +105,9 @@ EOF
|
|||
|
||||
chmod +x /healthcheck.sh
|
||||
|
||||
echo "Sleeping infinitely"
|
||||
log_params "zerotier-cli info:" "$(zerotier-cli info)"
|
||||
|
||||
log "Sleeping infinitely"
|
||||
while true
|
||||
do
|
||||
sleep 1
|
||||
|
|
21
ext/inja/LICENSE
Normal file
21
ext/inja/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021 Berscheid
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
391
ext/inja/README.md
Normal file
391
ext/inja/README.md
Normal file
|
@ -0,0 +1,391 @@
|
|||
[<div align="center"><img width="500" src="https://raw.githubusercontent.com/pantor/inja/master/doc/logo.svg?sanitize=true"></div>](https://github.com/pantor/inja/releases)
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/pantor/inja/actions">
|
||||
<img src="https://github.com/pantor/inja/workflows/CI/badge.svg" alt="CI Status">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/pantor/inja/actions">
|
||||
<img src="https://github.com/pantor/inja/workflows/Documentation/badge.svg" alt="Documentation Status">
|
||||
</a>
|
||||
|
||||
<a href="https://www.codacy.com/manual/pantor/inja?utm_source=github.com&utm_medium=referral&utm_content=pantor/inja&utm_campaign=Badge_Grade">
|
||||
<img src="https://app.codacy.com/project/badge/Grade/211718f7a36541819d1244c0e2ee6f08"/>
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/pantor/inja/releases">
|
||||
<img src="https://img.shields.io/github/release/pantor/inja.svg" alt="Github Releases">
|
||||
</a>
|
||||
|
||||
<a href="http://github.com/pantor/inja/issues">
|
||||
<img src="https://img.shields.io/github/issues/pantor/inja.svg" alt="Github Issues">
|
||||
</a>
|
||||
|
||||
<a href="https://raw.githubusercontent.com/pantor/inja/master/LICENSE">
|
||||
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="GitHub License">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Inja is a template engine for modern C++, loosely inspired by [jinja](http://jinja.pocoo.org) for python. It has an easy and yet powerful template syntax with all variables, loops, conditions, includes, callbacks, and comments you need, nested and combined as you like. Inja uses the wonderful [json](https://github.com/nlohmann/json) library by nlohmann for data input. Most importantly, inja needs only two header files, which is (nearly) as trivial as integration in C++ can get. Of course, everything is tested on all relevant compilers. Here is what it looks like:
|
||||
|
||||
```.cpp
|
||||
json data;
|
||||
data["name"] = "world";
|
||||
|
||||
inja::render("Hello {{ name }}!", data); // Returns "Hello world!"
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
Inja is a headers only library, which can be downloaded from the [releases](https://github.com/pantor/inja/releases) or directly from the `include/` or `single_include/` folder. Inja uses `nlohmann/json.hpp` (>= v3.8.0) as its single dependency, so make sure it can be included from `inja.hpp`. json can be downloaded [here](https://github.com/nlohmann/json/releases). Then integration is as easy as:
|
||||
|
||||
```.cpp
|
||||
#include <inja.hpp>
|
||||
|
||||
// Just for convenience
|
||||
using namespace inja;
|
||||
```
|
||||
|
||||
If you are using the [Meson Build System](http://mesonbuild.com), then you can wrap this repository as a subproject.
|
||||
|
||||
If you are using [Conan](https://conan.io) to manage your dependencies, have a look at [this repository](https://github.com/DEGoodmanWilson/conan-inja). Please file issues [here](https://github.com/DEGoodmanWilson/conan-inja/issues) if you experience problems with the packages.
|
||||
|
||||
You can also integrate inja in your project using [Hunter](https://github.com/cpp-pm/hunter), a package manager for C++.
|
||||
|
||||
If you are using [vcpkg](https://github.com/Microsoft/vcpkg) on your project for external dependencies, then you can use the [inja package](https://github.com/Microsoft/vcpkg/tree/master/ports/inja). Please see the vcpkg project for any issues regarding the packaging.
|
||||
|
||||
If you are using [cget](https://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install pantor/inja`. A specific version can be installed with `cget install pantor/inja@v2.1.0`.
|
||||
|
||||
On macOS, you can install inja via [Homebrew](https://formulae.brew.sh/formula/inja#default) and `brew install inja`.
|
||||
|
||||
If you are using [conda](https://docs.conda.io/en/latest/), you can install the latest version from [conda-forge](https://anaconda.org/conda-forge/inja) with `conda install -c conda-forge inja`.
|
||||
|
||||
## Tutorial
|
||||
|
||||
This tutorial will give you an idea how to use inja. It will explain the most important concepts and give practical advices using examples and executable code. Beside this tutorial, you may check out the [documentation](https://pantor.github.io/inja).
|
||||
|
||||
### Template Rendering
|
||||
|
||||
The basic template rendering takes a template as a `std::string` and a `json` object for all data. It returns the rendered template as an `std::string`.
|
||||
|
||||
```.cpp
|
||||
json data;
|
||||
data["name"] = "world";
|
||||
|
||||
render("Hello {{ name }}!", data); // Returns std::string "Hello world!"
|
||||
render_to(std::cout, "Hello {{ name }}!", data); // Writes "Hello world!" to stream
|
||||
```
|
||||
|
||||
For more advanced usage, an environment is recommended.
|
||||
```.cpp
|
||||
Environment env;
|
||||
|
||||
// Render a string with json data
|
||||
std::string result = env.render("Hello {{ name }}!", data); // "Hello world!"
|
||||
|
||||
// Or directly read a template file
|
||||
Template temp = env.parse_template("./templates/greeting.txt");
|
||||
std::string result = env.render(temp, data); // "Hello world!"
|
||||
|
||||
data["name"] = "Inja";
|
||||
std::string result = env.render(temp, data); // "Hello Inja!"
|
||||
|
||||
// Or read the template file (and/or the json file) directly from the environment
|
||||
result = env.render_file("./templates/greeting.txt", data);
|
||||
result = env.render_file_with_json_file("./templates/greeting.txt", "./data.json");
|
||||
|
||||
// Or write a rendered template file
|
||||
env.write(temp, data, "./result.txt");
|
||||
env.write_with_json_file("./templates/greeting.txt", "./data.json", "./result.txt");
|
||||
```
|
||||
|
||||
The environment class can be configured to your needs.
|
||||
```.cpp
|
||||
// With default settings
|
||||
Environment env_default;
|
||||
|
||||
// With global path to template files and where files will be saved
|
||||
Environment env_1 {"../path/templates/"};
|
||||
|
||||
// With separate input and output path
|
||||
Environment env_2 {"../path/templates/", "../path/results/"};
|
||||
|
||||
// With other opening and closing strings (here the defaults)
|
||||
env.set_expression("{{", "}}"); // Expressions
|
||||
env.set_comment("{#", "#}"); // Comments
|
||||
env.set_statement("{%", "%}"); // Statements {% %} for many things, see below
|
||||
env.set_line_statement("##"); // Line statements ## (just an opener)
|
||||
```
|
||||
|
||||
### Variables
|
||||
|
||||
Variables are rendered within the `{{ ... }}` expressions.
|
||||
```.cpp
|
||||
json data;
|
||||
data["neighbour"] = "Peter";
|
||||
data["guests"] = {"Jeff", "Tom", "Patrick"};
|
||||
data["time"]["start"] = 16;
|
||||
data["time"]["end"] = 22;
|
||||
|
||||
// Indexing in array
|
||||
render("{{ guests.1 }}", data); // "Tom"
|
||||
|
||||
// Objects
|
||||
render("{{ time.start }} to {{ time.end + 1 }}pm", data); // "16 to 23pm"
|
||||
```
|
||||
If no variable is found, valid JSON is printed directly, otherwise an `inja::RenderError` is thrown.
|
||||
|
||||
### Statements
|
||||
|
||||
Statements can be written either with the `{% ... %}` syntax or the `##` syntax for entire lines. Note that `##` needs to start the line without indentation. The most important statements are loops, conditions and file includes. All statements can be nested.
|
||||
|
||||
#### Loops
|
||||
|
||||
```.cpp
|
||||
// Combining loops and line statements
|
||||
render(R"(Guest List:
|
||||
## for guest in guests
|
||||
{{ loop.index1 }}: {{ guest }}
|
||||
## endfor )", data)
|
||||
|
||||
/* Guest List:
|
||||
1: Jeff
|
||||
2: Tom
|
||||
3: Patrick */
|
||||
```
|
||||
In a loop, the special variables `loop.index (number)`, `loop.index1 (number)`, `loop.is_first (boolean)` and `loop.is_last (boolean)` are defined. In nested loops, the parent loop variables are available e.g. via `loop.parent.index`. You can also iterate over objects like `{% for key, value in time %}`.
|
||||
|
||||
#### Conditions
|
||||
|
||||
Conditions support the typical if, else if and else statements. Following conditions are for example possible:
|
||||
```.cpp
|
||||
// Standard comparisons with a variable
|
||||
render("{% if time.hour >= 20 %}Serve{% else if time.hour >= 18 %}Make{% endif %} dinner.", data); // Serve dinner.
|
||||
|
||||
// Variable in list
|
||||
render("{% if neighbour in guests %}Turn up the music!{% endif %}", data); // Turn up the music!
|
||||
|
||||
// Logical operations
|
||||
render("{% if guest_count < (3+2) and all_tired %}Sleepy...{% else %}Keep going...{% endif %}", data); // Sleepy...
|
||||
|
||||
// Negations
|
||||
render("{% if not guest_count %}The End{% endif %}", data); // The End
|
||||
```
|
||||
|
||||
#### Includes
|
||||
|
||||
You can either include other in-memory templates or from the file system.
|
||||
```.cpp
|
||||
// To include in-memory templates, add them to the environment first
|
||||
inja::Template content_template = env.parse("Hello {{ neighbour }}!");
|
||||
env.include_template("content", content_template);
|
||||
env.render("Content: {% include \"content\" %}", data); // "Content: Hello Peter!"
|
||||
|
||||
// Other template files are included relative from the current file location
|
||||
render("{% include \"footer.html\" %}", data);
|
||||
```
|
||||
If a corresponding template could not be found in the file system, the *include callback* is called:
|
||||
```.cpp
|
||||
// The callback takes the current path and the wanted include name and returns a template
|
||||
env.set_include_callback([&env](const std::string& path, const std::string& template_name) {
|
||||
return env.parse("Hello {{ neighbour }} from " + template_name);
|
||||
});
|
||||
|
||||
// You can disable to search for templates in the file system via
|
||||
env.set_search_included_templates_in_files(false);
|
||||
```
|
||||
|
||||
Inja will throw an `inja::RenderError` if an included file is not found and no callback is specified. To disable this error, you can call `env.set_throw_at_missing_includes(false)`.
|
||||
|
||||
#### Assignments
|
||||
|
||||
Variables can also be defined within the template using the set statment.
|
||||
```.cpp
|
||||
render("{% set new_hour=23 %}{{ new_hour }}pm", data); // "23pm"
|
||||
render("{% set time.start=18 %}{{ time.start }}pm", data); // using json pointers
|
||||
```
|
||||
|
||||
Assignments only set the value within the rendering context; they do not modify the json object passed into the `render` call.
|
||||
|
||||
### Functions
|
||||
|
||||
A few functions are implemented within the inja template syntax. They can be called with
|
||||
```.cpp
|
||||
// Upper and lower function, for string cases
|
||||
render("Hello {{ upper(neighbour) }}!", data); // "Hello PETER!"
|
||||
render("Hello {{ lower(neighbour) }}!", data); // "Hello peter!"
|
||||
|
||||
// Range function, useful for loops
|
||||
render("{% for i in range(4) %}{{ loop.index1 }}{% endfor %}", data); // "1234"
|
||||
render("{% for i in range(3) %}{{ at(guests, i) }} {% endfor %}", data); // "Jeff Tom Patrick "
|
||||
|
||||
// Length function (please don't combine with range, use list directly...)
|
||||
render("I count {{ length(guests) }} guests.", data); // "I count 3 guests."
|
||||
|
||||
// Get first and last element in a list
|
||||
render("{{ first(guests) }} was first.", data); // "Jeff was first."
|
||||
render("{{ last(guests) }} was last.", data); // "Patir was last."
|
||||
|
||||
// Sort a list
|
||||
render("{{ sort([3,2,1]) }}", data); // "[1,2,3]"
|
||||
render("{{ sort(guests) }}", data); // "[\"Jeff\", \"Patrick\", \"Tom\"]"
|
||||
|
||||
// Join a list with a separator
|
||||
render("{{ join([1,2,3], \" + \") }}", data); // "1 + 2 + 3"
|
||||
render("{{ join(guests, \", \") }}", data); // "Jeff, Patrick, Tom"
|
||||
|
||||
// Round numbers to a given precision
|
||||
render("{{ round(3.1415, 0) }}", data); // 3
|
||||
render("{{ round(3.1415, 3) }}", data); // 3.142
|
||||
|
||||
// Check if a value is odd, even or divisible by a number
|
||||
render("{{ odd(42) }}", data); // false
|
||||
render("{{ even(42) }}", data); // true
|
||||
render("{{ divisibleBy(42, 7) }}", data); // true
|
||||
|
||||
// Maximum and minimum values from a list
|
||||
render("{{ max([1, 2, 3]) }}", data); // 3
|
||||
render("{{ min([-2.4, -1.2, 4.5]) }}", data); // -2.4
|
||||
|
||||
// Convert strings to numbers
|
||||
render("{{ int(\"2\") == 2 }}", data); // true
|
||||
render("{{ float(\"1.8\") > 2 }}", data); // false
|
||||
|
||||
// Set default values if variables are not defined
|
||||
render("Hello {{ default(neighbour, \"my friend\") }}!", data); // "Hello Peter!"
|
||||
render("Hello {{ default(colleague, \"my friend\") }}!", data); // "Hello my friend!"
|
||||
|
||||
// Access an objects value dynamically
|
||||
render("{{ at(time, \"start\") }} to {{ time.end }}", data); // "16 to 22"
|
||||
|
||||
// Check if a key exists in an object
|
||||
render("{{ exists(\"guests\") }}", data); // "true"
|
||||
render("{{ exists(\"city\") }}", data); // "false"
|
||||
render("{{ existsIn(time, \"start\") }}", data); // "true"
|
||||
render("{{ existsIn(time, neighbour) }}", data); // "false"
|
||||
|
||||
// Check if a key is a specific type
|
||||
render("{{ isString(neighbour) }}", data); // "true"
|
||||
render("{{ isArray(guests) }}", data); // "true"
|
||||
// Implemented type checks: isArray, isBoolean, isFloat, isInteger, isNumber, isObject, isString,
|
||||
```
|
||||
|
||||
### Callbacks
|
||||
|
||||
You can create your own and more complex functions with callbacks. These are implemented with `std::function`, so you can for example use C++ lambdas. Inja `Arguments` are a vector of json pointers.
|
||||
```.cpp
|
||||
Environment env;
|
||||
|
||||
/*
|
||||
* Callbacks are defined by its:
|
||||
* - name,
|
||||
* - (optional) number of arguments,
|
||||
* - callback function.
|
||||
*/
|
||||
env.add_callback("double", 1, [](Arguments& args) {
|
||||
int number = args.at(0)->get<int>(); // Adapt the index and type of the argument
|
||||
return 2 * number;
|
||||
});
|
||||
|
||||
// You can then use a callback like a regular function
|
||||
env.render("{{ double(16) }}", data); // "32"
|
||||
|
||||
// Inja falls back to variadic callbacks if the number of expected arguments is omitted.
|
||||
env.add_callback("argmax", [](Arguments& args) {
|
||||
auto result = std::max_element(args.begin(), args.end(), [](const json* a, const json* b) { return *a < *b;});
|
||||
return std::distance(args.begin(), result);
|
||||
});
|
||||
env.render("{{ argmax(4, 2, 6) }}", data); // "2"
|
||||
env.render("{{ argmax(0, 2, 6, 8, 3) }}", data); // "3"
|
||||
|
||||
// A callback without argument can be used like a dynamic variable:
|
||||
std::string greet = "Hello";
|
||||
env.add_callback("double-greetings", 0, [greet](Arguments args) {
|
||||
return greet + " " + greet + "!";
|
||||
});
|
||||
env.render("{{ double-greetings }}", data); // "Hello Hello!"
|
||||
```
|
||||
You can also add a void callback without return variable, e.g. for debugging:
|
||||
```.cpp
|
||||
env.add_void_callback("log", 1, [greet](Arguments args) {
|
||||
std::cout << "logging: " << args[0] << std::endl;
|
||||
});
|
||||
env.render("{{ log(neighbour) }}", data); // Prints nothing to result, only to cout...
|
||||
```
|
||||
|
||||
### Template Inheritance
|
||||
|
||||
Template inheritance allows you to build a base *skeleton* template that contains all the common elements and defines blocks that child templates can override. Lets show an example: The base template
|
||||
```.html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<title>{% block title %}{% endblock %} - My Webpage</title>
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">{% block content %}{% endblock %}</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
contains three `blocks` that child templates can fill in. The child template
|
||||
```.html
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Index{% endblock %}
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style type="text/css">
|
||||
.important { color: #336699; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Index</h1>
|
||||
<p class="important">
|
||||
Welcome to my blog!
|
||||
</p>
|
||||
{% endblock %}
|
||||
```
|
||||
calls a parent template with the `extends` keyword; it should be the first element in the template. It is possible to render the contents of the parent block by calling `super()`. In the case of multiple levels of `{% extends %}`, super references may be called with an argument (e.g. `super(2)`) to skip levels in the inheritance tree.
|
||||
|
||||
### Whitespace Control
|
||||
|
||||
In the default configuration, no whitespace is removed while rendering the file. To support a more readable template style, you can configure the environment to control whitespaces before and after a statement automatically. While enabling `set_trim_blocks` removes the first newline after a statement, `set_lstrip_blocks` strips tabs and spaces from the beginning of a line to the start of a block.
|
||||
|
||||
```.cpp
|
||||
Environment env;
|
||||
env.set_trim_blocks(true);
|
||||
env.set_lstrip_blocks(true);
|
||||
```
|
||||
|
||||
With both `trim_blocks` and `lstrip_blocks` enabled, you can put statements on their own lines. Furthermore, you can also strip whitespaces for both statements and expressions by hand. If you add a minus sign (`-`) to the start or end, the whitespaces before or after that block will be removed:
|
||||
|
||||
```.cpp
|
||||
render("Hello {{- name -}} !", data); // "Hello Inja!"
|
||||
render("{% if neighbour in guests -%} I was there{% endif -%} !", data); // Renders without any whitespaces
|
||||
```
|
||||
|
||||
Stripping behind a statement or expression also removes any newlines.
|
||||
|
||||
### Comments
|
||||
|
||||
Comments can be written with the `{# ... #}` syntax.
|
||||
```.cpp
|
||||
render("Hello{# Todo #}!", data); // "Hello!"
|
||||
```
|
||||
|
||||
### Exceptions
|
||||
|
||||
Inja uses exceptions to handle ill-formed template input. However, exceptions can be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `INJA_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls.
|
||||
|
||||
|
||||
## Supported compilers
|
||||
|
||||
Inja uses the `string_view` feature of the C++17 STL. Currently, the following compilers are tested:
|
||||
|
||||
- GCC 7 - 11 (and possibly later)
|
||||
- Clang 5 - 12 (and possibly later)
|
||||
- Microsoft Visual C++ 2017 15.0 - 2022 (and possibly later)
|
||||
|
||||
A list of supported compiler / os versions can be found in the [CI definition](https://github.com/pantor/inja/blob/master/.github/workflows/ci.yml).
|
2949
ext/inja/inja.hpp
Normal file
2949
ext/inja/inja.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -701,7 +701,7 @@
|
|||
<key>USE_HFS+_COMPRESSION</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.8.7</string>
|
||||
<string>1.10.0</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,12 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<DOCUMENT Type="Advanced Installer" CreateVersion="10.9" version="19.2" Modules="enterprise" RootPath="." Language="en" Id="{DC564647-6BF0-4550-87F4-89C938D0159C}">
|
||||
<DOCUMENT Type="Advanced Installer" CreateVersion="10.9" version="19.5" Modules="enterprise" RootPath="." Language="en" Id="{DC564647-6BF0-4550-87F4-89C938D0159C}">
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.ProjectOptionsComponent">
|
||||
<ROW Name="HiddenItems" Value="ActSyncAppComponent;CPLAppletComponent;AutorunComponent;GameUxComponent;SilverlightSlnComponent;AppXAppDetailsComponent;FixupComponent;AppXCapabilitiesComponent;AppXDependenciesComponent;AppXProductDetailsComponent;AppXVisualAssetsComponent;AppXAppDeclarationsComponent;AppXUriRulesComponent;MsiXDiffComponent;MsixManifestEditorComponent"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiPropsComponent">
|
||||
<ROW Property="AI_BITMAP_DISPLAY_MODE" Value="0"/>
|
||||
<ROW Property="AI_CURRENT_YEAR" Value="2022" ValueLocId="-"/>
|
||||
<ROW Property="AI_EMBD_MSI_EXTR_PATH" Value="[TempFolder]" ValueLocId="-"/>
|
||||
<ROW Property="AI_EXTERNALUIUNINSTALLERNAME" MultiBuildValue="DefaultBuild:aiui"/>
|
||||
<ROW Property="AI_FINDEXE_TITLE" Value="Select the installation package for [|ProductName]" ValueLocId="AI.Property.FindExeTitle"/>
|
||||
<ROW Property="AI_PACKAGING_TOOL" Value="Advanced Installer 19.5 build 36301275" ValueLocId="-"/>
|
||||
<ROW Property="AI_PREDEF_LCONDS_PROPS" Value="AI_DETECTED_DOTNET_VERSION"/>
|
||||
<ROW Property="AI_PREREQ_REPAIR_ENABLED" MultiBuildValue="ExeBuild:1"/>
|
||||
<ROW Property="AI_PRODUCTNAME_ARP" Value="ZeroTier One"/>
|
||||
<ROW Property="AI_REQUIRED_DOTNET_DISPLAY" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
|
||||
<ROW Property="AI_REQUIRED_DOTNET_VERSION" MultiBuildValue="DefaultBuild:4.5" ValueLocId="-"/>
|
||||
|
@ -27,10 +32,10 @@
|
|||
<ROW Property="LIMITUI" MultiBuildValue="DefaultBuild:1"/>
|
||||
<ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>
|
||||
<ROW Property="Manufacturer" Value="ZeroTier, Inc."/>
|
||||
<ROW Property="ProductCode" Value="1033:{1CF2BF7E-ADE7-440B-A50A-F2912D8B4D0D} " Type="16"/>
|
||||
<ROW Property="ProductCode" Value="1033:{5FF7375F-69D4-4CAA-800B-3EA1E587AAAE} " Type="16"/>
|
||||
<ROW Property="ProductLanguage" Value="1033"/>
|
||||
<ROW Property="ProductName" Value="ZeroTier One"/>
|
||||
<ROW Property="ProductVersion" Value="1.8.6"/>
|
||||
<ROW Property="ProductVersion" Value="1.10.0"/>
|
||||
<ROW Property="REBOOT" MultiBuildValue="DefaultBuild:ReallySuppress"/>
|
||||
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
|
||||
<ROW Property="UpgradeCode" Value="{B0E2A5F3-88B6-4E77-B922-CB4739B4C4C8}"/>
|
||||
|
@ -49,33 +54,38 @@
|
|||
<ROW Property="ZTHEADLESS" Value="No"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiDirsComponent">
|
||||
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1" DirectoryOptions="3"/>
|
||||
<ROW Directory="APPDIR" Directory_Parent="TARGETDIR" DefaultDir="APPDIR:." IsPseudoRoot="1" DirectoryOptions="15"/>
|
||||
<ROW Directory="CommonAppDataFolder" Directory_Parent="TARGETDIR" DefaultDir="COMMON~1|CommonAppDataFolder" IsPseudoRoot="1"/>
|
||||
<ROW Directory="One_Dir" Directory_Parent="ZeroTier_Dir" DefaultDir="One"/>
|
||||
<ROW Directory="One_Dir" Directory_Parent="ZeroTier_Dir" DefaultDir="One" DirectoryOptions="12"/>
|
||||
<ROW Directory="ProgramFilesFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~1|ProgramFilesFolder" IsPseudoRoot="1"/>
|
||||
<ROW Directory="ProgramMenuFolder" Directory_Parent="TARGETDIR" DefaultDir="PROGRA~2|ProgramMenuFolder" IsPseudoRoot="1"/>
|
||||
<ROW Directory="TARGETDIR" DefaultDir="SourceDir"/>
|
||||
<ROW Directory="ZeroTier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="ZeroTier"/>
|
||||
<ROW Directory="ZeroTier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="ZeroTier" DirectoryOptions="12"/>
|
||||
<ROW Directory="i686_1_Dir" Directory_Parent="ProgramMenuFolder" DefaultDir=".:i686"/>
|
||||
<ROW Directory="i686_Dir" Directory_Parent="APPDIR" DefaultDir=".:i686" DirectoryOptions="3"/>
|
||||
<ROW Directory="networks.d_Dir" Directory_Parent="One_Dir" DefaultDir="networks.d"/>
|
||||
<ROW Directory="regid.201001.com.zerotier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="REGID2~1.ZER|regid.2010-01.com.zerotier"/>
|
||||
<ROW Directory="tapwindows_Dir" Directory_Parent="One_Dir" DefaultDir="TAP-WI~1|tap-windows"/>
|
||||
<ROW Directory="x64_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x64"/>
|
||||
<ROW Directory="x86_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x86"/>
|
||||
<ROW Directory="i686_Dir" Directory_Parent="APPDIR" DefaultDir=".:i686" DirectoryOptions="15"/>
|
||||
<ROW Directory="networks.d_Dir" Directory_Parent="One_Dir" DefaultDir="networks.d" DirectoryOptions="12"/>
|
||||
<ROW Directory="regid.201001.com.zerotier_Dir" Directory_Parent="CommonAppDataFolder" DefaultDir="REGID2~1.ZER|regid.2010-01.com.zerotier" DirectoryOptions="12"/>
|
||||
<ROW Directory="tapwindows_Dir" Directory_Parent="One_Dir" DefaultDir="TAP-WI~1|tap-windows" DirectoryOptions="12"/>
|
||||
<ROW Directory="x64_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x64" DirectoryOptions="12"/>
|
||||
<ROW Directory="x86_Dir" Directory_Parent="tapwindows_Dir" DefaultDir="x86" DirectoryOptions="12"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCompsComponent">
|
||||
<ROW Component="A918597FE054CCCB65ABDBA0AD8F63C" ComponentId="{458A5336-4527-4409-BB9D-D074790820A6}" Directory_="APPDIR" Attributes="4" KeyPath="A918597FE054CCCB65ABDBA0AD8F63C" Options="2"/>
|
||||
<ROW Component="AI_CustomARPName" ComponentId="{B098B41F-3C1C-4D4E-BB89-FF0C81A26E9C}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
|
||||
<ROW Component="A918597FE054CCCB65ABDBA0AD8F63C" ComponentId="{9EBBA2D0-7170-4C6C-9B07-9405F08DC282}" Directory_="APPDIR" Attributes="4" KeyPath="A918597FE054CCCB65ABDBA0AD8F63C" Options="2"/>
|
||||
<ROW Component="AI_CustomARPName" ComponentId="{B1226053-207C-4922-AF29-49542B56F5FB}" Directory_="APPDIR" Attributes="4" KeyPath="DisplayName" Options="1"/>
|
||||
<ROW Component="AI_DisableModify" ComponentId="{46FFA8C5-A0CB-4E05-9AD3-911D543DE8CA}" Directory_="APPDIR" Attributes="4" KeyPath="NoModify" Options="1"/>
|
||||
<ROW Component="AI_ExePath" ComponentId="{8E02B36C-7A19-429B-A93E-77A9261AC918}" Directory_="APPDIR" Attributes="4" KeyPath="AI_ExePath"/>
|
||||
<ROW Component="APPDIR" ComponentId="{4DD7907D-D7FE-4CD6-B1A0-B5C1625F5133}" Directory_="APPDIR" Attributes="0"/>
|
||||
<ROW Component="C4FE6FD5B7C4D07B3A313E754A9A6A8" ComponentId="{7A501107-9EEE-45A6-9609-F5E1A7372448}" Directory_="APPDIR" Attributes="260" KeyPath="C4FE6FD5B7C4D07B3A313E754A9A6A8" Options="2"/>
|
||||
<ROW Component="C4FE6FD5B7C4D07B3A313E754A9A6A8" ComponentId="{8F2CBC66-14B3-4DF4-8F6E-4B79B080BB12}" Directory_="APPDIR" Attributes="4" KeyPath="C4FE6FD5B7C4D07B3A313E754A9A6A8" Options="2"/>
|
||||
<ROW Component="One" ComponentId="{41AB11E7-066E-414A-96F8-F051D3D3B353}" Directory_="One_Dir" Attributes="0"/>
|
||||
<ROW Component="ProductInformation" ComponentId="{DB078D04-EA8E-4A7C-9001-89BAD932F9D9}" Directory_="APPDIR" Attributes="4" KeyPath="Version"/>
|
||||
<ROW Component="RequiredApplication" ComponentId="{92E37C98-F8B3-4A85-AE77-3D8D9A223776}" Directory_="APPDIR" Attributes="4" Condition="VersionNT >= 1000" KeyPath="RequiredApplication" Options="2"/>
|
||||
<ROW Component="ZeroTier" ComponentId="{8864F744-9BDF-4891-88A1-6D23D76BCCB1}" Directory_="ZeroTier_Dir" Attributes="0"/>
|
||||
<ROW Component="i686" ComponentId="{6EC46014-3BFD-4017-ACBC-C4417D1D6361}" Directory_="i686_1_Dir" Attributes="0"/>
|
||||
<ROW Component="i686_1" ComponentId="{60156BDC-31D7-47EE-A307-B62129607DD5}" Directory_="i686_Dir" Attributes="0"/>
|
||||
<ROW Component="networks.d" ComponentId="{EF54D0DF-889F-41DC-AF5C-4E7F96AB1C8B}" Directory_="networks.d_Dir" Attributes="0"/>
|
||||
<ROW Component="regid.201001.com.zerotier" ComponentId="{A39C80FC-6A8F-454F-9052-10DAC3C3B139}" Directory_="regid.201001.com.zerotier_Dir" Attributes="0"/>
|
||||
<ROW Component="tapwindows" ComponentId="{3E9CBCCE-EC9D-4802-B8FD-DADB4CC532A2}" Directory_="tapwindows_Dir" Attributes="0"/>
|
||||
<ROW Component="x64" ComponentId="{4DD1F90B-53F1-4390-BDF1-E6D9B39B8D80}" Directory_="x64_Dir" Attributes="0"/>
|
||||
<ROW Component="x86" ComponentId="{8E83C577-3C22-49B7-82A8-369BE1F19224}" Directory_="x86_Dir" Attributes="0"/>
|
||||
<ROW Component="zerotier_desktop_ui.exe" ComponentId="{61A7F53C-C6C3-418D-A652-2E4D9F8173AA}" Directory_="APPDIR" Attributes="256" Condition="ZTHEADLESS = "No" AND VersionNT64" KeyPath="zerotier_desktop_ui.exe"/>
|
||||
<ROW Component="zerotier_desktop_ui.exe_1" ComponentId="{5CFEA823-6D17-4EAA-BBAA-810E1C89555D}" Directory_="i686_Dir" Attributes="0" Condition="ZTHEADLESS = "No" AND NOT VersionNT64" KeyPath="zerotier_desktop_ui.exe_1"/>
|
||||
<ROW Component="zerotierone_x64.exe" ComponentId="{DFCFB72D-B055-4E60-B6D8-81FF585C2183}" Directory_="One_Dir" Attributes="256" Condition="VersionNT64" KeyPath="zerotierone_x64.exe"/>
|
||||
|
@ -84,10 +94,9 @@
|
|||
<ROW Component="zttap300_x86_win10" ComponentId="{9F913E48-095B-4EA3-98DA-EDAB1593F3E3}" Directory_="x86_Dir" Attributes="0" Condition="NOT VersionNT64" KeyPath="zttap300.cat_3" Type="0"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
|
||||
<ROW Feature="A918597FE054CCCB65ABDBA0AD8F63C" Title="Visual C++ Redistributable for Visual Studio 2015-2019 x86" Description="Visual C++ Redistributable for Visual Studio 2015-2019 x86" Display="3" Level="1" Attributes="0"/>
|
||||
<ROW Feature="C4FE6FD5B7C4D07B3A313E754A9A6A8" Title="Visual C++ Redistributable for Visual Studio 2015-2019 x64" Description="Visual C++ Redistributable for Visual Studio 2015-2019 x64" Display="5" Level="1" Attributes="0"/>
|
||||
<ROW Feature="A918597FE054CCCB65ABDBA0AD8F63C" Title="Visual C++ Redistributable for Visual Studio 2015-2022 x86" Description="Visual C++ Redistributable for Visual Studio 2015-2022 x86" Display="5" Level="1" Attributes="0"/>
|
||||
<ROW Feature="C4FE6FD5B7C4D07B3A313E754A9A6A8" Title="Visual C++ Redistributable for Visual Studio 2015-2022 x64" Description="Visual C++ Redistributable for Visual Studio 2015-2022 x64" Display="3" Level="1" Attributes="0"/>
|
||||
<ROW Feature="MainFeature" Title="MainFeature" Description="Description" Display="1" Level="1" Directory_="APPDIR" Attributes="0"/>
|
||||
<ROW Feature="RequiredApplication" Title="Microsoft Edge Webview2 Runtime" Description="Microsoft Edge Webview2 Runtime" Display="7" Level="1" Attributes="0"/>
|
||||
<ROW Feature="ZeroTierOne" Title="MainFeature" Description="ZeroTier One" Display="0" Level="1" Directory_="APPDIR" Attributes="0"/>
|
||||
<ATTRIBUTE name="CurrentFeature" value="ZeroTierOne"/>
|
||||
</COMPONENT>
|
||||
|
@ -242,9 +251,6 @@
|
|||
<ROW Dialog_="VerifyReadyDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_PATCH" Ordering="199"/>
|
||||
<ROW Dialog_="VerifyReadyDlg" Control_="Back" Event="NewDialog" Argument="PatchWelcomeDlg" Condition="AI_PATCH" Ordering="203"/>
|
||||
<ROW Dialog_="ResumeDlg" Control_="Install" Event="EndDialog" Argument="Return" Condition="AI_RESUME" Ordering="299"/>
|
||||
<ROW Dialog_="ExitDialog" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="301"/>
|
||||
<ROW Dialog_="FatalError" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="102"/>
|
||||
<ROW Dialog_="UserExit" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="101"/>
|
||||
<ROW Dialog_="Windows7Warning" Control_="Cancel" Event="SpawnDialog" Argument="CancelDlg" Condition="1" Ordering="100"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="SpawnDialog" Argument="OutOfRbDiskDlg" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)" Ordering="5" Options="2"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Next" Event="EnableRollback" Argument="False" Condition="AI_INSTALL AND OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"" Ordering="6" Options="2"/>
|
||||
|
@ -256,12 +262,21 @@
|
|||
<ROW Dialog_="WelcomeDlg" Control_="Back" Event="[ButtonText_Next]" Argument="[AI_ButtonText_Next_Orig]" Condition="AI_INSTALL" Ordering="0" Options="2"/>
|
||||
<ROW Dialog_="WelcomeDlg" Control_="Back" Event="[Text_Next]" Argument="[AI_Text_Next_Orig]" Condition="AI_INSTALL" Ordering="1" Options="2"/>
|
||||
<ROW Dialog_="ExitDialog" Control_="Finish" Event="DoAction" Argument="AI_ChainerScheduleReboot" Condition="Not AIEXTERNALUI" Ordering="302"/>
|
||||
<ROW Dialog_="ExitDialog" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="303"/>
|
||||
<ROW Dialog_="FatalError" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="102"/>
|
||||
<ROW Dialog_="UserExit" Control_="Finish" Event="DoAction" Argument="AI_CleanPrereq" Condition="1" Ordering="101"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
|
||||
<ROW Directory_="networks.d_Dir" Component_="networks.d" ManualDelete="false"/>
|
||||
<ROW Directory_="regid.201001.com.zerotier_Dir" Component_="regid.201001.com.zerotier" ManualDelete="false"/>
|
||||
<ROW Directory_="APPDIR" Component_="APPDIR" ManualDelete="true"/>
|
||||
<ROW Directory_="i686_1_Dir" Component_="i686" ManualDelete="false"/>
|
||||
<ROW Directory_="ZeroTier_Dir" Component_="ZeroTier" ManualDelete="true"/>
|
||||
<ROW Directory_="One_Dir" Component_="One" ManualDelete="false"/>
|
||||
<ROW Directory_="tapwindows_Dir" Component_="tapwindows" ManualDelete="false"/>
|
||||
<ROW Directory_="x64_Dir" Component_="x64" ManualDelete="false"/>
|
||||
<ROW Directory_="x86_Dir" Component_="x86" ManualDelete="false"/>
|
||||
<ROW Directory_="i686_Dir" Component_="i686_1" ManualDelete="false"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
|
||||
<ROW Action="AI_AppSearchEx" Type="1" Source="Prereq.dll" Target="DoAppSearchEx"/>
|
||||
|
@ -308,6 +323,7 @@
|
|||
<ROW Action="AI_RESTORE_LOCATION" Type="65" Source="aicustact.dll" Target="RestoreLocation"/>
|
||||
<ROW Action="AI_RemoveExternalUIStub" Type="1" Source="ExternalUICleaner.dll" Target="RemoveExternalUIStub"/>
|
||||
<ROW Action="AI_ResolveKnownFolders" Type="1" Source="aicustact.dll" Target="AI_ResolveKnownFolders"/>
|
||||
<ROW Action="AI_ResolveLocalizedCredentials" Type="1" Source="aicustact.dll" Target="GetLocalizedCredentials"/>
|
||||
<ROW Action="AI_RollbackChainers" Type="11585" Source="chainersupport.dll" Target="RollbackChainedPackages" WithoutSeq="true"/>
|
||||
<ROW Action="AI_SHOW_LOG" Type="65" Source="aicustact.dll" Target="LaunchLogFile" WithoutSeq="true"/>
|
||||
<ROW Action="AI_STORE_LOCATION" Type="51" Source="ARPINSTALLLOCATION" Target="[APPDIR]"/>
|
||||
|
@ -353,11 +369,16 @@
|
|||
<ROW Feature_="ZeroTierOne" Component_="AI_DisableModify"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="zerotier_desktop_ui.exe"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="zerotier_desktop_ui.exe_1"/>
|
||||
<ROW Feature_="A918597FE054CCCB65ABDBA0AD8F63C" Component_="A918597FE054CCCB65ABDBA0AD8F63C"/>
|
||||
<ROW Feature_="C4FE6FD5B7C4D07B3A313E754A9A6A8" Component_="C4FE6FD5B7C4D07B3A313E754A9A6A8"/>
|
||||
<ROW Feature_="RequiredApplication" Component_="RequiredApplication"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="AI_ExePath"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="i686"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="ZeroTier"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="One"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="tapwindows"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="x64"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="x86"/>
|
||||
<ROW Feature_="ZeroTierOne" Component_="i686_1"/>
|
||||
<ROW Feature_="C4FE6FD5B7C4D07B3A313E754A9A6A8" Component_="C4FE6FD5B7C4D07B3A313E754A9A6A8"/>
|
||||
<ROW Feature_="A918597FE054CCCB65ABDBA0AD8F63C" Component_="A918597FE054CCCB65ABDBA0AD8F63C"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
|
||||
<ROW Name="ZeroTierIcon.exe" SourcePath="..\..\..\artwork\ZeroTierIcon.ico" Index="0"/>
|
||||
|
@ -367,12 +388,12 @@
|
|||
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=""" Sequence="749"/>
|
||||
<ROW Action="AI_STORE_LOCATION" Condition="(Not Installed) OR REINSTALL" Sequence="1502"/>
|
||||
<ROW Action="AI_PREPARE_UPGRADE" Condition="AI_UPGRADE="No" AND (Not Installed)" Sequence="1397"/>
|
||||
<ROW Action="AI_ResolveKnownFolders" Sequence="52"/>
|
||||
<ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
|
||||
<ROW Action="AI_XmlInstall" Condition="(REMOVE <> "ALL")" Sequence="5103"/>
|
||||
<ROW Action="AI_DATA_SETTER" Condition="(REMOVE <> "ALL")" Sequence="5102"/>
|
||||
<ROW Action="AI_XmlUninstall" Condition="(REMOVE)" Sequence="3102"/>
|
||||
<ROW Action="AI_DATA_SETTER_1" Condition="(REMOVE)" Sequence="3101"/>
|
||||
<ROW Action="InstallFinalize" Sequence="6602" SeqType="0" MsiKey="InstallFinalize"/>
|
||||
<ROW Action="InstallFinalize" Sequence="6604" SeqType="0" MsiKey="InstallFinalize"/>
|
||||
<ROW Action="AI_RemoveExternalUIStub" Condition="(REMOVE="ALL") AND ((VersionNT > 500) OR((VersionNT = 500) AND (ServicePackLevel >= 4)))" Sequence="1501"/>
|
||||
<ROW Action="TapDeviceRemove32" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( NOT VersionNT64 )" Sequence="1605"/>
|
||||
<ROW Action="TapDeviceRemove64" Condition="( Installed AND ( REMOVE = "ALL" OR AI_INSTALL_MODE = "Remove" ) AND NOT UPGRADINGPRODUCTCODE ) AND ( VersionNT64 )" Sequence="1606"/>
|
||||
|
@ -393,7 +414,7 @@
|
|||
<ROW Action="AI_DeleteLzma" Condition="SETUPEXEDIR="" AND Installed AND (REMOVE<>"ALL") AND (AI_INSTALL_MODE<>"Remove") AND (NOT PATCH)" Sequence="6594" Builds="ExeBuild"/>
|
||||
<ROW Action="TerminateUIOld" Sequence="1602"/>
|
||||
<ROW Action="AI_DATA_SETTER_6" Sequence="1601"/>
|
||||
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
|
||||
<ROW Action="AI_EnableDebugLog" Sequence="52"/>
|
||||
<ROW Action="AI_AppSearchEx" Sequence="101"/>
|
||||
<ROW Action="AI_PrepareChainers" Condition="VersionMsi >= "4.05"" Sequence="5851"/>
|
||||
<ROW Action="AI_ExtractFiles" Sequence="1399" Builds="ExeBuild"/>
|
||||
|
@ -401,21 +422,24 @@
|
|||
<ROW Action="AI_GetArpIconPath" Sequence="1401"/>
|
||||
<ROW Action="TerminateUINew" Sequence="1604"/>
|
||||
<ROW Action="AI_DATA_SETTER_5" Sequence="1603"/>
|
||||
<ROW Action="AI_ConfigureChainer" Condition="((UILevel = 2) OR (UILevel = 3)) AND (NOT UPGRADINGPRODUCTCODE)" Sequence="6600"/>
|
||||
<ROW Action="AI_LaunchChainer" Condition="AI_PREREQ_CHAINER AND (NOT UPGRADINGPRODUCTCODE)" Sequence="6601"/>
|
||||
<ROW Action="LaunchUI" Condition="( NOT Installed ) AND ( ZTHEADLESS = "No" )" Sequence="6605"/>
|
||||
<ROW Action="AI_DETECT_MODERNWIN" Condition="(VersionNT >= 603)" Sequence="54" MsiKey="AI_DETECT_MODERNWIN"/>
|
||||
<ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>
|
||||
<ROW Action="AI_ConfigureChainer" Condition="((UILevel = 2) OR (UILevel = 3)) AND (NOT UPGRADINGPRODUCTCODE)" Sequence="6602"/>
|
||||
<ROW Action="AI_LaunchChainer" Condition="AI_PREREQ_CHAINER AND (NOT UPGRADINGPRODUCTCODE)" Sequence="6603"/>
|
||||
<ROW Action="AI_VerifyPrereq" Sequence="1101"/>
|
||||
<ROW Action="LaunchUI" Condition="( NOT Installed ) AND ( ZTHEADLESS = "No" )" Sequence="6603"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstallUISequenceComponent">
|
||||
<ROW Action="AI_RESTORE_LOCATION" Condition="APPDIR=""" Sequence="749"/>
|
||||
<ROW Action="AI_ResolveKnownFolders" Sequence="53"/>
|
||||
<ROW Action="AI_DpiContentScale" Sequence="52"/>
|
||||
<ROW Action="AI_ResolveKnownFolders" Sequence="54"/>
|
||||
<ROW Action="AI_DpiContentScale" Sequence="53"/>
|
||||
<ROW Action="AI_BACKUP_AI_SETUPEXEPATH" Sequence="99"/>
|
||||
<ROW Action="AI_RESTORE_AI_SETUPEXEPATH" Condition="AI_SETUPEXEPATH_ORIGINAL" Sequence="103"/>
|
||||
<ROW Action="ExecuteAction" Sequence="1299" SeqType="0" MsiKey="ExecuteAction"/>
|
||||
<ROW Action="AI_DetectSoftware" Sequence="102"/>
|
||||
<ROW Action="AI_EnableDebugLog" Sequence="51"/>
|
||||
<ROW Action="AI_EnableDebugLog" Sequence="52"/>
|
||||
<ROW Action="AI_AppSearchEx" Sequence="101"/>
|
||||
<ROW Action="AI_ResolveLocalizedCredentials" Sequence="51"/>
|
||||
<ROW Action="AI_DownloadPrereq" Sequence="1296"/>
|
||||
<ROW Action="AI_ExtractPrereq" Sequence="1297"/>
|
||||
<ROW Action="AI_InstallPrerequisite" Sequence="1298"/>
|
||||
|
@ -433,6 +457,23 @@
|
|||
<ROW Condition="SETUPEXEDIR OR (REMOVE="ALL")" Description="This package can only be run from a bootstrapper." DescriptionLocId="AI.LaunchCondition.RequireBootstrapper" IsPredefined="true" Builds="ExeBuild"/>
|
||||
<ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild;ExeBuild"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiLockPermComponent">
|
||||
<ROW LockObject="ZeroTier_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="ZeroTier_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="One_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="One_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="networks.d_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="networks.d_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="tapwindows_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="tapwindows_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="x64_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="x64_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="x86_Dir" Table="CreateFolder" User="[GRP_ADMINISTRATORS]" Permission="1245631" Flags="0"/>
|
||||
<ROW LockObject="x86_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="regid.201001.com.zerotier_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="APPDIR" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
<ROW LockObject="i686_Dir" Table="CreateFolder" User="[GRP_EVERYONE]" Permission="1179817" Flags="0"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent">
|
||||
<ROW Signature_="AI_EXE_PATH_CU" Root="1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
|
||||
<ROW Signature_="AI_EXE_PATH_LM" Root="2" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
|
||||
|
@ -469,7 +510,6 @@
|
|||
<ROW Registry="ProductVersion_1" Root="-1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="\"/>
|
||||
<ROW Registry="Publisher" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Publisher" Value="[Manufacturer]" Component_="AI_CustomARPName"/>
|
||||
<ROW Registry="Readme" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="Readme" Value="[ARPREADME]" Component_="AI_CustomARPName"/>
|
||||
<ROW Registry="RequiredApplication" Root="-1" Key="Software\Caphyon\Advanced Installer\Prereqs\[ProductCode]\[ProductVersion]" Name="RequiredApplication" Value="1" Component_="RequiredApplication"/>
|
||||
<ROW Registry="Software" Root="-1" Key="Software" Name="\"/>
|
||||
<ROW Registry="URLInfoAbout" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLInfoAbout" Value="[ARPURLINFOABOUT]" Component_="AI_CustomARPName"/>
|
||||
<ROW Registry="URLUpdateInfo" Root="-1" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\[ProductName] [ProductVersion]" Name="URLUpdateInfo" Value="[ARPURLUPDATEINFO]" Component_="AI_CustomARPName"/>
|
||||
|
@ -501,17 +541,14 @@
|
|||
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.PreReqComponent">
|
||||
<ROW PrereqKey="A918597FE054CCCB65ABDBA0AD8F63C" DisplayName="Visual C++ Redistributable for Visual Studio 2015-2019 x86" VersionMin="14.26" SetupFileUrl="https://download.visualstudio.microsoft.com/download/pr/d60aa805-26e9-47df-b4e3-cd6fcc392333/A06AAC66734A618AB33C1522920654DDFC44FC13CAFAA0F0AB85B199C3D51DC0/VC_redist.x86.exe" Location="1" ExactSize="14413048" WinNT64Versions="Windows XP/Vista/Windows 7/Windows 8 x64/Windows 8.1 x64/Windows 10 x64/Windows 11 x64" Operator="0" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="f" MD5="fe6eae1c34528d1ea224569dcdc35618" TargetName="Visual C++ Redistributable for Visual Studio 2015-2019" Feature="A918597FE054CCCB65ABDBA0AD8F63C"/>
|
||||
<ROW PrereqKey="C4FE6FD5B7C4D07B3A313E754A9A6A8" DisplayName="Visual C++ Redistributable for Visual Studio 2015-2019 x64" VersionMin="14.26" SetupFileUrl="https://download.visualstudio.microsoft.com/download/pr/d60aa805-26e9-47df-b4e3-cd6fcc392333/7D7105C52FCD6766BEEE1AE162AA81E278686122C1E44890712326634D0B055E/VC_redist.x64.exe" Location="1" ExactSize="14974616" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" Operator="1" ComLine="/q /norestart" BasicUiComLine="/q /norestart" NoUiComLine="/q /norestart" Options="xf" MD5="264c296cc0bf00db6ba8e7bf8cc4e706" TargetName="Visual C++ Redistributable for Visual Studio 2015-2019" Feature="C4FE6FD5B7C4D07B3A313E754A9A6A8"/>
|
||||
<ROW PrereqKey="RequiredApplication" DisplayName="Microsoft Edge Webview2 Runtime" SetupFileUrl="https://go.microsoft.com/fwlink/p/?LinkId=2124703" Location="1" ExactSize="0" Operator="1" ComLine="/silent /install" BasicUiComLine="/silent /install" NoUiComLine="/silent /install" Options="fx" TargetName="MicrosoftEdgeWebview2Setup.exe" Feature="RequiredApplication"/>
|
||||
<ATTRIBUTE name="PrereqsOrder" value="A918597FE054CCCB65ABDBA0AD8F63C C4FE6FD5B7C4D07B3A313E754A9A6A8 RequiredApplication"/>
|
||||
<ROW PrereqKey="A918597FE054CCCB65ABDBA0AD8F63C" DisplayName="Visual C++ Redistributable for Visual Studio 2015-2022 x86" VersionMin="14.30" SetupFileUrl="Prerequisites\Visual C++ Redistributable for Visual Studio 2015-2022\VC_redist.x86.exe" Location="0" ExactSize="0" WinNTVersions="Windows Vista RTM x86, Windows Vista SP1 x86, Windows Server 2008 RTM x86, Windows 7 RTM x86" WinNT64Versions="Windows Vista RTM x64, Windows Vista SP1 x64, Windows Server 2008 RTM x64, Windows 7 RTM x64, Windows Server 2008 R2 RTM x64" Operator="0" NoUiComLine="/q /norestart" Options="f" TargetName="Visual C++ Redistributable for Visual Studio 2015-2022\VC_redist.x86.exe" Feature="A918597FE054CCCB65ABDBA0AD8F63C"/>
|
||||
<ROW PrereqKey="C4FE6FD5B7C4D07B3A313E754A9A6A8" DisplayName="Visual C++ Redistributable for Visual Studio 2015-2022 x64" VersionMin="14.30" SetupFileUrl="Prerequisites\Visual C++ Redistributable for Visual Studio 2015-2022\VC_redist.x64.exe" Location="0" ExactSize="0" WinNTVersions="Windows 9x/ME/NT/2000/XP/Vista/Windows 7/Windows 8 x86/Windows 8.1 x86/Windows 10 x86" WinNT64Versions="Windows Vista RTM x64, Windows Vista SP1 x64, Windows Server 2008 RTM x64, Windows 7 RTM x64, Windows Server 2008 R2 RTM x64" Operator="1" NoUiComLine="/q /norestart" Options="xf" TargetName="Visual C++ Redistributable for Visual Studio 2015-2022\VC_redist.x64.exe" Feature="C4FE6FD5B7C4D07B3A313E754A9A6A8"/>
|
||||
<ATTRIBUTE name="PrereqsOrder" value="C4FE6FD5B7C4D07B3A313E754A9A6A8 A918597FE054CCCB65ABDBA0AD8F63C"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.PreReqSearchComponent">
|
||||
<ROW SearchKey="A918597FE054CCCB65ABDBA0AD8F63CSyst" Prereq="A918597FE054CCCB65ABDBA0AD8F63C" SearchType="0" SearchString="[SystemFolder]vcruntime140.dll" VerMin="14.26.28720" Order="2" Property="PreReqSearch_1_A918597FE054CCCB65AB"/>
|
||||
<ROW SearchKey="A918597FE054CCCB65ABDBA0AD8F63CVers" Prereq="A918597FE054CCCB65ABDBA0AD8F63C" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.26.28720" Order="1" Property="PreReqSearch_A918597FE054CCCB65ABDB"/>
|
||||
<ROW SearchKey="C4FE6FD5B7C4D07B3A313E754A9A6A8Vers" Prereq="C4FE6FD5B7C4D07B3A313E754A9A6A8" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.26.28720" Order="1" Property="PreReqSearch_C4FE6FD5B7C4D07B3A313E" Platform="1"/>
|
||||
<ROW SearchKey="F3017226FE2A42958BDF00C3A9A7E4C5" Prereq="RequiredApplication" SearchType="5" SearchString="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Order="2" Property="PreReqSearch_1" Platform="1"/>
|
||||
<ROW SearchKey="SystemFolderfile.dll" Prereq="RequiredApplication" SearchType="5" SearchString="HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Order="1" Property="PreReqSearch" Platform="1"/>
|
||||
<ROW SearchKey="A918597FE054CCCB65ABDBA0AD8F63CSyst" Prereq="A918597FE054CCCB65ABDBA0AD8F63C" SearchType="0" SearchString="[SystemFolder]vcruntime140.dll" VerMin="14.30.30704" Order="2" Property="PreReqSearch_1_A918597FE054CCCB65AB"/>
|
||||
<ROW SearchKey="A918597FE054CCCB65ABDBA0AD8F63CVers" Prereq="A918597FE054CCCB65ABDBA0AD8F63C" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.30.30704" Order="1" Property="PreReqSearch_A918597FE054CCCB65ABDB"/>
|
||||
<ROW SearchKey="C4FE6FD5B7C4D07B3A313E754A9A6A8Vers" Prereq="C4FE6FD5B7C4D07B3A313E754A9A6A8" SearchType="2" SearchString="HKLM\SOFTWARE\Microsoft\DevDiv\VC\Servicing\14.0\RuntimeMinimum\Version" VerMin="14.30.30704" Order="1" Property="PreReqSearch_C4FE6FD5B7C4D07B3A313E"/>
|
||||
<ROW SearchKey="UpgradeCode" SearchType="4" SearchString="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}" Order="2" Property="ZTTAP300_X86_INSTALLED"/>
|
||||
<ROW SearchKey="_" SearchType="4" SearchString="{88AA80DE-14CA-4443-B024-6EC13F3EDDAD}" Order="1" Property="ZTTAP300_X64_INSTALLED"/>
|
||||
</COMPONENT>
|
||||
|
@ -536,10 +573,10 @@
|
|||
<ROW XmlAttribute="xsischemaLocation" XmlElement="swidsoftware_identification_tag" Name="xsi:schemaLocation" Flags="14" Order="3" Value="http://standards.iso.org/iso/19770/-2/2008/schema.xsd software_identification_tag.xsd"/>
|
||||
</COMPONENT>
|
||||
<COMPONENT cid="caphyon.advinst.msicomp.XmlElementComponent">
|
||||
<ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="6" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidbuild" ParentElement="swidnumeric" Name="swid:build" Condition="1" Order="2" Flags="14" Text="0" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidentitlement_required_indicator" ParentElement="swidsoftware_identification_tag" Name="swid:entitlement_required_indicator" Condition="1" Order="0" Flags="14" Text="false" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidmajor" ParentElement="swidnumeric" Name="swid:major" Condition="1" Order="0" Flags="14" Text="1" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidminor" ParentElement="swidnumeric" Name="swid:minor" Condition="1" Order="1" Flags="14" Text="8" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidminor" ParentElement="swidnumeric" Name="swid:minor" Condition="1" Order="1" Flags="14" Text="10" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidname" ParentElement="swidproduct_version" Name="swid:name" Condition="1" Order="0" Flags="14" Text="[ProductVersion]" UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidname_1" ParentElement="swidsoftware_creator" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc." UpdateIndexInParent="0"/>
|
||||
<ROW XmlElement="swidname_2" ParentElement="swidsoftware_licensor" Name="swid:name" Condition="1" Order="0" Flags="14" Text="ZeroTier, Inc." UpdateIndexInParent="0"/>
|
||||
|
|
|
@ -1079,7 +1079,8 @@ enum ZT_Architecture
|
|||
ZT_ARCHITECTURE_DOTNET_CLR = 13,
|
||||
ZT_ARCHITECTURE_JAVA_JVM = 14,
|
||||
ZT_ARCHITECTURE_WEB = 15,
|
||||
ZT_ARCHITECTURE_S390X = 16
|
||||
ZT_ARCHITECTURE_S390X = 16,
|
||||
ZT_ARCHITECTURE_LOONGARCH64 = 17
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1404,11 +1405,6 @@ typedef struct
|
|||
*/
|
||||
int bondingPolicy;
|
||||
|
||||
/**
|
||||
* The health status of the bond to this peer
|
||||
*/
|
||||
bool isHealthy;
|
||||
|
||||
/**
|
||||
* The number of links that comprise the bond to this peer that are considered alive
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This requires GNU make, which is typically "gmake" on BSD systems
|
||||
|
||||
INCLUDES=
|
||||
INCLUDES=-isystem ext
|
||||
DEFS=
|
||||
LIBS=
|
||||
|
||||
|
@ -152,7 +152,7 @@ endif
|
|||
|
||||
override DEFS+=-DZT_BUILD_PLATFORM=$(ZT_BUILD_PLATFORM) -DZT_BUILD_ARCHITECTURE=$(ZT_ARCHITECTURE) -DZT_SOFTWARE_UPDATE_DEFAULT="\"disable\""
|
||||
|
||||
CXXFLAGS+=$(CFLAGS) -std=c++11 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1
|
||||
CXXFLAGS+=$(CFLAGS) -std=c++17 #-D_GLIBCXX_USE_C99 -D_GLIBCXX_USE_C99_MATH -D_GLIBCXX_USE_C99_MATH_TR1
|
||||
|
||||
all: one
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# Automagically pick CLANG or RH/CentOS newer GCC if present
|
||||
# This is only done if we have not overridden these with an environment or CLI variable
|
||||
ifeq ($(origin CC),default)
|
||||
CC:=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi)
|
||||
CC:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/gcc ]; then echo /opt/rh/devtoolset-8/root/usr/bin/gcc; else echo $(CC); fi)
|
||||
CC:=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi)
|
||||
CC:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/gcc ]; then echo /opt/rh/devtoolset-8/root/usr/bin/gcc; else echo $(CC); fi)
|
||||
endif
|
||||
ifeq ($(origin CXX),default)
|
||||
CXX:=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi)
|
||||
CXX:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/g++ ]; then echo /opt/rh/devtoolset-8/root/usr/bin/g++; else echo $(CXX); fi)
|
||||
CXX:=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi)
|
||||
CXX:=$(shell if [ -e /opt/rh/devtoolset-8/root/usr/bin/g++ ]; then echo /opt/rh/devtoolset-8/root/usr/bin/g++; else echo $(CXX); fi)
|
||||
endif
|
||||
|
||||
INCLUDES?=-Izeroidc/target
|
||||
INCLUDES?=-Izeroidc/target -isystem ext
|
||||
DEFS?=
|
||||
LDLIBS?=
|
||||
DESTDIR?=
|
||||
|
@ -31,7 +31,7 @@ ifeq ($(MINIUPNPC_IS_NEW_ENOUGH),1)
|
|||
override DEFS+=-DZT_USE_SYSTEM_MINIUPNPC
|
||||
LDLIBS+=-lminiupnpc
|
||||
else
|
||||
override DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING=\"Linux\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
override DEFS+=-DMINIUPNP_STATICLIB -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DOS_STRING="\"Linux\"" -DMINIUPNPC_VERSION_STRING="\"2.0\"" -DUPNP_VERSION_STRING="\"UPnP/1.1\"" -DENABLE_STRNATPMPERR
|
||||
ONE_OBJS+=ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o
|
||||
endif
|
||||
ifeq ($(wildcard /usr/include/natpmp.h),)
|
||||
|
@ -59,32 +59,33 @@ ifeq ($(ZT_SANITIZE),1)
|
|||
endif
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
override CFLAGS+=-Wall -Wno-deprecated -g -O -pthread $(INCLUDES) $(DEFS)
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -g -O -std=c++11 -pthread $(INCLUDES) $(DEFS)
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -g -O -std=c++17 -pthread $(INCLUDES) $(DEFS)
|
||||
ZT_TRACE=1
|
||||
RUSTFLAGS=
|
||||
# The following line enables optimization for the crypto code, since
|
||||
# C25519 in particular is almost UNUSABLE in -O0 even on a 3ghz box!
|
||||
node/Salsa20.o node/SHA512.o node/C25519.o node/Poly1305.o: CXXFLAGS=-Wall -O2 -g -pthread $(INCLUDES) $(DEFS)
|
||||
else
|
||||
CFLAGS?=-O3 -fstack-protector -fPIE
|
||||
CFLAGS?=-O3 -fstack-protector
|
||||
override CFLAGS+=-Wall -Wno-deprecated -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
CXXFLAGS?=-O3 -fstack-protector -fPIE
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -std=c++11 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
CXXFLAGS?=-O3 -fstack-protector
|
||||
override CXXFLAGS+=-Wall -Wno-deprecated -std=c++17 -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
LDFLAGS=-pie -Wl,-z,relro,-z,now
|
||||
RUSTFLAGS=--release
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_QNAP), 1)
|
||||
override DEFS+=-D__QNAP__
|
||||
override DEFS+=-D__QNAP__
|
||||
ZT_EMBEDDED=1
|
||||
endif
|
||||
ifeq ($(ZT_UBIQUITI), 1)
|
||||
override DEFS+=-D__UBIQUITI__
|
||||
override DEFS+=-D__UBIQUITI__
|
||||
ZT_EMBEDDED=1
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_SYNOLOGY), 1)
|
||||
override CFLAGS+=-fPIC
|
||||
override CXXFLAGS+=-fPIC
|
||||
override DEFS+=-D__SYNOLOGY__
|
||||
ZT_EMBEDDED=1
|
||||
endif
|
||||
|
||||
ifeq ($(ZT_DISABLE_COMPRESSION), 1)
|
||||
|
@ -213,9 +214,9 @@ ifeq ($(CC_MACH),armv7hl)
|
|||
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),armv7ve)
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
|
||||
ZT_ARCHITECTURE=3
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
ZT_USE_ARM32_NEON_ASM_CRYPTO=1
|
||||
endif
|
||||
ifeq ($(CC_MACH),arm64)
|
||||
ZT_ARCHITECTURE=4
|
||||
|
@ -249,6 +250,10 @@ endif
|
|||
ifeq ($(CC_MACH),riscv64)
|
||||
ZT_ARCHITECTURE=0
|
||||
endif
|
||||
ifeq ($(CC_MACH),loongarch64)
|
||||
ZT_ARCHITECTURE=17
|
||||
override DEFS+=-DZT_NO_TYPE_PUNNING
|
||||
endif
|
||||
|
||||
# Fail if system architecture could not be determined
|
||||
ifeq ($(ZT_ARCHITECTURE),999)
|
||||
|
@ -268,10 +273,13 @@ ifeq ($(ZT_IA32),1)
|
|||
endif
|
||||
|
||||
ifeq ($(ZT_SSO_SUPPORTED), 1)
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
LDLIBS+=zeroidc/target/debug/libzeroidc.a -ldl -lssl -lcrypto
|
||||
else
|
||||
LDLIBS+=zeroidc/target/release/libzeroidc.a -ldl -lssl -lcrypto
|
||||
ifeq ($(ZT_EMBEDDED),)
|
||||
override DEFS+=-DZT_SSO_SUPPORTED=1
|
||||
ifeq ($(ZT_DEBUG),1)
|
||||
LDLIBS+=zeroidc/target/debug/libzeroidc.a -ldl -lssl -lcrypto
|
||||
else
|
||||
LDLIBS+=zeroidc/target/release/libzeroidc.a -ldl -lssl -lcrypto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -306,8 +314,8 @@ ifeq ($(ZT_ARCHITECTURE),3)
|
|||
override CXXFLAGS+=-march=armv5t -mfloat-abi=soft -msoft-float -mno-unaligned-access -marm
|
||||
ZT_USE_ARM32_NEON_ASM_CRYPTO=0
|
||||
else
|
||||
override CFLAGS+=-mfloat-abi=hard -march=armv6kz -marm -mfpu=vfp -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
|
||||
override CXXFLAGS+=-mfloat-abi=hard -march=armv6kz -marm -mfpu=vfp -fexceptions -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
|
||||
override CFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
|
||||
override CXXFLAGS+=-mfloat-abi=hard -march=armv6zk -marm -mfpu=vfp -fexceptions -mno-unaligned-access -mtp=cp15 -mcpu=arm1176jzf-s
|
||||
ZT_USE_ARM32_NEON_ASM_CRYPTO=0
|
||||
endif
|
||||
endif
|
||||
|
@ -326,12 +334,20 @@ ifeq ($(ZT_USE_ARM32_NEON_ASM_CRYPTO),1)
|
|||
override CORE_OBJS+=ext/arm32-neon-salsa2012-asm/salsa2012.o
|
||||
endif
|
||||
|
||||
# Position Independence
|
||||
override CFLAGS+=-fPIC -fPIE
|
||||
override CXXFLAGS+=-fPIC -fPIE
|
||||
|
||||
.PHONY: all
|
||||
all: one
|
||||
|
||||
.PHONY: one
|
||||
one: zerotier-one zerotier-idtool zerotier-cli
|
||||
|
||||
from_builder:
|
||||
ln -sf zerotier-one zerotier-idtool
|
||||
ln -sf zerotier-one zerotier-cli
|
||||
|
||||
zerotier-one: $(CORE_OBJS) $(ONE_OBJS) one.o
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LDLIBS)
|
||||
|
||||
|
@ -344,7 +360,7 @@ zerotier-cli: zerotier-one
|
|||
$(ONE_OBJS): zeroidc
|
||||
|
||||
libzerotiercore.a: FORCE
|
||||
make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++11 -fstack-protector -fPIC" $(CORE_OBJS)
|
||||
make CFLAGS="-O3 -fstack-protector -fPIC" CXXFLAGS="-O3 -std=c++17 -fstack-protector -fPIC" $(CORE_OBJS)
|
||||
ar rcs libzerotiercore.a $(CORE_OBJS)
|
||||
ranlib libzerotiercore.a
|
||||
|
||||
|
@ -384,9 +400,11 @@ debug: FORCE
|
|||
make ZT_DEBUG=1 selftest
|
||||
|
||||
ifeq ($(ZT_SSO_SUPPORTED), 1)
|
||||
ifeq ($(ZT_EMBEDDED),)
|
||||
zeroidc: FORCE
|
||||
# export PATH=/root/.cargo/bin:$$PATH; cd zeroidc && cargo build -j1 $(RUSTFLAGS)
|
||||
export PATH=/root/.cargo/bin:$$PATH; cd zeroidc && cargo build $(RUSTFLAGS)
|
||||
export PATH=/${HOME}/.cargo/bin:$$PATH; cd zeroidc && cargo build $(RUSTFLAGS)
|
||||
endif
|
||||
else
|
||||
zeroidc:
|
||||
endif
|
||||
|
@ -440,6 +458,20 @@ uninstall: FORCE
|
|||
|
||||
# These are just for convenience for building Linux packages
|
||||
|
||||
echo_flags:
|
||||
@echo "=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~"
|
||||
@echo "echo_flags :: CC=$(CC)"
|
||||
@echo "echo_flags :: CXX=$(CXX)"
|
||||
@echo "echo_flags :: CFLAGS=$(CFLAGS)"
|
||||
@echo "echo_flags :: CXXFLAGS=$(CXXFLAGS)"
|
||||
@echo "echo_flags :: LDFLAGS=$(LDFLAGS)"
|
||||
@echo "echo_flags :: RUSTFLAGS=$(RUSTFLAGS)"
|
||||
@echo "=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~"
|
||||
|
||||
# debian: echo_flags
|
||||
# @echo "building deb package"
|
||||
# debuild --no-lintian -b -uc -us
|
||||
|
||||
debian: FORCE
|
||||
debuild --no-lintian -I -i -us -uc -nc -b
|
||||
|
||||
|
@ -478,4 +510,20 @@ snap-upload-stable: FORCE
|
|||
snapcraft upload --release=stable $${SNAPFILE};\
|
||||
done
|
||||
|
||||
synology-pkg: FORCE
|
||||
cd pkg/synology ; ./build.sh build
|
||||
|
||||
synology-docker: FORCE
|
||||
cd pkg/synology/dsm7-docker/; ./build.sh build-and-push
|
||||
|
||||
munge_rpm:
|
||||
@:$(call check_defined, VERSION)
|
||||
@echo "Updating rpm spec to $(VERSION)"
|
||||
ci/scripts/munge_rpm_spec.sh zerotier-one.spec $(VERSION) "Adam Ierymenko <adam.ierymenko@zerotier.com>" "see https://github.com/zerotier/ZeroTierOne for release notes"
|
||||
|
||||
munge_deb:
|
||||
@:$(call check_defined, VERSION)
|
||||
@echo "Updating debian/changelog to $(VERSION)"
|
||||
ci/scripts/munge_debian_changelog.sh debian/changelog $(VERSION) "Adam Ierymenko <adam.ierymenko@zerotier.com>" "see https://github.com/zerotier/ZeroTierOne for release notes"
|
||||
|
||||
FORCE:
|
||||
|
|
10
make-mac.mk
10
make-mac.mk
|
@ -2,7 +2,7 @@ CC=clang
|
|||
CXX=clang++
|
||||
TOPDIR=$(shell PWD)
|
||||
|
||||
INCLUDES=-I$(shell PWD)/zeroidc/target
|
||||
INCLUDES=-I$(shell PWD)/zeroidc/target -isystem $(TOPDIR)/ext
|
||||
DEFS=
|
||||
LIBS=
|
||||
ARCH_FLAGS=-arch x86_64 -arch arm64
|
||||
|
@ -47,10 +47,10 @@ endif
|
|||
# Use fast ASM Salsa20/12 for x64 processors
|
||||
DEFS+=-DZT_USE_X64_ASM_SALSA2012
|
||||
CORE_OBJS+=ext/x64-salsa2012-asm/salsa2012.o
|
||||
CXXFLAGS=$(CFLAGS) -std=c++11 -stdlib=libc++
|
||||
CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++
|
||||
|
||||
# Build miniupnpc and nat-pmp as included libraries -- extra defs are required for these sources
|
||||
DEFS+=-DMACOSX -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
DEFS+=-DMACOSX -DZT_SSO_SUPPORTED -DZT_USE_MINIUPNPC -DMINIUPNP_STATICLIB -D_DARWIN_C_SOURCE -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR -D_BSD_SOURCE -D_DEFAULT_SOURCE -DOS_STRING=\"Darwin/15.0.0\" -DMINIUPNPC_VERSION_STRING=\"2.0\" -DUPNP_VERSION_STRING=\"UPnP/1.1\" -DENABLE_STRNATPMPERR
|
||||
ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connecthostport.o ext/miniupnpc/igd_desc_parse.o ext/miniupnpc/minisoap.o ext/miniupnpc/minissdpc.o ext/miniupnpc/miniupnpc.o ext/miniupnpc/miniwget.o ext/miniupnpc/minixml.o ext/miniupnpc/portlistingparse.o ext/miniupnpc/receivedata.o ext/miniupnpc/upnpcommands.o ext/miniupnpc/upnpdev.o ext/miniupnpc/upnperrors.o ext/miniupnpc/upnpreplyparse.o osdep/PortMapper.o
|
||||
ifeq ($(ZT_CONTROLLER),1)
|
||||
MACOS_VERSION_MIN=10.15
|
||||
|
@ -154,6 +154,10 @@ selftest: $(CORE_OBJS) $(ONE_OBJS) selftest.o
|
|||
|
||||
zerotier-selftest: selftest
|
||||
|
||||
# Make compile_commands.json for clangd editor extensions. Probably works on Linux too.
|
||||
compile_commands: FORCE
|
||||
compiledb make ZT_DEBUG=1
|
||||
|
||||
# Requires Packages: http://s.sudre.free.fr/Software/Packages/about.html
|
||||
mac-dist-pkg: FORCE
|
||||
packagesbuild "ext/installfiles/mac/ZeroTier One.pkgproj"
|
||||
|
|
438
node/Bond.cpp
438
node/Bond.cpp
|
@ -12,11 +12,12 @@
|
|||
/****/
|
||||
|
||||
#include "Bond.hpp"
|
||||
|
||||
#include "Switch.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -39,6 +40,9 @@ std::map<std::string, std::map<std::string, SharedPtr<Link> > > Bond::_interface
|
|||
|
||||
bool Bond::linkAllowed(std::string& policyAlias, SharedPtr<Link> link)
|
||||
{
|
||||
if (! link) {
|
||||
return false;
|
||||
}
|
||||
bool foundInDefinitions = false;
|
||||
if (_linkDefinitions.count(policyAlias)) {
|
||||
auto it = _linkDefinitions[policyAlias].begin();
|
||||
|
@ -90,7 +94,7 @@ SharedPtr<Bond> Bond::getBondByPeerId(int64_t identity)
|
|||
return _bonds.count(identity) ? _bonds[identity] : SharedPtr<Bond>();
|
||||
}
|
||||
|
||||
SharedPtr<Bond> Bond::createTransportTriggeredBond(const RuntimeEnvironment* renv, const SharedPtr<Peer>& peer)
|
||||
SharedPtr<Bond> Bond::createBond(const RuntimeEnvironment* renv, const SharedPtr<Peer>& peer)
|
||||
{
|
||||
Mutex::Lock _l(_bonds_m);
|
||||
int64_t identity = peer->identity().address().toInt();
|
||||
|
@ -145,7 +149,13 @@ SharedPtr<Bond> Bond::createTransportTriggeredBond(const RuntimeEnvironment* ren
|
|||
return SharedPtr<Bond>();
|
||||
}
|
||||
|
||||
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket)
|
||||
void Bond::destroyBond(uint64_t peerId)
|
||||
{
|
||||
Mutex::Lock _l(_bonds_m);
|
||||
_bonds.erase(peerId);
|
||||
}
|
||||
|
||||
SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded = false)
|
||||
{
|
||||
Mutex::Lock _l(_links_m);
|
||||
char ifname[64] = { 0 };
|
||||
|
@ -153,10 +163,14 @@ SharedPtr<Link> Bond::getLinkBySocket(const std::string& policyAlias, uint64_t l
|
|||
std::string ifnameStr(ifname);
|
||||
auto search = _interfaceToLinkMap[policyAlias].find(ifnameStr);
|
||||
if (search == _interfaceToLinkMap[policyAlias].end()) {
|
||||
// If the link wasn't already known, add a new entry
|
||||
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_SPARE, "", 0.0);
|
||||
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
||||
return s;
|
||||
if (createIfNeeded) {
|
||||
SharedPtr<Link> s = new Link(ifnameStr, 0, 0, true, ZT_BOND_SLAVE_MODE_SPARE, "", 0.0);
|
||||
_interfaceToLinkMap[policyAlias].insert(std::pair<std::string, SharedPtr<Link> >(ifnameStr, s));
|
||||
return s;
|
||||
}
|
||||
else {
|
||||
return SharedPtr<Link>();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return search->second;
|
||||
|
@ -218,10 +232,12 @@ Bond::Bond(const RuntimeEnvironment* renv, SharedPtr<Bond> originalBond, const S
|
|||
void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
||||
{
|
||||
Mutex::Lock _l(_paths_m);
|
||||
debug("attempting to nominate link %s", pathToStr(path).c_str());
|
||||
/**
|
||||
* Ensure the link is allowed and the path is not already present
|
||||
*/
|
||||
if (! RR->bc->linkAllowed(_policyAlias, getLink(path))) {
|
||||
if (! RR->bc->linkAllowed(_policyAlias, getLinkBySocket(_policyAlias, path->localSocket(), true))) {
|
||||
debug("link %s is not permitted according to user-specified rules", pathToStr(path).c_str());
|
||||
return;
|
||||
}
|
||||
bool alreadyPresent = false;
|
||||
|
@ -229,6 +245,7 @@ void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
|||
// Sanity check
|
||||
if (path.ptr() == _paths[i].p.ptr()) {
|
||||
alreadyPresent = true;
|
||||
debug("link %s already exists", pathToStr(path).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -247,20 +264,22 @@ void Bond::nominatePathToBond(const SharedPtr<Path>& path, int64_t now)
|
|||
// Determine if there are any other paths on this link
|
||||
bool bFoundCommonLink = false;
|
||||
SharedPtr<Link> commonLink = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
for (unsigned int j = 0; j < ZT_MAX_PEER_NETWORK_PATHS; ++j) {
|
||||
if (_paths[j].p && _paths[j].p.ptr() != _paths[i].p.ptr()) {
|
||||
if (RR->bc->getLinkBySocket(_policyAlias, _paths[j].p->localSocket()) == commonLink) {
|
||||
bFoundCommonLink = true;
|
||||
_paths[j].onlyPathOnLink = false;
|
||||
if (commonLink) {
|
||||
for (unsigned int j = 0; j < ZT_MAX_PEER_NETWORK_PATHS; ++j) {
|
||||
if (_paths[j].p && _paths[j].p.ptr() != _paths[i].p.ptr()) {
|
||||
if (RR->bc->getLinkBySocket(_policyAlias, _paths[j].p->localSocket()) == commonLink, true) {
|
||||
bFoundCommonLink = true;
|
||||
_paths[j].onlyPathOnLink = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
_paths[i].ipvPref = sl->ipvPref();
|
||||
_paths[i].mode = sl->mode();
|
||||
_paths[i].enabled = sl->enabled();
|
||||
_paths[i].onlyPathOnLink = ! bFoundCommonLink;
|
||||
}
|
||||
_paths[i].ipvPref = sl->ipvPref();
|
||||
_paths[i].mode = sl->mode();
|
||||
_paths[i].enabled = sl->enabled();
|
||||
_paths[i].onlyPathOnLink = ! bFoundCommonLink;
|
||||
}
|
||||
log("nominate link %s", pathToStr(path).c_str());
|
||||
log("nominated link %s", pathToStr(path).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +332,7 @@ SharedPtr<Path> Bond::getAppropriatePath(int64_t now, int32_t flowId)
|
|||
}
|
||||
// Reset striping counter
|
||||
_rrPacketsSentOnCurrLink = 0;
|
||||
if (_numBondedPaths == 1 || _rrIdx >= (ZT_MAX_PEER_NETWORK_PATHS-1)) {
|
||||
if (_numBondedPaths == 1 || _rrIdx >= (ZT_MAX_PEER_NETWORK_PATHS - 1)) {
|
||||
_rrIdx = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -367,7 +386,7 @@ void Bond::recordIncomingInvalidPacket(const SharedPtr<Path>& path)
|
|||
Mutex::Lock _l(_paths_m);
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p == path) {
|
||||
_paths[i].packetValiditySamples.push(false);
|
||||
//_paths[i].packetValiditySamples.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,9 +407,10 @@ void Bond::recordOutgoingPacket(const SharedPtr<Path>& path, uint64_t packetId,
|
|||
_lastFrame = now;
|
||||
}
|
||||
if (shouldRecord) {
|
||||
//_paths[pathIdx].expectingAckAsOf = now;
|
||||
//_paths[pathIdx].totalBytesSentSinceLastAckRecieved += payloadLength;
|
||||
//_paths[pathIdx].unackedBytes += payloadLength;
|
||||
// Take note that we're expecting a VERB_ACK on this path as of a specific time
|
||||
if (_paths[pathIdx].qosStatsOut.size() < ZT_QOS_MAX_OUTSTANDING_RECORDS) {
|
||||
if (_paths[pathIdx].qosStatsOut.size() < ZT_QOS_MAX_PENDING_RECORDS) {
|
||||
_paths[pathIdx].qosStatsOut[packetId] = now;
|
||||
}
|
||||
}
|
||||
|
@ -423,9 +443,25 @@ void Bond::recordIncomingPacket(const SharedPtr<Path>& path, uint64_t packetId,
|
|||
_lastFrame = now;
|
||||
}
|
||||
if (shouldRecord) {
|
||||
_paths[pathIdx].qosStatsIn[packetId] = now;
|
||||
++(_paths[pathIdx].packetsReceivedSinceLastQoS);
|
||||
_paths[pathIdx].packetValiditySamples.push(true);
|
||||
if (_paths[pathIdx].qosStatsIn.size() < ZT_QOS_MAX_PENDING_RECORDS) {
|
||||
// debug("Recording QoS information (table size = %d)", _paths[pathIdx].qosStatsIn.size());
|
||||
_paths[pathIdx].qosStatsIn[packetId] = now;
|
||||
++(_paths[pathIdx].packetsReceivedSinceLastQoS);
|
||||
//_paths[pathIdx].packetValiditySamples.push(true);
|
||||
}
|
||||
else {
|
||||
debug("QoS buffer full, will not record information");
|
||||
}
|
||||
/*
|
||||
if (_paths[pathIdx].ackStatsIn.size() < ZT_ACK_MAX_PENDING_RECORDS) {
|
||||
//debug("Recording ACK information (table size = %d)", _paths[pathIdx].ackStatsIn.size());
|
||||
_paths[pathIdx].ackStatsIn[packetId] = payloadLength;
|
||||
++(_paths[pathIdx].packetsReceivedSinceLastAck);
|
||||
}
|
||||
else {
|
||||
debug("ACK buffer full, will not record information");
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -470,6 +506,16 @@ void Bond::receivedQoS(const SharedPtr<Path>& path, int64_t now, int count, uint
|
|||
_paths[pathIdx].qosRecordSize.push(count);
|
||||
}
|
||||
|
||||
void Bond::receivedAck(int pathIdx, int64_t now, int32_t ackedBytes)
|
||||
{
|
||||
/*
|
||||
Mutex::Lock _l(_paths_m);
|
||||
debug("received ACK of %d bytes on path %s, there are still %d un-acked bytes", ackedBytes, pathToStr(_paths[pathIdx].p).c_str(), _paths[pathIdx].unackedBytes);
|
||||
_paths[pathIdx].lastAckReceived = now;
|
||||
_paths[pathIdx].unackedBytes = (ackedBytes > _paths[pathIdx].unackedBytes) ? 0 : _paths[pathIdx].unackedBytes - ackedBytes;
|
||||
*/
|
||||
}
|
||||
|
||||
int32_t Bond::generateQoSPacket(int pathIdx, int64_t now, char* qosBuffer)
|
||||
{
|
||||
int32_t len = 0;
|
||||
|
@ -544,7 +590,6 @@ bool Bond::assignFlowToBondedPath(SharedPtr<Flow>& flow, int64_t now)
|
|||
}
|
||||
flow->assignPath(_abPathIdx, now);
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[flow->assignedPath].p->localSocket());
|
||||
debug("assign out-flow %04x to link %s (%lu / %lu flows)", flow->id, pathToStr(_paths[flow->assignedPath].p).c_str(), _paths[flow->assignedPath].assignedFlowCount, (unsigned long)_flows.size());
|
||||
return true;
|
||||
}
|
||||
|
@ -631,22 +676,24 @@ void Bond::processIncomingPathNegotiationRequest(uint64_t now, SharedPtr<Path>&
|
|||
return;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[pathIdx].p->localSocket());
|
||||
if (remoteUtility > _localUtility) {
|
||||
_paths[pathIdx].p->address().toString(pathStr);
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) greater than local utility (%d), switching to suggested link\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
if (remoteUtility < _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) less than local utility (%d), not switching\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
}
|
||||
if (remoteUtility == _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) equal to local utility (%d)\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
if (_peer->_id.address().toInt() > RR->node->identity().address().toInt()) {
|
||||
debug("agree with peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
if (link) {
|
||||
if (remoteUtility > _localUtility) {
|
||||
_paths[pathIdx].p->address().toString(pathStr);
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) greater than local utility (%d), switching to suggested link\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
else {
|
||||
debug("ignore petition from peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
if (remoteUtility < _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) less than local utility (%d), not switching\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
}
|
||||
if (remoteUtility == _localUtility) {
|
||||
debug("peer suggests alternate link %s/%s, remote utility (%d) equal to local utility (%d)\n", link->ifname().c_str(), pathStr, remoteUtility, _localUtility);
|
||||
if (_peer->_id.address().toInt() > RR->node->identity().address().toInt()) {
|
||||
debug("agree with peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
_negotiatedPathIdx = pathIdx;
|
||||
}
|
||||
else {
|
||||
debug("ignore petition from peer to use alternate link %s/%s\n", link->ifname().c_str(), pathStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -717,16 +764,42 @@ void Bond::sendPATH_NEGOTIATION_REQUEST(void* tPtr, int pathIdx)
|
|||
if (_paths[pathIdx].p->address()) {
|
||||
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
||||
RR->node->putPacket(tPtr, _paths[pathIdx].p->localSocket(), _paths[pathIdx].p->address(), outp.data(), outp.size());
|
||||
_overheadBytes += outp.size();
|
||||
}
|
||||
}
|
||||
|
||||
void Bond::sendACK(void* tPtr, int pathIdx, int64_t localSocket, const InetAddress& atAddress, int64_t now)
|
||||
{
|
||||
/*
|
||||
Packet outp(_peer->_id.address(), RR->identity.address(), Packet::VERB_ACK);
|
||||
int32_t bytesToAck = 0;
|
||||
std::map<uint64_t, uint64_t>::iterator it = _paths[pathIdx].ackStatsIn.begin();
|
||||
while (it != _paths[pathIdx].ackStatsIn.end()) {
|
||||
bytesToAck += it->second;
|
||||
++it;
|
||||
}
|
||||
debug("sending ACK of %d bytes on path %s (table size = %d)", bytesToAck, pathToStr(_paths[pathIdx].p).c_str(), _paths[pathIdx].ackStatsIn.size());
|
||||
outp.append<uint32_t>(bytesToAck);
|
||||
if (atAddress) {
|
||||
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
||||
RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size());
|
||||
}
|
||||
else {
|
||||
RR->sw->send(tPtr, outp, false);
|
||||
}
|
||||
_paths[pathIdx].ackStatsIn.clear();
|
||||
_paths[pathIdx].packetsReceivedSinceLastAck = 0;
|
||||
_paths[pathIdx].lastAckSent = now;
|
||||
*/
|
||||
}
|
||||
|
||||
void Bond::sendQOS_MEASUREMENT(void* tPtr, int pathIdx, int64_t localSocket, const InetAddress& atAddress, int64_t now)
|
||||
{
|
||||
int64_t _now = RR->node->now();
|
||||
Packet outp(_peer->_id.address(), RR->identity.address(), Packet::VERB_QOS_MEASUREMENT);
|
||||
char qosData[ZT_QOS_MAX_PACKET_SIZE];
|
||||
int16_t len = generateQoSPacket(pathIdx, _now, qosData);
|
||||
_overheadBytes += len;
|
||||
// debug("sending QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
||||
if (len) {
|
||||
outp.append(qosData, len);
|
||||
if (atAddress) {
|
||||
|
@ -738,8 +811,8 @@ void Bond::sendQOS_MEASUREMENT(void* tPtr, int pathIdx, int64_t localSocket, con
|
|||
}
|
||||
_paths[pathIdx].packetsReceivedSinceLastQoS = 0;
|
||||
_paths[pathIdx].lastQoSMeasurement = now;
|
||||
_overheadBytes += outp.size();
|
||||
}
|
||||
// debug("send QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
||||
}
|
||||
|
||||
void Bond::processBackgroundBondTasks(void* tPtr, int64_t now)
|
||||
|
@ -761,9 +834,9 @@ void Bond::processBackgroundBondTasks(void* tPtr, int64_t now)
|
|||
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p && _paths[i].allowed()) {
|
||||
if (_isLeaf) {
|
||||
if ((_monitorInterval > 0) && (((now - _paths[i].p->_lastIn) >= _monitorInterval) /*|| ((now - _paths[i].p->_lastOut) >= _monitorInterval)*/)) {
|
||||
if ((_monitorInterval > 0) && (((now - _paths[i].p->_lastIn) >= (_paths[i].alive ? _monitorInterval : _failoverInterval)))) {
|
||||
if ((_peer->remoteVersionProtocol() >= 5) && (! ((_peer->remoteVersionMajor() == 1) && (_peer->remoteVersionMinor() == 1) && (_peer->remoteVersionRevision() == 0)))) {
|
||||
Packet outp(_peer->address(), RR->identity.address(), Packet::VERB_ECHO); // ECHO (this is our bond's heartbeat)
|
||||
Packet outp(_peer->address(), RR->identity.address(), Packet::VERB_ECHO); // ECHO (this is our bond's heartbeat)
|
||||
outp.armor(_peer->key(), true, _peer->aesKeysIfSupported());
|
||||
RR->node->expectReplyTo(outp.packetId());
|
||||
RR->node->putPacket(tPtr, _paths[i].p->localSocket(), _paths[i].p->address(), outp.data(), outp.size());
|
||||
|
@ -776,6 +849,12 @@ void Bond::processBackgroundBondTasks(void* tPtr, int64_t now)
|
|||
if (_paths[i].needsToSendQoS(now, _qosSendInterval)) {
|
||||
sendQOS_MEASUREMENT(tPtr, i, _paths[i].p->localSocket(), _paths[i].p->address(), now);
|
||||
}
|
||||
// ACK
|
||||
/*
|
||||
if (_paths[i].needsToSendAck(now, _ackSendInterval)) {
|
||||
sendACK(tPtr, i, _paths[i].p->localSocket(), _paths[i].p->address(), now);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -815,6 +894,24 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
|||
if (! _paths[i].p) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove expired or invalid links from bond
|
||||
*/
|
||||
SharedPtr<Link> link = getLink(_paths[i].p);
|
||||
if (! link) {
|
||||
log("link is no longer valid, removing from bond");
|
||||
_paths[i] = NominatedPath();
|
||||
_paths[i].p = SharedPtr<Path>();
|
||||
continue;
|
||||
}
|
||||
if ((now - _paths[i].p->_lastIn) > (ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD)) {
|
||||
log("link (%s) has expired or is invalid, removing from bond", pathToStr(_paths[i].p).c_str());
|
||||
_paths[i] = NominatedPath();
|
||||
_paths[i].p = SharedPtr<Path>();
|
||||
continue;
|
||||
}
|
||||
|
||||
tmpNumTotalLinks++;
|
||||
if (_paths[i].eligible) {
|
||||
tmpNumAliveLinks++;
|
||||
|
@ -875,42 +972,18 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
|||
}
|
||||
|
||||
/**
|
||||
* Determine health status to report to user
|
||||
* Trigger status report if number of links change
|
||||
*/
|
||||
_numAliveLinks = tmpNumAliveLinks;
|
||||
_numTotalLinks = tmpNumTotalLinks;
|
||||
bool tmpHealthStatus = true;
|
||||
|
||||
if (_policy == ZT_BOND_POLICY_BROADCAST) {
|
||||
if (_numAliveLinks < 1) {
|
||||
// Considered healthy if we're able to send frames at all
|
||||
tmpHealthStatus = false;
|
||||
}
|
||||
}
|
||||
if ((_policy == ZT_BOND_POLICY_BALANCE_RR) || (_policy == ZT_BOND_POLICY_BALANCE_XOR) || (_policy == ZT_BOND_POLICY_BALANCE_AWARE || (_policy == ZT_BOND_POLICY_ACTIVE_BACKUP))) {
|
||||
if (_numAliveLinks < _numTotalLinks) {
|
||||
tmpHealthStatus = false;
|
||||
}
|
||||
}
|
||||
if (tmpHealthStatus != _isHealthy) {
|
||||
std::string healthStatusStr;
|
||||
if (tmpHealthStatus == true) {
|
||||
healthStatusStr = "HEALTHY";
|
||||
}
|
||||
else {
|
||||
healthStatusStr = "DEGRADED";
|
||||
}
|
||||
log("bond is %s (%d/%d links)", healthStatusStr.c_str(), _numAliveLinks, _numTotalLinks);
|
||||
if ((_numAliveLinks != tmpNumAliveLinks) || (_numTotalLinks != tmpNumTotalLinks)) {
|
||||
dumpInfo(now, true);
|
||||
}
|
||||
|
||||
_isHealthy = tmpHealthStatus;
|
||||
|
||||
/**
|
||||
* Curate the set of paths that are part of the bond proper. Select a set of paths
|
||||
* per logical link according to eligibility and user-specified constraints.
|
||||
*/
|
||||
|
||||
if ((_policy == ZT_BOND_POLICY_BALANCE_RR) || (_policy == ZT_BOND_POLICY_BALANCE_XOR) || (_policy == ZT_BOND_POLICY_BALANCE_AWARE)) {
|
||||
if (! _numBondedPaths) {
|
||||
rebuildBond = true;
|
||||
|
@ -923,7 +996,9 @@ void Bond::curateBond(int64_t now, bool rebuildBond)
|
|||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
linkMap[link].push_back(i);
|
||||
if (link) {
|
||||
linkMap[link].push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Re-form bond from link<->path map
|
||||
|
@ -1008,15 +1083,19 @@ void Bond::estimatePathQuality(int64_t now)
|
|||
uint32_t totUserSpecifiedLinkSpeed = 0;
|
||||
if (_numBondedPaths) { // Compute relative user-specified speeds of links
|
||||
for (unsigned int i = 0; i < _numBondedPaths; ++i) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (_paths[i].p && _paths[i].allowed()) {
|
||||
totUserSpecifiedLinkSpeed += link->speed();
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (link) {
|
||||
totUserSpecifiedLinkSpeed += link->speed();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < _numBondedPaths; ++i) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (_paths[i].p && _paths[i].allowed()) {
|
||||
link->setRelativeSpeed((uint8_t)round(((float)link->speed() / (float)totUserSpecifiedLinkSpeed) * 255));
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (link) {
|
||||
link->setRelativeSpeed((uint8_t)round(((float)link->speed() / (float)totUserSpecifiedLinkSpeed) * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1044,7 +1123,7 @@ void Bond::estimatePathQuality(int64_t now)
|
|||
// Compute/Smooth average of real-world observations
|
||||
_paths[i].latencyMean = _paths[i].latencySamples.mean();
|
||||
_paths[i].latencyVariance = _paths[i].latencySamples.stddev();
|
||||
_paths[i].packetErrorRatio = 1.0 - (_paths[i].packetValiditySamples.count() ? _paths[i].packetValiditySamples.mean() : 1.0);
|
||||
//_paths[i].packetErrorRatio = 1.0 - (_paths[i].packetValiditySamples.count() ? _paths[i].packetValiditySamples.mean() : 1.0);
|
||||
|
||||
if (userHasSpecifiedLinkSpeeds()) {
|
||||
// Use user-reported metrics
|
||||
|
@ -1054,20 +1133,52 @@ void Bond::estimatePathQuality(int64_t now)
|
|||
_paths[i].throughputVariance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Drain unacknowledged QoS records
|
||||
int qosRecordTimeout = (_qosSendInterval * 3);
|
||||
std::map<uint64_t, uint64_t>::iterator it = _paths[i].qosStatsOut.begin();
|
||||
uint64_t currentLostRecords = 0;
|
||||
int numDroppedQosOutRecords = 0;
|
||||
while (it != _paths[i].qosStatsOut.end()) {
|
||||
int qosRecordTimeout = 5000; //_paths[i].p->monitorInterval() * ZT_BOND_QOS_ACK_INTERVAL_MULTIPLIER * 8;
|
||||
if ((now - it->second) >= qosRecordTimeout) {
|
||||
// Packet was lost
|
||||
it = _paths[i].qosStatsOut.erase(it);
|
||||
++currentLostRecords;
|
||||
++numDroppedQosOutRecords;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (numDroppedQosOutRecords) {
|
||||
log("Dropped %d QOS out-records", numDroppedQosOutRecords);
|
||||
}
|
||||
|
||||
/*
|
||||
for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (! _paths[i].p) {
|
||||
continue;
|
||||
}
|
||||
// if ((now - _paths[i].lastAckReceived) > ackSendInterval) {
|
||||
// debug("been a while since ACK");
|
||||
// if (_paths[i].unackedBytes > 0) {
|
||||
// _paths[i].unackedBytes / _paths[i].bytesSen
|
||||
// }
|
||||
// }
|
||||
}
|
||||
*/
|
||||
|
||||
it = _paths[i].qosStatsIn.begin();
|
||||
int numDroppedQosInRecords = 0;
|
||||
while (it != _paths[i].qosStatsIn.end()) {
|
||||
if ((now - it->second) >= qosRecordTimeout) {
|
||||
it = _paths[i].qosStatsIn.erase(it);
|
||||
++numDroppedQosInRecords;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (numDroppedQosInRecords) {
|
||||
log("Dropped %d QOS in-records", numDroppedQosInRecords);
|
||||
}
|
||||
|
||||
quality[i] = 0;
|
||||
totQuality = 0;
|
||||
|
@ -1197,6 +1308,7 @@ void Bond::dequeueNextActiveBackupPath(uint64_t now)
|
|||
|
||||
bool Bond::abForciblyRotateLink()
|
||||
{
|
||||
Mutex::Lock _l(_paths_m);
|
||||
if (_policy == ZT_BOND_POLICY_ACTIVE_BACKUP) {
|
||||
int prevPathIdx = _abPathIdx;
|
||||
dequeueNextActiveBackupPath(RR->node->now());
|
||||
|
@ -1209,9 +1321,14 @@ bool Bond::abForciblyRotateLink()
|
|||
void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
||||
{
|
||||
int prevActiveBackupPathIdx = _abPathIdx;
|
||||
int nonPreferredPathIdx;
|
||||
int nonPreferredPathIdx = ZT_MAX_PEER_NETWORK_PATHS;
|
||||
bool bFoundPrimaryLink = false;
|
||||
|
||||
if (_abPathIdx != ZT_MAX_PEER_NETWORK_PATHS && ! _paths[_abPathIdx].p) {
|
||||
_abPathIdx = ZT_MAX_PEER_NETWORK_PATHS;
|
||||
log("main active-backup path has been removed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate periodic status report
|
||||
*/
|
||||
|
@ -1227,7 +1344,6 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
log("failover queue is empty, bond is no longer fault-tolerant");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select initial "active" active-backup link
|
||||
*/
|
||||
|
@ -1241,7 +1357,6 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
* simply find the next eligible path.
|
||||
*/
|
||||
if (! userHasSpecifiedLinks()) {
|
||||
debug("no user-specified links");
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p && _paths[i].eligible) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
|
@ -1253,6 +1368,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [Manual mode]
|
||||
* The user has specified links or failover rules that the bonding policy should adhere to.
|
||||
|
@ -1264,34 +1380,38 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
continue;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
if (_paths[i].eligible && link->primary()) {
|
||||
if (! _paths[i].preferred()) {
|
||||
// Found path on primary link, take note in case we don't find a preferred path
|
||||
nonPreferredPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
}
|
||||
if (_paths[i].preferred()) {
|
||||
_abPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (link) {
|
||||
log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
if (link) {
|
||||
if (_paths[i].eligible && link->primary()) {
|
||||
if (! _paths[i].preferred()) {
|
||||
// Found path on primary link, take note in case we don't find a preferred path
|
||||
nonPreferredPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
}
|
||||
if (_paths[i].preferred()) {
|
||||
_abPathIdx = i;
|
||||
bFoundPrimaryLink = true;
|
||||
if (_paths[_abPathIdx].p) {
|
||||
SharedPtr<Link> abLink = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (abLink) {
|
||||
log("found preferred primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
break; // Found preferred path on primary link
|
||||
}
|
||||
}
|
||||
break; // Found preferred path on primary link
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bFoundPrimaryLink && nonPreferredPathIdx) {
|
||||
if (bFoundPrimaryLink && (nonPreferredPathIdx != ZT_MAX_PEER_NETWORK_PATHS)) {
|
||||
log("found non-preferred primary link");
|
||||
_abPathIdx = nonPreferredPathIdx;
|
||||
}
|
||||
if (_abPathIdx == ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
log("user-designated primary link is not yet ready");
|
||||
log("user-designated primary link is not available");
|
||||
// TODO: Should wait for some time (failover interval?) and then switch to spare link
|
||||
}
|
||||
}
|
||||
|
||||
else if (! userHasSpecifiedPrimaryLink()) {
|
||||
log("user did not specify a primary link, select first available link");
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p && _paths[i].eligible) {
|
||||
_abPathIdx = i;
|
||||
|
@ -1299,28 +1419,36 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
}
|
||||
}
|
||||
if (_abPathIdx != ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (link) {
|
||||
log("select non-primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
if (_paths[_abPathIdx].p) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[_abPathIdx].p->localSocket());
|
||||
if (link) {
|
||||
log("select non-primary link %s", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Short-circuit if we don't have an active link yet
|
||||
if (_abPathIdx == ZT_MAX_PEER_NETWORK_PATHS) {
|
||||
// Short-circuit if we don't have an active link yet. Everything below is optimization from the base case
|
||||
if (_abPathIdx < 0 || _abPathIdx == ZT_MAX_PEER_NETWORK_PATHS || (! _paths[_abPathIdx].p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove ineligible paths from the failover link queue
|
||||
for (std::deque<int>::iterator it(_abFailoverQueue.begin()); it != _abFailoverQueue.end();) {
|
||||
if (! _paths[(*it)].p) {
|
||||
log("link is no longer valid, removing from failover queue (%zu links remain in queue)", _abFailoverQueue.size());
|
||||
it = _abFailoverQueue.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (_paths[(*it)].p && ! _paths[(*it)].eligible) {
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[(*it)].p->localSocket());
|
||||
it = _abFailoverQueue.erase(it);
|
||||
if (link) {
|
||||
log("link %s is ineligible, removing from failover queue (%zu links in queue)", pathToStr(_paths[_abPathIdx].p).c_str(), _abFailoverQueue.size());
|
||||
log("link %s is ineligible, removing from failover queue (%zu links remain in queue)", pathToStr(_paths[_abPathIdx].p).c_str(), _abFailoverQueue.size());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
|
@ -1345,7 +1473,9 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
continue;
|
||||
}
|
||||
SharedPtr<Link> link = RR->bc->getLinkBySocket(_policyAlias, _paths[i].p->localSocket());
|
||||
|
||||
if (! link) {
|
||||
continue;
|
||||
}
|
||||
int failoverScoreHandicap = _paths[i].failoverScore;
|
||||
if (_paths[i].preferred()) {
|
||||
failoverScoreHandicap += ZT_BOND_FAILOVER_HANDICAP_PREFERRED;
|
||||
|
@ -1375,17 +1505,19 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (_paths[i].p.ptr() != _paths[_abPathIdx].p.ptr()) {
|
||||
bool bFoundPathInQueue = false;
|
||||
for (std::deque<int>::iterator it(_abFailoverQueue.begin()); it != _abFailoverQueue.end(); ++it) {
|
||||
if (_paths[i].p.ptr() == _paths[(*it)].p.ptr()) {
|
||||
bFoundPathInQueue = true;
|
||||
if (_paths[i].p) {
|
||||
if (_paths[i].p.ptr() != _paths[_abPathIdx].p.ptr()) {
|
||||
bool bFoundPathInQueue = false;
|
||||
for (std::deque<int>::iterator it(_abFailoverQueue.begin()); it != _abFailoverQueue.end(); ++it) {
|
||||
if (_paths[(*it)].p && (_paths[i].p.ptr() == _paths[(*it)].p.ptr())) {
|
||||
bFoundPathInQueue = true;
|
||||
}
|
||||
}
|
||||
if (! bFoundPathInQueue) {
|
||||
_abFailoverQueue.push_front(i);
|
||||
log("add link %s to failover queue (%zu links in queue)", pathToStr(_paths[i].p).c_str(), _abFailoverQueue.size());
|
||||
addPathToBond(0, i);
|
||||
}
|
||||
}
|
||||
if (! bFoundPathInQueue) {
|
||||
_abFailoverQueue.push_front(i);
|
||||
log("add link %s to failover queue (%zu links in queue)", pathToStr(_paths[i].p).c_str(), _abFailoverQueue.size());
|
||||
addPathToBond(0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1406,7 +1538,11 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
if (! _paths[i].eligible) {
|
||||
failoverScoreHandicap = -10000;
|
||||
}
|
||||
if (getLink(_paths[i].p)->primary() && _abLinkSelectMethod != ZT_BOND_RESELECTION_POLICY_OPTIMIZE) {
|
||||
SharedPtr<Link> link = getLink(_paths[i].p);
|
||||
if (! link) {
|
||||
continue;
|
||||
}
|
||||
if (link->primary() && _abLinkSelectMethod != ZT_BOND_RESELECTION_POLICY_OPTIMIZE) {
|
||||
// If using "optimize" primary re-select mode, ignore user link designations
|
||||
failoverScoreHandicap = ZT_BOND_FAILOVER_HANDICAP_PRIMARY;
|
||||
}
|
||||
|
@ -1458,7 +1594,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
/**
|
||||
* Fulfill primary re-select obligations
|
||||
*/
|
||||
if (_paths[_abPathIdx].p && ! _paths[_abPathIdx].eligible) { // Implicit ZT_BOND_RESELECTION_POLICY_FAILURE
|
||||
if (! _paths[_abPathIdx].eligible) { // Implicit ZT_BOND_RESELECTION_POLICY_FAILURE
|
||||
log("link %s has failed, select link from failover queue (%zu links in queue)", pathToStr(_paths[_abPathIdx].p).c_str(), _abFailoverQueue.size());
|
||||
if (! _abFailoverQueue.empty()) {
|
||||
dequeueNextActiveBackupPath(now);
|
||||
|
@ -1474,16 +1610,29 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
if (prevActiveBackupPathIdx != _abPathIdx) {
|
||||
_lastActiveBackupPathChange = now;
|
||||
}
|
||||
if (_abFailoverQueue.empty()) {
|
||||
return; // No sense in continuing since there are no links to switch to
|
||||
}
|
||||
|
||||
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_ALWAYS) {
|
||||
if (_paths[_abPathIdx].p && ! getLink(_paths[_abPathIdx].p)->primary() && getLink(_paths[_abFailoverQueue.front()].p)->primary()) {
|
||||
SharedPtr<Link> abLink = getLink(_paths[_abPathIdx].p);
|
||||
if (! _paths[_abFailoverQueue.front()].p) {
|
||||
log("invalid link. not switching");
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPtr<Link> abFailoverLink = getLink(_paths[_abFailoverQueue.front()].p);
|
||||
if (abLink && ! abLink->primary() && _paths[_abFailoverQueue.front()].p && abFailoverLink && abFailoverLink->primary()) {
|
||||
dequeueNextActiveBackupPath(now);
|
||||
log("switch back to available primary link %s (select mode: always)", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
}
|
||||
if (_abLinkSelectMethod == ZT_BOND_RESELECTION_POLICY_BETTER) {
|
||||
if (_paths[_abPathIdx].p && ! getLink(_paths[_abPathIdx].p)->primary()) {
|
||||
SharedPtr<Link> abLink = getLink(_paths[_abPathIdx].p);
|
||||
if (abLink && ! abLink->primary()) {
|
||||
// Active backup has switched to "better" primary link according to re-select policy.
|
||||
if (getLink(_paths[_abFailoverQueue.front()].p)->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
|
||||
SharedPtr<Link> abFailoverLink = getLink(_paths[_abFailoverQueue.front()].p);
|
||||
if (_paths[_abFailoverQueue.front()].p && abFailoverLink && abFailoverLink->primary() && (_paths[_abFailoverQueue.front()].failoverScore > _paths[_abPathIdx].failoverScore)) {
|
||||
dequeueNextActiveBackupPath(now);
|
||||
log("switch back to user-defined primary link %s (select mode: better)", pathToStr(_paths[_abPathIdx].p).c_str());
|
||||
}
|
||||
|
@ -1510,11 +1659,7 @@ void Bond::processActiveBackupTasks(void* tPtr, int64_t now)
|
|||
if ((failoverScoreDifference > 0) && (failoverScoreDifference > thresholdQuantity)) {
|
||||
SharedPtr<Path> oldPath = _paths[_abPathIdx].p;
|
||||
dequeueNextActiveBackupPath(now);
|
||||
log("switch from %s (score: %d) to better link %s (score: %d) (select mode: optimize)",
|
||||
pathToStr(oldPath).c_str(),
|
||||
prevFScore,
|
||||
pathToStr(_paths[_abPathIdx].p).c_str(),
|
||||
newFScore);
|
||||
log("switch from %s (score: %d) to better link %s (score: %d) (select mode: optimize)", pathToStr(oldPath).c_str(), prevFScore, pathToStr(_paths[_abPathIdx].p).c_str(), newFScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1530,6 +1675,7 @@ void Bond::initTimers()
|
|||
_lastPathNegotiationCheck = 0;
|
||||
_lastPathNegotiationReceived = 0;
|
||||
_lastQoSRateCheck = 0;
|
||||
_lastAckRateCheck = 0;
|
||||
_lastQualityEstimation = 0;
|
||||
_lastBondStatusLog = 0;
|
||||
_lastSummaryDump = 0;
|
||||
|
@ -1562,10 +1708,6 @@ void Bond::setBondParameters(int policy, SharedPtr<Bond> templateBond, bool useT
|
|||
_localUtility = 0;
|
||||
_negotiatedPathIdx = 0;
|
||||
|
||||
// QOS Verb (and related checks)
|
||||
|
||||
_qosCutoffCount = 0;
|
||||
|
||||
// User preferences which may override the default bonding algorithm's behavior
|
||||
|
||||
_userHasSpecifiedPrimaryLink = false;
|
||||
|
@ -1574,7 +1716,6 @@ void Bond::setBondParameters(int policy, SharedPtr<Bond> templateBond, bool useT
|
|||
|
||||
// Bond status
|
||||
|
||||
_isHealthy = false;
|
||||
_numAliveLinks = 0;
|
||||
_numTotalLinks = 0;
|
||||
_numBondedPaths = 0;
|
||||
|
@ -1650,7 +1791,7 @@ void Bond::setBondParameters(int policy, SharedPtr<Bond> templateBond, bool useT
|
|||
memcpy(_qw, templateBond->_qw, ZT_QOS_WEIGHT_SIZE * sizeof(float));
|
||||
}
|
||||
|
||||
if (!_isLeaf) {
|
||||
if (! _isLeaf) {
|
||||
_policy = ZT_BOND_POLICY_ACTIVE_BACKUP;
|
||||
}
|
||||
|
||||
|
@ -1659,7 +1800,9 @@ void Bond::setBondParameters(int policy, SharedPtr<Bond> templateBond, bool useT
|
|||
_monitorInterval = _failoverInterval / ZT_BOND_ECHOS_PER_FAILOVER_INTERVAL;
|
||||
_qualityEstimationInterval = _failoverInterval * 2;
|
||||
_qosSendInterval = _failoverInterval * 2;
|
||||
_ackSendInterval = _failoverInterval * 2;
|
||||
_qosCutoffCount = 0;
|
||||
_ackCutoffCount = 0;
|
||||
_defaultPathRefractoryPeriod = 8000;
|
||||
}
|
||||
|
||||
|
@ -1678,17 +1821,24 @@ void Bond::setUserQualityWeights(float weights[], int len)
|
|||
|
||||
SharedPtr<Link> Bond::getLink(const SharedPtr<Path>& path)
|
||||
{
|
||||
return RR->bc->getLinkBySocket(_policyAlias, path->localSocket());
|
||||
return ! path ? SharedPtr<Link>() : RR->bc->getLinkBySocket(_policyAlias, path->localSocket());
|
||||
}
|
||||
|
||||
std::string Bond::pathToStr(const SharedPtr<Path>& path)
|
||||
{
|
||||
#ifdef ZT_TRACE
|
||||
char pathStr[64] = { 0 };
|
||||
char fullPathStr[384] = { 0 };
|
||||
path->address().toString(pathStr);
|
||||
snprintf(fullPathStr, 384, "%.16llx-%s/%s", (unsigned long long)(path->localSocket()), getLink(path)->ifname().c_str(), pathStr);
|
||||
return std::string(fullPathStr);
|
||||
if (path) {
|
||||
char pathStr[64] = { 0 };
|
||||
char fullPathStr[384] = { 0 };
|
||||
path->address().toString(pathStr);
|
||||
SharedPtr<Link> link = getLink(path);
|
||||
if (link) {
|
||||
std::string ifnameStr = std::string(link->ifname());
|
||||
snprintf(fullPathStr, 384, "%.16llx-%s/%s", (unsigned long long)(path->localSocket()), ifnameStr.c_str(), pathStr);
|
||||
return std::string(fullPathStr);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
|
@ -1700,11 +1850,11 @@ void Bond::dumpPathStatus(int64_t now, int pathIdx)
|
|||
std::string aliveOrDead = _paths[pathIdx].alive ? std::string("alive") : std::string("dead");
|
||||
std::string eligibleOrNot = _paths[pathIdx].eligible ? std::string("eligible") : std::string("ineligible");
|
||||
std::string bondedOrNot = _paths[pathIdx].bonded ? std::string("bonded") : std::string("unbonded");
|
||||
log("path[%2d] --- %5s (in %7d, out: %7d), %10s, %8s, flows=%-6d lat=%-8.3f pdv=%-7.3f err=%-6.4f loss=%-6.4f alloc=%-3d --- (%s)",
|
||||
log("path[%2u] --- %5s (in %7lld, out: %7lld), %10s, %8s, flows=%-6u lat=%-8.3f pdv=%-7.3f err=%-6.4f loss=%-6.4f alloc=%-3u --- (%s)",
|
||||
pathIdx,
|
||||
aliveOrDead.c_str(),
|
||||
_paths[pathIdx].p->age(now),
|
||||
(now - _paths[pathIdx].p->_lastOut),
|
||||
static_cast<long long int>(_paths[pathIdx].p->age(now)),
|
||||
static_cast<long long int>(_paths[pathIdx].p->_lastOut == 0 ? 0 : now - _paths[pathIdx].p->_lastOut),
|
||||
eligibleOrNot.c_str(),
|
||||
bondedOrNot.c_str(),
|
||||
_paths[pathIdx].assignedFlowCount,
|
||||
|
@ -1727,7 +1877,7 @@ void Bond::dumpInfo(int64_t now, bool force)
|
|||
_lastSummaryDump = now;
|
||||
float overhead = (_overheadBytes / (timeSinceLastDump / 1000.0f) / 1000.0f);
|
||||
_overheadBytes = 0;
|
||||
log("bond: bp=%d, fi=%d, mi=%d, ud=%d, dd=%d, flows=%lu, leaf=%d, overhead=%f KB/s",
|
||||
log("bond: bp=%d, fi=%d, mi=%d, ud=%d, dd=%d, flows=%lu, leaf=%d, overhead=%f KB/s, links=(%d/%d)",
|
||||
_policy,
|
||||
_failoverInterval,
|
||||
_monitorInterval,
|
||||
|
@ -1735,7 +1885,9 @@ void Bond::dumpInfo(int64_t now, bool force)
|
|||
_downDelay,
|
||||
(unsigned long)_flows.size(),
|
||||
_isLeaf,
|
||||
overhead);
|
||||
overhead,
|
||||
_numAliveLinks,
|
||||
_numTotalLinks);
|
||||
for (int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) {
|
||||
if (_paths[i].p) {
|
||||
dumpPathStatus(now, i);
|
||||
|
|
|
@ -436,7 +436,14 @@ class Bond {
|
|||
* @param peer Remote peer that this bond services
|
||||
* @return A pointer to the newly created Bond
|
||||
*/
|
||||
static SharedPtr<Bond> createTransportTriggeredBond(const RuntimeEnvironment* renv, const SharedPtr<Peer>& peer);
|
||||
static SharedPtr<Bond> createBond(const RuntimeEnvironment* renv, const SharedPtr<Peer>& peer);
|
||||
|
||||
/**
|
||||
* Remove a bond from the bond controller.
|
||||
*
|
||||
* @param peerId Remote peer that this bond services
|
||||
*/
|
||||
static void destroyBond(uint64_t peerId);
|
||||
|
||||
/**
|
||||
* Periodically perform maintenance tasks for the bonding layer.
|
||||
|
@ -451,9 +458,10 @@ class Bond {
|
|||
*
|
||||
* @param policyAlias Policy in use
|
||||
* @param localSocket Local source socket
|
||||
* @param createIfNeeded Whether a Link object is created if the name wasn't previously in the link map
|
||||
* @return Physical link definition
|
||||
*/
|
||||
static SharedPtr<Link> getLinkBySocket(const std::string& policyAlias, uint64_t localSocket);
|
||||
static SharedPtr<Link> getLinkBySocket(const std::string& policyAlias, uint64_t localSocket, bool createIfNeeded);
|
||||
|
||||
/**
|
||||
* Gets a reference to a physical link definition given its human-readable system name.
|
||||
|
@ -630,6 +638,15 @@ class Bond {
|
|||
*/
|
||||
void receivedQoS(const SharedPtr<Path>& path, int64_t now, int count, uint64_t* rx_id, uint16_t* rx_ts);
|
||||
|
||||
/**
|
||||
* Process the contents of an inbound VERB_ACK to gather path quality observations.
|
||||
*
|
||||
* @param pathIdx Path over which packet was received
|
||||
* @param now Current time
|
||||
* @param ackedBytes Number of bytes ACKed by this VERB_ACK
|
||||
*/
|
||||
void receivedAck(int pathIdx, int64_t now, int32_t ackedBytes);
|
||||
|
||||
/**
|
||||
* Generate the contents of a VERB_QOS_MEASUREMENT packet.
|
||||
*
|
||||
|
@ -871,6 +888,26 @@ class Bond {
|
|||
*/
|
||||
void processBackgroundBondTasks(void* tPtr, int64_t now);
|
||||
|
||||
/**
|
||||
* Rate limit gate for VERB_ACK
|
||||
*
|
||||
* @param now Current time
|
||||
* @return Whether the incoming packet should be rate-gated
|
||||
*/
|
||||
inline bool rateGateACK(const int64_t now)
|
||||
{
|
||||
_ackCutoffCount++;
|
||||
int numToDrain = _lastAckRateCheck ? (now - _lastAckRateCheck) / ZT_ACK_DRAINAGE_DIVISOR : _ackCutoffCount;
|
||||
_lastAckRateCheck = now;
|
||||
if (_ackCutoffCount > numToDrain) {
|
||||
_ackCutoffCount -= numToDrain;
|
||||
}
|
||||
else {
|
||||
_ackCutoffCount = 0;
|
||||
}
|
||||
return (_ackCutoffCount < ZT_ACK_CUTOFF_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rate limit gate for VERB_QOS_MEASUREMENT
|
||||
*
|
||||
|
@ -1020,14 +1057,6 @@ class Bond {
|
|||
return _policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the health status of the bond
|
||||
*/
|
||||
inline bool isHealthy()
|
||||
{
|
||||
return _isHealthy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of links comprising this bond which are considered alive
|
||||
*/
|
||||
|
@ -1142,6 +1171,9 @@ class Bond {
|
|||
*
|
||||
*/
|
||||
void log(const char* fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
{
|
||||
#ifdef ZT_TRACE
|
||||
time_t rawtime;
|
||||
|
@ -1171,6 +1203,9 @@ class Bond {
|
|||
*
|
||||
*/
|
||||
void debug(const char* fmt, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
{
|
||||
#ifdef ZT_DEBUG
|
||||
time_t rawtime;
|
||||
|
@ -1198,7 +1233,11 @@ class Bond {
|
|||
private:
|
||||
struct NominatedPath {
|
||||
NominatedPath()
|
||||
: lastQoSMeasurement(0)
|
||||
: lastAckSent(0)
|
||||
, lastAckReceived(0)
|
||||
, unackedBytes(0)
|
||||
, packetsReceivedSinceLastAck(0)
|
||||
, lastQoSMeasurement(0)
|
||||
, lastThroughputEstimation(0)
|
||||
, lastRefractoryUpdate(0)
|
||||
, lastAliveToggle(0)
|
||||
|
@ -1289,6 +1328,15 @@ class Bond {
|
|||
return ((packetsReceivedSinceLastQoS >= ZT_QOS_TABLE_SIZE) || ((now - lastQoSMeasurement) > qosSendInterval)) && packetsReceivedSinceLastQoS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param now Current time
|
||||
* @return Whether an ACK (VERB_ACK) packet needs to be emitted at this time
|
||||
*/
|
||||
inline bool needsToSendAck(int64_t now, int ackSendInterval)
|
||||
{
|
||||
return ((now - lastAckSent) >= ackSendInterval || (packetsReceivedSinceLastAck == ZT_QOS_TABLE_SIZE)) && packetsReceivedSinceLastAck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset packet counters
|
||||
*/
|
||||
|
@ -1300,6 +1348,7 @@ class Bond {
|
|||
|
||||
std::map<uint64_t, uint64_t> qosStatsOut; // id:egress_time
|
||||
std::map<uint64_t, uint64_t> qosStatsIn; // id:now
|
||||
std::map<uint64_t, uint64_t> ackStatsIn; // id:now
|
||||
|
||||
RingBuffer<int, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> qosRecordSize;
|
||||
RingBuffer<float, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> qosRecordLossSamples;
|
||||
|
@ -1308,6 +1357,11 @@ class Bond {
|
|||
RingBuffer<float, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> throughputVarianceSamples;
|
||||
RingBuffer<uint16_t, ZT_QOS_SHORTTERM_SAMPLE_WIN_SIZE> latencySamples;
|
||||
|
||||
uint64_t lastAckSent;
|
||||
uint64_t lastAckReceived;
|
||||
uint64_t unackedBytes;
|
||||
uint64_t packetsReceivedSinceLastAck;
|
||||
|
||||
uint64_t lastQoSMeasurement; // Last time that a VERB_QOS_MEASUREMENT was sent out on this path.
|
||||
uint64_t lastThroughputEstimation; // Last time that the path's throughput was estimated.
|
||||
uint64_t lastRefractoryUpdate; // The last time that the refractory period was updated.
|
||||
|
@ -1344,7 +1398,7 @@ class Bond {
|
|||
int packetsIn;
|
||||
int packetsOut;
|
||||
|
||||
AtomicCounter __refCount;
|
||||
// AtomicCounter __refCount;
|
||||
|
||||
SharedPtr<Path> p;
|
||||
void set(uint64_t now, const SharedPtr<Path>& path)
|
||||
|
@ -1490,7 +1544,6 @@ class Bond {
|
|||
/**
|
||||
* Link state reporting
|
||||
*/
|
||||
bool _isHealthy;
|
||||
uint8_t _numAliveLinks;
|
||||
uint8_t _numTotalLinks;
|
||||
|
||||
|
@ -1508,7 +1561,9 @@ class Bond {
|
|||
* Rate-limiting
|
||||
*/
|
||||
uint16_t _qosCutoffCount;
|
||||
uint16_t _ackCutoffCount;
|
||||
uint64_t _lastQoSRateCheck;
|
||||
uint64_t _lastAckRateCheck;
|
||||
uint16_t _pathNegotiationCutoffCount;
|
||||
uint64_t _lastPathNegotiationReceived;
|
||||
|
||||
|
|
|
@ -50,16 +50,17 @@
|
|||
#define __UNIX_LIKE__
|
||||
#endif
|
||||
#include <endian.h>
|
||||
|
||||
#if (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64) || defined(__aarch64__))
|
||||
#define OIDC_SUPPORTED 1
|
||||
#else
|
||||
#define OIDC_SUPPORTED 0
|
||||
#ifdef ZT_SSO_SUPPORTED
|
||||
#define ZT_SSO_ENABLED 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define OIDC_SUPPORTED 1
|
||||
#ifdef ZT_SSO_SUPPORTED
|
||||
#define ZT_SSO_ENABLED 1
|
||||
#endif
|
||||
#define likely(x) __builtin_expect((x),1)
|
||||
#define unlikely(x) __builtin_expect((x),0)
|
||||
#include <TargetConditionals.h>
|
||||
|
@ -73,7 +74,9 @@
|
|||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#define OIDC_SUPPORTED 0
|
||||
#ifdef ZT_SSO_SUPPORTED
|
||||
#define ZT_SSO_ENABLED 0
|
||||
#endif
|
||||
#ifndef __UNIX_LIKE__
|
||||
#define __UNIX_LIKE__
|
||||
#endif
|
||||
|
@ -89,7 +92,9 @@
|
|||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define OIDC_SUPPORTED 1
|
||||
#ifdef ZT_SSO_SUPPORTED
|
||||
#define ZT_SSO_ENABLED 1
|
||||
#endif
|
||||
#ifndef __WINDOWS__
|
||||
#define __WINDOWS__
|
||||
#endif
|
||||
|
@ -368,9 +373,14 @@
|
|||
#define ZT_QOS_TABLE_SIZE ((ZT_QOS_MAX_PACKET_SIZE * 8) / (64 + 16))
|
||||
|
||||
/**
|
||||
* Maximum number of outgoing packets we monitor for QoS information
|
||||
* Maximum number of packets we monitor for ACK information at any given time
|
||||
*/
|
||||
#define ZT_QOS_MAX_OUTSTANDING_RECORDS (1024 * 16)
|
||||
#define ZT_ACK_MAX_PENDING_RECORDS (32 * 1024)
|
||||
|
||||
/**
|
||||
* Maximum number of packets we monitor for QoS information at any given time
|
||||
*/
|
||||
#define ZT_QOS_MAX_PENDING_RECORDS (ZT_QOS_TABLE_SIZE * 3)
|
||||
|
||||
/**
|
||||
* Interval used for rate-limiting the computation of path quality estimates.
|
||||
|
@ -525,14 +535,14 @@
|
|||
#define ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY 8
|
||||
|
||||
/**
|
||||
* Time horizon for VERB_NETWORK_CREDENTIALS cutoff
|
||||
* Rate limit for network credential pushes from peer.
|
||||
*/
|
||||
#define ZT_PEER_CREDENTIALS_CUTOFF_TIME 60000
|
||||
#define ZT_PEER_CREDENTIALS_RATE_LIMIT 1000
|
||||
|
||||
/**
|
||||
* Maximum number of VERB_NETWORK_CREDENTIALS within cutoff time
|
||||
* Rate limit for responding to peer credential requests
|
||||
*/
|
||||
#define ZT_PEER_CREDENTIALS_CUTOFF_LIMIT 15
|
||||
#define ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT 1000
|
||||
|
||||
/**
|
||||
* WHOIS rate limit (we allow these to be pretty fast)
|
||||
|
@ -571,13 +581,13 @@
|
|||
* Anything below this value gets into thrashing territory since we divide
|
||||
* this value by ZT_BOND_ECHOS_PER_FAILOVER_INTERVAL to send ECHOs often.
|
||||
*/
|
||||
#define ZT_BOND_FAILOVER_MIN_INTERVAL 250
|
||||
#define ZT_BOND_FAILOVER_MIN_INTERVAL 500
|
||||
|
||||
/**
|
||||
* How many times per failover interval that an ECHO is sent. This should be
|
||||
* at least 2. Anything more then 4 starts to increase overhead significantly.
|
||||
*/
|
||||
#define ZT_BOND_ECHOS_PER_FAILOVER_INTERVAL 4
|
||||
#define ZT_BOND_ECHOS_PER_FAILOVER_INTERVAL 3
|
||||
|
||||
/**
|
||||
* A defensive timer to prevent path quality metrics from being
|
||||
|
|
|
@ -47,14 +47,13 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
|
|||
try {
|
||||
// Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear)
|
||||
const unsigned int c = cipher();
|
||||
bool trusted = false;
|
||||
if (c == ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH) {
|
||||
// If this is marked as a packet via a trusted path, check source address and path ID.
|
||||
// Obviously if no trusted paths are configured this always returns false and such
|
||||
// packets are dropped on the floor.
|
||||
const uint64_t tpid = trustedPathId();
|
||||
if (RR->topology->shouldInboundPathBeTrusted(_path->address(),tpid)) {
|
||||
trusted = true;
|
||||
_authenticated = true;
|
||||
} else {
|
||||
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"path not trusted");
|
||||
return true;
|
||||
|
@ -66,7 +65,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
|
|||
|
||||
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
|
||||
if (peer) {
|
||||
if (!trusted) {
|
||||
if (!_authenticated) {
|
||||
if (!dearmor(peer->key(), peer->aesKeys())) {
|
||||
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
|
||||
peer->recordIncomingInvalidPacket(_path);
|
||||
|
@ -79,6 +78,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
|
|||
return true;
|
||||
}
|
||||
|
||||
_authenticated = true;
|
||||
const Packet::Verb v = verb();
|
||||
|
||||
bool r = true;
|
||||
|
@ -88,6 +88,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
|
|||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),v,0,Packet::VERB_NOP,false,0,ZT_QOS_NO_FLOW);
|
||||
break;
|
||||
case Packet::VERB_HELLO: r = _doHELLO(RR,tPtr,true); break;
|
||||
case Packet::VERB_ACK : r = _doACK(RR,tPtr,peer); break;
|
||||
case Packet::VERB_QOS_MEASUREMENT: r = _doQOS_MEASUREMENT(RR,tPtr,peer); break;
|
||||
case Packet::VERB_ERROR: r = _doERROR(RR,tPtr,peer); break;
|
||||
case Packet::VERB_OK: r = _doOK(RR,tPtr,peer); break;
|
||||
|
@ -169,7 +170,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
|||
const SharedPtr<Network> network(RR->node->network(networkId));
|
||||
const int64_t now = RR->node->now();
|
||||
if ((network)&&(network->config().com))
|
||||
network->pushCredentialsNow(tPtr,peer->address(),now);
|
||||
network->peerRequestedCredentials(tPtr,peer->address(),now);
|
||||
} break;
|
||||
|
||||
case Packet::ERROR_NETWORK_ACCESS_DENIED_: {
|
||||
|
@ -250,28 +251,47 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doQOS_MEASUREMENT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
bool IncomingPacket::_doACK(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer)
|
||||
{
|
||||
/*
|
||||
SharedPtr<Bond> bond = peer->bond();
|
||||
if (! bond || ! bond->rateGateACK(RR->node->now())) {
|
||||
return true;
|
||||
}
|
||||
int32_t ackedBytes;
|
||||
if (payloadLength() != sizeof(ackedBytes)) {
|
||||
return true; // ignore
|
||||
}
|
||||
memcpy(&ackedBytes, payload(), sizeof(ackedBytes));
|
||||
if (bond) {
|
||||
bond->receivedAck(_path, RR->node->now(), Utils::ntoh(ackedBytes));
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IncomingPacket::_doQOS_MEASUREMENT(const RuntimeEnvironment* RR, void* tPtr, const SharedPtr<Peer>& peer)
|
||||
{
|
||||
SharedPtr<Bond> bond = peer->bond();
|
||||
if (!bond || !bond->rateGateQoS(RR->node->now(), _path)) {
|
||||
if (! bond || ! bond->rateGateQoS(RR->node->now(), _path)) {
|
||||
return true;
|
||||
}
|
||||
if (payloadLength() > ZT_QOS_MAX_PACKET_SIZE || payloadLength() < ZT_QOS_MIN_PACKET_SIZE) {
|
||||
return true; // ignore
|
||||
return true; // ignore
|
||||
}
|
||||
const int64_t now = RR->node->now();
|
||||
uint64_t rx_id[ZT_QOS_TABLE_SIZE];
|
||||
uint16_t rx_ts[ZT_QOS_TABLE_SIZE];
|
||||
char *begin = (char *)payload();
|
||||
char *ptr = begin;
|
||||
char* begin = (char*)payload();
|
||||
char* ptr = begin;
|
||||
int count = 0;
|
||||
unsigned int len = payloadLength();
|
||||
// Read packet IDs and latency compensation intervals for each packet tracked by this QoS packet
|
||||
while (ptr < (begin + len) && (count < ZT_QOS_TABLE_SIZE)) {
|
||||
memcpy((void*)&rx_id[count], ptr, sizeof(uint64_t));
|
||||
ptr+=sizeof(uint64_t);
|
||||
ptr += sizeof(uint64_t);
|
||||
memcpy((void*)&rx_ts[count], ptr, sizeof(uint16_t));
|
||||
ptr+=sizeof(uint16_t);
|
||||
ptr += sizeof(uint16_t);
|
||||
count++;
|
||||
}
|
||||
if (bond) {
|
||||
|
@ -860,7 +880,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
|
|||
bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
uint64_t now = RR->node->now();
|
||||
if (!peer->rateGateEchoRequest(now)) {
|
||||
if (!_path->rateGateEchoRequest(now)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1057,10 +1077,8 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c
|
|||
{
|
||||
const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PACKET_IDX_PAYLOAD)));
|
||||
if (network) {
|
||||
//fprintf(stderr, "IncomingPacket::_doNETWORK_CONFIG %.16llx\n", network->id());
|
||||
const uint64_t configUpdateId = network->handleConfigChunk(tPtr,packetId(),source(),*this,ZT_PACKET_IDX_PAYLOAD);
|
||||
if (configUpdateId) {
|
||||
//fprintf(stderr, "Have config update ID: %llu\n", configUpdateId);
|
||||
Packet outp(peer->address(), RR->identity.address(), Packet::VERB_OK);
|
||||
outp.append((uint8_t)Packet::VERB_ECHO);
|
||||
outp.append((uint64_t)packetId());
|
||||
|
@ -1069,9 +1087,7 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c
|
|||
const int64_t now = RR->node->now();
|
||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||
if (!_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now())) {
|
||||
//fprintf(stderr, "Error sending VERB_OK after NETWORK_CONFIG packet for %.16llx\n", network->id());
|
||||
}
|
||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1098,16 +1114,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
|
|||
} catch ( ... ) {} // discard invalid COMs
|
||||
}
|
||||
|
||||
bool trustEstablished = false;
|
||||
if (network) {
|
||||
if (network->gate(tPtr,peer)) {
|
||||
trustEstablished = true;
|
||||
} else {
|
||||
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool trustEstablished = (network) ? network->gate(tPtr,peer) : false;
|
||||
const int64_t now = RR->node->now();
|
||||
if ((gatherLimit > 0)&&((trustEstablished)||(RR->topology->amUpstream())||(RR->node->localControllerHasAuthorized(now,nwid,peer->address())))) {
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK);
|
||||
|
@ -1224,9 +1231,6 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
|||
}
|
||||
|
||||
peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,true,nwid,ZT_QOS_NO_FLOW);
|
||||
} else {
|
||||
_sendErrorNeedCredentials(RR,tPtr,peer,nwid);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -51,7 +51,9 @@ class IncomingPacket : public Packet
|
|||
public:
|
||||
IncomingPacket() :
|
||||
Packet(),
|
||||
_receiveTime(0)
|
||||
_receiveTime(0),
|
||||
_path(),
|
||||
_authenticated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -67,7 +69,8 @@ public:
|
|||
IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now) :
|
||||
Packet(data,len),
|
||||
_receiveTime(now),
|
||||
_path(path)
|
||||
_path(path),
|
||||
_authenticated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -85,6 +88,7 @@ public:
|
|||
copyFrom(data,len);
|
||||
_receiveTime = now;
|
||||
_path = path;
|
||||
_authenticated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,6 +116,7 @@ private:
|
|||
// been authenticated, decrypted, decompressed, and classified.
|
||||
bool _doERROR(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated);
|
||||
bool _doACK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doQOS_MEASUREMENT(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
bool _doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer);
|
||||
|
@ -134,6 +139,7 @@ private:
|
|||
|
||||
uint64_t _receiveTime;
|
||||
SharedPtr<Path> _path;
|
||||
bool _authenticated;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -115,7 +115,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
RR->t->credentialRejected(tPtr,com,"old");
|
||||
return ADD_REJECTED;
|
||||
}
|
||||
if ((newts == oldts)&&(_com == com))
|
||||
if (_com == com)
|
||||
return ADD_ACCEPTED_REDUNDANT;
|
||||
|
||||
switch(com.verify(RR,tPtr)) {
|
||||
|
@ -123,6 +123,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
RR->t->credentialRejected(tPtr,com,"invalid");
|
||||
return ADD_REJECTED;
|
||||
case 0:
|
||||
//printf("%.16llx %.10llx replacing COM %lld with %lld\n", com.networkId(), com.issuedTo().toInt(), _com.timestamp(), com.timestamp()); fflush(stdout);
|
||||
_com = com;
|
||||
return ADD_ACCEPTED_NEW;
|
||||
case 1:
|
||||
|
|
|
@ -64,13 +64,9 @@ public:
|
|||
*/
|
||||
void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf);
|
||||
|
||||
/**
|
||||
* @return True if we haven't pushed credentials in a long time (to cause proactive credential push)
|
||||
*/
|
||||
inline bool shouldPushCredentials(const int64_t now) const
|
||||
{
|
||||
return ((now - _lastPushedCredentials) > ZT_PEER_ACTIVITY_TIMEOUT);
|
||||
}
|
||||
inline int64_t lastPushedCredentials() { return _lastPushedCredentials; }
|
||||
inline int64_t comTimestamp() { return _com.timestamp(); }
|
||||
inline int64_t comRevocationThreshold() { return _comRevocationThreshold; }
|
||||
|
||||
/**
|
||||
* Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
|
||||
|
@ -96,9 +92,7 @@ public:
|
|||
*/
|
||||
inline bool isAllowedOnNetwork(const NetworkConfig &thisNodeNetworkConfig, const Identity &otherNodeIdentity) const
|
||||
{
|
||||
if (thisNodeNetworkConfig.isPublic()) return true;
|
||||
if (_com.timestamp() <= _comRevocationThreshold) return false;
|
||||
return thisNodeNetworkConfig.com.agreesWith(_com, otherNodeIdentity);
|
||||
return thisNodeNetworkConfig.isPublic() || (((_com.timestamp() > _comRevocationThreshold) && (thisNodeNetworkConfig.com.agreesWith(_com, otherNodeIdentity))));
|
||||
}
|
||||
|
||||
inline bool recentlyAssociated(const int64_t now) const
|
||||
|
|
|
@ -1223,10 +1223,16 @@ void Network::requestConfiguration(void *tPtr)
|
|||
bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
const int64_t now = RR->node->now();
|
||||
//int64_t comTimestamp = 0;
|
||||
//int64_t comRevocationThreshold = 0;
|
||||
Mutex::Lock _l(_lock);
|
||||
try {
|
||||
if (_config) {
|
||||
Membership *m = _memberships.get(peer->address());
|
||||
//if (m) {
|
||||
// comTimestamp = m->comTimestamp();
|
||||
// comRevocationThreshold = m->comRevocationThreshold();
|
||||
//}
|
||||
if ( (_config.isPublic()) || ((m)&&(m->isAllowedOnNetwork(_config, peer->identity()))) ) {
|
||||
if (!m)
|
||||
m = &(_membership(peer->address()));
|
||||
|
@ -1237,6 +1243,8 @@ bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
|
|||
}
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
//printf("%.16llx %.10llx not allowed, COM ts %lld revocation %lld\n", _id, peer->address().toInt(), comTimestamp, comRevocationThreshold); fflush(stdout);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -372,10 +372,13 @@ public:
|
|||
* @param to Destination peer address
|
||||
* @param now Current time
|
||||
*/
|
||||
inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now)
|
||||
inline void peerRequestedCredentials(void *tPtr,const Address &to,const int64_t now)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
_membership(to).pushCredentials(RR,tPtr,now,to,_config);
|
||||
Membership &m = _membership(to);
|
||||
const int64_t lastPushed = m.lastPushedCredentials();
|
||||
if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_CREDENTIALS_REQUEST_RATE_LIMIT))
|
||||
m.pushCredentials(RR,tPtr,now,to,_config);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -389,7 +392,8 @@ public:
|
|||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
Membership &m = _membership(to);
|
||||
if (m.shouldPushCredentials(now))
|
||||
const int64_t lastPushed = m.lastPushedCredentials();
|
||||
if ((lastPushed < _lastConfigUpdate)||((now - lastPushed) > ZT_PEER_ACTIVITY_TIMEOUT))
|
||||
m.pushCredentials(RR,tPtr,now,to,_config);
|
||||
}
|
||||
|
||||
|
@ -439,7 +443,7 @@ private:
|
|||
Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
|
||||
NetworkConfig _config;
|
||||
uint64_t _lastConfigUpdate;
|
||||
int64_t _lastConfigUpdate;
|
||||
|
||||
struct _IncomingConfigChunk
|
||||
{
|
||||
|
|
|
@ -41,20 +41,19 @@
|
|||
#include "Trace.hpp"
|
||||
|
||||
/**
|
||||
* Default maximum time delta for COMs, tags, and capabilities
|
||||
*
|
||||
* The current value is two hours, providing ample time for a controller to
|
||||
* experience fail-over, etc.
|
||||
* Default time delta for COMs, tags, and capabilities
|
||||
*/
|
||||
#define ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA 7200000ULL
|
||||
#define ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_DFL_MAX_DELTA ((int64_t)(1000 * 60 * 30))
|
||||
|
||||
/**
|
||||
* Default minimum credential TTL and maxDelta for COM timestamps
|
||||
*
|
||||
* This is just slightly over three minutes and provides three retries for
|
||||
* all currently online members to refresh.
|
||||
* Maximum time delta for COMs, tags, and capabilities
|
||||
*/
|
||||
#define ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA 185000ULL
|
||||
#define ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA ((int64_t)(1000 * 60 * 60 * 2))
|
||||
|
||||
/**
|
||||
* Minimum credential TTL and maxDelta for COM timestamps
|
||||
*/
|
||||
#define ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MIN_MAX_DELTA ((int64_t)(1000 * 60 * 5))
|
||||
|
||||
/**
|
||||
* Flag: enable broadcast
|
||||
|
|
|
@ -509,7 +509,6 @@ ZT_PeerList *Node::peers() const
|
|||
if (pi->second->bond()) {
|
||||
p->isBonded = pi->second->bond();
|
||||
p->bondingPolicy = pi->second->bond()->policy();
|
||||
p->isHealthy = pi->second->bond()->isHealthy();
|
||||
p->numAliveLinks = pi->second->bond()->getNumAliveLinks();
|
||||
p->numTotalLinks = pi->second->bond()->getNumTotalLinks();
|
||||
}
|
||||
|
@ -741,7 +740,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
|
|||
n->setAccessDenied(nullptr);
|
||||
break;
|
||||
case NetworkController::NC_ERROR_AUTHENTICATION_REQUIRED: {
|
||||
fprintf(stderr, "\n\nGot auth required\n\n");
|
||||
//fprintf(stderr, "\n\nGot auth required\n\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
_lastOut(0),
|
||||
_lastIn(0),
|
||||
_lastTrustEstablishedPacketReceived(0),
|
||||
_lastEchoRequestReceived(0),
|
||||
_localSocket(-1),
|
||||
_latency(0xffff),
|
||||
_addr(),
|
||||
|
@ -93,6 +94,7 @@ public:
|
|||
_lastOut(0),
|
||||
_lastIn(0),
|
||||
_lastTrustEstablishedPacketReceived(0),
|
||||
_lastEchoRequestReceived(0),
|
||||
_localSocket(localSocket),
|
||||
_latency(0xffff),
|
||||
_addr(addr),
|
||||
|
@ -266,6 +268,18 @@ public:
|
|||
*/
|
||||
inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
|
||||
|
||||
/**
|
||||
* Rate limit gate for inbound ECHO requests
|
||||
*/
|
||||
inline bool rateGateEchoRequest(const int64_t now)
|
||||
{
|
||||
if ((now - _lastEchoRequestReceived) >= (ZT_PEER_GENERAL_RATE_LIMIT / 6)) {
|
||||
_lastEchoRequestReceived = now;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void *_bondingMetricPtr;
|
||||
|
||||
private:
|
||||
|
@ -273,6 +287,9 @@ private:
|
|||
volatile int64_t _lastOut;
|
||||
volatile int64_t _lastIn;
|
||||
volatile int64_t _lastTrustEstablishedPacketReceived;
|
||||
|
||||
int64_t _lastEchoRequestReceived;
|
||||
|
||||
int64_t _localSocket;
|
||||
volatile unsigned int _latency;
|
||||
InetAddress _addr;
|
||||
|
|
|
@ -34,7 +34,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
|
|||
_lastTriedMemorizedPath(0),
|
||||
_lastDirectPathPushSent(0),
|
||||
_lastDirectPathPushReceive(0),
|
||||
_lastEchoRequestReceived(0),
|
||||
_lastCredentialRequestSent(0),
|
||||
_lastWhoisRequestReceived(0),
|
||||
_lastCredentialsReceived(0),
|
||||
|
@ -48,7 +47,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
|
|||
_vRevision(0),
|
||||
_id(peerIdentity),
|
||||
_directPathPushCutoffCount(0),
|
||||
_credentialsCutoffCount(0),
|
||||
_echoRequestCutoffCount(0),
|
||||
_localMultipathSupported(false),
|
||||
_lastComputedAggregateMeanLatency(0)
|
||||
|
@ -224,6 +222,8 @@ void Peer::received(
|
|||
if (sinceLastPush >= ((hops == 0) ? ZT_DIRECT_PATH_PUSH_INTERVAL_HAVEPATH : ZT_DIRECT_PATH_PUSH_INTERVAL)) {
|
||||
_lastDirectPathPushSent = now;
|
||||
std::vector<InetAddress> pathsToPush(RR->node->directPaths());
|
||||
std::vector<InetAddress> ma = RR->sa->whoami();
|
||||
pathsToPush.insert(pathsToPush.end(), ma.begin(), ma.end());
|
||||
if (!pathsToPush.empty()) {
|
||||
std::vector<InetAddress>::const_iterator p(pathsToPush.begin());
|
||||
while (p != pathsToPush.end()) {
|
||||
|
@ -453,7 +453,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
|
|||
if (atAddress) {
|
||||
outp.armor(_key,false,nullptr); // false == don't encrypt full payload, but add MAC
|
||||
RR->node->expectReplyTo(outp.packetId());
|
||||
RR->node->putPacket(tPtr,localSocket,atAddress,outp.data(),outp.size());
|
||||
RR->node->putPacket(tPtr,-1,atAddress,outp.data(),outp.size());
|
||||
} else {
|
||||
RR->node->expectReplyTo(outp.packetId());
|
||||
RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
|
||||
|
@ -502,7 +502,7 @@ void Peer::performMultipathStateCheck(void *tPtr, int64_t now)
|
|||
_localMultipathSupported = ((numAlivePaths >= 1) && (RR->bc->inUse()) && (ZT_PROTO_VERSION > 9));
|
||||
if (_localMultipathSupported && !_bond) {
|
||||
if (RR->bc) {
|
||||
_bond = RR->bc->createTransportTriggeredBond(RR, this);
|
||||
_bond = RR->bc->createBond(RR, this);
|
||||
/**
|
||||
* Allow new bond to retroactively learn all paths known to this peer
|
||||
*/
|
||||
|
|
|
@ -53,7 +53,10 @@ private:
|
|||
Peer() {} // disabled to prevent bugs -- should not be constructed uninitialized
|
||||
|
||||
public:
|
||||
~Peer() { Utils::burn(_key,sizeof(_key)); }
|
||||
~Peer() {
|
||||
Utils::burn(_key,sizeof(_key));
|
||||
RR->bc->destroyBond(_id.address().toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new peer
|
||||
|
@ -387,11 +390,11 @@ public:
|
|||
*/
|
||||
inline bool rateGateCredentialsReceived(const int64_t now)
|
||||
{
|
||||
if ((now - _lastCredentialsReceived) <= ZT_PEER_CREDENTIALS_CUTOFF_TIME)
|
||||
++_credentialsCutoffCount;
|
||||
else _credentialsCutoffCount = 0;
|
||||
_lastCredentialsReceived = now;
|
||||
return (_credentialsCutoffCount < ZT_PEER_CREDENTIALS_CUTOFF_LIMIT);
|
||||
if ((now - _lastCredentialsReceived) >= ZT_PEER_CREDENTIALS_RATE_LIMIT) {
|
||||
_lastCredentialsReceived = now;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -418,18 +421,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rate limit gate for inbound ECHO requests
|
||||
*/
|
||||
inline bool rateGateEchoRequest(const int64_t now)
|
||||
{
|
||||
if ((now - _lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) {
|
||||
_lastEchoRequestReceived = now;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a peer for storage in local cache
|
||||
*
|
||||
|
@ -546,7 +537,6 @@ private:
|
|||
int64_t _lastTriedMemorizedPath;
|
||||
int64_t _lastDirectPathPushSent;
|
||||
int64_t _lastDirectPathPushReceive;
|
||||
int64_t _lastEchoRequestReceived;
|
||||
int64_t _lastCredentialRequestSent;
|
||||
int64_t _lastWhoisRequestReceived;
|
||||
int64_t _lastCredentialsReceived;
|
||||
|
@ -573,7 +563,6 @@ private:
|
|||
Identity _id;
|
||||
|
||||
unsigned int _directPathPushCutoffCount;
|
||||
unsigned int _credentialsCutoffCount;
|
||||
unsigned int _echoRequestCutoffCount;
|
||||
|
||||
AtomicCounter __refCount;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
* @param tgt Target node whose credential(s) are being revoked
|
||||
* @param ct Credential type being revoked
|
||||
*/
|
||||
Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
||||
Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const int64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
||||
_id(i),
|
||||
_credentialId(cid),
|
||||
_networkId(nwid),
|
||||
|
@ -155,7 +155,7 @@ public:
|
|||
_networkId = b.template at<uint64_t>(p); p += 8;
|
||||
p += 4; // 4 bytes, currently unused
|
||||
_credentialId = b.template at<uint32_t>(p); p += 4;
|
||||
_threshold = b.template at<uint64_t>(p); p += 8;
|
||||
_threshold = (int64_t)b.template at<uint64_t>(p); p += 8;
|
||||
_flags = b.template at<uint64_t>(p); p += 8;
|
||||
_target.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
||||
_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && !defined(__MINGW32__)))
|
||||
#if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || (defined(__WINDOWS__) && !defined(__MINGW32__) && !defined(_M_ARM64)))
|
||||
#define ZT_SALSA20_SSE 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -99,6 +99,21 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<InetAddress> SelfAwareness::whoami()
|
||||
{
|
||||
std::vector<InetAddress> surfaceAddresses;
|
||||
Mutex::Lock _l(_phy_m);
|
||||
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
|
||||
PhySurfaceKey *k = (PhySurfaceKey *)0;
|
||||
PhySurfaceEntry *e = (PhySurfaceEntry *)0;
|
||||
while (i.next(k,e)) {
|
||||
if (std::find(surfaceAddresses.begin(), surfaceAddresses.end(), e->mySurface) == surfaceAddresses.end()) {
|
||||
surfaceAddresses.push_back(e->mySurface);
|
||||
}
|
||||
}
|
||||
return surfaceAddresses;
|
||||
}
|
||||
|
||||
void SelfAwareness::clean(int64_t now)
|
||||
{
|
||||
Mutex::Lock _l(_phy_m);
|
||||
|
|
|
@ -44,6 +44,13 @@ public:
|
|||
*/
|
||||
void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now);
|
||||
|
||||
/**
|
||||
* Return all known external surface addresses reported by peers
|
||||
*
|
||||
* @return A vector of InetAddress(es)
|
||||
*/
|
||||
std::vector<InetAddress> whoami();
|
||||
|
||||
/**
|
||||
* Clean up database periodically
|
||||
*
|
||||
|
|
40
one.cpp
40
one.cpp
|
@ -88,7 +88,7 @@
|
|||
|
||||
#include "service/OneService.hpp"
|
||||
|
||||
#include "ext/json/json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <SystemConfiguration/SystemConfiguration.h>
|
||||
|
@ -523,31 +523,23 @@ static int cli(int argc,char **argv)
|
|||
printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str());
|
||||
} else {
|
||||
bool bFoundBond = false;
|
||||
printf(" <peer> <bondtype> <status> <links>" ZT_EOL_S);
|
||||
printf(" <peer> <bondtype> <links>" ZT_EOL_S);
|
||||
if (j.is_array()) {
|
||||
for(unsigned long k=0;k<j.size();++k) {
|
||||
nlohmann::json &p = j[k];
|
||||
bool isBonded = p["isBonded"];
|
||||
if (isBonded) {
|
||||
int8_t bondingPolicy = p["bondingPolicy"];
|
||||
bool isHealthy = p["isHealthy"];
|
||||
int8_t numAliveLinks = p["numAliveLinks"];
|
||||
int8_t numTotalLinks = p["numTotalLinks"];
|
||||
bFoundBond = true;
|
||||
std::string healthStr;
|
||||
if (isHealthy) {
|
||||
healthStr = "HEALTHY";
|
||||
} else {
|
||||
healthStr = "DEGRADED";
|
||||
}
|
||||
std::string policyStr = "none";
|
||||
if (bondingPolicy >= ZT_BOND_POLICY_NONE && bondingPolicy <= ZT_BOND_POLICY_BALANCE_AWARE) {
|
||||
policyStr = Bond::getPolicyStrByCode(bondingPolicy);
|
||||
}
|
||||
printf("%10s %32s %8s %d/%d" ZT_EOL_S,
|
||||
printf("%10s %32s %d/%d" ZT_EOL_S,
|
||||
OSUtils::jsonString(p ["address"],"-").c_str(),
|
||||
policyStr.c_str(),
|
||||
healthStr.c_str(),
|
||||
numAliveLinks,
|
||||
numTotalLinks);
|
||||
}
|
||||
|
@ -617,12 +609,6 @@ static int cli(int argc,char **argv)
|
|||
if (json) {
|
||||
printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str());
|
||||
} else {
|
||||
std::string healthStr;
|
||||
if (OSUtils::jsonInt(j["isHealthy"],0)) {
|
||||
healthStr = "Healthy";
|
||||
} else {
|
||||
healthStr = "Degraded";
|
||||
}
|
||||
int numAliveLinks = OSUtils::jsonInt(j["numAliveLinks"],0);
|
||||
int numTotalLinks = OSUtils::jsonInt(j["numTotalLinks"],0);
|
||||
printf("Peer : %s\n", arg1.c_str());
|
||||
|
@ -630,7 +616,6 @@ static int cli(int argc,char **argv)
|
|||
//if (bondingPolicy == ZT_BOND_POLICY_ACTIVE_BACKUP) {
|
||||
printf("Link Select Method : %d\n", (int)OSUtils::jsonInt(j["linkSelectMethod"],0));
|
||||
//}
|
||||
printf("Status : %s\n", healthStr.c_str());
|
||||
printf("Links : %d/%d\n", numAliveLinks, numTotalLinks);
|
||||
printf("Failover Interval : %d (ms)\n", (int)OSUtils::jsonInt(j["failoverInterval"],0));
|
||||
printf("Up Delay : %d (ms)\n", (int)OSUtils::jsonInt(j["upDelay"],0));
|
||||
|
@ -705,33 +690,23 @@ static int cli(int argc,char **argv)
|
|||
printf("%s" ZT_EOL_S,OSUtils::jsonDump(j).c_str());
|
||||
} else {
|
||||
bool bFoundBond = false;
|
||||
printf(" <peer> <bondtype> <status> <links>" ZT_EOL_S);
|
||||
printf(" <peer> <bondtype> <links>" ZT_EOL_S);
|
||||
if (j.is_array()) {
|
||||
for(unsigned long k=0;k<j.size();++k) {
|
||||
nlohmann::json &p = j[k];
|
||||
bool isBonded = p["isBonded"];
|
||||
if (isBonded) {
|
||||
int8_t bondingPolicy = p["bondingPolicy"];
|
||||
bool isHealthy = p["isHealthy"];
|
||||
int8_t numAliveLinks = p["numAliveLinks"];
|
||||
int8_t numTotalLinks = p["numTotalLinks"];
|
||||
|
||||
bFoundBond = true;
|
||||
std::string healthStr;
|
||||
if (isHealthy) {
|
||||
healthStr = "Healthy";
|
||||
} else {
|
||||
healthStr = "Degraded";
|
||||
}
|
||||
std::string policyStr = "none";
|
||||
if (bondingPolicy >= ZT_BOND_POLICY_NONE && bondingPolicy <= ZT_BOND_POLICY_BALANCE_AWARE) {
|
||||
policyStr = Bond::getPolicyStrByCode(bondingPolicy);
|
||||
}
|
||||
|
||||
printf("%10s %32s %8s %d/%d" ZT_EOL_S,
|
||||
printf("%10s %32s %d/%d" ZT_EOL_S,
|
||||
OSUtils::jsonString(p["address"],"-").c_str(),
|
||||
policyStr.c_str(),
|
||||
healthStr.c_str(),
|
||||
numAliveLinks,
|
||||
numTotalLinks);
|
||||
}
|
||||
|
@ -800,7 +775,10 @@ static int cli(int argc,char **argv)
|
|||
if (status == "AUTHENTICATION_REQUIRED") {
|
||||
printf(" AUTH EXPIRED, URL: %s" ZT_EOL_S, OSUtils::jsonString(n["authenticationURL"], "(null)").c_str());
|
||||
} else if (status == "OK") {
|
||||
printf(" AUTH OK, expires in: %lld seconds" ZT_EOL_S, ((int64_t)authenticationExpiryTime - OSUtils::now()) / 1000LL);
|
||||
int64_t expiresIn = ((int64_t)authenticationExpiryTime - OSUtils::now()) / 1000LL;
|
||||
if (expiresIn >= 0) {
|
||||
printf(" AUTH OK, expires in: %lld seconds" ZT_EOL_S, expiresIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
#include <net/if.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -311,7 +311,7 @@ class Binder {
|
|||
if (! gotViaProc) {
|
||||
struct ifaddrs* ifatbl = (struct ifaddrs*)0;
|
||||
struct ifaddrs* ifa;
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
// set up an IPv6 socket so we can check the state of interfaces via SIOCGIFAFLAG_IN6
|
||||
int infoSock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
|
@ -320,7 +320,7 @@ class Binder {
|
|||
while (ifa) {
|
||||
if ((ifa->ifa_name) && (ifa->ifa_addr)) {
|
||||
InetAddress ip = *(ifa->ifa_addr);
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
// Check if the address is an IPv6 Temporary Address, macOS/BSD version
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6* sa6 = (struct sockaddr_in6*)ifa->ifa_addr;
|
||||
|
@ -368,7 +368,7 @@ class Binder {
|
|||
else {
|
||||
interfacesEnumerated = false;
|
||||
}
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__)
|
||||
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__LINUX__) && !defined(ZT_SDK)
|
||||
close(infoSock);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#endif
|
||||
|
||||
#ifndef OMIT_JSON_SUPPORT
|
||||
#include "../ext/json/json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
namespace ZeroTier {
|
||||
|
|
|
@ -229,23 +229,33 @@ public:
|
|||
* @param s Socket object
|
||||
* @return Underlying OS-type (usually int or long) file descriptor associated with object
|
||||
*/
|
||||
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket *s) throw() { return reinterpret_cast<PhySocketImpl *>(s)->sock; }
|
||||
static inline ZT_PHY_SOCKFD_TYPE getDescriptor(PhySocket* s) throw()
|
||||
{
|
||||
return reinterpret_cast<PhySocketImpl*>(s)->sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s Socket object
|
||||
* @return Pointer to user object
|
||||
*/
|
||||
static inline void** getuptr(PhySocket *s) throw() { return &(reinterpret_cast<PhySocketImpl *>(s)->uptr); }
|
||||
static inline void** getuptr(PhySocket* s) throw()
|
||||
{
|
||||
return &(reinterpret_cast<PhySocketImpl*>(s)->uptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s Socket object
|
||||
* @param nameBuf Buffer to store name of interface which this Socket object is bound to
|
||||
* @param buflen Length of buffer to copy name into
|
||||
*/
|
||||
static inline void getIfName(PhySocket *s, char *nameBuf, int buflen)
|
||||
static inline void getIfName(PhySocket* s, char* nameBuf, int buflen)
|
||||
{
|
||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
||||
return;
|
||||
}
|
||||
if (s) {
|
||||
memcpy(nameBuf, reinterpret_cast<PhySocketImpl *>(s)->ifname, buflen);
|
||||
memcpy(nameBuf, reinterpret_cast<PhySocketImpl*>(s)->ifname, buflen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,10 +264,14 @@ public:
|
|||
* @param ifname Buffer containing name of interface that this Socket object is bound to
|
||||
* @param len Length of name of interface
|
||||
*/
|
||||
static inline void setIfName(PhySocket *s, char *ifname, int len)
|
||||
static inline void setIfName(PhySocket* s, char* ifname, int len)
|
||||
{
|
||||
PhySocketImpl& sws = *(reinterpret_cast<PhySocketImpl*>(s));
|
||||
if (sws.type == ZT_PHY_SOCKET_CLOSED) {
|
||||
return;
|
||||
}
|
||||
if (s) {
|
||||
memcpy(&(reinterpret_cast<PhySocketImpl *>(s)->ifname), ifname, len);
|
||||
memcpy(&(reinterpret_cast<PhySocketImpl*>(s)->ifname), ifname, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,21 +284,27 @@ public:
|
|||
inline void whack()
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::send(_whackSendSocket,(const char *)this,1,0);
|
||||
::send(_whackSendSocket, (const char*)this, 1, 0);
|
||||
#else
|
||||
(void)(::write(_whackSendSocket,(PhySocket *)this,1));
|
||||
(void)(::write(_whackSendSocket, (PhySocket*)this, 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Number of open sockets
|
||||
*/
|
||||
inline unsigned long count() const throw() { return _socks.size(); }
|
||||
inline unsigned long count() const throw()
|
||||
{
|
||||
return _socks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum number of sockets allowed
|
||||
*/
|
||||
inline unsigned long maxCount() const throw() { return ZT_PHY_MAX_SOCKETS; }
|
||||
inline unsigned long maxCount() const throw()
|
||||
{
|
||||
return ZT_PHY_MAX_SOCKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a raw file descriptor in a PhySocket structure
|
||||
|
|
4
pkg/README.md
Normal file
4
pkg/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
Third-party packaging
|
||||
=====
|
||||
|
||||
Builds packages for various embedded devices and appliances and platforms
|
10
pkg/asustor/Dockerfile
Normal file
10
pkg/asustor/Dockerfile
Normal file
|
@ -0,0 +1,10 @@
|
|||
# vim: ft=dockerfile
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
RUN apt-get update -qq && apt-get install python2.7 -y
|
||||
|
||||
COPY apkg-tools.py /apkg-tools.py
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
13
pkg/asustor/build.sh
Executable file
13
pkg/asustor/build.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
build_packages()
|
||||
{
|
||||
sudo docker run -v $(pwd):/zto ztasustor
|
||||
}
|
||||
|
||||
build_container()
|
||||
{
|
||||
sudo docker build -t ztasustor . --load
|
||||
}
|
||||
|
||||
"$@"
|
29
pkg/asustor/entrypoint.sh
Executable file
29
pkg/asustor/entrypoint.sh
Executable file
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
|
||||
ZTO_VER=$(git describe --abbrev=0 --tags)
|
||||
ZTO_COMMIT=$(git rev-parse HEAD)
|
||||
ZTO_DESC=$(jq -r '.desc' ../config.json)
|
||||
|
||||
# Clean up any pre-existing packages
|
||||
find pkg/asustor -type f -name "*.apk" -exec rm -rvf {} \;
|
||||
# Copy current license
|
||||
cp ../../LICENSE.txt zerotier/control/license.txt
|
||||
# Configure package data
|
||||
tmp="config-tmp.json"
|
||||
jq --arg a "$ZTO_VER" '.general.version = $a' pkg/asustor/zerotier/CONTROL/config.json > $tmp && mv $tmp pkg/asustor/zerotier/CONTROL/config.json
|
||||
echo $ZTO_DESC > pkg/asustor/zerotier/CONTROL/description.txt
|
||||
|
||||
# Copy binaries into pkg directory
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-aarch64 pkg/asustor/zerotier/bin/zerotier-one.aarch64
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-i386 pkg/asustor/zerotier/bin/zerotier-one.i386
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-x86_64 pkg/asustor/zerotier/bin/zerotier-one.x86-64
|
||||
|
||||
# Package
|
||||
python pkg/asustor/apkg-tools.py create pkg/asustor/zerotier
|
||||
rm -rf output/asustor
|
||||
mkdir -p output/asustor
|
||||
mv ./*.apk output/asustor
|
||||
|
||||
# Show output product
|
||||
cat pkg/asustor/zerotier/CONTROL/config.json
|
||||
tree output/asustor
|
15
pkg/asustor/zerotier/CONTROL/config.json
Normal file
15
pkg/asustor/zerotier/CONTROL/config.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"general": {
|
||||
"package": "zerotier",
|
||||
"name": "ZeroTier",
|
||||
"version": "1.8.6",
|
||||
"depends": [],
|
||||
"conflicts": [],
|
||||
"developer": "ZeroTier, Inc.",
|
||||
"maintainer": "ZeroTier, Inc.",
|
||||
"email": "support@zerotier.com",
|
||||
"website": "http://www.zerotier.com/",
|
||||
"architecture": "any",
|
||||
"firmware": "2.1.0"
|
||||
}
|
||||
}
|
1
pkg/asustor/zerotier/CONTROL/description.txt
Normal file
1
pkg/asustor/zerotier/CONTROL/description.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Securely connect any device, anywhere.
|
BIN
pkg/asustor/zerotier/CONTROL/icon.png
Normal file
BIN
pkg/asustor/zerotier/CONTROL/icon.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 144 KiB |
149
pkg/asustor/zerotier/CONTROL/license.txt
Normal file
149
pkg/asustor/zerotier/CONTROL/license.txt
Normal file
|
@ -0,0 +1,149 @@
|
|||
-----------------------------------------------------------------------------
|
||||
|
||||
Business Source License 1.1
|
||||
|
||||
License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
|
||||
"Business Source License" is a trademark of MariaDB Corporation Ab.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Parameters
|
||||
|
||||
Licensor: ZeroTier, Inc.
|
||||
Licensed Work: ZeroTier Network Virtualization Engine 1.4.4
|
||||
The Licensed Work is (c)2019 ZeroTier, Inc.
|
||||
Additional Use Grant: You may make use of the Licensed Work, provided you
|
||||
do not use it in any of the following ways:
|
||||
|
||||
* Sell hosted ZeroTier services as a "SaaS" Product
|
||||
|
||||
(1) Operate or sell access to ZeroTier root servers,
|
||||
network controllers, or authorization key or certificate
|
||||
generation components of the Licensed Work as a
|
||||
for-profit service, regardless of whether the use of
|
||||
these components is sold alone or is bundled with other
|
||||
services. Note that this does not apply to the use of
|
||||
ZeroTier behind the scenes to operate a service not
|
||||
related to ZeroTier network administration.
|
||||
|
||||
* Create Non-Open-Source Commercial Derviative Works
|
||||
|
||||
(2) Link or directly include the Licensed Work in a
|
||||
commercial or for-profit application or other product
|
||||
not distributed under an Open Source Initiative (OSI)
|
||||
compliant license. See: https://opensource.org/licenses
|
||||
|
||||
(3) Remove the name, logo, copyright, or other branding
|
||||
material from the Licensed Work to create a "rebranded"
|
||||
or "white labeled" version to distribute as part of
|
||||
any commercial or for-profit product or service.
|
||||
|
||||
* Certain Government Uses
|
||||
|
||||
(4) Use or deploy the Licensed Work in a government
|
||||
setting in support of any active government function
|
||||
or operation with the exception of the following:
|
||||
physical or mental health care, family and social
|
||||
services, social welfare, senior care, child care, and
|
||||
the care of persons with disabilities.
|
||||
|
||||
Change Date: 2025-01-01
|
||||
|
||||
Change License: Apache License version 2.0 as published by the Apache
|
||||
Software Foundation
|
||||
https://www.apache.org/licenses/
|
||||
|
||||
Alternative Licensing
|
||||
|
||||
If you would like to use the Licensed Work in any way that conflicts with
|
||||
the stipulations of the Additional Use Grant, contact ZeroTier, Inc. to
|
||||
obtain an alternative commercial license.
|
||||
|
||||
Visit us on the web at: https://www.zerotier.com/
|
||||
|
||||
Notice
|
||||
|
||||
The Business Source License (this document, or the "License") is not an Open
|
||||
Source license. However, the Licensed Work will eventually be made available
|
||||
under an Open Source License, as stated in this License.
|
||||
|
||||
For more information on the use of the Business Source License for ZeroTier
|
||||
products, please visit our pricing page which contains license details and
|
||||
and license FAQ: https://zerotier.com/pricing
|
||||
|
||||
For more information on the use of the Business Source License generally,
|
||||
please visit the Adopting and Developing Business Source License FAQ at
|
||||
https://mariadb.com/bsl-faq-adopting.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Business Source License 1.1
|
||||
|
||||
Terms
|
||||
|
||||
The Licensor hereby grants you the right to copy, modify, create derivative
|
||||
works, redistribute, and make non-production use of the Licensed Work. The
|
||||
Licensor may make an Additional Use Grant, above, permitting limited
|
||||
production use.
|
||||
|
||||
Effective on the Change Date, or the fourth anniversary of the first publicly
|
||||
available distribution of a specific version of the Licensed Work under this
|
||||
License, whichever comes first, the Licensor hereby grants you rights under
|
||||
the terms of the Change License, and the rights granted in the paragraph
|
||||
above terminate.
|
||||
|
||||
If your use of the Licensed Work does not comply with the requirements
|
||||
currently in effect as described in this License, you must purchase a
|
||||
commercial license from the Licensor, its affiliated entities, or authorized
|
||||
resellers, or you must refrain from using the Licensed Work.
|
||||
|
||||
All copies of the original and modified Licensed Work, and derivative works
|
||||
of the Licensed Work, are subject to this License. This License applies
|
||||
separately for each version of the Licensed Work and the Change Date may vary
|
||||
for each version of the Licensed Work released by Licensor.
|
||||
|
||||
You must conspicuously display this License on each original or modified copy
|
||||
of the Licensed Work. If you receive the Licensed Work in original or
|
||||
modified form from a third party, the terms and conditions set forth in this
|
||||
License apply to your use of that work.
|
||||
|
||||
Any use of the Licensed Work in violation of this License will automatically
|
||||
terminate your rights under this License for the current and all other
|
||||
versions of the Licensed Work.
|
||||
|
||||
This License does not grant you any right in any trademark or logo of
|
||||
Licensor or its affiliates (provided that you may use a trademark or logo of
|
||||
Licensor as expressly required by this License).
|
||||
|
||||
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
||||
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
||||
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
|
||||
TITLE.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
MariaDB hereby grants you permission to use this License’s text to license
|
||||
your works, and to refer to it using the trademark "Business Source License",
|
||||
as long as you comply with the Covenants of Licensor below.
|
||||
|
||||
Covenants of Licensor
|
||||
|
||||
In consideration of the right to use this License’s text and the "Business
|
||||
Source License" name and trademark, Licensor covenants to MariaDB, and to all
|
||||
other recipients of the licensed work to be provided by Licensor:
|
||||
|
||||
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
||||
or a license that is compatible with GPL Version 2.0 or a later version,
|
||||
where "compatible" means that software provided under the Change License can
|
||||
be included in a program with software provided under GPL Version 2.0 or a
|
||||
later version. Licensor may specify additional Change Licenses without
|
||||
limitation.
|
||||
|
||||
2. To either: (a) specify an additional grant of rights to use that does not
|
||||
impose any additional restriction on the right granted in this License, as
|
||||
the Additional Use Grant; or (b) insert the text "None".
|
||||
|
||||
3. To specify a Change Date.
|
||||
|
||||
4. Not to modify this License in any other way.
|
24
pkg/asustor/zerotier/CONTROL/post-install.sh
Executable file
24
pkg/asustor/zerotier/CONTROL/post-install.sh
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
APKG_PKG_DIR=/usr/local/AppCentral/zerotier
|
||||
|
||||
case "$APKG_PKG_STATUS" in
|
||||
|
||||
install)
|
||||
modprobe tun
|
||||
mkdir -p /usr/local/bin
|
||||
mv ${APKG_PKG_DIR}/bin/zerotier-one.${AS_NAS_ARCH} ${APKG_PKG_DIR}/bin/zerotier-one
|
||||
ln -s ${APKG_PKG_DIR}/bin/zerotier-one /usr/local/bin/zerotier-cli
|
||||
ln -s ${APKG_PKG_DIR}/bin/zerotier-one /usr/local/bin/zerotier-idtool
|
||||
ln -s $APKG_PKG_DIR/data /var/lib/zerotier-one
|
||||
;;
|
||||
upgrade)
|
||||
# post upgrade script here (restore data)
|
||||
# cp -af $APKG_TEMP_DIR/* $APKG_PKG_DIR/etc/.
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
exit 0
|
3
pkg/asustor/zerotier/CONTROL/post-uninstall.sh
Executable file
3
pkg/asustor/zerotier/CONTROL/post-uninstall.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
rm -rf /var/lib/zerotier-one/
|
0
pkg/asustor/zerotier/CONTROL/pre-install.sh
Executable file
0
pkg/asustor/zerotier/CONTROL/pre-install.sh
Executable file
0
pkg/asustor/zerotier/CONTROL/pre-uninstall.sh
Executable file
0
pkg/asustor/zerotier/CONTROL/pre-uninstall.sh
Executable file
26
pkg/asustor/zerotier/CONTROL/start-stop.sh
Executable file
26
pkg/asustor/zerotier/CONTROL/start-stop.sh
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /etc/script/lib/command.sh
|
||||
|
||||
APKG_PKG_DIR=/usr/local/AppCentral/zerotier
|
||||
|
||||
case $1 in
|
||||
|
||||
start)
|
||||
modprobe tun
|
||||
# start script here
|
||||
$APKG_PKG_DIR/bin/zerotier-one $APKG_PKG_DIR/data -d
|
||||
;;
|
||||
|
||||
stop)
|
||||
# stop script here
|
||||
pkill zerotier
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "usage: $0 {start|stop}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
1
pkg/asustor/zerotier/apkg-version
Normal file
1
pkg/asustor/zerotier/apkg-version
Normal file
|
@ -0,0 +1 @@
|
|||
2.0
|
58
pkg/asustor/zerotier/www/index.html
Normal file
58
pkg/asustor/zerotier/www/index.html
Normal file
|
@ -0,0 +1,58 @@
|
|||
<div class="header">
|
||||
<h2 id="zerotier">ZeroTier</h2>
|
||||
</div>
|
||||
|
||||
<p>Welcome! ZeroTier is a peer-to-peer encrypted virtual networking solution that enables you to create Local Area Networks with static IP assignments for all of your devices. Access your NAS from anywhere in the world with a single IP and without the need of cloud services backhauling your traffic. To use the CLI:</p>
|
||||
<h2 id="using-the-cli-via-ssh-">Using the CLI via SSH:</h2>
|
||||
<ol>
|
||||
<li><p>Using your (admin) account, enable SSH:</p>
|
||||
<ul>
|
||||
<li><strong><code>Services</code></strong> -> <strong><code>Terminal</code></strong> -> <strong><code>Enable SSH</code></strong> (set to port <code>22</code>)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>From a computer, open a terminal and SSH into your NAS device:</p>
|
||||
<ul>
|
||||
<li><strong><code>ssh admin@your_nas_device_lan_ip</code></strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>Create account and network ID at <a href="https://my.zerotier.com">my.zerotier.com</a></p>
|
||||
<ul>
|
||||
<li><em>Note: This account is merely to administer your network. Your traffic is not handled by ZeroTier except in the case where a direct connection cannot be established. This is a courtesy service we offer for free that you can disable if you'd like. In any case, your traffic is <a href="https://www.zerotier.com/manual/#2_1_3">fully encrypted</a> end-to-end.</em></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>Join your device to the network:</p>
|
||||
<ul>
|
||||
<li><strong><code>zerotier-cli join your_network_id</code></strong></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><p>Use <a href="https://my.zerotier.com">my.zerotier.com</a> to authorize your NAS device to join your network.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h2 id="help-and-support-in-order-of-relevance-">Help and support (in order of relevance)</h2>
|
||||
<ul>
|
||||
<li>Github Repository: <a href="https://github.com/zerotier/ZeroTierNAS/issues">https://github.com/zerotier/ZeroTierNAS</a></li>
|
||||
<li>Forums: <a href="https://discuss.zerotier.com">https://discuss.zerotier.com</a></li>
|
||||
<li>Contact: <a href="mailto:support@zerotier.com">support@zerotier.com</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="footer">
|
||||
<h2 id="zerotier"><h2>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
padding: 1px;
|
||||
text-align: center;
|
||||
background: #F2B464;
|
||||
color: black;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 1px;
|
||||
text-align: center;
|
||||
background: #F2B464;
|
||||
color: black;
|
||||
font-size: 30px;
|
||||
}
|
||||
</style>
|
6
pkg/config.json
Normal file
6
pkg/config.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"version": "1.8.7",
|
||||
"rev": "1",
|
||||
"desc": "Securely connect any device, anywhere.",
|
||||
"email": "support@zerotier.com"
|
||||
}
|
8
pkg/qnap/Dockerfile
Normal file
8
pkg/qnap/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
|||
# vim: ft=dockerfile
|
||||
|
||||
FROM ubuntu:20.04
|
||||
|
||||
# COPY zerotier/qbuild /qbuild
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
13
pkg/qnap/build.sh
Executable file
13
pkg/qnap/build.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
build_packages()
|
||||
{
|
||||
sudo docker run -v $(pwd):/zto ztqnap
|
||||
}
|
||||
|
||||
build_container()
|
||||
{
|
||||
sudo docker build -t ztqnap . --load
|
||||
}
|
||||
|
||||
"$@"
|
76
pkg/qnap/entrypoint.sh
Executable file
76
pkg/qnap/entrypoint.sh
Executable file
|
@ -0,0 +1,76 @@
|
|||
#!/bin/bash
|
||||
|
||||
ZTO_VER=$(git describe --abbrev=0 --tags)
|
||||
ZTO_COMMIT=$(git rev-parse HEAD)
|
||||
ZTO_DESC=$(jq -r '.desc' ../config.json)
|
||||
|
||||
mkdir -p pkg/qnap/zerotier/arm_64
|
||||
mkdir -p pkg/qnap/zerotier/arm_x09
|
||||
mkdir -p pkg/qnap/zerotier/arm_x10
|
||||
mkdir -p pkg/qnap/zerotier/arm_x12
|
||||
mkdir -p pkg/qnap/zerotier/arm_x19
|
||||
mkdir -p pkg/qnap/zerotier/arm_x31
|
||||
mkdir -p pkg/qnap/zerotier/arm_x41
|
||||
mkdir -p pkg/qnap/zerotier/x86_64
|
||||
mkdir -p pkg/qnap/zerotier/x86
|
||||
mkdir -p pkg/qnap/zerotier/x86_ce53xx
|
||||
|
||||
cat > pkg/qnap/zerotier/qpkg.cfg <<- EOM
|
||||
# Update package config
|
||||
# Name of the packaged application.
|
||||
QPKG_NAME="zerotier"
|
||||
# Name of the display application.
|
||||
QPKG_DISPLAY_NAME="ZeroTier"
|
||||
# Version of the packaged application.
|
||||
QPKG_VER="$ZTO_VER"
|
||||
# Author or maintainer of the package
|
||||
QPKG_AUTHOR="ZeroTier, Inc."
|
||||
# License for the packaged application
|
||||
QPKG_LICENSE="BUSL-1.1"
|
||||
# One-line description of the packaged application
|
||||
QPKG_SUMMARY="$ZTO_DESC"
|
||||
|
||||
# Preferred number in start/stop sequence.
|
||||
QPKG_RC_NUM="101"
|
||||
# Init-script used to control the start and stop of the installed application.
|
||||
QPKG_SERVICE_PROGRAM="zerotier.sh"
|
||||
|
||||
# Specifies any packages required for the current package to operate.
|
||||
QPKG_REQUIRE="QVPN Service"
|
||||
# Specifies what packages cannot be installed if the current package
|
||||
# is to operate properly.
|
||||
#QPKG_CONFLICT="Python, OPT/sed"
|
||||
# Name of configuration file (multiple definitions are allowed).
|
||||
#QPKG_CONFIG="myApp.conf"
|
||||
#QPKG_CONFIG="/etc/config/myApp.conf"
|
||||
# Port number used by service program.
|
||||
QPKG_SERVICE_PORT="9993"
|
||||
|
||||
# Minimum QTS version requirement
|
||||
QTS_MINI_VERSION="4.1.0"
|
||||
# Maximum QTS version requirement
|
||||
QTS_MAX_VERSION="5.0.0"
|
||||
|
||||
# Location of icons for the packaged application.
|
||||
QDK_DATA_DIR_ICONS="icons"
|
||||
EOM
|
||||
|
||||
# Copy binaries into pkg directory
|
||||
# See: https://github.com/qnap-dev/QDK
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-aarch64 pkg/qnap/zerotier/arm_64/zerotier-one
|
||||
#cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-armv5tejl pkg/qnap/zerotier/arm-x09/zerotier-one
|
||||
#cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-armv5tel pkg/qnap/zerotier/arm-x19/zerotier-one
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-armhf pkg/qnap/zerotier/arm-x31/zerotier-one
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-armhf pkg/qnap/zerotier/arm-x41/zerotier-one
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-i386 pkg/qnap/zerotier/x86/zerotier-one
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-x86_64 pkg/qnap/zerotier/x86_64/zerotier-one
|
||||
cp -vf output/static/zerotier-one.${ZTO_VER}.alpine-i386 pkg/qnap/zerotier/x86_ce53xx/zerotier-one
|
||||
|
||||
rm -rf output/qnap/*
|
||||
|
||||
pushd pkg/qnap/zerotier
|
||||
./qbuild #--build-arch arm-x31
|
||||
cp -f build/* ../../../output/qnap
|
||||
|
||||
# Show output product
|
||||
cd popd
|
3
pkg/qnap/qdk.conf
Normal file
3
pkg/qnap/qdk.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
QDK_VERSION=2.3.11
|
||||
QDK_PATH_P=`pwd | awk 'BEGIN { FS = "QDK" } ; { print $1 }'`
|
||||
QDK_PATH="${QDK_PATH_P}/QDK"
|
7
pkg/qnap/zerotier/Makefile
Normal file
7
pkg/qnap/zerotier/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
.PHONY: all
|
||||
|
||||
all:
|
||||
@$(CC) -o qpkg_encrypt qpkg_encrypt.c
|
||||
|
||||
clean:
|
||||
rm -rf /bin/qpkg_encrypt
|
0
pkg/qnap/zerotier/arm_64/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_64/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x09/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x09/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x10/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x10/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x12/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x12/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x19/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x19/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x31/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x31/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x41/.gitkeep
Normal file
0
pkg/qnap/zerotier/arm_x41/.gitkeep
Normal file
0
pkg/qnap/zerotier/config/.gitkeep
Normal file
0
pkg/qnap/zerotier/config/.gitkeep
Normal file
0
pkg/qnap/zerotier/icons/.gitkeep
Normal file
0
pkg/qnap/zerotier/icons/.gitkeep
Normal file
BIN
pkg/qnap/zerotier/icons/ZeroTier.gif
Normal file
BIN
pkg/qnap/zerotier/icons/ZeroTier.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 2.7 KiB |
BIN
pkg/qnap/zerotier/icons/ZeroTier_80.gif
Normal file
BIN
pkg/qnap/zerotier/icons/ZeroTier_80.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 2.7 KiB |
BIN
pkg/qnap/zerotier/icons/ZeroTier_gray.gif
Normal file
BIN
pkg/qnap/zerotier/icons/ZeroTier_gray.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.9 KiB |
158
pkg/qnap/zerotier/package_routines
Normal file
158
pkg/qnap/zerotier/package_routines
Normal file
|
@ -0,0 +1,158 @@
|
|||
######################################################################
|
||||
# List of available definitions (it's not necessary to uncomment them)
|
||||
######################################################################
|
||||
###### Command definitions #####
|
||||
#CMD_AWK="/bin/awk"
|
||||
#CMD_CAT="/bin/cat"
|
||||
#CMD_CHMOD="/bin/chmod"
|
||||
#CMD_CHOWN="/bin/chown"
|
||||
#CMD_CP="/bin/cp"
|
||||
#CMD_CUT="/bin/cut"
|
||||
#CMD_DATE="/bin/date"
|
||||
#CMD_ECHO="/bin/echo"
|
||||
#CMD_EXPR="/usr/bin/expr"
|
||||
#CMD_FIND="/usr/bin/find"
|
||||
#CMD_GETCFG="/sbin/getcfg"
|
||||
#CMD_GREP="/bin/grep"
|
||||
#CMD_GZIP="/bin/gzip"
|
||||
#CMD_HOSTNAME="/bin/hostname"
|
||||
#CMD_LN="/bin/ln"
|
||||
#CMD_LOG_TOOL="/sbin/log_tool"
|
||||
#CMD_MD5SUM="/bin/md5sum"
|
||||
#CMD_MKDIR="/bin/mkdir"
|
||||
#CMD_MV="/bin/mv"
|
||||
#CMD_RM="/bin/rm"
|
||||
#CMD_RMDIR="/bin/rmdir"
|
||||
#CMD_SED="/bin/sed"
|
||||
#CMD_SETCFG="/sbin/setcfg"
|
||||
#CMD_SLEEP="/bin/sleep"
|
||||
#CMD_SORT="/usr/bin/sort"
|
||||
#CMD_SYNC="/bin/sync"
|
||||
#CMD_TAR="/bin/tar"
|
||||
#CMD_TOUCH="/bin/touch"
|
||||
#CMD_WGET="/usr/bin/wget"
|
||||
#CMD_WLOG="/sbin/write_log"
|
||||
#CMD_XARGS="/usr/bin/xargs"
|
||||
#CMD_7Z="/usr/local/sbin/7z"
|
||||
#
|
||||
###### System definitions #####
|
||||
#SYS_EXTRACT_DIR="$(pwd)"
|
||||
#SYS_CONFIG_DIR="/etc/config"
|
||||
#SYS_INIT_DIR="/etc/init.d"
|
||||
#SYS_STARTUP_DIR="/etc/rcS.d"
|
||||
#SYS_SHUTDOWN_DIR="/etc/rcK.d"
|
||||
#SYS_RSS_IMG_DIR="/home/httpd/RSS/images"
|
||||
#SYS_QPKG_DATA_FILE_GZIP="./data.tar.gz"
|
||||
#SYS_QPKG_DATA_FILE_BZIP2="./data.tar.bz2"
|
||||
#SYS_QPKG_DATA_FILE_7ZIP="./data.tar.7z"
|
||||
#SYS_QPKG_DATA_CONFIG_FILE="./conf.tar.gz"
|
||||
#SYS_QPKG_DATA_MD5SUM_FILE="./md5sum"
|
||||
#SYS_QPKG_DATA_PACKAGES_FILE="./Packages.gz"
|
||||
#SYS_QPKG_CONFIG_FILE="$SYS_CONFIG_DIR/qpkg.conf"
|
||||
#SYS_QPKG_CONF_FIELD_QPKGFILE="QPKG_File"
|
||||
#SYS_QPKG_CONF_FIELD_NAME="Name"
|
||||
#SYS_QPKG_CONF_FIELD_VERSION="Version"
|
||||
#SYS_QPKG_CONF_FIELD_ENABLE="Enable"
|
||||
#SYS_QPKG_CONF_FIELD_DATE="Date"
|
||||
#SYS_QPKG_CONF_FIELD_SHELL="Shell"
|
||||
#SYS_QPKG_CONF_FIELD_INSTALL_PATH="Install_Path"
|
||||
#SYS_QPKG_CONF_FIELD_CONFIG_PATH="Config_Path"
|
||||
#SYS_QPKG_CONF_FIELD_WEBUI="WebUI"
|
||||
#SYS_QPKG_CONF_FIELD_WEBPORT="Web_Port"
|
||||
#SYS_QPKG_CONF_FIELD_SERVICEPORT="Service_Port"
|
||||
#SYS_QPKG_CONF_FIELD_SERVICE_PIDFILE="Pid_File"
|
||||
#SYS_QPKG_CONF_FIELD_AUTHOR="Author"
|
||||
#SYS_QPKG_CONF_FIELD_RC_NUMBER="RC_Number"
|
||||
## The following variables are assigned values at run-time.
|
||||
#SYS_HOSTNAME=$($CMD_HOSTNAME)
|
||||
## Data file name (one of SYS_QPKG_DATA_FILE_GZIP, SYS_QPKG_DATA_FILE_BZIP2,
|
||||
## or SYS_QPKG_DATA_FILE_7ZIP)
|
||||
#SYS_QPKG_DATA_FILE=
|
||||
## Base location.
|
||||
#SYS_QPKG_BASE=""
|
||||
## Base location of QPKG installed packages.
|
||||
#SYS_QPKG_INSTALL_PATH=""
|
||||
## Location of installed software.
|
||||
#SYS_QPKG_DIR=""
|
||||
## If the QPKG should be enabled or disabled after the installation/upgrade.
|
||||
#SYS_QPKG_SERVICE_ENABLED=""
|
||||
## Architecture of the device the QPKG is installed on.
|
||||
#SYS_CPU_ARCH=""
|
||||
## Name and location of system shares
|
||||
#SYS_PUBLIC_SHARE=""
|
||||
#SYS_PUBLIC_PATH=""
|
||||
#SYS_DOWNLOAD_SHARE=""
|
||||
#SYS_DOWNLOAD_PATH=""
|
||||
#SYS_MULTIMEDIA_SHARE=""
|
||||
#SYS_MULTIMEDIA_PATH=""
|
||||
#SYS_RECORDINGS_SHARE=""
|
||||
#SYS_RECORDINGS_PATH=""
|
||||
#SYS_USB_SHARE=""
|
||||
#SYS_USB_PATH=""
|
||||
#SYS_WEB_SHARE=""
|
||||
#SYS_WEB_PATH=""
|
||||
## Path to ipkg or opkg package tool if installed.
|
||||
#CMD_PKG_TOOL=
|
||||
#
|
||||
|
||||
######################################################################
|
||||
# All package specific functions shall call 'err_log MSG' if an error
|
||||
# is detected that shall terminate the installation.
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
# Define any package specific operations that shall be performed when
|
||||
# the package is removed.
|
||||
######################################################################
|
||||
|
||||
#PKG_PRE_REMOVE="{
|
||||
#}"
|
||||
|
||||
PKG_MAIN_REMOVE="{
|
||||
rm -rf /usr/sbin/zerotier-cli
|
||||
# all identity files are stored in the Install_Path and will be removed automatically
|
||||
}"
|
||||
|
||||
#PKG_POST_REMOVE="{
|
||||
#}"
|
||||
|
||||
######################################################################
|
||||
# Define any package specific initialization that shall be performed
|
||||
# before the package is installed.
|
||||
######################################################################
|
||||
|
||||
pkg_init()
|
||||
{
|
||||
modprobe tun
|
||||
}
|
||||
|
||||
|
||||
######################################################################
|
||||
# Define any package specific requirement checks that shall be
|
||||
# performed before the package is installed.
|
||||
######################################################################
|
||||
|
||||
#pkg_check_requirement()
|
||||
#{
|
||||
#}
|
||||
|
||||
######################################################################
|
||||
# Define any package specific operations that shall be performed when
|
||||
# the package is installed.
|
||||
######################################################################
|
||||
|
||||
#pkg_pre_install()
|
||||
#{
|
||||
# log "pkg_pre_install"
|
||||
#}
|
||||
|
||||
#pkg_install()
|
||||
#{
|
||||
# log "pkg_install"
|
||||
#}
|
||||
|
||||
pkg_post_install()
|
||||
{
|
||||
log $SYS_QPKG_INSTALL_PATH
|
||||
modprobe tun
|
||||
}
|
99
pkg/qnap/zerotier/qpkg.cfg
Normal file
99
pkg/qnap/zerotier/qpkg.cfg
Normal file
|
@ -0,0 +1,99 @@
|
|||
# Update package config
|
||||
# Name of the packaged application.
|
||||
QPKG_NAME="zerotier"
|
||||
# Name of the display application.
|
||||
QPKG_DISPLAY_NAME="ZeroTier"
|
||||
# Version of the packaged application.
|
||||
QPKG_VER="1.8.4"
|
||||
# Author or maintainer of the package
|
||||
QPKG_AUTHOR="ZeroTier, Inc."
|
||||
# License for the packaged application
|
||||
QPKG_LICENSE="BUSL-1.1"
|
||||
# One-line description of the packaged application
|
||||
QPKG_SUMMARY="Securely connect any device, anywhere."
|
||||
|
||||
# Preferred number in start/stop sequence.
|
||||
QPKG_RC_NUM="101"
|
||||
# Init-script used to control the start and stop of the installed application.
|
||||
QPKG_SERVICE_PROGRAM="zerotier.sh"
|
||||
|
||||
# Specifies any packages required for the current package to operate.
|
||||
QPKG_REQUIRE="QVPN Service"
|
||||
# Specifies what packages cannot be installed if the current package
|
||||
# is to operate properly.
|
||||
#QPKG_CONFLICT="Python, OPT/sed"
|
||||
# Name of configuration file (multiple definitions are allowed).
|
||||
#QPKG_CONFIG="myApp.conf"
|
||||
#QPKG_CONFIG="/etc/config/myApp.conf"
|
||||
# Port number used by service program.
|
||||
QPKG_SERVICE_PORT="9993"
|
||||
# Location of file with running service's PID
|
||||
#QPKG_SERVICE_PIDFILE="/var/lib/zerotier-one/zerotier-one.pid"
|
||||
# Relative path to web interface
|
||||
#QPKG_WEBUI=""
|
||||
# Port number for the web interface.
|
||||
#QPKG_WEB_PORT=""
|
||||
# Port number for the SSL web interface.
|
||||
#QPKG_WEB_SSL_PORT=""
|
||||
|
||||
# Use QTS HTTP Proxy and set Proxy_Path in the qpkg.conf.
|
||||
# When the QPKG has its own HTTP service port, and want clients to connect via QTS HTTP port (default 8080).
|
||||
# Usually use this option when the QPKG need to connect via myQNAPcloud service.
|
||||
#QPKG_USE_PROXY="1"
|
||||
#QPKG_PROXY_PATH="/qpkg_name"
|
||||
|
||||
#Desktop Application (since 4.1)
|
||||
# Set value to 1 means to open the QPKG's Web UI inside QTS desktop instead of new window.
|
||||
#QPKG_DESKTOP_APP="1"
|
||||
# Desktop Application Window default inner width (since 4.1) (not over 1178)
|
||||
#QPKG_DESKTOP_APP_WIN_WIDTH=""
|
||||
# Desktop Application Window default inner width (since 4.1) (not over 600)
|
||||
#QPKG_DESKTOP_APP_WIN_HEIGHT=""
|
||||
|
||||
# Minimum QTS version requirement
|
||||
QTS_MINI_VERSION="4.1.0"
|
||||
# Maximum QTS version requirement
|
||||
QTS_MAX_VERSION="5.0.0"
|
||||
|
||||
# Select volume
|
||||
# 1: support installation
|
||||
# 2: support migration
|
||||
# 3 (1+2): support both installation and migration
|
||||
#QPKG_VOLUME_SELECT="0"
|
||||
|
||||
# Set timeout for QPKG enable and QPKG disable (since 4.1.0)
|
||||
# Format in seconds (enable, disable)
|
||||
#QPKG_TIMEOUT="10,30"
|
||||
|
||||
# Visible setting for the QPKG that has web UI, show this QPKG on the Main menu of
|
||||
# 1(default): administrators, 2: all NAS users.
|
||||
#QPKG_VISIBLE="2"
|
||||
|
||||
# Location of the chroot environment (only TS-x09)
|
||||
#QPKG_ROOTFS=""
|
||||
# Init-script used to controls the start and stop of the
|
||||
# installed application (only TS-x09)
|
||||
#QPKG_SERVICE_PROGRAM_CHROOT=""
|
||||
|
||||
# Location of icons for the packaged application.
|
||||
QDK_DATA_DIR_ICONS="icons"
|
||||
# Location of files specific to arm-x09 packages.
|
||||
#QDK_DATA_DIR_X09="arm-x09"
|
||||
# Location of files specific to arm-x19 packages.
|
||||
#QDK_DATA_DIR_X19="arm-x19"
|
||||
# Location of files specific to arm-x31 packages.
|
||||
#QDK_DATA_DIR_X31="arm-x31"
|
||||
# Location of files specific to arm-x41 packages.
|
||||
#QDK_DATA_DIR_X41="arm_al"
|
||||
# Location of files specific to x86 packages.
|
||||
#QDK_DATA_DIR_X86="x86"
|
||||
# Location of files specific to x86 (64-bit) packages.
|
||||
#QDK_DATA_DIR_X86_64="x86_64"
|
||||
# Location of files common to all architectures.
|
||||
#QDK_DATA_DIR_SHARED="shared"
|
||||
# Location of configuration files.
|
||||
#QDK_DATA_DIR_CONFIG="config"
|
||||
# Name of local data package.
|
||||
#QDK_DATA_FILE=""
|
||||
# Name of extra package (multiple definitions are allowed).
|
||||
#QDK_EXTRA_FILE=""
|
0
pkg/qnap/zerotier/shared/.gitkeep
Normal file
0
pkg/qnap/zerotier/shared/.gitkeep
Normal file
BIN
pkg/qnap/zerotier/shared/.qpkg_icon.gif
Normal file
BIN
pkg/qnap/zerotier/shared/.qpkg_icon.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.8 KiB |
BIN
pkg/qnap/zerotier/shared/.qpkg_icon_80.gif
Normal file
BIN
pkg/qnap/zerotier/shared/.qpkg_icon_80.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 1.8 KiB |
BIN
pkg/qnap/zerotier/shared/.qpkg_icon_gray.gif
Normal file
BIN
pkg/qnap/zerotier/shared/.qpkg_icon_gray.gif
Normal file
Binary file not shown.
After ![]() (image error) Size: 2.3 KiB |
34
pkg/qnap/zerotier/shared/zerotier.sh
Executable file
34
pkg/qnap/zerotier/shared/zerotier.sh
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
CONF=/etc/config/qpkg.conf
|
||||
QPKG_NAME="zerotier"
|
||||
QPKG_ROOT=`/sbin/getcfg $QPKG_NAME Install_Path -f ${CONF}`
|
||||
APACHE_ROOT=/share/`/sbin/getcfg SHARE_DEF defWeb -d Qweb -f /etc/config/def_share.info`
|
||||
case "$1" in
|
||||
start)
|
||||
modprobe tun
|
||||
ln -s $QPKG_ROOT/zerotier-one /usr/sbin/zerotier-cli
|
||||
ln -s $QPKG_ROOT/zerotier-one /usr/bin/zerotier-cli
|
||||
ln -s $QPKG_ROOT /var/lib/zerotier-one
|
||||
ENABLED=$(/sbin/getcfg $QPKG_NAME Enable -u -d FALSE -f $CONF)
|
||||
if [ "$ENABLED" != "TRUE" ]; then
|
||||
echo "$QPKG_NAME is disabled."
|
||||
exit 1
|
||||
fi
|
||||
$QPKG_ROOT/zerotier-one $QPKG_ROOT -d
|
||||
;;
|
||||
|
||||
stop)
|
||||
killall zerotier-one
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue