refactoring, more config, packaging
This commit is contained in:
parent
444f65d76d
commit
ef1f5d7b52
95
Cargo.lock
generated
95
Cargo.lock
generated
@ -1259,6 +1259,7 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer 0.10.2",
|
"block-buffer 0.10.2",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1308,7 +1309,7 @@ dependencies = [
|
|||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"sha2",
|
"sha2 0.9.9",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1813,7 +1814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest 0.9.0",
|
"digest 0.9.0",
|
||||||
"hmac",
|
"hmac 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1826,6 +1827,15 @@ dependencies = [
|
|||||||
"digest 0.9.0",
|
"digest 0.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest 0.10.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
@ -2046,7 +2056,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"ndk",
|
"ndk",
|
||||||
"ndk-glue",
|
"ndk-glue",
|
||||||
"rpassword",
|
"rpassword 5.0.1",
|
||||||
"secret-service",
|
"secret-service",
|
||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
@ -2167,6 +2177,24 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libsystemd"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8144587c71c16756b1055d3dcb0c75cb605a10ecd6523cc33702d5f90902bf6d"
|
||||||
|
dependencies = [
|
||||||
|
"hmac 0.12.1",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"nix 0.23.1",
|
||||||
|
"nom 7.1.0",
|
||||||
|
"once_cell",
|
||||||
|
"serde 1.0.136",
|
||||||
|
"sha2 0.10.2",
|
||||||
|
"thiserror",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -3280,6 +3308,18 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rpassword"
|
||||||
|
version = "6.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"serde 1.0.136",
|
||||||
|
"serde_json",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtnetlink"
|
name = "rtnetlink"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -3451,7 +3491,7 @@ dependencies = [
|
|||||||
"num 0.3.1",
|
"num 0.3.1",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde 1.0.136",
|
"serde 1.0.136",
|
||||||
"sha2",
|
"sha2 0.9.9",
|
||||||
"zbus",
|
"zbus",
|
||||||
"zbus_macros",
|
"zbus_macros",
|
||||||
"zvariant",
|
"zvariant",
|
||||||
@ -3699,6 +3739,17 @@ dependencies = [
|
|||||||
"opaque-debug 0.3.0",
|
"opaque-debug 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures 0.2.1",
|
||||||
|
"digest 0.10.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
@ -3709,6 +3760,18 @@ dependencies = [
|
|||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-async-std"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4aa94397e2023af5b7cff5b8d4785e935cfb77f0e4aab0cae3b26258ace556"
|
||||||
|
dependencies = [
|
||||||
|
"async-io",
|
||||||
|
"futures-lite",
|
||||||
|
"libc",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-mio"
|
name = "signal-hook-mio"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -3861,6 +3924,16 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "systemd-journal-logger"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2b2b2ff370208ad472629786a66dc252933843755a1d620a54a8fdd0fccb31f"
|
||||||
|
dependencies = [
|
||||||
|
"libsystemd",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tap"
|
name = "tap"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -4124,6 +4197,15 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
|
dependencies = [
|
||||||
|
"serde 1.0.136",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "value-bag"
|
name = "value-bag"
|
||||||
version = "1.0.0-alpha.8"
|
version = "1.0.0-alpha.8"
|
||||||
@ -4294,12 +4376,17 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
|
"nix 0.23.1",
|
||||||
"parking_lot 0.12.0",
|
"parking_lot 0.12.0",
|
||||||
|
"rpassword 6.0.1",
|
||||||
"serde 1.0.136",
|
"serde 1.0.136",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"serial_test 0.6.0",
|
"serial_test 0.6.0",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-async-std",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
|
"systemd-journal-logger",
|
||||||
"url",
|
"url",
|
||||||
"veilid-core",
|
"veilid-core",
|
||||||
"windows-service",
|
"windows-service",
|
||||||
|
35
Earthfile
35
Earthfile
@ -72,7 +72,7 @@ deps:
|
|||||||
|
|
||||||
code:
|
code:
|
||||||
FROM +deps
|
FROM +deps
|
||||||
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-wasm Cargo.lock Cargo.toml /veilid
|
COPY --dir .cargo external files scripts veilid-cli veilid-core veilid-server veilid-flutter veilid-wasm Cargo.lock Cargo.toml /veilid
|
||||||
WORKDIR /veilid
|
WORKDIR /veilid
|
||||||
|
|
||||||
# Clippy only
|
# Clippy only
|
||||||
@ -113,3 +113,36 @@ unit-tests-linux-amd64:
|
|||||||
unit-tests-linux-arm64:
|
unit-tests-linux-arm64:
|
||||||
FROM +code
|
FROM +code
|
||||||
RUN cargo test --target aarch64-unknown-linux-gnu --release
|
RUN cargo test --target aarch64-unknown-linux-gnu --release
|
||||||
|
|
||||||
|
# Package
|
||||||
|
package-linux-amd64:
|
||||||
|
FROM +build-linux-amd64
|
||||||
|
#################################
|
||||||
|
### DEBIAN DPKG .DEB FILES
|
||||||
|
#################################
|
||||||
|
COPY --dir package /veilid
|
||||||
|
# veilid-server
|
||||||
|
RUN /veilid/package/debian/earthly_make_veilid_server_deb.sh amd64 x86_64-unknown-linux-gnu
|
||||||
|
SAVE ARTIFACT --keep-ts /dpkg/out/*.deb AS LOCAL ./target/packages/
|
||||||
|
# veilid-cli
|
||||||
|
RUN /veilid/package/debian/earthly_make_veilid_cli_deb.sh amd64 x86_64-unknown-linux-gnu
|
||||||
|
# save artifacts
|
||||||
|
SAVE ARTIFACT --keep-ts /dpkg/out/*.deb AS LOCAL ./target/packages/
|
||||||
|
|
||||||
|
package-linux-arm64:
|
||||||
|
FROM +build-linux-arm64
|
||||||
|
#################################
|
||||||
|
### DEBIAN DPKG .DEB FILES
|
||||||
|
#################################
|
||||||
|
COPY --dir package /veilid
|
||||||
|
# veilid-server
|
||||||
|
RUN /veilid/package/debian/earthly_make_veilid_server_deb.sh arm64 aarch64-unknown-linux-gnu
|
||||||
|
SAVE ARTIFACT --keep-ts /dpkg/out/*.deb AS LOCAL ./target/packages/
|
||||||
|
# veilid-cli
|
||||||
|
RUN /veilid/package/debian/earthly_make_veilid_cli_deb.sh arm64 aarch64-unknown-linux-gnu
|
||||||
|
# save artifacts
|
||||||
|
SAVE ARTIFACT --keep-ts /dpkg/out/*.deb AS LOCAL ./target/packages/
|
||||||
|
|
||||||
|
package-linux:
|
||||||
|
BUILD +package-linux-amd64
|
||||||
|
BUILD +package-linux-arm64
|
4
package/cargo_version.sh
Executable file
4
package/cargo_version.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
INPUTFILE=$1
|
||||||
|
cat $1 | grep version | head -n 1 | cut -d\" -f 2
|
19
package/debian/earthly_make_veilid_cli_deb.sh
Executable file
19
package/debian/earthly_make_veilid_cli_deb.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ARCH=$1
|
||||||
|
CARGO_ARCH=$2
|
||||||
|
CARGO_VERSION="$(/veilid/package/cargo_version.sh /veilid/veilid-cli/Cargo.toml)"
|
||||||
|
rm -rf /dpkg
|
||||||
|
mkdir -p /dpkg/out
|
||||||
|
|
||||||
|
# veilid-cli dpkg control
|
||||||
|
cp -rf /veilid/package/debian/veilid-cli /dpkg
|
||||||
|
/veilid/package/replace_variable.sh /dpkg/veilid-cli/DEBIAN/control CARGO_VERSION $CARGO_VERSION
|
||||||
|
/veilid/package/replace_variable.sh /dpkg/veilid-cli/DEBIAN/control ARCH $ARCH
|
||||||
|
# veilid-cli executable
|
||||||
|
mkdir -p /dpkg/veilid-cli/usr/bin
|
||||||
|
cp -f /veilid/target/$CARGO_ARCH/release/veilid-cli /dpkg/veilid-cli/usr/bin
|
||||||
|
# pack it up
|
||||||
|
dpkg-deb -b /dpkg/veilid-cli/
|
||||||
|
mv /dpkg/veilid-cli.deb /dpkg/out/veilid-cli-$CARGO_VERSION-$ARCH.deb
|
25
package/debian/earthly_make_veilid_server_deb.sh
Executable file
25
package/debian/earthly_make_veilid_server_deb.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ARCH=$1
|
||||||
|
CARGO_ARCH=$2
|
||||||
|
CARGO_VERSION="$(/veilid/package/cargo_version.sh /veilid/veilid-server/Cargo.toml)"
|
||||||
|
rm -rf /dpkg
|
||||||
|
mkdir -p /dpkg/out
|
||||||
|
|
||||||
|
# veilid-server dpkg control
|
||||||
|
cp -rf /veilid/package/debian/veilid-server /dpkg
|
||||||
|
/veilid/package/replace_variable.sh /dpkg/veilid-server/DEBIAN/control CARGO_VERSION $CARGO_VERSION
|
||||||
|
/veilid/package/replace_variable.sh /dpkg/veilid-server/DEBIAN/control ARCH $ARCH
|
||||||
|
# veilid-server configuration
|
||||||
|
mkdir -p /dpkg/veilid-server/etc/veilid-server
|
||||||
|
cp -f /veilid/package/linux/veilid-server.conf /dpkg/veilid-server/etc/veilid-server/veilid-server.conf
|
||||||
|
# veilid-server systemd unit file
|
||||||
|
mkdir -p /dpkg/veilid-server/etc/systemd/system
|
||||||
|
cp -f /veilid/package/systemd/veilid-server.service /dpkg/veilid-server/etc/systemd/system
|
||||||
|
# veilid-server executable
|
||||||
|
mkdir -p /dpkg/veilid-server/usr/bin
|
||||||
|
cp -f /veilid/target/$CARGO_ARCH/release/veilid-server /dpkg/veilid-server/usr/bin
|
||||||
|
# pack it up
|
||||||
|
dpkg-deb -b /dpkg/veilid-server/
|
||||||
|
mv /dpkg/veilid-server.deb /dpkg/out/veilid-server-$CARGO_VERSION-$ARCH.deb
|
10
package/debian/veilid-cli/DEBIAN/control
Normal file
10
package/debian/veilid-cli/DEBIAN/control
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Package: veilid-cli
|
||||||
|
Version: $CARGO_VERSION
|
||||||
|
Section: network
|
||||||
|
Priority: optional
|
||||||
|
Architecture: $ARCH
|
||||||
|
Depends: libc6 (>= 2.23)
|
||||||
|
Maintainer: jsmith@veilid.org
|
||||||
|
Description: Veilid Server Command Line Interface
|
||||||
|
The Veilid peer-to-peer network server command line interface
|
||||||
|
|
6
package/debian/veilid-cli/DEBIAN/postinst
Executable file
6
package/debian/veilid-cli/DEBIAN/postinst
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chmod 755 /usr/bin/veilid-cli
|
9
package/debian/veilid-server/DEBIAN/control
Normal file
9
package/debian/veilid-server/DEBIAN/control
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Package: veilid-server
|
||||||
|
Version: $CARGO_VERSION
|
||||||
|
Section: network
|
||||||
|
Priority: optional
|
||||||
|
Architecture: $ARCH
|
||||||
|
Depends: libc6 (>= 2.23)
|
||||||
|
Maintainer: jsmith@veilid.org
|
||||||
|
Description: Veilid Server
|
||||||
|
The Veilid peer-to-peer network server
|
47
package/debian/veilid-server/DEBIAN/postinst
Executable file
47
package/debian/veilid-server/DEBIAN/postinst
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Add veilid user and group
|
||||||
|
adduser --system --group veilid &>/dev/null || true
|
||||||
|
|
||||||
|
# Make db folders
|
||||||
|
mkdir -p /var/db/veilid-server/protected_store
|
||||||
|
mkdir -p /var/db/veilid-server/table_store
|
||||||
|
mkdir -p /var/db/veilid-server/block_store
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chown -R veilid:veilid /var/db/veilid-server
|
||||||
|
chmod 0750 /var/db/veilid-server/protected_store
|
||||||
|
chmod 0750 /var/db/veilid-server/table_store
|
||||||
|
chmod 0750 /var/db/veilid-server/block_store
|
||||||
|
chmod 0750 /var/db/veilid-server
|
||||||
|
|
||||||
|
chmod 755 /usr/bin/veilid-server
|
||||||
|
|
||||||
|
# Add and start systemd unit
|
||||||
|
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ] || [ "$1" = "abort-deconfigure" ] || [ "$1" = "abort-remove" ] ; then
|
||||||
|
# This will only remove masks created by d-s-h on package removal.
|
||||||
|
deb-systemd-helper unmask 'veilid-server.service' >/dev/null || true
|
||||||
|
|
||||||
|
# was-enabled defaults to true, so new installations run enable.
|
||||||
|
if deb-systemd-helper --quiet was-enabled 'veilid-server.service'; then
|
||||||
|
# Enables the unit on first installation, creates new
|
||||||
|
# symlinks on upgrades if the unit file has changed.
|
||||||
|
deb-systemd-helper enable 'veilid-server.service' >/dev/null || true
|
||||||
|
else
|
||||||
|
# Update the statefile to add new symlinks (if any), which need to be
|
||||||
|
# cleaned up on purge. Also remove old symlinks.
|
||||||
|
deb-systemd-helper update-state 'veilid-server.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl --system daemon-reload >/dev/null || true
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
_dh_action=restart
|
||||||
|
else
|
||||||
|
_dh_action=start
|
||||||
|
fi
|
||||||
|
deb-systemd-invoke $_dh_action 'veilid-server.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
18
package/debian/veilid-server/DEBIAN/postrm
Executable file
18
package/debian/veilid-server/DEBIAN/postrm
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl --system daemon-reload >/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "remove" ]; then
|
||||||
|
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||||
|
deb-systemd-helper mask 'veilid-server.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
elif [ "$1" = "purge" ]; then
|
||||||
|
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||||
|
deb-systemd-helper purge 'veilid-server.service' >/dev/null || true
|
||||||
|
deb-systemd-helper unmask 'veilid-server.service' >/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -rf /var/db/veilid-server
|
||||||
|
fi
|
6
package/debian/veilid-server/DEBIAN/prerm
Executable file
6
package/debian/veilid-server/DEBIAN/prerm
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
|
||||||
|
deb-systemd-invoke stop 'veilid-server.service' >/dev/null || true
|
||||||
|
fi
|
20
package/linux/veilid-server.conf
Normal file
20
package/linux/veilid-server.conf
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Veilid Server
|
||||||
|
# =============
|
||||||
|
#
|
||||||
|
# Default Server Configuration
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
---
|
||||||
|
daemon:
|
||||||
|
enabled: true
|
||||||
|
pid_file: '/run/veilid-server.pid'
|
||||||
|
working_directory: '/'
|
||||||
|
user: veilid
|
||||||
|
group: veilid
|
||||||
|
logging:
|
||||||
|
system:
|
||||||
|
enabled: true
|
||||||
|
level: info
|
||||||
|
terminal:
|
||||||
|
enabled: false
|
7
package/replace_variable.sh
Executable file
7
package/replace_variable.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
INPUTFILE=$1
|
||||||
|
VARIABLE_NAME=$2
|
||||||
|
VARIABLE_VALUE=$3
|
||||||
|
|
||||||
|
sed -i "s/\$$VARIABLE_NAME/$VARIABLE_VALUE/g" "$INPUTFILE"
|
20
package/systemd/veilid-server.service
Normal file
20
package/systemd/veilid-server.service
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# /etc/systemd/system/veilid-server.service
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=The Veilid peer-to-peer network server
|
||||||
|
Requires=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
PIDFile=/run/veilid-server.pid
|
||||||
|
ExecStartPre=/usr/bin/rm -f /run/veilid-server.pid
|
||||||
|
ExecStart=/usr/bin/veilid-server
|
||||||
|
ExecReload=/bin/kill -s HUP $MAINPID
|
||||||
|
KillSignal=SIGQUIT
|
||||||
|
TimeoutStopSec=5
|
||||||
|
KillMode=mixed
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -146,8 +146,8 @@ def main():
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
sub_args = base_args.copy()
|
sub_args = base_args.copy()
|
||||||
sub_args.append("--subnode_index={}".format(n))
|
sub_args.append("--subnode-index={}".format(n))
|
||||||
sub_args.append("--bootstrap={}".format(main_di))
|
sub_args.append("--bootstrap-nodes={}".format(main_di))
|
||||||
if args.wait_for_debug and (str(n) in args.wait_for_debug):
|
if args.wait_for_debug and (str(n) in args.wait_for_debug):
|
||||||
sub_args.append("--wait-for-debug")
|
sub_args.append("--wait-for-debug")
|
||||||
|
|
||||||
|
@ -88,14 +88,29 @@ impl ClientApiConnection {
|
|||||||
}
|
}
|
||||||
async fn process_veilid_state<'a>(
|
async fn process_veilid_state<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
state: veilid_state::Reader<'a>,
|
veilid_state: veilid_state::Reader<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
|
||||||
// Process attachment state
|
// Process attachment state
|
||||||
let attachment = state.reborrow().get_attachment().map_err(map_to_string)?;
|
let attachment = veilid_state
|
||||||
let state = attachment.get_state().map_err(map_to_string)?;
|
.reborrow()
|
||||||
inner.comproc.update_attachment(state);
|
.get_attachment()
|
||||||
|
.map_err(map_to_string)?;
|
||||||
|
let attachment_state = attachment.get_state().map_err(map_to_string)?;
|
||||||
|
|
||||||
|
let network = veilid_state
|
||||||
|
.reborrow()
|
||||||
|
.get_network()
|
||||||
|
.map_err(map_to_string)?;
|
||||||
|
let started = network.get_started();
|
||||||
|
let bps_down = network.get_bps_down();
|
||||||
|
let bps_up = network.get_bps_up();
|
||||||
|
|
||||||
|
inner.comproc.update_attachment(attachment_state);
|
||||||
|
inner
|
||||||
|
.comproc
|
||||||
|
.update_network_status(started, bps_down, bps_up);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -277,6 +277,12 @@ debug - send a debugging command to the Veilid server
|
|||||||
self.inner_mut().ui.set_attachment_state(state);
|
self.inner_mut().ui.set_attachment_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_network_status(&mut self, started: bool, bps_down: u64, bps_up: u64) {
|
||||||
|
self.inner_mut()
|
||||||
|
.ui
|
||||||
|
.set_network_status(started, bps_down, bps_up);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_log_message(&mut self, message: &str) {
|
pub fn add_log_message(&mut self, message: &str) {
|
||||||
self.inner().ui.add_node_event(message);
|
self.inner().ui.add_node_event(message);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ pub type UICallback = Box<dyn Fn(&mut Cursive) + Send>;
|
|||||||
|
|
||||||
struct UIState {
|
struct UIState {
|
||||||
attachment_state: Dirty<AttachmentState>,
|
attachment_state: Dirty<AttachmentState>,
|
||||||
|
network_started: Dirty<bool>,
|
||||||
|
network_down_up: Dirty<(f32, f32)>,
|
||||||
connection_state: Dirty<ConnectionState>,
|
connection_state: Dirty<ConnectionState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ impl UIState {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
attachment_state: Dirty::new(AttachmentState::Detached),
|
attachment_state: Dirty::new(AttachmentState::Detached),
|
||||||
|
network_started: Dirty::new(false),
|
||||||
|
network_down_up: Dirty::new((0.0, 0.0)),
|
||||||
connection_state: Dirty::new(ConnectionState::Disconnected),
|
connection_state: Dirty::new(ConnectionState::Disconnected),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,6 +225,15 @@ impl UI {
|
|||||||
AttachmentState::Detaching => "Detaching [////]",
|
AttachmentState::Detaching => "Detaching [////]",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn render_network_status(inner: &mut UIInner) -> String {
|
||||||
|
match inner.ui_state.network_started.get() {
|
||||||
|
false => "Down: ----KB/s Up: ----KB/s".to_owned(),
|
||||||
|
true => {
|
||||||
|
let (d, u) = inner.ui_state.network_down_up.get();
|
||||||
|
format!("Down: {:.2}KB/s Up: {:.2}KB/s", d, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fn render_button_attach<'a>(inner: &mut UIInner) -> (&'a str, bool) {
|
fn render_button_attach<'a>(inner: &mut UIInner) -> (&'a str, bool) {
|
||||||
if let ConnectionState::Connected(_, _) = inner.ui_state.connection_state.get() {
|
if let ConnectionState::Connected(_, _) = inner.ui_state.connection_state.get() {
|
||||||
match inner.ui_state.attachment_state.get() {
|
match inner.ui_state.attachment_state.get() {
|
||||||
@ -576,7 +589,7 @@ impl UI {
|
|||||||
status.append_styled("|", ColorStyle::highlight_inactive());
|
status.append_styled("|", ColorStyle::highlight_inactive());
|
||||||
// Add bandwidth status
|
// Add bandwidth status
|
||||||
status.append_styled(
|
status.append_styled(
|
||||||
" Down: 0.0KB/s Up: 0.0KB/s ",
|
format!(" {} ", UI::render_network_status(&mut inner)),
|
||||||
ColorStyle::highlight_inactive(),
|
ColorStyle::highlight_inactive(),
|
||||||
);
|
);
|
||||||
status.append_styled("|", ColorStyle::highlight_inactive());
|
status.append_styled("|", ColorStyle::highlight_inactive());
|
||||||
@ -599,6 +612,12 @@ impl UI {
|
|||||||
refresh_statusbar = true;
|
refresh_statusbar = true;
|
||||||
refresh_button_attach = true;
|
refresh_button_attach = true;
|
||||||
}
|
}
|
||||||
|
if inner.ui_state.network_started.take_dirty() {
|
||||||
|
refresh_statusbar = true;
|
||||||
|
}
|
||||||
|
if inner.ui_state.network_down_up.take_dirty() {
|
||||||
|
refresh_statusbar = true;
|
||||||
|
}
|
||||||
if inner.ui_state.connection_state.take_dirty() {
|
if inner.ui_state.connection_state.take_dirty() {
|
||||||
refresh_statusbar = true;
|
refresh_statusbar = true;
|
||||||
refresh_button_attach = true;
|
refresh_button_attach = true;
|
||||||
@ -757,6 +776,15 @@ impl UI {
|
|||||||
inner.ui_state.attachment_state.set(state);
|
inner.ui_state.attachment_state.set(state);
|
||||||
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
}
|
}
|
||||||
|
pub fn set_network_status(&mut self, started: bool, bps_down: u64, bps_up: u64) {
|
||||||
|
let mut inner = self.inner.borrow_mut();
|
||||||
|
inner.ui_state.network_started.set(started);
|
||||||
|
inner.ui_state.network_down_up.set((
|
||||||
|
((bps_down as f64) / 1000.0f64) as f32,
|
||||||
|
((bps_up as f64) / 1000.0f64) as f32,
|
||||||
|
));
|
||||||
|
let _ = inner.cb_sink.send(Box::new(UI::update_cb));
|
||||||
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
let mut inner = self.inner.borrow_mut();
|
let mut inner = self.inner.borrow_mut();
|
||||||
inner.ui_state.connection_state.set(state);
|
inner.ui_state.connection_state.set(state);
|
||||||
|
@ -136,10 +136,10 @@ impl Log for ApiLogger {
|
|||||||
|
|
||||||
let s = format!("{}{}{}", tgt, loc, record.args());
|
let s = format!("{}{}{}", tgt, loc, record.args());
|
||||||
|
|
||||||
(inner.update_callback)(VeilidUpdate::Log {
|
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
|
||||||
log_level: ll,
|
log_level: ll,
|
||||||
message: s,
|
message: s,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,15 +271,18 @@ impl AttachmentManager {
|
|||||||
let network_manager = {
|
let network_manager = {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.update_callback = Some(update_callback.clone());
|
inner.update_callback = Some(update_callback.clone());
|
||||||
|
let update_callback2 = update_callback.clone();
|
||||||
inner.attachment_machine.set_state_change_callback(Arc::new(
|
inner.attachment_machine.set_state_change_callback(Arc::new(
|
||||||
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
move |_old_state: AttachmentState, new_state: AttachmentState| {
|
||||||
update_callback(VeilidUpdate::Attachment { state: new_state })
|
update_callback2(VeilidUpdate::Attachment(VeilidStateAttachment {
|
||||||
|
state: new_state,
|
||||||
|
}))
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
inner.network_manager.clone()
|
inner.network_manager.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
network_manager.init().await?;
|
network_manager.init(update_callback).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -356,4 +359,10 @@ impl AttachmentManager {
|
|||||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
||||||
attachment_machine.state()
|
attachment_machine.state()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_veilid_state(&self) -> VeilidStateAttachment {
|
||||||
|
VeilidStateAttachment {
|
||||||
|
state: self.get_state(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,14 @@ impl Network {
|
|||||||
.interfaces
|
.interfaces
|
||||||
.best_addresses()
|
.best_addresses()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| SocketAddr::new(*a, from.port()))
|
.filter_map(|a| {
|
||||||
|
// We create sockets that are only ipv6 or ipv6 (not dual, so only translate matching unspecified address)
|
||||||
|
if (a.is_ipv4() && from.is_ipv4()) || (a.is_ipv6() && from.is_ipv6()) {
|
||||||
|
Some(SocketAddr::new(*a, from.port()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,6 +445,7 @@ impl Network {
|
|||||||
log_net!("updating network class");
|
log_net!("updating network class");
|
||||||
|
|
||||||
let protocol_config = self.inner.lock().protocol_config.unwrap_or_default();
|
let protocol_config = self.inner.lock().protocol_config.unwrap_or_default();
|
||||||
|
let old_network_class = self.inner.lock().network_class;
|
||||||
|
|
||||||
let context = DiscoveryContext::new(self.routing_table(), self.clone());
|
let context = DiscoveryContext::new(self.routing_table(), self.clone());
|
||||||
|
|
||||||
@ -470,9 +471,10 @@ impl Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let network_class = context.inner.lock().network_class;
|
let network_class = context.inner.lock().network_class;
|
||||||
self.inner.lock().network_class = network_class;
|
if network_class != old_network_class {
|
||||||
|
self.inner.lock().network_class = network_class;
|
||||||
log_net!(debug "network class set to {:?}", network_class);
|
log_net!(debug "network class changed to {:?}", network_class);
|
||||||
|
}
|
||||||
|
|
||||||
// send updates to everyone
|
// send updates to everyone
|
||||||
self.routing_table().send_node_info_updates();
|
self.routing_table().send_node_info_updates();
|
||||||
|
@ -291,6 +291,8 @@ impl Network {
|
|||||||
let local_dial_info_list = self.create_udp_inbound_sockets(ip_addrs, udp_port).await?;
|
let local_dial_info_list = self.create_udp_inbound_sockets(ip_addrs, udp_port).await?;
|
||||||
let mut static_public = false;
|
let mut static_public = false;
|
||||||
|
|
||||||
|
trace!("UDP: listener started on {:#?}", local_dial_info_list);
|
||||||
|
|
||||||
// Register local dial info
|
// Register local dial info
|
||||||
for di in &local_dial_info_list {
|
for di in &local_dial_info_list {
|
||||||
// If the local interface address is global, or we are enabling local peer scope
|
// If the local interface address is global, or we are enabling local peer scope
|
||||||
@ -397,7 +399,7 @@ impl Network {
|
|||||||
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
trace!("WS: listener started");
|
trace!("WS: listener started on {:#?}", socket_addresses);
|
||||||
|
|
||||||
let mut static_public = false;
|
let mut static_public = false;
|
||||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||||
@ -515,7 +517,7 @@ impl Network {
|
|||||||
wss_port,
|
wss_port,
|
||||||
ip_addrs
|
ip_addrs
|
||||||
);
|
);
|
||||||
let _socket_addresses = self
|
let socket_addresses = self
|
||||||
.start_tcp_listener(
|
.start_tcp_listener(
|
||||||
ip_addrs,
|
ip_addrs,
|
||||||
wss_port,
|
wss_port,
|
||||||
@ -523,7 +525,7 @@ impl Network {
|
|||||||
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
trace!("WSS: listener started");
|
trace!("WSS: listener started on {:#?}", socket_addresses);
|
||||||
|
|
||||||
// NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS
|
// NOTE: No interface dial info for WSS, as there is no way to connect to a local dialinfo via TLS
|
||||||
// If the hostname is specified, it is the public dialinfo via the URL. If no hostname
|
// If the hostname is specified, it is the public dialinfo via the URL. If no hostname
|
||||||
@ -629,7 +631,7 @@ impl Network {
|
|||||||
Box::new(|_, _, a| Box::new(RawTcpProtocolHandler::new(a))),
|
Box::new(|_, _, a| Box::new(RawTcpProtocolHandler::new(a))),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
trace!("TCP: listener started");
|
trace!("TCP: listener started on {:#?}", socket_addresses);
|
||||||
|
|
||||||
let mut static_public = false;
|
let mut static_public = false;
|
||||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||||
|
@ -90,6 +90,7 @@ pub enum SendDataKind {
|
|||||||
struct NetworkManagerInner {
|
struct NetworkManagerInner {
|
||||||
routing_table: Option<RoutingTable>,
|
routing_table: Option<RoutingTable>,
|
||||||
components: Option<NetworkComponents>,
|
components: Option<NetworkComponents>,
|
||||||
|
update_callback: Option<UpdateCallback>,
|
||||||
stats: NetworkManagerStats,
|
stats: NetworkManagerStats,
|
||||||
client_whitelist: LruCache<key::DHTKey, ClientWhitelistEntry>,
|
client_whitelist: LruCache<key::DHTKey, ClientWhitelistEntry>,
|
||||||
relay_node: Option<NodeRef>,
|
relay_node: Option<NodeRef>,
|
||||||
@ -116,6 +117,7 @@ impl NetworkManager {
|
|||||||
NetworkManagerInner {
|
NetworkManagerInner {
|
||||||
routing_table: None,
|
routing_table: None,
|
||||||
components: None,
|
components: None,
|
||||||
|
update_callback: None,
|
||||||
stats: NetworkManagerStats::default(),
|
stats: NetworkManagerStats::default(),
|
||||||
client_whitelist: LruCache::new_unbounded(),
|
client_whitelist: LruCache::new_unbounded(),
|
||||||
relay_node: None,
|
relay_node: None,
|
||||||
@ -205,10 +207,11 @@ impl NetworkManager {
|
|||||||
self.inner.lock().relay_node.clone()
|
self.inner.lock().relay_node.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init(&self) -> Result<(), String> {
|
pub async fn init(&self, update_callback: UpdateCallback) -> Result<(), String> {
|
||||||
let routing_table = RoutingTable::new(self.clone());
|
let routing_table = RoutingTable::new(self.clone());
|
||||||
routing_table.init().await?;
|
routing_table.init().await?;
|
||||||
self.inner.lock().routing_table = Some(routing_table.clone());
|
self.inner.lock().routing_table = Some(routing_table.clone());
|
||||||
|
self.inner.lock().update_callback = Some(update_callback);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn terminate(&self) {
|
pub async fn terminate(&self) {
|
||||||
@ -219,6 +222,7 @@ impl NetworkManager {
|
|||||||
if let Some(routing_table) = routing_table {
|
if let Some(routing_table) = routing_table {
|
||||||
routing_table.terminate().await;
|
routing_table.terminate().await;
|
||||||
}
|
}
|
||||||
|
self.inner.lock().update_callback = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn internal_startup(&self) -> Result<(), String> {
|
pub async fn internal_startup(&self) -> Result<(), String> {
|
||||||
@ -256,9 +260,16 @@ impl NetworkManager {
|
|||||||
self.shutdown().await;
|
self.shutdown().await;
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.send_network_update();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_started(&self) -> bool {
|
||||||
|
self.inner.lock().components.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn shutdown(&self) {
|
pub async fn shutdown(&self) {
|
||||||
trace!("NetworkManager::shutdown begin");
|
trace!("NetworkManager::shutdown begin");
|
||||||
|
|
||||||
@ -272,8 +283,13 @@ impl NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset the state
|
// reset the state
|
||||||
let mut inner = self.inner.lock();
|
{
|
||||||
inner.components = None;
|
let mut inner = self.inner.lock();
|
||||||
|
inner.components = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send update
|
||||||
|
self.send_network_update();
|
||||||
|
|
||||||
trace!("NetworkManager::shutdown end");
|
trace!("NetworkManager::shutdown end");
|
||||||
}
|
}
|
||||||
@ -334,7 +350,9 @@ impl NetworkManager {
|
|||||||
// if things can't restart, then we fail out of the attachment manager
|
// if things can't restart, then we fail out of the attachment manager
|
||||||
if net.needs_restart() {
|
if net.needs_restart() {
|
||||||
net.shutdown().await;
|
net.shutdown().await;
|
||||||
|
self.send_network_update();
|
||||||
net.startup().await?;
|
net.startup().await?;
|
||||||
|
self.send_network_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the routing table tick
|
// Run the routing table tick
|
||||||
@ -1155,35 +1173,41 @@ impl NetworkManager {
|
|||||||
// Compute transfer statistics for the low level network
|
// Compute transfer statistics for the low level network
|
||||||
async fn rolling_transfers_task_routine(self, last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
async fn rolling_transfers_task_routine(self, last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
||||||
log_net!("--- network manager rolling_transfers task");
|
log_net!("--- network manager rolling_transfers task");
|
||||||
let inner = &mut *self.inner.lock();
|
{
|
||||||
|
let inner = &mut *self.inner.lock();
|
||||||
|
|
||||||
// Roll the low level network transfer stats for our address
|
// Roll the low level network transfer stats for our address
|
||||||
inner
|
inner
|
||||||
.stats
|
.stats
|
||||||
.self_stats
|
.self_stats
|
||||||
.transfer_stats_accounting
|
.transfer_stats_accounting
|
||||||
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
||||||
|
|
||||||
// Roll all per-address transfers
|
// Roll all per-address transfers
|
||||||
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
||||||
for (addr, stats) in &mut inner.stats.per_address_stats {
|
for (addr, stats) in &mut inner.stats.per_address_stats {
|
||||||
stats.transfer_stats_accounting.roll_transfers(
|
stats.transfer_stats_accounting.roll_transfers(
|
||||||
last_ts,
|
last_ts,
|
||||||
cur_ts,
|
cur_ts,
|
||||||
&mut stats.transfer_stats,
|
&mut stats.transfer_stats,
|
||||||
);
|
);
|
||||||
|
|
||||||
// While we're here, lets see if this address has timed out
|
// While we're here, lets see if this address has timed out
|
||||||
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
||||||
// it's dead, put it in the dead list
|
// it's dead, put it in the dead list
|
||||||
dead_addrs.insert(*addr);
|
dead_addrs.insert(*addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the dead addresses from our tables
|
||||||
|
for da in &dead_addrs {
|
||||||
|
inner.stats.per_address_stats.remove(da);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the dead addresses from our tables
|
// Send update
|
||||||
for da in &dead_addrs {
|
self.send_network_update();
|
||||||
inner.stats.per_address_stats.remove(da);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1220,6 +1244,45 @@ impl NetworkManager {
|
|||||||
.add_down(bytes);
|
.add_down(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get stats
|
||||||
|
pub fn get_stats(&self) -> NetworkManagerStats {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
inner.stats.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_veilid_state_inner(inner: &NetworkManagerInner) -> VeilidStateNetwork {
|
||||||
|
if inner.components.is_some() {
|
||||||
|
VeilidStateNetwork {
|
||||||
|
started: true,
|
||||||
|
bps_down: inner.stats.self_stats.transfer_stats.down.average,
|
||||||
|
bps_up: inner.stats.self_stats.transfer_stats.up.average,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VeilidStateNetwork {
|
||||||
|
started: false,
|
||||||
|
bps_down: 0,
|
||||||
|
bps_up: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_veilid_state(&self) -> VeilidStateNetwork {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
Self::get_veilid_state_inner(&*inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_network_update(&self) {
|
||||||
|
let (update_cb, state) = {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
let update_cb = inner.update_callback.clone();
|
||||||
|
if update_cb.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let state = Self::get_veilid_state_inner(&*inner);
|
||||||
|
(update_cb.unwrap(), state)
|
||||||
|
};
|
||||||
|
update_cb(VeilidUpdate::Network(state));
|
||||||
|
}
|
||||||
|
|
||||||
// Determine if a local IP address has changed
|
// Determine if a local IP address has changed
|
||||||
// this means we should restart the low level network and and recreate all of our dial info
|
// this means we should restart the low level network and and recreate all of our dial info
|
||||||
// Wait until we have received confirmation from N different peers
|
// Wait until we have received confirmation from N different peers
|
||||||
|
@ -205,10 +205,6 @@ impl ReceiptManager {
|
|||||||
let config = self.core().config();
|
let config = self.core().config();
|
||||||
let c = config.get();
|
let c = config.get();
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.max_server_signal_leases = c.network.leases.max_server_signal_leases as usize;
|
|
||||||
inner.max_server_relay_leases = c.network.leases.max_server_relay_leases as usize;
|
|
||||||
inner.max_client_signal_leases = c.network.leases.max_client_signal_leases as usize;
|
|
||||||
inner.max_client_relay_leases = c.network.leases.max_client_relay_leases as usize;
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -22,20 +22,36 @@ impl RoutingTable {
|
|||||||
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
pub fn debug_info_dialinfo(&self) -> String {
|
pub fn debug_info_dialinfo(&self, txt_format: bool) -> String {
|
||||||
let ldis = self.dial_info_details(RoutingDomain::LocalNetwork);
|
if txt_format {
|
||||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
let mut out = String::new();
|
||||||
let mut out = String::new();
|
|
||||||
|
|
||||||
out += "Local Network Dial Info Details:\n";
|
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||||
for (n, ldi) in ldis.iter().enumerate() {
|
if gdis.is_empty() {
|
||||||
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
out += "No TXT Record DialInfo\n";
|
||||||
|
} else {
|
||||||
|
out += "TXT Record DialInfo:\n";
|
||||||
|
out += &format!("{}\n", self.node_id().encode());
|
||||||
|
for gdi in gdis {
|
||||||
|
out += &format!("{}\n", gdi.dial_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
} else {
|
||||||
|
let ldis = self.dial_info_details(RoutingDomain::LocalNetwork);
|
||||||
|
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||||
|
let mut out = String::new();
|
||||||
|
|
||||||
|
out += "Local Network Dial Info Details:\n";
|
||||||
|
for (n, ldi) in ldis.iter().enumerate() {
|
||||||
|
out += &format!(" {:>2}: {:?}\n", n, ldi);
|
||||||
|
}
|
||||||
|
out += "Public Internet Dial Info Details:\n";
|
||||||
|
for (n, gdi) in gdis.iter().enumerate() {
|
||||||
|
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
||||||
|
}
|
||||||
|
out
|
||||||
}
|
}
|
||||||
out += "Public Internet Dial Info Details:\n";
|
|
||||||
for (n, gdi) in gdis.iter().enumerate() {
|
|
||||||
out += &format!(" {:>2}: {:?}\n", n, gdi);
|
|
||||||
}
|
|
||||||
out
|
|
||||||
}
|
}
|
||||||
pub fn debug_info_entries(&self, limit: usize, min_state: BucketEntryState) -> String {
|
pub fn debug_info_entries(&self, limit: usize, min_state: BucketEntryState) -> String {
|
||||||
let inner = self.inner.lock();
|
let inner = self.inner.lock();
|
||||||
|
@ -771,17 +771,36 @@ impl RoutingTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn resolve_bootstrap(&self, bootstrap: Vec<String>) -> Result<Vec<String>, String> {
|
||||||
|
let mut out = Vec::<String>::new();
|
||||||
|
for bh in bootstrap {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
async fn bootstrap_task_routine(self) -> Result<(), String> {
|
async fn bootstrap_task_routine(self) -> Result<(), String> {
|
||||||
let bootstrap = {
|
let (bootstrap, bootstrap_nodes) = {
|
||||||
let c = self.config.get();
|
let c = self.config.get();
|
||||||
c.network.bootstrap.clone()
|
(
|
||||||
|
c.network.bootstrap.clone(),
|
||||||
|
c.network.bootstrap_nodes.clone(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
log_rtab!("--- bootstrap_task");
|
log_rtab!("--- bootstrap_task");
|
||||||
|
|
||||||
|
// If we aren't specifying a bootstrap node list explicitly, then pull from the bootstrap server(s)
|
||||||
|
let bootstrap_nodes = if !bootstrap_nodes.is_empty() {
|
||||||
|
bootstrap_nodes
|
||||||
|
} else {
|
||||||
|
// Resolve bootstrap servers and recurse their TXT entries
|
||||||
|
self.resolve_bootstrap(bootstrap).await?
|
||||||
|
};
|
||||||
|
|
||||||
// Map all bootstrap entries to a single key with multiple dialinfo
|
// Map all bootstrap entries to a single key with multiple dialinfo
|
||||||
let mut bsmap: BTreeMap<DHTKey, Vec<DialInfoDetail>> = BTreeMap::new();
|
let mut bsmap: BTreeMap<DHTKey, Vec<DialInfoDetail>> = BTreeMap::new();
|
||||||
for b in bootstrap {
|
for b in bootstrap_nodes {
|
||||||
let ndis = NodeDialInfo::from_str(b.as_str())
|
let ndis = NodeDialInfo::from_str(b.as_str())
|
||||||
.map_err(map_to_string)
|
.map_err(map_to_string)
|
||||||
.map_err(logthru_rtab!("Invalid dial info in bootstrap entry: {}", b))?;
|
.map_err(logthru_rtab!("Invalid dial info in bootstrap entry: {}", b))?;
|
||||||
@ -794,7 +813,7 @@ impl RoutingTable {
|
|||||||
class: DialInfoClass::Direct, // Bootstraps are always directly reachable
|
class: DialInfoClass::Direct, // Bootstraps are always directly reachable
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
log_rtab!(" bootstrap list: {:?}", bsmap);
|
log_rtab!(" bootstrap node dialinfo: {:?}", bsmap);
|
||||||
|
|
||||||
// Run all bootstrap operations concurrently
|
// Run all bootstrap operations concurrently
|
||||||
let mut unord = FuturesUnordered::new();
|
let mut unord = FuturesUnordered::new();
|
||||||
|
@ -192,9 +192,12 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
|||||||
"network.max_connections_per_ip6_prefix_size" => Ok(Box::new(56u32)),
|
"network.max_connections_per_ip6_prefix_size" => Ok(Box::new(56u32)),
|
||||||
"network.max_connection_frequency_per_min" => Ok(Box::new(8u32)),
|
"network.max_connection_frequency_per_min" => Ok(Box::new(8u32)),
|
||||||
"network.client_whitelist_timeout_ms" => Ok(Box::new(300_000u32)),
|
"network.client_whitelist_timeout_ms" => Ok(Box::new(300_000u32)),
|
||||||
|
"network.reverse_connection_receipt_time_ms" => Ok(Box::new(5_000u32)),
|
||||||
|
"network.hole_punch_receipt_time_ms" => Ok(Box::new(5_000u32)),
|
||||||
"network.node_id" => Ok(Box::new(dht::key::DHTKey::default())),
|
"network.node_id" => Ok(Box::new(dht::key::DHTKey::default())),
|
||||||
"network.node_id_secret" => Ok(Box::new(dht::key::DHTKeySecret::default())),
|
"network.node_id_secret" => Ok(Box::new(dht::key::DHTKeySecret::default())),
|
||||||
"network.bootstrap" => Ok(Box::new(Vec::<String>::new())),
|
"network.bootstrap" => Ok(Box::new(Vec::<String>::new())),
|
||||||
|
"network.bootstrap_nodes" => Ok(Box::new(Vec::<String>::new())),
|
||||||
"network.routing_table.limit_over_attached" => Ok(Box::new(64u32)),
|
"network.routing_table.limit_over_attached" => Ok(Box::new(64u32)),
|
||||||
"network.routing_table.limit_fully_attached" => Ok(Box::new(32u32)),
|
"network.routing_table.limit_fully_attached" => Ok(Box::new(32u32)),
|
||||||
"network.routing_table.limit_attached_strong" => Ok(Box::new(16u32)),
|
"network.routing_table.limit_attached_strong" => Ok(Box::new(16u32)),
|
||||||
@ -255,10 +258,6 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
|
|||||||
"network.protocol.wss.listen_address" => Ok(Box::new("".to_owned())),
|
"network.protocol.wss.listen_address" => Ok(Box::new("".to_owned())),
|
||||||
"network.protocol.wss.path" => Ok(Box::new(String::from("ws"))),
|
"network.protocol.wss.path" => Ok(Box::new(String::from("ws"))),
|
||||||
"network.protocol.wss.url" => Ok(Box::new(Option::<String>::None)),
|
"network.protocol.wss.url" => Ok(Box::new(Option::<String>::None)),
|
||||||
"network.leases.max_server_signal_leases" => Ok(Box::new(256u32)),
|
|
||||||
"network.leases.max_server_relay_leases" => Ok(Box::new(8u32)),
|
|
||||||
"network.leases.max_client_signal_leases" => Ok(Box::new(2u32)),
|
|
||||||
"network.leases.max_client_relay_leases" => Ok(Box::new(2u32)),
|
|
||||||
_ => {
|
_ => {
|
||||||
let err = format!("config key '{}' doesn't exist", key);
|
let err = format!("config key '{}' doesn't exist", key);
|
||||||
debug!("{}", err);
|
debug!("{}", err);
|
||||||
@ -318,9 +317,12 @@ pub async fn test_config() {
|
|||||||
assert_eq!(inner.network.max_connections_per_ip6_prefix_size, 56u32);
|
assert_eq!(inner.network.max_connections_per_ip6_prefix_size, 56u32);
|
||||||
assert_eq!(inner.network.max_connection_frequency_per_min, 8u32);
|
assert_eq!(inner.network.max_connection_frequency_per_min, 8u32);
|
||||||
assert_eq!(inner.network.client_whitelist_timeout_ms, 300_000u32);
|
assert_eq!(inner.network.client_whitelist_timeout_ms, 300_000u32);
|
||||||
|
assert_eq!(inner.network.reverse_connection_receipt_time_ms, 5_000u32);
|
||||||
|
assert_eq!(inner.network.hole_punch_receipt_time_ms, 5_000u32);
|
||||||
assert!(!inner.network.node_id.valid);
|
assert!(!inner.network.node_id.valid);
|
||||||
assert!(!inner.network.node_id_secret.valid);
|
assert!(!inner.network.node_id_secret.valid);
|
||||||
assert_eq!(inner.network.bootstrap, Vec::<String>::new());
|
assert_eq!(inner.network.bootstrap, Vec::<String>::new());
|
||||||
|
assert_eq!(inner.network.bootstrap_nodes, Vec::<String>::new());
|
||||||
assert_eq!(inner.network.rpc.concurrency, 2u32);
|
assert_eq!(inner.network.rpc.concurrency, 2u32);
|
||||||
assert_eq!(inner.network.rpc.queue_size, 128u32);
|
assert_eq!(inner.network.rpc.queue_size, 128u32);
|
||||||
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
||||||
|
@ -79,10 +79,16 @@ impl VeilidAPI {
|
|||||||
Ok(routing_table.debug_info_buckets(min_state))
|
Ok(routing_table.debug_info_buckets(min_state))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_dialinfo(&self, _args: String) -> Result<String, VeilidAPIError> {
|
async fn debug_dialinfo(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||||
|
let args: Vec<String> = args.split_whitespace().map(|s| s.to_owned()).collect();
|
||||||
|
let is_txt = if args.len() == 1 {
|
||||||
|
args[0] == "txt"
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
// Dump routing table dialinfo
|
// Dump routing table dialinfo
|
||||||
let routing_table = self.network_manager()?.routing_table();
|
let routing_table = self.network_manager()?.routing_table();
|
||||||
Ok(routing_table.debug_info_dialinfo())
|
Ok(routing_table.debug_info_dialinfo(is_txt))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn debug_entries(&self, args: String) -> Result<String, VeilidAPIError> {
|
async fn debug_entries(&self, args: String) -> Result<String, VeilidAPIError> {
|
||||||
@ -147,7 +153,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
// Must be detached
|
// Must be detached
|
||||||
if !matches!(
|
if !matches!(
|
||||||
self.get_state().await?.attachment,
|
self.get_state().await?.attachment.state,
|
||||||
AttachmentState::Detached
|
AttachmentState::Detached
|
||||||
) {
|
) {
|
||||||
return Err(VeilidAPIError::Internal {
|
return Err(VeilidAPIError::Internal {
|
||||||
@ -168,7 +174,7 @@ impl VeilidAPI {
|
|||||||
if args[0] == "buckets" {
|
if args[0] == "buckets" {
|
||||||
// Must be detached
|
// Must be detached
|
||||||
if matches!(
|
if matches!(
|
||||||
self.get_state().await?.attachment,
|
self.get_state().await?.attachment.state,
|
||||||
AttachmentState::Detached | AttachmentState::Detaching
|
AttachmentState::Detached | AttachmentState::Detaching
|
||||||
) {
|
) {
|
||||||
return Err(VeilidAPIError::Internal {
|
return Err(VeilidAPIError::Internal {
|
||||||
@ -194,7 +200,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
async fn debug_attach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
async fn debug_attach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
self.get_state().await?.attachment,
|
self.get_state().await?.attachment.state,
|
||||||
AttachmentState::Detached
|
AttachmentState::Detached
|
||||||
) {
|
) {
|
||||||
return Err(VeilidAPIError::Internal {
|
return Err(VeilidAPIError::Internal {
|
||||||
@ -209,7 +215,7 @@ impl VeilidAPI {
|
|||||||
|
|
||||||
async fn debug_detach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
async fn debug_detach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.get_state().await?.attachment,
|
self.get_state().await?.attachment.state,
|
||||||
AttachmentState::Detaching
|
AttachmentState::Detaching
|
||||||
) {
|
) {
|
||||||
return Err(VeilidAPIError::Internal {
|
return Err(VeilidAPIError::Internal {
|
||||||
|
@ -167,22 +167,37 @@ impl VeilidLogLevel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct VeilidStateLog {
|
||||||
|
pub log_level: VeilidLogLevel,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct VeilidStateAttachment {
|
||||||
|
pub state: AttachmentState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct VeilidStateNetwork {
|
||||||
|
pub started: bool,
|
||||||
|
pub bps_down: u64,
|
||||||
|
pub bps_up: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(tag = "kind")]
|
#[serde(tag = "kind")]
|
||||||
pub enum VeilidUpdate {
|
pub enum VeilidUpdate {
|
||||||
Log {
|
Log(VeilidStateLog),
|
||||||
log_level: VeilidLogLevel,
|
Attachment(VeilidStateAttachment),
|
||||||
message: String,
|
Network(VeilidStateNetwork),
|
||||||
},
|
|
||||||
Attachment {
|
|
||||||
state: AttachmentState,
|
|
||||||
},
|
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidState {
|
pub struct VeilidState {
|
||||||
pub attachment: AttachmentState,
|
pub attachment: VeilidStateAttachment,
|
||||||
|
pub network: VeilidStateNetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -745,8 +760,37 @@ impl fmt::Display for DialInfo {
|
|||||||
match self {
|
match self {
|
||||||
DialInfo::UDP(di) => write!(f, "udp|{}", di.socket_address),
|
DialInfo::UDP(di) => write!(f, "udp|{}", di.socket_address),
|
||||||
DialInfo::TCP(di) => write!(f, "tcp|{}", di.socket_address),
|
DialInfo::TCP(di) => write!(f, "tcp|{}", di.socket_address),
|
||||||
DialInfo::WS(di) => write!(f, "ws|{}|{}", di.socket_address, di.request),
|
DialInfo::WS(di) => {
|
||||||
DialInfo::WSS(di) => write!(f, "wss|{}|{}", di.socket_address, di.request),
|
let url = format!("ws://{}", di.request);
|
||||||
|
let split_url = SplitUrl::from_str(&url).unwrap();
|
||||||
|
match split_url.host {
|
||||||
|
SplitUrlHost::Hostname(_) => {
|
||||||
|
write!(f, "ws|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
||||||
|
}
|
||||||
|
SplitUrlHost::IpAddr(a) => {
|
||||||
|
if di.socket_address.to_ip_addr() == a {
|
||||||
|
write!(f, "ws|{}", di.request)
|
||||||
|
} else {
|
||||||
|
panic!("resolved address does not match url: {}", di.request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DialInfo::WSS(di) => {
|
||||||
|
let url = format!("wss://{}", di.request);
|
||||||
|
let split_url = SplitUrl::from_str(&url).unwrap();
|
||||||
|
match split_url.host {
|
||||||
|
SplitUrlHost::Hostname(_) => {
|
||||||
|
write!(f, "wss|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
||||||
|
}
|
||||||
|
SplitUrlHost::IpAddr(_) => {
|
||||||
|
panic!(
|
||||||
|
"secure websockets can not use ip address in request: {}",
|
||||||
|
di.request
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -767,18 +811,50 @@ impl FromStr for DialInfo {
|
|||||||
Ok(DialInfo::tcp(socket_address))
|
Ok(DialInfo::tcp(socket_address))
|
||||||
}
|
}
|
||||||
"ws" => {
|
"ws" => {
|
||||||
let (sa, rest) = rest.split_once('|').ok_or_else(|| {
|
let url = format!("ws://{}", rest);
|
||||||
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
let split_url = SplitUrl::from_str(&url)
|
||||||
})?;
|
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?;
|
||||||
let socket_address = SocketAddress::from_str(sa)?;
|
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
||||||
DialInfo::try_ws(socket_address, format!("ws://{}", rest))
|
return Err(parse_error!("incorrect scheme for WS dialinfo", url));
|
||||||
|
}
|
||||||
|
let url_port = split_url.port.unwrap_or(80u16);
|
||||||
|
|
||||||
|
match rest.split_once('|') {
|
||||||
|
Some((sa, rest)) => {
|
||||||
|
let address = Address::from_str(sa)?;
|
||||||
|
|
||||||
|
DialInfo::try_ws(
|
||||||
|
SocketAddress::new(address, url_port),
|
||||||
|
format!("ws://{}", rest),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let address = Address::from_str(&split_url.host.to_string())?;
|
||||||
|
DialInfo::try_ws(
|
||||||
|
SocketAddress::new(address, url_port),
|
||||||
|
format!("ws://{}", rest),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"wss" => {
|
"wss" => {
|
||||||
let (sa, rest) = rest.split_once('|').ok_or_else(|| {
|
let url = format!("wss://{}", rest);
|
||||||
|
let split_url = SplitUrl::from_str(&url)
|
||||||
|
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?;
|
||||||
|
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
||||||
|
return Err(parse_error!("incorrect scheme for WSS dialinfo", url));
|
||||||
|
}
|
||||||
|
let url_port = split_url.port.unwrap_or(443u16);
|
||||||
|
|
||||||
|
let (a, rest) = rest.split_once('|').ok_or_else(|| {
|
||||||
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||||
})?;
|
})?;
|
||||||
let socket_address = SocketAddress::from_str(sa)?;
|
|
||||||
DialInfo::try_wss(socket_address, format!("wss://{}", rest))
|
let address = Address::from_str(a)?;
|
||||||
|
DialInfo::try_wss(
|
||||||
|
SocketAddress::new(address, url_port),
|
||||||
|
format!("wss://{}", rest),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)),
|
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)),
|
||||||
}
|
}
|
||||||
@ -819,6 +895,14 @@ impl DialInfo {
|
|||||||
url
|
url
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
||||||
|
if socket_address.to_ip_addr() != a {
|
||||||
|
return Err(parse_error!(
|
||||||
|
format!("request address does not match socket address: {}", a),
|
||||||
|
socket_address
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Self::WS(DialInfoWS {
|
Ok(Self::WS(DialInfoWS {
|
||||||
socket_address: socket_address.to_canonical(),
|
socket_address: socket_address.to_canonical(),
|
||||||
request: url[5..].to_string(),
|
request: url[5..].to_string(),
|
||||||
@ -1497,11 +1581,19 @@ impl VeilidAPI {
|
|||||||
// get a full copy of the current state
|
// get a full copy of the current state
|
||||||
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
||||||
let attachment_manager = self.attachment_manager()?;
|
let attachment_manager = self.attachment_manager()?;
|
||||||
|
let network_manager = attachment_manager.network_manager();
|
||||||
|
|
||||||
|
let attachment = attachment_manager.get_veilid_state();
|
||||||
|
let network = network_manager.get_veilid_state();
|
||||||
|
|
||||||
Ok(VeilidState {
|
Ok(VeilidState {
|
||||||
attachment: attachment_manager.get_state(),
|
attachment,
|
||||||
|
network,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get network connectedness
|
||||||
|
|
||||||
// connect to the network
|
// connect to the network
|
||||||
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
||||||
let attachment_manager = self.attachment_manager()?;
|
let attachment_manager = self.attachment_manager()?;
|
||||||
|
@ -104,7 +104,6 @@ pub struct VeilidConfigDHT {
|
|||||||
pub min_peer_count: u32,
|
pub min_peer_count: u32,
|
||||||
pub min_peer_refresh_time_ms: u32,
|
pub min_peer_refresh_time_ms: u32,
|
||||||
pub validate_dial_info_receipt_time_ms: u32,
|
pub validate_dial_info_receipt_time_ms: u32,
|
||||||
pub nearby_node_percentage: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -117,13 +116,6 @@ pub struct VeilidConfigRPC {
|
|||||||
pub max_route_hop_count: u8,
|
pub max_route_hop_count: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct VeilidConfigLeases {
|
|
||||||
pub max_server_signal_leases: u32,
|
|
||||||
pub max_server_relay_leases: u32,
|
|
||||||
pub max_client_signal_leases: u32,
|
|
||||||
pub max_client_relay_leases: u32,
|
|
||||||
}
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct VeilidConfigRoutingTable {
|
pub struct VeilidConfigRoutingTable {
|
||||||
pub limit_over_attached: u32,
|
pub limit_over_attached: u32,
|
||||||
@ -147,6 +139,7 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub node_id: key::DHTKey,
|
pub node_id: key::DHTKey,
|
||||||
pub node_id_secret: key::DHTKeySecret,
|
pub node_id_secret: key::DHTKeySecret,
|
||||||
pub bootstrap: Vec<String>,
|
pub bootstrap: Vec<String>,
|
||||||
|
pub bootstrap_nodes: Vec<String>,
|
||||||
pub routing_table: VeilidConfigRoutingTable,
|
pub routing_table: VeilidConfigRoutingTable,
|
||||||
pub rpc: VeilidConfigRPC,
|
pub rpc: VeilidConfigRPC,
|
||||||
pub dht: VeilidConfigDHT,
|
pub dht: VeilidConfigDHT,
|
||||||
@ -157,7 +150,6 @@ pub struct VeilidConfigNetwork {
|
|||||||
pub tls: VeilidConfigTLS,
|
pub tls: VeilidConfigTLS,
|
||||||
pub application: VeilidConfigApplication,
|
pub application: VeilidConfigApplication,
|
||||||
pub protocol: VeilidConfigProtocol,
|
pub protocol: VeilidConfigProtocol,
|
||||||
pub leases: VeilidConfigLeases,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -305,6 +297,7 @@ impl VeilidConfig {
|
|||||||
get_config!(inner.network.max_connection_frequency_per_min);
|
get_config!(inner.network.max_connection_frequency_per_min);
|
||||||
get_config!(inner.network.client_whitelist_timeout_ms);
|
get_config!(inner.network.client_whitelist_timeout_ms);
|
||||||
get_config!(inner.network.bootstrap);
|
get_config!(inner.network.bootstrap);
|
||||||
|
get_config!(inner.network.bootstrap_nodes);
|
||||||
get_config!(inner.network.routing_table.limit_over_attached);
|
get_config!(inner.network.routing_table.limit_over_attached);
|
||||||
get_config!(inner.network.routing_table.limit_fully_attached);
|
get_config!(inner.network.routing_table.limit_fully_attached);
|
||||||
get_config!(inner.network.routing_table.limit_attached_strong);
|
get_config!(inner.network.routing_table.limit_attached_strong);
|
||||||
@ -365,10 +358,6 @@ impl VeilidConfig {
|
|||||||
get_config!(inner.network.protocol.wss.listen_address);
|
get_config!(inner.network.protocol.wss.listen_address);
|
||||||
get_config!(inner.network.protocol.wss.path);
|
get_config!(inner.network.protocol.wss.path);
|
||||||
get_config!(inner.network.protocol.wss.url);
|
get_config!(inner.network.protocol.wss.url);
|
||||||
get_config!(inner.network.leases.max_server_signal_leases);
|
|
||||||
get_config!(inner.network.leases.max_server_relay_leases);
|
|
||||||
get_config!(inner.network.leases.max_client_signal_leases);
|
|
||||||
get_config!(inner.network.leases.max_client_relay_leases);
|
|
||||||
}
|
}
|
||||||
// Validate settings
|
// Validate settings
|
||||||
self.validate()?;
|
self.validate()?;
|
||||||
|
@ -38,104 +38,102 @@ Future<VeilidConfig> getDefaultVeilidConfig() async {
|
|||||||
delete: false,
|
delete: false,
|
||||||
),
|
),
|
||||||
network: VeilidConfigNetwork(
|
network: VeilidConfigNetwork(
|
||||||
|
connectionInitialTimeoutMs: 2000,
|
||||||
|
connectionInactivityTimeoutMs: 60000,
|
||||||
|
maxConnectionsPerIp4: 8,
|
||||||
|
maxConnectionsPerIp6Prefix: 8,
|
||||||
|
maxConnectionsPerIp6PrefixSize: 56,
|
||||||
|
maxConnectionFrequencyPerMin: 8,
|
||||||
|
clientWhitelistTimeoutMs: 300000,
|
||||||
|
reverseConnectionReceiptTimeMs: 5000,
|
||||||
|
holePunchReceiptTimeMs: 5000,
|
||||||
|
nodeId: "",
|
||||||
|
nodeIdSecret: "",
|
||||||
|
bootstrap: [],
|
||||||
|
bootstrapNodes: [],
|
||||||
|
routingTable: VeilidConfigRoutingTable(
|
||||||
|
limitOverAttached: 64,
|
||||||
|
limitFullyAttached: 32,
|
||||||
|
limitAttachedStrong: 16,
|
||||||
|
limitAttachedGood: 8,
|
||||||
|
limitAttachedWeak: 4,
|
||||||
|
),
|
||||||
|
rpc: VeilidConfigRPC(
|
||||||
|
concurrency: 0,
|
||||||
|
queueSize: 1024,
|
||||||
|
maxTimestampBehindMs: 10000,
|
||||||
|
maxTimestampAheadMs: 10000,
|
||||||
|
timeoutMs: 10000,
|
||||||
|
maxRouteHopCount: 7,
|
||||||
|
),
|
||||||
|
dht: VeilidConfigDHT(
|
||||||
|
resolveNodeTimeoutMs: null,
|
||||||
|
resolveNodeCount: 20,
|
||||||
|
resolveNodeFanout: 3,
|
||||||
|
maxFindNodeCount: 20,
|
||||||
|
getValueTimeoutMs: null,
|
||||||
|
getValueCount: 20,
|
||||||
|
getValueFanout: 3,
|
||||||
|
setValueTimeoutMs: null,
|
||||||
|
setValueCount: 20,
|
||||||
|
setValueFanout: 5,
|
||||||
|
minPeerCount: 20,
|
||||||
|
minPeerRefreshTimeMs: 2000,
|
||||||
|
validateDialInfoReceiptTimeMs: 5000,
|
||||||
|
),
|
||||||
|
upnp: true,
|
||||||
|
natpmp: true,
|
||||||
|
enableLocalPeerScope: false,
|
||||||
|
restrictedNatRetries: 3,
|
||||||
|
tls: VeilidConfigTLS(
|
||||||
|
certificatePath: "",
|
||||||
|
privateKeyPath: "",
|
||||||
connectionInitialTimeoutMs: 2000,
|
connectionInitialTimeoutMs: 2000,
|
||||||
connectionInactivityTimeoutMs: 60000,
|
),
|
||||||
maxConnectionsPerIp4: 8,
|
application: VeilidConfigApplication(
|
||||||
maxConnectionsPerIp6Prefix: 8,
|
https: VeilidConfigHTTPS(
|
||||||
maxConnectionsPerIp6PrefixSize: 56,
|
enabled: false,
|
||||||
maxConnectionFrequencyPerMin: 8,
|
|
||||||
clientWhitelistTimeoutMs: 300000,
|
|
||||||
nodeId: "",
|
|
||||||
nodeIdSecret: "",
|
|
||||||
bootstrap: [],
|
|
||||||
routingTable: VeilidConfigRoutingTable(
|
|
||||||
limitOverAttached: 64,
|
|
||||||
limitFullyAttached: 32,
|
|
||||||
limitAttachedStrong: 16,
|
|
||||||
limitAttachedGood: 8,
|
|
||||||
limitAttachedWeak: 4,
|
|
||||||
),
|
|
||||||
rpc: VeilidConfigRPC(
|
|
||||||
concurrency: 0,
|
|
||||||
queueSize: 1024,
|
|
||||||
maxTimestampBehindMs: 10000,
|
|
||||||
maxTimestampAheadMs: 10000,
|
|
||||||
timeoutMs: 10000,
|
|
||||||
maxRouteHopCount: 7,
|
|
||||||
),
|
|
||||||
dht: VeilidConfigDHT(
|
|
||||||
resolveNodeTimeoutMs: null,
|
|
||||||
resolveNodeCount: 20,
|
|
||||||
resolveNodeFanout: 3,
|
|
||||||
maxFindNodeCount: 20,
|
|
||||||
getValueTimeoutMs: null,
|
|
||||||
getValueCount: 20,
|
|
||||||
getValueFanout: 3,
|
|
||||||
setValueTimeoutMs: null,
|
|
||||||
setValueCount: 20,
|
|
||||||
setValueFanout: 5,
|
|
||||||
minPeerCount: 20,
|
|
||||||
minPeerRefreshTimeMs: 2000,
|
|
||||||
validateDialInfoReceiptTimeMs: 5000,
|
|
||||||
),
|
|
||||||
upnp: true,
|
|
||||||
natpmp: true,
|
|
||||||
enableLocalPeerScope: false,
|
|
||||||
restrictedNatRetries: 3,
|
|
||||||
tls: VeilidConfigTLS(
|
|
||||||
certificatePath: "",
|
|
||||||
privateKeyPath: "",
|
|
||||||
connectionInitialTimeoutMs: 2000,
|
|
||||||
),
|
|
||||||
application: VeilidConfigApplication(
|
|
||||||
https: VeilidConfigHTTPS(
|
|
||||||
enabled: false,
|
|
||||||
listenAddress: "",
|
|
||||||
path: "",
|
|
||||||
url: null,
|
|
||||||
),
|
|
||||||
http: VeilidConfigHTTP(
|
|
||||||
enabled: false,
|
|
||||||
listenAddress: "",
|
|
||||||
path: "",
|
|
||||||
url: null,
|
|
||||||
)),
|
|
||||||
protocol: VeilidConfigProtocol(
|
|
||||||
udp: VeilidConfigUDP(
|
|
||||||
enabled: !kIsWeb,
|
|
||||||
socketPoolSize: 0,
|
|
||||||
listenAddress: "",
|
listenAddress: "",
|
||||||
publicAddress: null,
|
path: "",
|
||||||
),
|
|
||||||
tcp: VeilidConfigTCP(
|
|
||||||
connect: !kIsWeb,
|
|
||||||
listen: !kIsWeb,
|
|
||||||
maxConnections: 32,
|
|
||||||
listenAddress: "",
|
|
||||||
publicAddress: null,
|
|
||||||
),
|
|
||||||
ws: VeilidConfigWS(
|
|
||||||
connect: true,
|
|
||||||
listen: !kIsWeb,
|
|
||||||
maxConnections: 16,
|
|
||||||
listenAddress: "",
|
|
||||||
path: "ws",
|
|
||||||
url: null,
|
url: null,
|
||||||
),
|
),
|
||||||
wss: VeilidConfigWSS(
|
http: VeilidConfigHTTP(
|
||||||
connect: true,
|
enabled: false,
|
||||||
listen: false,
|
|
||||||
maxConnections: 16,
|
|
||||||
listenAddress: "",
|
listenAddress: "",
|
||||||
path: "ws",
|
path: "",
|
||||||
url: null,
|
url: null,
|
||||||
),
|
)),
|
||||||
|
protocol: VeilidConfigProtocol(
|
||||||
|
udp: VeilidConfigUDP(
|
||||||
|
enabled: !kIsWeb,
|
||||||
|
socketPoolSize: 0,
|
||||||
|
listenAddress: "",
|
||||||
|
publicAddress: null,
|
||||||
),
|
),
|
||||||
leases: VeilidConfigLeases(
|
tcp: VeilidConfigTCP(
|
||||||
maxServerSignalLeases: 256,
|
connect: !kIsWeb,
|
||||||
maxServerRelayLeases: 8,
|
listen: !kIsWeb,
|
||||||
maxClientSignalLeases: 2,
|
maxConnections: 32,
|
||||||
maxClientRelayLeases: 2,
|
listenAddress: "",
|
||||||
)),
|
publicAddress: null,
|
||||||
|
),
|
||||||
|
ws: VeilidConfigWS(
|
||||||
|
connect: true,
|
||||||
|
listen: !kIsWeb,
|
||||||
|
maxConnections: 16,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "ws",
|
||||||
|
url: null,
|
||||||
|
),
|
||||||
|
wss: VeilidConfigWSS(
|
||||||
|
connect: true,
|
||||||
|
listen: false,
|
||||||
|
maxConnections: 16,
|
||||||
|
listenAddress: "",
|
||||||
|
path: "ws",
|
||||||
|
url: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -518,36 +518,6 @@ class VeilidConfigRoutingTable {
|
|||||||
|
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
class VeilidConfigLeases {
|
|
||||||
int maxServerSignalLeases;
|
|
||||||
int maxServerRelayLeases;
|
|
||||||
int maxClientSignalLeases;
|
|
||||||
int maxClientRelayLeases;
|
|
||||||
|
|
||||||
VeilidConfigLeases(
|
|
||||||
{required this.maxServerSignalLeases,
|
|
||||||
required this.maxServerRelayLeases,
|
|
||||||
required this.maxClientSignalLeases,
|
|
||||||
required this.maxClientRelayLeases});
|
|
||||||
|
|
||||||
Map<String, dynamic> get json {
|
|
||||||
return {
|
|
||||||
'max_server_signal_leases': maxServerSignalLeases,
|
|
||||||
'max_server_relay_leases': maxServerRelayLeases,
|
|
||||||
'max_client_signal_leases': maxClientSignalLeases,
|
|
||||||
'max_client_relay_leases': maxClientRelayLeases
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
VeilidConfigLeases.fromJson(Map<String, dynamic> json)
|
|
||||||
: maxServerSignalLeases = json['max_server_signal_leases'],
|
|
||||||
maxServerRelayLeases = json['max_server_relay_leases'],
|
|
||||||
maxClientSignalLeases = json['max_client_signal_leases'],
|
|
||||||
maxClientRelayLeases = json['max_client_relay_leases'];
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////
|
|
||||||
|
|
||||||
class VeilidConfigNetwork {
|
class VeilidConfigNetwork {
|
||||||
int connectionInitialTimeoutMs;
|
int connectionInitialTimeoutMs;
|
||||||
int connectionInactivityTimeoutMs;
|
int connectionInactivityTimeoutMs;
|
||||||
@ -556,9 +526,12 @@ class VeilidConfigNetwork {
|
|||||||
int maxConnectionsPerIp6PrefixSize;
|
int maxConnectionsPerIp6PrefixSize;
|
||||||
int maxConnectionFrequencyPerMin;
|
int maxConnectionFrequencyPerMin;
|
||||||
int clientWhitelistTimeoutMs;
|
int clientWhitelistTimeoutMs;
|
||||||
|
int reverseConnectionReceiptTimeMs;
|
||||||
|
int holePunchReceiptTimeMs;
|
||||||
String nodeId;
|
String nodeId;
|
||||||
String nodeIdSecret;
|
String nodeIdSecret;
|
||||||
List<String> bootstrap;
|
List<String> bootstrap;
|
||||||
|
List<String> bootstrapNodes;
|
||||||
VeilidConfigRoutingTable routingTable;
|
VeilidConfigRoutingTable routingTable;
|
||||||
VeilidConfigRPC rpc;
|
VeilidConfigRPC rpc;
|
||||||
VeilidConfigDHT dht;
|
VeilidConfigDHT dht;
|
||||||
@ -569,7 +542,6 @@ class VeilidConfigNetwork {
|
|||||||
VeilidConfigTLS tls;
|
VeilidConfigTLS tls;
|
||||||
VeilidConfigApplication application;
|
VeilidConfigApplication application;
|
||||||
VeilidConfigProtocol protocol;
|
VeilidConfigProtocol protocol;
|
||||||
VeilidConfigLeases leases;
|
|
||||||
|
|
||||||
VeilidConfigNetwork({
|
VeilidConfigNetwork({
|
||||||
required this.connectionInitialTimeoutMs,
|
required this.connectionInitialTimeoutMs,
|
||||||
@ -579,9 +551,12 @@ class VeilidConfigNetwork {
|
|||||||
required this.maxConnectionsPerIp6PrefixSize,
|
required this.maxConnectionsPerIp6PrefixSize,
|
||||||
required this.maxConnectionFrequencyPerMin,
|
required this.maxConnectionFrequencyPerMin,
|
||||||
required this.clientWhitelistTimeoutMs,
|
required this.clientWhitelistTimeoutMs,
|
||||||
|
required this.reverseConnectionReceiptTimeMs,
|
||||||
|
required this.holePunchReceiptTimeMs,
|
||||||
required this.nodeId,
|
required this.nodeId,
|
||||||
required this.nodeIdSecret,
|
required this.nodeIdSecret,
|
||||||
required this.bootstrap,
|
required this.bootstrap,
|
||||||
|
required this.bootstrapNodes,
|
||||||
required this.routingTable,
|
required this.routingTable,
|
||||||
required this.rpc,
|
required this.rpc,
|
||||||
required this.dht,
|
required this.dht,
|
||||||
@ -592,7 +567,6 @@ class VeilidConfigNetwork {
|
|||||||
required this.tls,
|
required this.tls,
|
||||||
required this.application,
|
required this.application,
|
||||||
required this.protocol,
|
required this.protocol,
|
||||||
required this.leases,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> get json {
|
Map<String, dynamic> get json {
|
||||||
@ -604,9 +578,12 @@ class VeilidConfigNetwork {
|
|||||||
'max_connections_per_ip6_prefix_size': maxConnectionsPerIp6PrefixSize,
|
'max_connections_per_ip6_prefix_size': maxConnectionsPerIp6PrefixSize,
|
||||||
'max_connection_frequency_per_min': maxConnectionFrequencyPerMin,
|
'max_connection_frequency_per_min': maxConnectionFrequencyPerMin,
|
||||||
'client_whitelist_timeout_ms': clientWhitelistTimeoutMs,
|
'client_whitelist_timeout_ms': clientWhitelistTimeoutMs,
|
||||||
|
'reverse_connection_receipt_time_ms': reverseConnectionReceiptTimeMs,
|
||||||
|
'hole_punch_receipt_time_ms': holePunchReceiptTimeMs,
|
||||||
'node_id': nodeId,
|
'node_id': nodeId,
|
||||||
'node_id_secret': nodeIdSecret,
|
'node_id_secret': nodeIdSecret,
|
||||||
'bootstrap': bootstrap,
|
'bootstrap': bootstrap,
|
||||||
|
'bootstrap_nodes': bootstrapNodes,
|
||||||
'routing_table': routingTable.json,
|
'routing_table': routingTable.json,
|
||||||
'rpc': rpc.json,
|
'rpc': rpc.json,
|
||||||
'dht': dht.json,
|
'dht': dht.json,
|
||||||
@ -617,7 +594,6 @@ class VeilidConfigNetwork {
|
|||||||
'tls': tls.json,
|
'tls': tls.json,
|
||||||
'application': application.json,
|
'application': application.json,
|
||||||
'protocol': protocol.json,
|
'protocol': protocol.json,
|
||||||
'leases': leases.json,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,9 +607,13 @@ class VeilidConfigNetwork {
|
|||||||
json['max_connections_per_ip6_prefix_size'],
|
json['max_connections_per_ip6_prefix_size'],
|
||||||
maxConnectionFrequencyPerMin = json['max_connection_frequency_per_min'],
|
maxConnectionFrequencyPerMin = json['max_connection_frequency_per_min'],
|
||||||
clientWhitelistTimeoutMs = json['client_whitelist_timeout_ms'],
|
clientWhitelistTimeoutMs = json['client_whitelist_timeout_ms'],
|
||||||
|
reverseConnectionReceiptTimeMs =
|
||||||
|
json['reverse_connection_receipt_time_ms'],
|
||||||
|
holePunchReceiptTimeMs = json['hole_punch_receipt_time_ms'],
|
||||||
nodeId = json['node_id'],
|
nodeId = json['node_id'],
|
||||||
nodeIdSecret = json['node_id_secret'],
|
nodeIdSecret = json['node_id_secret'],
|
||||||
bootstrap = json['bootstrap'],
|
bootstrap = json['bootstrap'],
|
||||||
|
bootstrapNodes = json['bootstrap_nodes'],
|
||||||
routingTable = VeilidConfigRoutingTable.fromJson(json['routing_table']),
|
routingTable = VeilidConfigRoutingTable.fromJson(json['routing_table']),
|
||||||
rpc = VeilidConfigRPC.fromJson(json['rpc']),
|
rpc = VeilidConfigRPC.fromJson(json['rpc']),
|
||||||
dht = VeilidConfigDHT.fromJson(json['dht']),
|
dht = VeilidConfigDHT.fromJson(json['dht']),
|
||||||
@ -643,8 +623,7 @@ class VeilidConfigNetwork {
|
|||||||
restrictedNatRetries = json['restricted_nat_retries'],
|
restrictedNatRetries = json['restricted_nat_retries'],
|
||||||
tls = VeilidConfigTLS.fromJson(json['tls']),
|
tls = VeilidConfigTLS.fromJson(json['tls']),
|
||||||
application = VeilidConfigApplication.fromJson(json['application']),
|
application = VeilidConfigApplication.fromJson(json['application']),
|
||||||
protocol = VeilidConfigProtocol.fromJson(json['protocol']),
|
protocol = VeilidConfigProtocol.fromJson(json['protocol']);
|
||||||
leases = VeilidConfigLeases.fromJson(json['leases']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
@ -824,6 +803,11 @@ abstract class VeilidUpdate {
|
|||||||
{
|
{
|
||||||
return VeilidUpdateAttachment(attachmentStateFromJson(json["state"]));
|
return VeilidUpdateAttachment(attachmentStateFromJson(json["state"]));
|
||||||
}
|
}
|
||||||
|
case "Network":
|
||||||
|
{
|
||||||
|
return VeilidUpdateNetwork(
|
||||||
|
json["started"], json["bps_up"], json["bps_down"]);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw VeilidAPIExceptionInternal(
|
throw VeilidAPIExceptionInternal(
|
||||||
@ -846,16 +830,50 @@ class VeilidUpdateAttachment implements VeilidUpdate {
|
|||||||
VeilidUpdateAttachment(this.state);
|
VeilidUpdateAttachment(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VeilidUpdateNetwork implements VeilidUpdate {
|
||||||
|
final bool started;
|
||||||
|
final int bpsDown;
|
||||||
|
final int bpsUp;
|
||||||
|
//
|
||||||
|
VeilidUpdateNetwork(this.started, this.bpsDown, this.bpsUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// VeilidStateAttachment
|
||||||
|
|
||||||
|
class VeilidStateAttachment {
|
||||||
|
final AttachmentState state;
|
||||||
|
|
||||||
|
VeilidStateAttachment(this.state);
|
||||||
|
|
||||||
|
VeilidStateAttachment.fromJson(Map<String, dynamic> json)
|
||||||
|
: state = attachmentStateFromJson(json['state']);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
/// VeilidStateNetwork
|
||||||
|
|
||||||
|
class VeilidStateNetwork {
|
||||||
|
final bool started;
|
||||||
|
|
||||||
|
VeilidStateNetwork(this.started);
|
||||||
|
|
||||||
|
VeilidStateNetwork.fromJson(Map<String, dynamic> json)
|
||||||
|
: started = json['started'];
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
/// VeilidState
|
/// VeilidState
|
||||||
|
|
||||||
class VeilidState {
|
class VeilidState {
|
||||||
final AttachmentState attachment;
|
final VeilidStateAttachment attachment;
|
||||||
|
final VeilidStateNetwork network;
|
||||||
|
|
||||||
VeilidState(this.attachment);
|
VeilidState(this.attachment, this.network);
|
||||||
|
|
||||||
VeilidState.fromJson(Map<String, dynamic> json)
|
VeilidState.fromJson(Map<String, dynamic> json)
|
||||||
: attachment = attachmentStateFromJson(json['attachment']);
|
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
||||||
|
network = VeilidStateNetwork.fromJson(json['network']);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
@ -33,12 +33,19 @@ ctrlc = "^3"
|
|||||||
lazy_static = "^1"
|
lazy_static = "^1"
|
||||||
bugsalot = "^0"
|
bugsalot = "^0"
|
||||||
flume = { version = "^0", features = ["async"] }
|
flume = { version = "^0", features = ["async"] }
|
||||||
|
rpassword = "^6"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
windows-service = "^0"
|
windows-service = "^0"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
daemonize = "^0"
|
daemonize = "^0"
|
||||||
|
signal-hook = "^0"
|
||||||
|
signal-hook-async-std = "^0"
|
||||||
|
nix = "^0"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
systemd-journal-logger = "^0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serial_test = "^0"
|
serial_test = "^0"
|
||||||
|
@ -11,19 +11,27 @@ enum AttachmentState {
|
|||||||
detaching @7;
|
detaching @7;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Attachment {
|
struct VeilidStateAttachment {
|
||||||
state @0 :AttachmentState;
|
state @0 :AttachmentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VeilidStateNetwork {
|
||||||
|
started @0 :Bool;
|
||||||
|
bpsDown @1 :UInt64;
|
||||||
|
bpsUp @2 :UInt64;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VeilidUpdate {
|
struct VeilidUpdate {
|
||||||
union {
|
union {
|
||||||
attachment @0 :Attachment;
|
attachment @0 :VeilidStateAttachment;
|
||||||
shutdown @1 :Void;
|
network @1 :VeilidStateNetwork;
|
||||||
|
shutdown @2 :Void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VeilidState {
|
struct VeilidState {
|
||||||
attachment @0 :Attachment;
|
attachment @0 :VeilidStateAttachment;
|
||||||
|
network @1 :VeilidStateNetwork;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Registration {}
|
interface Registration {}
|
||||||
|
@ -36,16 +36,26 @@ fn convert_update(
|
|||||||
mut rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
mut rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
||||||
) {
|
) {
|
||||||
match update {
|
match update {
|
||||||
veilid_core::VeilidUpdate::Log {
|
veilid_core::VeilidUpdate::Log(veilid_core::VeilidStateLog {
|
||||||
log_level: _,
|
log_level: _,
|
||||||
message: _,
|
message: _,
|
||||||
} => {
|
}) => {
|
||||||
panic!("Should not be logging to api in server!");
|
panic!("Should not be logging to api in server!");
|
||||||
}
|
}
|
||||||
veilid_core::VeilidUpdate::Attachment { state } => {
|
veilid_core::VeilidUpdate::Attachment(veilid_core::VeilidStateAttachment { state }) => {
|
||||||
let mut att = rpc_update.init_attachment();
|
let mut att = rpc_update.init_attachment();
|
||||||
att.set_state(convert_attachment_state(state));
|
att.set_state(convert_attachment_state(state));
|
||||||
}
|
}
|
||||||
|
veilid_core::VeilidUpdate::Network(veilid_core::VeilidStateNetwork {
|
||||||
|
started,
|
||||||
|
bps_down,
|
||||||
|
bps_up,
|
||||||
|
}) => {
|
||||||
|
let mut nb = rpc_update.init_network();
|
||||||
|
nb.set_started(*started);
|
||||||
|
nb.set_bps_down(*bps_down);
|
||||||
|
nb.set_bps_up(*bps_up);
|
||||||
|
}
|
||||||
veilid_core::VeilidUpdate::Shutdown => {
|
veilid_core::VeilidUpdate::Shutdown => {
|
||||||
rpc_update.set_shutdown(());
|
rpc_update.set_shutdown(());
|
||||||
}
|
}
|
||||||
@ -54,11 +64,15 @@ fn convert_update(
|
|||||||
|
|
||||||
fn convert_state(
|
fn convert_state(
|
||||||
state: &veilid_core::VeilidState,
|
state: &veilid_core::VeilidState,
|
||||||
rpc_state: crate::veilid_client_capnp::veilid_state::Builder,
|
mut rpc_state: crate::veilid_client_capnp::veilid_state::Builder,
|
||||||
) {
|
) {
|
||||||
rpc_state
|
let mut ab = rpc_state.reborrow().init_attachment();
|
||||||
.init_attachment()
|
ab.set_state(convert_attachment_state(&state.attachment.state));
|
||||||
.set_state(convert_attachment_state(&state.attachment));
|
|
||||||
|
let mut nb = rpc_state.reborrow().init_network();
|
||||||
|
nb.set_started(state.network.started);
|
||||||
|
nb.set_bps_down(state.network.bps_down);
|
||||||
|
nb.set_bps_up(state.network.bps_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- interface Registration ---------------------------------
|
// --- interface Registration ---------------------------------
|
||||||
|
@ -2,6 +2,7 @@ use crate::settings::*;
|
|||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use veilid_core::{DHTKey, DHTKeySecret};
|
||||||
|
|
||||||
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
|
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
|
||||||
let matches = Command::new("veilid-server")
|
let matches = Command::new("veilid-server")
|
||||||
@ -44,8 +45,8 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
|||||||
.help("Turn on trace logging on the terminal"),
|
.help("Turn on trace logging on the terminal"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("subnode_index")
|
Arg::new("subnode-index")
|
||||||
.long("subnode_index")
|
.long("subnode-index")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Run as an extra daemon on the same machine for testing purposes, specify a number greater than zero to offset the listening ports"),
|
.help("Run as an extra daemon on the same machine for testing purposes, specify a number greater than zero to offset the listening ports"),
|
||||||
)
|
)
|
||||||
@ -54,6 +55,14 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
|||||||
.long("generate-dht-key")
|
.long("generate-dht-key")
|
||||||
.help("Only generate a new dht key and print it"),
|
.help("Only generate a new dht key and print it"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("set-node-id")
|
||||||
|
.long("set-node-id")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("ID")
|
||||||
|
.help("Set the node id and secret key")
|
||||||
|
.long_help("To specify both node id and secret key on the command line, use a ID:SECRET syntax with a colon, like:\n zsVXz5aTU98vZxwTcDmvpcnO5g1B2jRO3wpdNiDrRgw:gJzQLmzuBvA-dFvEmLcYvLoO5bh7hzCWFzfpJHapZKg\nIf no colon is used, the node id is specified, and a prompt appears to enter the secret key interactively.")
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("delete-protected-store")
|
Arg::new("delete-protected-store")
|
||||||
.long("delete-protected-store")
|
.long("delete-protected-store")
|
||||||
@ -74,12 +83,25 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
|||||||
.long("dump-config")
|
.long("dump-config")
|
||||||
.help("Instead of running the server, print the configuration it would use to the console"),
|
.help("Instead of running the server, print the configuration it would use to the console"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("dump-txt-record")
|
||||||
|
.long("dump-txt-record")
|
||||||
|
.help("Prints the bootstrap TXT record for this node and then quits")
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("bootstrap")
|
Arg::new("bootstrap")
|
||||||
.long("bootstrap")
|
.long("bootstrap")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("BOOTSTRAP_LIST")
|
.value_name("BOOTSTRAP_LIST")
|
||||||
.help("Specify a list of bootstrap servers to use"),
|
.help("Specify a list of bootstrap hostnames to use")
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("bootstrap-nodes")
|
||||||
|
.conflicts_with("bootstrap")
|
||||||
|
.long("bootstrap-nodes")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("BOOTSTRAP_NODE_LIST")
|
||||||
|
.help("Specify a list of bootstrap node dialinfos to use"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("local")
|
Arg::new("local")
|
||||||
@ -123,16 +145,16 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
|||||||
|
|
||||||
// Set config from command line
|
// Set config from command line
|
||||||
if matches.occurrences_of("daemon") != 0 {
|
if matches.occurrences_of("daemon") != 0 {
|
||||||
settingsrw.daemon = true;
|
settingsrw.daemon.enabled = true;
|
||||||
settingsrw.logging.terminal.enabled = false;
|
settingsrw.logging.terminal.enabled = false;
|
||||||
}
|
}
|
||||||
if matches.occurrences_of("subnode_index") != 0 {
|
if matches.occurrences_of("subnode-index") != 0 {
|
||||||
let subnode_index = match matches.value_of("subnode_index") {
|
let subnode_index = match matches.value_of("subnode-index") {
|
||||||
Some(x) => x
|
Some(x) => x
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|e| format!("couldn't parse subnode index: {}", e))?,
|
.map_err(|e| format!("couldn't parse subnode index: {}", e))?,
|
||||||
None => {
|
None => {
|
||||||
return Err("value not specified for subnode_index".to_owned());
|
return Err("value not specified for subnode-index".to_owned());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if subnode_index == 0 {
|
if subnode_index == 0 {
|
||||||
@ -164,16 +186,61 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
|||||||
if matches.occurrences_of("delete-table-store") != 0 {
|
if matches.occurrences_of("delete-table-store") != 0 {
|
||||||
settingsrw.core.table_store.delete = true;
|
settingsrw.core.table_store.delete = true;
|
||||||
}
|
}
|
||||||
|
if matches.occurrences_of("dump-txt-record") != 0 {
|
||||||
|
// Turn off terminal logging so we can be interactive
|
||||||
|
settingsrw.logging.terminal.enabled = false;
|
||||||
|
}
|
||||||
|
if let Some(v) = matches.value_of("set-node-id") {
|
||||||
|
// Turn off terminal logging so we can be interactive
|
||||||
|
settingsrw.logging.terminal.enabled = false;
|
||||||
|
|
||||||
|
// Split or get secret
|
||||||
|
let (k, s) = if let Some((k, s)) = v.split_once(':') {
|
||||||
|
let k = DHTKey::try_decode(k)?;
|
||||||
|
let s = DHTKeySecret::try_decode(s)?;
|
||||||
|
(k, s)
|
||||||
|
} else {
|
||||||
|
let k = DHTKey::try_decode(v)?;
|
||||||
|
let buffer = rpassword::prompt_password("Enter secret key (will not echo): ")
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
let buffer = buffer.trim().to_string();
|
||||||
|
let s = DHTKeySecret::try_decode(&buffer)?;
|
||||||
|
(k, s)
|
||||||
|
};
|
||||||
|
settingsrw.core.network.node_id = k;
|
||||||
|
settingsrw.core.network.node_id_secret = s;
|
||||||
|
}
|
||||||
|
|
||||||
if matches.occurrences_of("bootstrap") != 0 {
|
if matches.occurrences_of("bootstrap") != 0 {
|
||||||
let bootstrap = match matches.value_of("bootstrap") {
|
let bootstrap_list = match matches.value_of("bootstrap-list") {
|
||||||
Some(x) => {
|
Some(x) => {
|
||||||
println!("Overriding bootstrap with: ");
|
println!("Overriding bootstrap list with: ");
|
||||||
|
let mut out: Vec<String> = Vec::new();
|
||||||
|
for x in x.split(',') {
|
||||||
|
let x = x.trim().to_string();
|
||||||
|
println!(" {}", x);
|
||||||
|
out.push(x);
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err("value not specified for bootstrap list".to_owned());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
settingsrw.core.network.bootstrap = bootstrap_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches.occurrences_of("bootstrap-nodes") != 0 {
|
||||||
|
let bootstrap_list = match matches.value_of("bootstrap-list") {
|
||||||
|
Some(x) => {
|
||||||
|
println!("Overriding bootstrap node list with: ");
|
||||||
let mut out: Vec<ParsedNodeDialInfo> = Vec::new();
|
let mut out: Vec<ParsedNodeDialInfo> = Vec::new();
|
||||||
for x in x.split(',') {
|
for x in x.split(',') {
|
||||||
|
let x = x.trim();
|
||||||
println!(" {}", x);
|
println!(" {}", x);
|
||||||
out.push(ParsedNodeDialInfo::from_str(x).map_err(|e| {
|
out.push(ParsedNodeDialInfo::from_str(x).map_err(|e| {
|
||||||
format!(
|
format!(
|
||||||
"unable to parse dial info in bootstrap list: {} for {}",
|
"unable to parse dial info in bootstrap node list: {} for {}",
|
||||||
e, x
|
e, x
|
||||||
)
|
)
|
||||||
})?);
|
})?);
|
||||||
@ -181,10 +248,10 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err("value not specified for bootstrap".to_owned());
|
return Err("value not specified for bootstrap node list".to_owned());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
settingsrw.core.network.bootstrap = bootstrap;
|
settingsrw.core.network.bootstrap_nodes = bootstrap_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply subnode index if we're testing
|
// Apply subnode index if we're testing
|
||||||
|
@ -28,7 +28,6 @@ fn main() -> Result<(), String> {
|
|||||||
|
|
||||||
// --- Dump Config ---
|
// --- Dump Config ---
|
||||||
if matches.occurrences_of("dump-config") != 0 {
|
if matches.occurrences_of("dump-config") != 0 {
|
||||||
//let cfg = config::Config::try_from(&*settingsr);
|
|
||||||
return serde_yaml::to_writer(std::io::stdout(), &*settings.read())
|
return serde_yaml::to_writer(std::io::stdout(), &*settings.read())
|
||||||
.map_err(|e| e.to_string());
|
.map_err(|e| e.to_string());
|
||||||
}
|
}
|
||||||
@ -40,8 +39,37 @@ fn main() -> Result<(), String> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if we're just running a quick command
|
||||||
|
let (server_mode, success, failure) = if matches.occurrences_of("set-node-id") != 0 {
|
||||||
|
(
|
||||||
|
ServerMode::ShutdownImmediate,
|
||||||
|
"Node Id and Secret set successfully",
|
||||||
|
"Failed to set Node Id and Secret",
|
||||||
|
)
|
||||||
|
} else if matches.occurrences_of("dump-txt-record") != 0 {
|
||||||
|
(ServerMode::DumpTXTRecord, "", "Failed to dump txt record")
|
||||||
|
} else {
|
||||||
|
(ServerMode::Normal, "", "")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle non-normal server modes
|
||||||
|
if !matches!(server_mode, ServerMode::Normal) {
|
||||||
|
// Init combined console/file logger
|
||||||
|
let logs = VeilidLogs::setup_normal_logs(settings.clone())?;
|
||||||
|
// run the server to set the node id and quit
|
||||||
|
return task::block_on(async { run_veilid_server(settings, logs, server_mode).await })
|
||||||
|
.map(|v| {
|
||||||
|
println!("{}", success);
|
||||||
|
v
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
println!("{}", failure);
|
||||||
|
e
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// --- Daemon Mode ----
|
// --- Daemon Mode ----
|
||||||
if settings.read().daemon {
|
if settings.read().daemon.enabled {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(windows)] {
|
if #[cfg(windows)] {
|
||||||
return windows::run_service(settings, matches).map_err(|e| format!("{}", e));
|
return windows::run_service(settings, matches).map_err(|e| format!("{}", e));
|
||||||
@ -61,5 +89,5 @@ fn main() -> Result<(), String> {
|
|||||||
.expect("Error setting Ctrl-C handler");
|
.expect("Error setting Ctrl-C handler");
|
||||||
|
|
||||||
// Run the server loop
|
// Run the server loop
|
||||||
task::block_on(async { run_veilid_server(settings, logs).await })
|
task::block_on(async { run_veilid_server(settings, logs, server_mode).await })
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,13 @@ use std::sync::Arc;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use veilid_core::xx::SingleShotEventual;
|
use veilid_core::xx::SingleShotEventual;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum ServerMode {
|
||||||
|
Normal,
|
||||||
|
ShutdownImmediate,
|
||||||
|
DumpTXTRecord,
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SHUTDOWN_SWITCH: Mutex<Option<SingleShotEventual<()>>> =
|
static ref SHUTDOWN_SWITCH: Mutex<Option<SingleShotEventual<()>>> =
|
||||||
Mutex::new(Some(SingleShotEventual::new(())));
|
Mutex::new(Some(SingleShotEventual::new(())));
|
||||||
@ -21,7 +28,11 @@ pub fn shutdown() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(), String> {
|
pub async fn run_veilid_server(
|
||||||
|
settings: Settings,
|
||||||
|
logs: VeilidLogs,
|
||||||
|
server_mode: ServerMode,
|
||||||
|
) -> Result<(), String> {
|
||||||
let settingsr = settings.read();
|
let settingsr = settings.read();
|
||||||
|
|
||||||
// Create client api state change pipe
|
// Create client api state change pipe
|
||||||
@ -44,7 +55,7 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
.map_err(|e| format!("VeilidCore startup failed: {}", e))?;
|
.map_err(|e| format!("VeilidCore startup failed: {}", e))?;
|
||||||
|
|
||||||
// Start client api if one is requested
|
// Start client api if one is requested
|
||||||
let mut capi = if settingsr.client_api.enabled {
|
let mut capi = if settingsr.client_api.enabled && matches!(server_mode, ServerMode::Normal) {
|
||||||
let some_capi = client_api::ClientApi::new(veilid_api.clone());
|
let some_capi = client_api::ClientApi::new(veilid_api.clone());
|
||||||
some_capi
|
some_capi
|
||||||
.clone()
|
.clone()
|
||||||
@ -55,16 +66,18 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Drop rwlock on settings
|
// Drop rwlock on settings
|
||||||
let auto_attach = settingsr.auto_attach;
|
let auto_attach = settingsr.auto_attach || !matches!(server_mode, ServerMode::Normal);
|
||||||
drop(settingsr);
|
drop(settingsr);
|
||||||
|
|
||||||
// Handle state changes on main thread for capnproto rpc
|
// Process all updates
|
||||||
let update_receiver_jh = capi.clone().map(|capi| {
|
let capi2 = capi.clone();
|
||||||
async_std::task::spawn_local(async move {
|
let update_receiver_jh = async_std::task::spawn_local(async move {
|
||||||
while let Ok(change) = receiver.recv_async().await {
|
while let Ok(change) = receiver.recv_async().await {
|
||||||
|
if let Some(capi) = &capi2 {
|
||||||
|
// Handle state changes on main thread for capnproto rpc
|
||||||
capi.clone().handle_update(change);
|
capi.clone().handle_update(change);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
});
|
});
|
||||||
// Handle log messages on main thread for capnproto rpc
|
// Handle log messages on main thread for capnproto rpc
|
||||||
let client_log_receiver_jh = capi.clone().and_then(|capi| {
|
let client_log_receiver_jh = capi.clone().and_then(|capi| {
|
||||||
@ -103,14 +116,49 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Auto-attach if desired
|
// Auto-attach if desired
|
||||||
|
let mut out = Ok(());
|
||||||
if auto_attach {
|
if auto_attach {
|
||||||
info!("Auto-attach to the Veilid network");
|
info!("Auto-attach to the Veilid network");
|
||||||
if let Err(e) = veilid_api.attach().await {
|
if let Err(e) = veilid_api.attach().await {
|
||||||
error!("Auto-attaching to the Veilid network failed: {:?}", e);
|
let outerr = format!("Auto-attaching to the Veilid network failed: {:?}", e);
|
||||||
|
error!("{}", outerr);
|
||||||
|
out = Err(outerr);
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process dump-txt-record
|
||||||
|
if matches!(server_mode, ServerMode::DumpTXTRecord) {
|
||||||
|
let start_time = Instant::now();
|
||||||
|
while Instant::now().duration_since(start_time) < Duration::from_secs(10) {
|
||||||
|
match veilid_api.get_state().await {
|
||||||
|
Ok(vs) => {
|
||||||
|
if vs.network.started {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let outerr = format!("Getting state failed: {:?}", e);
|
||||||
|
error!("{}", outerr);
|
||||||
|
out = Err(outerr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async_std::task::sleep(Duration::from_millis(100)).await;
|
||||||
|
}
|
||||||
|
match veilid_api.debug("dialinfo txt".to_string()).await {
|
||||||
|
Ok(v) => {
|
||||||
|
print!("{}", v);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let outerr = format!("Getting dial info failed: {:?}", e);
|
||||||
|
error!("{}", outerr);
|
||||||
|
out = Err(outerr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
// Idle while waiting to exit
|
// Idle while waiting to exit
|
||||||
let shutdown_switch = {
|
let shutdown_switch = {
|
||||||
let shutdown_switch_locked = SHUTDOWN_SWITCH.lock();
|
let shutdown_switch_locked = SHUTDOWN_SWITCH.lock();
|
||||||
@ -134,14 +182,12 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for update receiver to exit
|
// Wait for update receiver to exit
|
||||||
if let Some(update_receiver_jh) = update_receiver_jh {
|
update_receiver_jh.await;
|
||||||
update_receiver_jh.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for client api log receiver to exit
|
// Wait for client api log receiver to exit
|
||||||
if let Some(client_log_receiver_jh) = client_log_receiver_jh {
|
if let Some(client_log_receiver_jh) = client_log_receiver_jh {
|
||||||
client_log_receiver_jh.await;
|
client_log_receiver_jh.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
out
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,16 @@ use veilid_core::xx::*;
|
|||||||
pub fn load_default_config() -> Result<config::Config, config::ConfigError> {
|
pub fn load_default_config() -> Result<config::Config, config::ConfigError> {
|
||||||
let default_config = String::from(
|
let default_config = String::from(
|
||||||
r#"---
|
r#"---
|
||||||
daemon: false
|
daemon:
|
||||||
|
enabled: false
|
||||||
client_api:
|
client_api:
|
||||||
enabled: true
|
enabled: true
|
||||||
listen_address: 'localhost:5959'
|
listen_address: 'localhost:5959'
|
||||||
auto_attach: true
|
auto_attach: true
|
||||||
logging:
|
logging:
|
||||||
|
system:
|
||||||
|
enabled: false
|
||||||
|
level: 'info'
|
||||||
terminal:
|
terminal:
|
||||||
enabled: true
|
enabled: true
|
||||||
level: 'info'
|
level: 'info'
|
||||||
@ -31,14 +35,14 @@ logging:
|
|||||||
append: true
|
append: true
|
||||||
level: 'info'
|
level: 'info'
|
||||||
client:
|
client:
|
||||||
enabled: true
|
enabled: false
|
||||||
level: 'info'
|
level: 'info'
|
||||||
testing:
|
testing:
|
||||||
subnode_index: 0
|
subnode_index: 0
|
||||||
core:
|
core:
|
||||||
protected_store:
|
protected_store:
|
||||||
allow_insecure_fallback: true
|
allow_insecure_fallback: true
|
||||||
always_use_insecure_storage: false
|
always_use_insecure_storage: true
|
||||||
insecure_fallback_directory: '%INSECURE_FALLBACK_DIRECTORY%'
|
insecure_fallback_directory: '%INSECURE_FALLBACK_DIRECTORY%'
|
||||||
delete: false
|
delete: false
|
||||||
table_store:
|
table_store:
|
||||||
@ -55,9 +59,12 @@ core:
|
|||||||
max_connections_per_ip6_prefix_size: 56
|
max_connections_per_ip6_prefix_size: 56
|
||||||
max_connection_frequency_per_min: 8
|
max_connection_frequency_per_min: 8
|
||||||
client_whitelist_timeout_ms: 300000
|
client_whitelist_timeout_ms: 300000
|
||||||
|
reverse_connection_receipt_time_ms: 5000
|
||||||
|
hole_punch_receipt_time_ms: 5000
|
||||||
node_id: ''
|
node_id: ''
|
||||||
node_id_secret: ''
|
node_id_secret: ''
|
||||||
bootstrap: []
|
bootstrap: ['bootstrap.veilid.net']
|
||||||
|
bootstrap_nodes: []
|
||||||
routing_table:
|
routing_table:
|
||||||
limit_over_attached: 64
|
limit_over_attached: 64
|
||||||
limit_fully_attached: 32
|
limit_fully_attached: 32
|
||||||
@ -90,8 +97,8 @@ core:
|
|||||||
enable_local_peer_scope: false
|
enable_local_peer_scope: false
|
||||||
restricted_nat_retries: 3
|
restricted_nat_retries: 3
|
||||||
tls:
|
tls:
|
||||||
certificate_path: '/etc/veilid/server.crt'
|
certificate_path: '/etc/veilid-server/server.crt'
|
||||||
private_key_path: '/etc/veilid/private/server.key'
|
private_key_path: '/etc/veilid-server/private/server.key'
|
||||||
connection_initial_timeout_ms: 2000
|
connection_initial_timeout_ms: 2000
|
||||||
application:
|
application:
|
||||||
https:
|
https:
|
||||||
@ -130,11 +137,6 @@ core:
|
|||||||
listen_address: ':5150'
|
listen_address: ':5150'
|
||||||
path: 'ws'
|
path: 'ws'
|
||||||
# url: ''
|
# url: ''
|
||||||
leases:
|
|
||||||
max_server_signal_leases: 256
|
|
||||||
max_server_relay_leases: 8
|
|
||||||
max_client_signal_leases: 2
|
|
||||||
max_client_relay_leases: 2
|
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.replace(
|
.replace(
|
||||||
@ -402,6 +404,12 @@ pub struct File {
|
|||||||
pub level: LogLevel,
|
pub level: LogLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct System {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub level: LogLevel,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
@ -416,6 +424,7 @@ pub struct ClientApi {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Logging {
|
pub struct Logging {
|
||||||
|
pub system: System,
|
||||||
pub terminal: Terminal,
|
pub terminal: Terminal,
|
||||||
pub file: File,
|
pub file: File,
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
@ -522,14 +531,6 @@ pub struct Dht {
|
|||||||
pub validate_dial_info_receipt_time_ms: u32,
|
pub validate_dial_info_receipt_time_ms: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
pub struct Leases {
|
|
||||||
pub max_server_signal_leases: u32,
|
|
||||||
pub max_server_relay_leases: u32,
|
|
||||||
pub max_client_signal_leases: u32,
|
|
||||||
pub max_client_relay_leases: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct RoutingTable {
|
pub struct RoutingTable {
|
||||||
pub limit_over_attached: u32,
|
pub limit_over_attached: u32,
|
||||||
@ -548,9 +549,12 @@ pub struct Network {
|
|||||||
pub max_connections_per_ip6_prefix_size: u32,
|
pub max_connections_per_ip6_prefix_size: u32,
|
||||||
pub max_connection_frequency_per_min: u32,
|
pub max_connection_frequency_per_min: u32,
|
||||||
pub client_whitelist_timeout_ms: u32,
|
pub client_whitelist_timeout_ms: u32,
|
||||||
|
pub reverse_connection_receipt_time_ms: u32,
|
||||||
|
pub hole_punch_receipt_time_ms: u32,
|
||||||
pub node_id: veilid_core::DHTKey,
|
pub node_id: veilid_core::DHTKey,
|
||||||
pub node_id_secret: veilid_core::DHTKeySecret,
|
pub node_id_secret: veilid_core::DHTKeySecret,
|
||||||
pub bootstrap: Vec<ParsedNodeDialInfo>,
|
pub bootstrap: Vec<String>,
|
||||||
|
pub bootstrap_nodes: Vec<ParsedNodeDialInfo>,
|
||||||
pub routing_table: RoutingTable,
|
pub routing_table: RoutingTable,
|
||||||
pub rpc: Rpc,
|
pub rpc: Rpc,
|
||||||
pub dht: Dht,
|
pub dht: Dht,
|
||||||
@ -561,7 +565,6 @@ pub struct Network {
|
|||||||
pub tls: Tls,
|
pub tls: Tls,
|
||||||
pub application: Application,
|
pub application: Application,
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
pub leases: Leases,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
@ -597,9 +600,21 @@ pub struct Core {
|
|||||||
pub network: Network,
|
pub network: Network,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Daemon {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub pid_file: Option<String>,
|
||||||
|
pub chroot: Option<String>,
|
||||||
|
pub working_directory: Option<String>,
|
||||||
|
pub user: Option<String>,
|
||||||
|
pub group: Option<String>,
|
||||||
|
pub stdout_file: Option<String>,
|
||||||
|
pub stderr_file: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct SettingsInner {
|
pub struct SettingsInner {
|
||||||
pub daemon: bool,
|
pub daemon: Daemon,
|
||||||
pub client_api: ClientApi,
|
pub client_api: ClientApi,
|
||||||
pub auto_attach: bool,
|
pub auto_attach: bool,
|
||||||
pub logging: Logging,
|
pub logging: Logging,
|
||||||
@ -708,56 +723,68 @@ impl Settings {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_default_config_path() -> PathBuf {
|
fn is_root() -> bool {
|
||||||
// Get default configuration file location
|
cfg_if::cfg_if! {
|
||||||
let mut default_config_path =
|
if #[cfg(unix)] {
|
||||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
use nix::unistd::Uid;
|
||||||
PathBuf::from(my_proj_dirs.config_dir())
|
Uid::effective().is_root()
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from("./")
|
false
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_default_config_path() -> PathBuf {
|
||||||
|
let mut default_config_path = if Self::is_root() {
|
||||||
|
PathBuf::from("/etc/veilid-server")
|
||||||
|
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||||
|
PathBuf::from(my_proj_dirs.config_dir())
|
||||||
|
} else {
|
||||||
|
PathBuf::from("./")
|
||||||
|
};
|
||||||
|
|
||||||
default_config_path.push("veilid-server.conf");
|
default_config_path.push("veilid-server.conf");
|
||||||
|
|
||||||
default_config_path
|
default_config_path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_default_table_store_path() -> PathBuf {
|
pub fn get_default_table_store_path() -> PathBuf {
|
||||||
// Get default configuration file location
|
let mut default_db_path = if Self::is_root() {
|
||||||
let mut default_config_path =
|
PathBuf::from("/var/db/veilid-server")
|
||||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from("./")
|
PathBuf::from("./")
|
||||||
};
|
};
|
||||||
default_config_path.push("table_store");
|
default_db_path.push("table_store");
|
||||||
|
|
||||||
default_config_path
|
default_db_path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_default_block_store_path() -> PathBuf {
|
pub fn get_default_block_store_path() -> PathBuf {
|
||||||
// Get default configuration file location
|
let mut default_db_path = if Self::is_root() {
|
||||||
let mut default_config_path =
|
PathBuf::from("/var/db/veilid-server")
|
||||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from("./")
|
PathBuf::from("./")
|
||||||
};
|
};
|
||||||
default_config_path.push("block_store");
|
default_db_path.push("block_store");
|
||||||
|
|
||||||
default_config_path
|
default_db_path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_default_protected_store_insecure_fallback_directory() -> PathBuf {
|
pub fn get_default_protected_store_insecure_fallback_directory() -> PathBuf {
|
||||||
// Get default configuration file location
|
let mut default_db_path = if Self::is_root() {
|
||||||
let mut default_config_path =
|
PathBuf::from("/var/db/veilid-server")
|
||||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from("./")
|
PathBuf::from("./")
|
||||||
};
|
};
|
||||||
default_config_path.push("protected_store");
|
default_db_path.push("protected_store");
|
||||||
|
|
||||||
default_config_path
|
default_db_path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_core_config_callback(&self) -> veilid_core::ConfigCallback {
|
pub fn get_core_config_callback(&self) -> veilid_core::ConfigCallback {
|
||||||
@ -834,17 +861,23 @@ impl Settings {
|
|||||||
"network.max_connection_frequency_per_min" => Ok(Box::new(
|
"network.max_connection_frequency_per_min" => Ok(Box::new(
|
||||||
inner.core.network.max_connection_frequency_per_min,
|
inner.core.network.max_connection_frequency_per_min,
|
||||||
)),
|
)),
|
||||||
|
|
||||||
"network.client_whitelist_timeout_ms" => {
|
"network.client_whitelist_timeout_ms" => {
|
||||||
Ok(Box::new(inner.core.network.client_whitelist_timeout_ms))
|
Ok(Box::new(inner.core.network.client_whitelist_timeout_ms))
|
||||||
}
|
}
|
||||||
|
"network.reverse_connection_receipt_time_ms" => Ok(Box::new(
|
||||||
|
inner.core.network.reverse_connection_receipt_time_ms,
|
||||||
|
)),
|
||||||
|
"network.hole_punch_receipt_time_ms" => {
|
||||||
|
Ok(Box::new(inner.core.network.hole_punch_receipt_time_ms))
|
||||||
|
}
|
||||||
"network.node_id" => Ok(Box::new(inner.core.network.node_id)),
|
"network.node_id" => Ok(Box::new(inner.core.network.node_id)),
|
||||||
"network.node_id_secret" => Ok(Box::new(inner.core.network.node_id_secret)),
|
"network.node_id_secret" => Ok(Box::new(inner.core.network.node_id_secret)),
|
||||||
"network.bootstrap" => Ok(Box::new(
|
"network.bootstrap" => Ok(Box::new(inner.core.network.bootstrap.clone())),
|
||||||
|
"network.bootstrap_nodes" => Ok(Box::new(
|
||||||
inner
|
inner
|
||||||
.core
|
.core
|
||||||
.network
|
.network
|
||||||
.bootstrap
|
.bootstrap_nodes
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|e| e.node_dial_info_string)
|
.map(|e| e.node_dial_info_string)
|
||||||
@ -1112,18 +1145,6 @@ impl Settings {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|a| a.urlstring.clone()),
|
.map(|a| a.urlstring.clone()),
|
||||||
)),
|
)),
|
||||||
"network.leases.max_server_signal_leases" => {
|
|
||||||
Ok(Box::new(inner.core.network.leases.max_server_signal_leases))
|
|
||||||
}
|
|
||||||
"network.leases.max_server_relay_leases" => {
|
|
||||||
Ok(Box::new(inner.core.network.leases.max_server_relay_leases))
|
|
||||||
}
|
|
||||||
"network.leases.max_client_signal_leases" => {
|
|
||||||
Ok(Box::new(inner.core.network.leases.max_client_signal_leases))
|
|
||||||
}
|
|
||||||
"network.leases.max_client_relay_leases" => {
|
|
||||||
Ok(Box::new(inner.core.network.leases.max_client_relay_leases))
|
|
||||||
}
|
|
||||||
_ => Err(format!("config key '{}' doesn't exist", key)),
|
_ => Err(format!("config key '{}' doesn't exist", key)),
|
||||||
};
|
};
|
||||||
out
|
out
|
||||||
@ -1150,7 +1171,14 @@ mod tests {
|
|||||||
let settings = Settings::new(None).unwrap();
|
let settings = Settings::new(None).unwrap();
|
||||||
|
|
||||||
let s = settings.read();
|
let s = settings.read();
|
||||||
assert_eq!(s.daemon, false);
|
assert_eq!(s.daemon.enabled, false);
|
||||||
|
assert_eq!(s.daemon.pid_file, None);
|
||||||
|
assert_eq!(s.daemon.chroot, None);
|
||||||
|
assert_eq!(s.daemon.working_directory, None);
|
||||||
|
assert_eq!(s.daemon.user, None);
|
||||||
|
assert_eq!(s.daemon.group, None);
|
||||||
|
assert_eq!(s.daemon.stdout_file, None);
|
||||||
|
assert_eq!(s.daemon.stderr_file, None);
|
||||||
assert_eq!(s.client_api.enabled, true);
|
assert_eq!(s.client_api.enabled, true);
|
||||||
assert_eq!(s.client_api.listen_address.name, "localhost:5959");
|
assert_eq!(s.client_api.listen_address.name, "localhost:5959");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -1164,7 +1192,7 @@ mod tests {
|
|||||||
assert_eq!(s.logging.file.path, "");
|
assert_eq!(s.logging.file.path, "");
|
||||||
assert_eq!(s.logging.file.append, true);
|
assert_eq!(s.logging.file.append, true);
|
||||||
assert_eq!(s.logging.file.level, LogLevel::Info);
|
assert_eq!(s.logging.file.level, LogLevel::Info);
|
||||||
assert_eq!(s.logging.client.enabled, true);
|
assert_eq!(s.logging.client.enabled, false);
|
||||||
assert_eq!(s.logging.client.level, LogLevel::Info);
|
assert_eq!(s.logging.client.level, LogLevel::Info);
|
||||||
assert_eq!(s.testing.subnode_index, 0);
|
assert_eq!(s.testing.subnode_index, 0);
|
||||||
|
|
||||||
@ -1181,7 +1209,7 @@ mod tests {
|
|||||||
assert_eq!(s.core.block_store.delete, false);
|
assert_eq!(s.core.block_store.delete, false);
|
||||||
|
|
||||||
assert_eq!(s.core.protected_store.allow_insecure_fallback, true);
|
assert_eq!(s.core.protected_store.allow_insecure_fallback, true);
|
||||||
assert_eq!(s.core.protected_store.always_use_insecure_storage, false);
|
assert_eq!(s.core.protected_store.always_use_insecure_storage, true);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s.core.protected_store.insecure_fallback_directory,
|
s.core.protected_store.insecure_fallback_directory,
|
||||||
Settings::get_default_protected_store_insecure_fallback_directory()
|
Settings::get_default_protected_store_insecure_fallback_directory()
|
||||||
@ -1195,13 +1223,19 @@ mod tests {
|
|||||||
assert_eq!(s.core.network.max_connections_per_ip6_prefix_size, 56u32);
|
assert_eq!(s.core.network.max_connections_per_ip6_prefix_size, 56u32);
|
||||||
assert_eq!(s.core.network.max_connection_frequency_per_min, 8u32);
|
assert_eq!(s.core.network.max_connection_frequency_per_min, 8u32);
|
||||||
assert_eq!(s.core.network.client_whitelist_timeout_ms, 300_000u32);
|
assert_eq!(s.core.network.client_whitelist_timeout_ms, 300_000u32);
|
||||||
|
assert_eq!(s.core.network.reverse_connection_receipt_time_ms, 5_000u32);
|
||||||
|
assert_eq!(s.core.network.hole_punch_receipt_time_ms, 5_000u32);
|
||||||
assert_eq!(s.core.network.node_id, veilid_core::DHTKey::default());
|
assert_eq!(s.core.network.node_id, veilid_core::DHTKey::default());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s.core.network.node_id_secret,
|
s.core.network.node_id_secret,
|
||||||
veilid_core::DHTKeySecret::default()
|
veilid_core::DHTKeySecret::default()
|
||||||
);
|
);
|
||||||
//
|
//
|
||||||
assert!(s.core.network.bootstrap.is_empty());
|
assert_eq!(
|
||||||
|
s.core.network.bootstrap,
|
||||||
|
vec!["bootstrap.veilid.net".to_owned()]
|
||||||
|
);
|
||||||
|
assert_eq!(s.core.network.bootstrap_nodes, vec![]);
|
||||||
//
|
//
|
||||||
assert_eq!(s.core.network.rpc.concurrency, 0);
|
assert_eq!(s.core.network.rpc.concurrency, 0);
|
||||||
assert_eq!(s.core.network.rpc.queue_size, 1024);
|
assert_eq!(s.core.network.rpc.queue_size, 1024);
|
||||||
@ -1234,11 +1268,11 @@ mod tests {
|
|||||||
//
|
//
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s.core.network.tls.certificate_path,
|
s.core.network.tls.certificate_path,
|
||||||
std::path::PathBuf::from("/etc/veilid/server.crt")
|
std::path::PathBuf::from("/etc/veilid-server/server.crt")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
s.core.network.tls.private_key_path,
|
s.core.network.tls.private_key_path,
|
||||||
std::path::PathBuf::from("/etc/veilid/private/server.key")
|
std::path::PathBuf::from("/etc/veilid-server/private/server.key")
|
||||||
);
|
);
|
||||||
assert_eq!(s.core.network.tls.connection_initial_timeout_ms, 2_000u32);
|
assert_eq!(s.core.network.tls.connection_initial_timeout_ms, 2_000u32);
|
||||||
//
|
//
|
||||||
@ -1317,9 +1351,5 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(s.core.network.protocol.wss.url, None);
|
assert_eq!(s.core.network.protocol.wss.url, None);
|
||||||
//
|
//
|
||||||
assert_eq!(s.core.network.leases.max_server_signal_leases, 256);
|
|
||||||
assert_eq!(s.core.network.leases.max_server_relay_leases, 8);
|
|
||||||
assert_eq!(s.core.network.leases.max_client_signal_leases, 2);
|
|
||||||
assert_eq!(s.core.network.leases.max_client_relay_leases, 2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,102 @@
|
|||||||
|
use crate::server::*;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
use crate::veilid_logs::*;
|
||||||
|
use async_std::stream::StreamExt;
|
||||||
|
use async_std::task;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
// use log::*;
|
use signal_hook::consts::signal::*;
|
||||||
|
use signal_hook_async_std::Signals;
|
||||||
|
|
||||||
pub fn run_daemon(_settings: Settings, _matches: ArgMatches) -> Result<(), String> {
|
async fn handle_signals(mut signals: Signals) {
|
||||||
eprintln!("Windows Service mode not implemented yet.");
|
while let Some(signal) = signals.next().await {
|
||||||
Ok(())
|
match signal {
|
||||||
|
SIGHUP => {
|
||||||
|
// XXX: reload configuration?
|
||||||
|
}
|
||||||
|
SIGTERM | SIGINT | SIGQUIT => {
|
||||||
|
// Shutdown the system;
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String> {
|
||||||
|
let daemon = {
|
||||||
|
let mut daemon = daemonize::Daemonize::new();
|
||||||
|
let s = settings.read();
|
||||||
|
if let Some(pid_file) = &s.daemon.pid_file {
|
||||||
|
daemon = daemon.pid_file(pid_file).chown_pid_file(true);
|
||||||
|
}
|
||||||
|
if let Some(chroot) = &s.daemon.chroot {
|
||||||
|
daemon = daemon.chroot(chroot);
|
||||||
|
}
|
||||||
|
if let Some(working_directory) = &s.daemon.working_directory {
|
||||||
|
daemon = daemon.working_directory(working_directory);
|
||||||
|
}
|
||||||
|
if let Some(user) = &s.daemon.user {
|
||||||
|
daemon = daemon.user(user.as_str());
|
||||||
|
}
|
||||||
|
if let Some(group) = &s.daemon.group {
|
||||||
|
daemon = daemon.group(group.as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
let stdout_file = if let Some(stdout_file) = &s.daemon.stdout_file {
|
||||||
|
Some(
|
||||||
|
std::fs::File::create(stdout_file)
|
||||||
|
.map_err(|e| format!("Failed to create stdio file: {}", e))?,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
if let Some(stderr_file) = &s.daemon.stderr_file {
|
||||||
|
if Some(stderr_file) == s.daemon.stdout_file.as_ref() {
|
||||||
|
// same output file for stderr and stdout
|
||||||
|
daemon = daemon.stderr(
|
||||||
|
stdout_file
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.try_clone()
|
||||||
|
.map_err(|e| format!("Failed to clone stdout file: {}", e))?,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
daemon = daemon.stderr(
|
||||||
|
std::fs::File::create(stderr_file)
|
||||||
|
.map_err(|e| format!("Failed to create stderr file: {}", e))?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(stdout_file) = stdout_file {
|
||||||
|
daemon = daemon.stdout(stdout_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon
|
||||||
|
};
|
||||||
|
|
||||||
|
// Init combined console/file logger
|
||||||
|
let logs = VeilidLogs::setup_normal_logs(settings.clone())?;
|
||||||
|
|
||||||
|
// Daemonize
|
||||||
|
daemon
|
||||||
|
.start()
|
||||||
|
.map_err(|e| format!("Failed to daemonize: {}", e))?;
|
||||||
|
|
||||||
|
// Now, run the server
|
||||||
|
task::block_on(async {
|
||||||
|
// Catch signals
|
||||||
|
let signals = Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])
|
||||||
|
.map_err(|e| format!("failed to init signals: {}", e))?;
|
||||||
|
let handle = signals.handle();
|
||||||
|
|
||||||
|
let signals_task = async_std::task::spawn(handle_signals(signals));
|
||||||
|
|
||||||
|
let res = run_veilid_server(settings, logs, ServerMode::Normal).await;
|
||||||
|
|
||||||
|
// Terminate the signal stream.
|
||||||
|
handle.close();
|
||||||
|
signals_task.await;
|
||||||
|
|
||||||
|
res
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::log_safe_channel::*;
|
use crate::log_safe_channel::*;
|
||||||
use crate::settings::*;
|
use crate::settings::*;
|
||||||
|
use cfg_if::*;
|
||||||
|
use log::*;
|
||||||
use simplelog::*;
|
use simplelog::*;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -9,6 +11,84 @@ pub struct VeilidLogs {
|
|||||||
pub client_log_channel_closer: Option<LogSafeChannelCloser>,
|
pub client_log_channel_closer: Option<LogSafeChannelCloser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_os = "linux")] {
|
||||||
|
use systemd_journal_logger::JournalLog;
|
||||||
|
pub struct SystemLogger {
|
||||||
|
level_filter: LevelFilter,
|
||||||
|
config: Config,
|
||||||
|
journal_log: JournalLog<String,String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SystemLogger {
|
||||||
|
pub fn new(level_filter: LevelFilter, config: Config) -> Box<Self> {
|
||||||
|
Box::new(Self {
|
||||||
|
level_filter,
|
||||||
|
config,
|
||||||
|
journal_log: JournalLog::with_extra_fields(Vec::new())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn should_skip(record: &Record<'_>) -> bool {
|
||||||
|
// // If a module path and allowed list are available
|
||||||
|
// match (record.target(), &*config.filter_allow) {
|
||||||
|
// (path, allowed) if !allowed.is_empty() => {
|
||||||
|
// // Check that the module path matches at least one allow filter
|
||||||
|
// if !allowed.iter().any(|v| path.starts_with(&**v)) {
|
||||||
|
// // If not, skip any further writing
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// _ => {}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// If a module path and ignore list are available
|
||||||
|
match (record.target(), &veilid_core::DEFAULT_LOG_IGNORE_LIST) {
|
||||||
|
(path, ignore) if !ignore.is_empty() => {
|
||||||
|
// Check that the module path does not match any ignore filters
|
||||||
|
if ignore.iter().any(|v| path.starts_with(&**v)) {
|
||||||
|
// If not, skip any further writing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Log for SystemLogger {
|
||||||
|
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
|
||||||
|
metadata.level() <= self.level_filter
|
||||||
|
}
|
||||||
|
|
||||||
|
fn log(&self, record: &Record<'_>) {
|
||||||
|
if self.enabled(record.metadata()) && ! Self::should_skip(record) {
|
||||||
|
self.journal_log.log(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&self) {
|
||||||
|
self.journal_log.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SharedLogger for SystemLogger {
|
||||||
|
fn level(&self) -> LevelFilter {
|
||||||
|
self.level_filter
|
||||||
|
}
|
||||||
|
fn config(&self) -> Option<&Config> {
|
||||||
|
Some(&self.config)
|
||||||
|
}
|
||||||
|
fn as_log(self: Box<Self>) -> Box<dyn Log> {
|
||||||
|
Box::new(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl VeilidLogs {
|
impl VeilidLogs {
|
||||||
pub fn setup_normal_logs(settings: Settings) -> Result<VeilidLogs, String> {
|
pub fn setup_normal_logs(settings: Settings) -> Result<VeilidLogs, String> {
|
||||||
let settingsr = settings.read();
|
let settingsr = settings.read();
|
||||||
@ -64,6 +144,14 @@ impl VeilidLogs {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(target_os = "linux")] {
|
||||||
|
if settingsr.logging.system.enabled {
|
||||||
|
logs.push(SystemLogger::new(convert_loglevel(settingsr.logging.system.level), cb.build()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CombinedLogger::init(logs).map_err(|e| format!("failed to init logs: {}", e))?;
|
CombinedLogger::init(logs).map_err(|e| format!("failed to init logs: {}", e))?;
|
||||||
|
|
||||||
Ok(VeilidLogs {
|
Ok(VeilidLogs {
|
||||||
|
Loading…
Reference in New Issue
Block a user