mirror of
https://gitlab.com/veilid/veilid.git
synced 2024-10-01 01:26:08 -04:00
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 = [
|
||||
"block-buffer 0.10.2",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1308,7 +1309,7 @@ dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"rand 0.7.3",
|
||||
"sha2",
|
||||
"sha2 0.9.9",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
@ -1813,7 +1814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
||||
dependencies = [
|
||||
"digest 0.9.0",
|
||||
"hmac",
|
||||
"hmac 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1826,6 +1827,15 @@ dependencies = [
|
||||
"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]]
|
||||
name = "http"
|
||||
version = "0.2.6"
|
||||
@ -2046,7 +2056,7 @@ dependencies = [
|
||||
"log",
|
||||
"ndk",
|
||||
"ndk-glue",
|
||||
"rpassword",
|
||||
"rpassword 5.0.1",
|
||||
"secret-service",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
@ -2167,6 +2177,24 @@ dependencies = [
|
||||
"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]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.3.0"
|
||||
@ -3280,6 +3308,18 @@ dependencies = [
|
||||
"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]]
|
||||
name = "rtnetlink"
|
||||
version = "0.9.0"
|
||||
@ -3451,7 +3491,7 @@ dependencies = [
|
||||
"num 0.3.1",
|
||||
"rand 0.8.5",
|
||||
"serde 1.0.136",
|
||||
"sha2",
|
||||
"sha2 0.9.9",
|
||||
"zbus",
|
||||
"zbus_macros",
|
||||
"zvariant",
|
||||
@ -3699,6 +3739,17 @@ dependencies = [
|
||||
"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]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.13"
|
||||
@ -3709,6 +3760,18 @@ dependencies = [
|
||||
"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]]
|
||||
name = "signal-hook-mio"
|
||||
version = "0.2.1"
|
||||
@ -3861,6 +3924,16 @@ dependencies = [
|
||||
"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]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@ -4124,6 +4197,15 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "value-bag"
|
||||
version = "1.0.0-alpha.8"
|
||||
@ -4294,12 +4376,17 @@ dependencies = [
|
||||
"futures",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nix 0.23.1",
|
||||
"parking_lot 0.12.0",
|
||||
"rpassword 6.0.1",
|
||||
"serde 1.0.136",
|
||||
"serde_derive",
|
||||
"serde_yaml",
|
||||
"serial_test 0.6.0",
|
||||
"signal-hook",
|
||||
"signal-hook-async-std",
|
||||
"simplelog",
|
||||
"systemd-journal-logger",
|
||||
"url",
|
||||
"veilid-core",
|
||||
"windows-service",
|
||||
|
35
Earthfile
35
Earthfile
@ -72,7 +72,7 @@ deps:
|
||||
|
||||
code:
|
||||
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
|
||||
|
||||
# Clippy only
|
||||
@ -113,3 +113,36 @@ unit-tests-linux-amd64:
|
||||
unit-tests-linux-arm64:
|
||||
FROM +code
|
||||
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)
|
||||
|
||||
sub_args = base_args.copy()
|
||||
sub_args.append("--subnode_index={}".format(n))
|
||||
sub_args.append("--bootstrap={}".format(main_di))
|
||||
sub_args.append("--subnode-index={}".format(n))
|
||||
sub_args.append("--bootstrap-nodes={}".format(main_di))
|
||||
if args.wait_for_debug and (str(n) in args.wait_for_debug):
|
||||
sub_args.append("--wait-for-debug")
|
||||
|
||||
|
@ -88,14 +88,29 @@ impl ClientApiConnection {
|
||||
}
|
||||
async fn process_veilid_state<'a>(
|
||||
&'a mut self,
|
||||
state: veilid_state::Reader<'a>,
|
||||
veilid_state: veilid_state::Reader<'a>,
|
||||
) -> Result<(), String> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
// Process attachment state
|
||||
let attachment = state.reborrow().get_attachment().map_err(map_to_string)?;
|
||||
let state = attachment.get_state().map_err(map_to_string)?;
|
||||
inner.comproc.update_attachment(state);
|
||||
let attachment = veilid_state
|
||||
.reborrow()
|
||||
.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(())
|
||||
}
|
||||
|
@ -277,6 +277,12 @@ debug - send a debugging command to the Veilid server
|
||||
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) {
|
||||
self.inner().ui.add_node_event(message);
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ pub type UICallback = Box<dyn Fn(&mut Cursive) + Send>;
|
||||
|
||||
struct UIState {
|
||||
attachment_state: Dirty<AttachmentState>,
|
||||
network_started: Dirty<bool>,
|
||||
network_down_up: Dirty<(f32, f32)>,
|
||||
connection_state: Dirty<ConnectionState>,
|
||||
}
|
||||
|
||||
@ -56,6 +58,8 @@ impl UIState {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
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),
|
||||
}
|
||||
}
|
||||
@ -221,6 +225,15 @@ impl UI {
|
||||
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) {
|
||||
if let ConnectionState::Connected(_, _) = inner.ui_state.connection_state.get() {
|
||||
match inner.ui_state.attachment_state.get() {
|
||||
@ -576,7 +589,7 @@ impl UI {
|
||||
status.append_styled("|", ColorStyle::highlight_inactive());
|
||||
// Add bandwidth status
|
||||
status.append_styled(
|
||||
" Down: 0.0KB/s Up: 0.0KB/s ",
|
||||
format!(" {} ", UI::render_network_status(&mut inner)),
|
||||
ColorStyle::highlight_inactive(),
|
||||
);
|
||||
status.append_styled("|", ColorStyle::highlight_inactive());
|
||||
@ -599,6 +612,12 @@ impl UI {
|
||||
refresh_statusbar = 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() {
|
||||
refresh_statusbar = true;
|
||||
refresh_button_attach = true;
|
||||
@ -757,6 +776,15 @@ impl UI {
|
||||
inner.ui_state.attachment_state.set(state);
|
||||
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) {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
inner.ui_state.connection_state.set(state);
|
||||
|
@ -136,10 +136,10 @@ impl Log for ApiLogger {
|
||||
|
||||
let s = format!("{}{}{}", tgt, loc, record.args());
|
||||
|
||||
(inner.update_callback)(VeilidUpdate::Log {
|
||||
(inner.update_callback)(VeilidUpdate::Log(VeilidStateLog {
|
||||
log_level: ll,
|
||||
message: s,
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,15 +271,18 @@ impl AttachmentManager {
|
||||
let network_manager = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.update_callback = Some(update_callback.clone());
|
||||
let update_callback2 = update_callback.clone();
|
||||
inner.attachment_machine.set_state_change_callback(Arc::new(
|
||||
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()
|
||||
};
|
||||
|
||||
network_manager.init().await?;
|
||||
network_manager.init(update_callback).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -356,4 +359,10 @@ impl AttachmentManager {
|
||||
let attachment_machine = self.inner.lock().attachment_machine.clone();
|
||||
attachment_machine.state()
|
||||
}
|
||||
|
||||
pub fn get_veilid_state(&self) -> VeilidStateAttachment {
|
||||
VeilidStateAttachment {
|
||||
state: self.get_state(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +214,14 @@ impl Network {
|
||||
.interfaces
|
||||
.best_addresses()
|
||||
.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()
|
||||
}
|
||||
}
|
||||
|
@ -445,6 +445,7 @@ impl Network {
|
||||
log_net!("updating network class");
|
||||
|
||||
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());
|
||||
|
||||
@ -470,9 +471,10 @@ impl Network {
|
||||
}
|
||||
|
||||
let network_class = context.inner.lock().network_class;
|
||||
self.inner.lock().network_class = network_class;
|
||||
|
||||
log_net!(debug "network class set to {:?}", network_class);
|
||||
if network_class != old_network_class {
|
||||
self.inner.lock().network_class = network_class;
|
||||
log_net!(debug "network class changed to {:?}", network_class);
|
||||
}
|
||||
|
||||
// send updates to everyone
|
||||
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 mut static_public = false;
|
||||
|
||||
trace!("UDP: listener started on {:#?}", local_dial_info_list);
|
||||
|
||||
// Register local dial info
|
||||
for di in &local_dial_info_list {
|
||||
// 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))),
|
||||
)
|
||||
.await?;
|
||||
trace!("WS: listener started");
|
||||
trace!("WS: listener started on {:#?}", socket_addresses);
|
||||
|
||||
let mut static_public = false;
|
||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||
@ -515,7 +517,7 @@ impl Network {
|
||||
wss_port,
|
||||
ip_addrs
|
||||
);
|
||||
let _socket_addresses = self
|
||||
let socket_addresses = self
|
||||
.start_tcp_listener(
|
||||
ip_addrs,
|
||||
wss_port,
|
||||
@ -523,7 +525,7 @@ impl Network {
|
||||
Box::new(|c, t, a| Box::new(WebsocketProtocolHandler::new(c, t, a))),
|
||||
)
|
||||
.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
|
||||
// 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))),
|
||||
)
|
||||
.await?;
|
||||
trace!("TCP: listener started");
|
||||
trace!("TCP: listener started on {:#?}", socket_addresses);
|
||||
|
||||
let mut static_public = false;
|
||||
let mut registered_addresses: HashSet<IpAddr> = HashSet::new();
|
||||
|
@ -90,6 +90,7 @@ pub enum SendDataKind {
|
||||
struct NetworkManagerInner {
|
||||
routing_table: Option<RoutingTable>,
|
||||
components: Option<NetworkComponents>,
|
||||
update_callback: Option<UpdateCallback>,
|
||||
stats: NetworkManagerStats,
|
||||
client_whitelist: LruCache<key::DHTKey, ClientWhitelistEntry>,
|
||||
relay_node: Option<NodeRef>,
|
||||
@ -116,6 +117,7 @@ impl NetworkManager {
|
||||
NetworkManagerInner {
|
||||
routing_table: None,
|
||||
components: None,
|
||||
update_callback: None,
|
||||
stats: NetworkManagerStats::default(),
|
||||
client_whitelist: LruCache::new_unbounded(),
|
||||
relay_node: None,
|
||||
@ -205,10 +207,11 @@ impl NetworkManager {
|
||||
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());
|
||||
routing_table.init().await?;
|
||||
self.inner.lock().routing_table = Some(routing_table.clone());
|
||||
self.inner.lock().update_callback = Some(update_callback);
|
||||
Ok(())
|
||||
}
|
||||
pub async fn terminate(&self) {
|
||||
@ -219,6 +222,7 @@ impl NetworkManager {
|
||||
if let Some(routing_table) = routing_table {
|
||||
routing_table.terminate().await;
|
||||
}
|
||||
self.inner.lock().update_callback = None;
|
||||
}
|
||||
|
||||
pub async fn internal_startup(&self) -> Result<(), String> {
|
||||
@ -256,9 +260,16 @@ impl NetworkManager {
|
||||
self.shutdown().await;
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
self.send_network_update();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_started(&self) -> bool {
|
||||
self.inner.lock().components.is_some()
|
||||
}
|
||||
|
||||
pub async fn shutdown(&self) {
|
||||
trace!("NetworkManager::shutdown begin");
|
||||
|
||||
@ -272,8 +283,13 @@ impl NetworkManager {
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
@ -334,7 +350,9 @@ impl NetworkManager {
|
||||
// if things can't restart, then we fail out of the attachment manager
|
||||
if net.needs_restart() {
|
||||
net.shutdown().await;
|
||||
self.send_network_update();
|
||||
net.startup().await?;
|
||||
self.send_network_update();
|
||||
}
|
||||
|
||||
// Run the routing table tick
|
||||
@ -1155,35 +1173,41 @@ impl NetworkManager {
|
||||
// Compute transfer statistics for the low level network
|
||||
async fn rolling_transfers_task_routine(self, last_ts: u64, cur_ts: u64) -> Result<(), String> {
|
||||
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
|
||||
inner
|
||||
.stats
|
||||
.self_stats
|
||||
.transfer_stats_accounting
|
||||
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
||||
// Roll the low level network transfer stats for our address
|
||||
inner
|
||||
.stats
|
||||
.self_stats
|
||||
.transfer_stats_accounting
|
||||
.roll_transfers(last_ts, cur_ts, &mut inner.stats.self_stats.transfer_stats);
|
||||
|
||||
// Roll all per-address transfers
|
||||
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
||||
for (addr, stats) in &mut inner.stats.per_address_stats {
|
||||
stats.transfer_stats_accounting.roll_transfers(
|
||||
last_ts,
|
||||
cur_ts,
|
||||
&mut stats.transfer_stats,
|
||||
);
|
||||
// Roll all per-address transfers
|
||||
let mut dead_addrs: HashSet<PerAddressStatsKey> = HashSet::new();
|
||||
for (addr, stats) in &mut inner.stats.per_address_stats {
|
||||
stats.transfer_stats_accounting.roll_transfers(
|
||||
last_ts,
|
||||
cur_ts,
|
||||
&mut stats.transfer_stats,
|
||||
);
|
||||
|
||||
// While we're here, lets see if this address has timed out
|
||||
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
||||
// it's dead, put it in the dead list
|
||||
dead_addrs.insert(*addr);
|
||||
// While we're here, lets see if this address has timed out
|
||||
if cur_ts - stats.last_seen_ts >= IPADDR_MAX_INACTIVE_DURATION_US {
|
||||
// it's dead, put it in the dead list
|
||||
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
|
||||
for da in &dead_addrs {
|
||||
inner.stats.per_address_stats.remove(da);
|
||||
}
|
||||
// Send update
|
||||
self.send_network_update();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1220,6 +1244,45 @@ impl NetworkManager {
|
||||
.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
|
||||
// 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
|
||||
|
@ -205,10 +205,6 @@ impl ReceiptManager {
|
||||
let config = self.core().config();
|
||||
let c = config.get();
|
||||
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(())
|
||||
|
@ -22,20 +22,36 @@ impl RoutingTable {
|
||||
|
||||
out
|
||||
}
|
||||
pub fn debug_info_dialinfo(&self) -> String {
|
||||
let ldis = self.dial_info_details(RoutingDomain::LocalNetwork);
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
let mut out = String::new();
|
||||
pub fn debug_info_dialinfo(&self, txt_format: bool) -> String {
|
||||
if txt_format {
|
||||
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);
|
||||
let gdis = self.dial_info_details(RoutingDomain::PublicInternet);
|
||||
if gdis.is_empty() {
|
||||
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 {
|
||||
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> {
|
||||
let bootstrap = {
|
||||
let (bootstrap, bootstrap_nodes) = {
|
||||
let c = self.config.get();
|
||||
c.network.bootstrap.clone()
|
||||
(
|
||||
c.network.bootstrap.clone(),
|
||||
c.network.bootstrap_nodes.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
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
|
||||
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())
|
||||
.map_err(map_to_string)
|
||||
.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
|
||||
});
|
||||
}
|
||||
log_rtab!(" bootstrap list: {:?}", bsmap);
|
||||
log_rtab!(" bootstrap node dialinfo: {:?}", bsmap);
|
||||
|
||||
// Run all bootstrap operations concurrently
|
||||
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_connection_frequency_per_min" => Ok(Box::new(8u32)),
|
||||
"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_secret" => Ok(Box::new(dht::key::DHTKeySecret::default())),
|
||||
"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_fully_attached" => Ok(Box::new(32u32)),
|
||||
"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.path" => Ok(Box::new(String::from("ws"))),
|
||||
"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);
|
||||
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_connection_frequency_per_min, 8u32);
|
||||
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_secret.valid);
|
||||
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.queue_size, 128u32);
|
||||
assert_eq!(inner.network.rpc.timeout_ms, 10_000u32);
|
||||
|
@ -79,10 +79,16 @@ impl VeilidAPI {
|
||||
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
|
||||
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> {
|
||||
@ -147,7 +153,7 @@ impl VeilidAPI {
|
||||
|
||||
// Must be detached
|
||||
if !matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@ -168,7 +174,7 @@ impl VeilidAPI {
|
||||
if args[0] == "buckets" {
|
||||
// Must be detached
|
||||
if matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached | AttachmentState::Detaching
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@ -194,7 +200,7 @@ impl VeilidAPI {
|
||||
|
||||
async fn debug_attach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
if !matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detached
|
||||
) {
|
||||
return Err(VeilidAPIError::Internal {
|
||||
@ -209,7 +215,7 @@ impl VeilidAPI {
|
||||
|
||||
async fn debug_detach(&self, _args: String) -> Result<String, VeilidAPIError> {
|
||||
if matches!(
|
||||
self.get_state().await?.attachment,
|
||||
self.get_state().await?.attachment.state,
|
||||
AttachmentState::Detaching
|
||||
) {
|
||||
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)]
|
||||
#[serde(tag = "kind")]
|
||||
pub enum VeilidUpdate {
|
||||
Log {
|
||||
log_level: VeilidLogLevel,
|
||||
message: String,
|
||||
},
|
||||
Attachment {
|
||||
state: AttachmentState,
|
||||
},
|
||||
Log(VeilidStateLog),
|
||||
Attachment(VeilidStateAttachment),
|
||||
Network(VeilidStateNetwork),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct VeilidState {
|
||||
pub attachment: AttachmentState,
|
||||
pub attachment: VeilidStateAttachment,
|
||||
pub network: VeilidStateNetwork,
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -745,8 +760,37 @@ impl fmt::Display for DialInfo {
|
||||
match self {
|
||||
DialInfo::UDP(di) => write!(f, "udp|{}", di.socket_address),
|
||||
DialInfo::TCP(di) => write!(f, "tcp|{}", di.socket_address),
|
||||
DialInfo::WS(di) => write!(f, "ws|{}|{}", di.socket_address, di.request),
|
||||
DialInfo::WSS(di) => write!(f, "wss|{}|{}", di.socket_address, di.request),
|
||||
DialInfo::WS(di) => {
|
||||
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))
|
||||
}
|
||||
"ws" => {
|
||||
let (sa, rest) = rest.split_once('|').ok_or_else(|| {
|
||||
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
||||
})?;
|
||||
let socket_address = SocketAddress::from_str(sa)?;
|
||||
DialInfo::try_ws(socket_address, format!("ws://{}", rest))
|
||||
let url = format!("ws://{}", rest);
|
||||
let split_url = SplitUrl::from_str(&url)
|
||||
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?;
|
||||
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
||||
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" => {
|
||||
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)
|
||||
})?;
|
||||
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)),
|
||||
}
|
||||
@ -819,6 +895,14 @@ impl DialInfo {
|
||||
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 {
|
||||
socket_address: socket_address.to_canonical(),
|
||||
request: url[5..].to_string(),
|
||||
@ -1497,11 +1581,19 @@ impl VeilidAPI {
|
||||
// get a full copy of the current state
|
||||
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
||||
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 {
|
||||
attachment: attachment_manager.get_state(),
|
||||
attachment,
|
||||
network,
|
||||
})
|
||||
}
|
||||
|
||||
// get network connectedness
|
||||
|
||||
// connect to the network
|
||||
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
||||
let attachment_manager = self.attachment_manager()?;
|
||||
|
@ -104,7 +104,6 @@ pub struct VeilidConfigDHT {
|
||||
pub min_peer_count: u32,
|
||||
pub min_peer_refresh_time_ms: u32,
|
||||
pub validate_dial_info_receipt_time_ms: u32,
|
||||
pub nearby_node_percentage: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
@ -117,13 +116,6 @@ pub struct VeilidConfigRPC {
|
||||
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)]
|
||||
pub struct VeilidConfigRoutingTable {
|
||||
pub limit_over_attached: u32,
|
||||
@ -147,6 +139,7 @@ pub struct VeilidConfigNetwork {
|
||||
pub node_id: key::DHTKey,
|
||||
pub node_id_secret: key::DHTKeySecret,
|
||||
pub bootstrap: Vec<String>,
|
||||
pub bootstrap_nodes: Vec<String>,
|
||||
pub routing_table: VeilidConfigRoutingTable,
|
||||
pub rpc: VeilidConfigRPC,
|
||||
pub dht: VeilidConfigDHT,
|
||||
@ -157,7 +150,6 @@ pub struct VeilidConfigNetwork {
|
||||
pub tls: VeilidConfigTLS,
|
||||
pub application: VeilidConfigApplication,
|
||||
pub protocol: VeilidConfigProtocol,
|
||||
pub leases: VeilidConfigLeases,
|
||||
}
|
||||
|
||||
#[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.client_whitelist_timeout_ms);
|
||||
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_fully_attached);
|
||||
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.path);
|
||||
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
|
||||
self.validate()?;
|
||||
|
@ -38,104 +38,102 @@ Future<VeilidConfig> getDefaultVeilidConfig() async {
|
||||
delete: false,
|
||||
),
|
||||
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,
|
||||
connectionInactivityTimeoutMs: 60000,
|
||||
maxConnectionsPerIp4: 8,
|
||||
maxConnectionsPerIp6Prefix: 8,
|
||||
maxConnectionsPerIp6PrefixSize: 56,
|
||||
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,
|
||||
),
|
||||
application: VeilidConfigApplication(
|
||||
https: VeilidConfigHTTPS(
|
||||
enabled: false,
|
||||
listenAddress: "",
|
||||
publicAddress: null,
|
||||
),
|
||||
tcp: VeilidConfigTCP(
|
||||
connect: !kIsWeb,
|
||||
listen: !kIsWeb,
|
||||
maxConnections: 32,
|
||||
listenAddress: "",
|
||||
publicAddress: null,
|
||||
),
|
||||
ws: VeilidConfigWS(
|
||||
connect: true,
|
||||
listen: !kIsWeb,
|
||||
maxConnections: 16,
|
||||
listenAddress: "",
|
||||
path: "ws",
|
||||
path: "",
|
||||
url: null,
|
||||
),
|
||||
wss: VeilidConfigWSS(
|
||||
connect: true,
|
||||
listen: false,
|
||||
maxConnections: 16,
|
||||
http: VeilidConfigHTTP(
|
||||
enabled: false,
|
||||
listenAddress: "",
|
||||
path: "ws",
|
||||
path: "",
|
||||
url: null,
|
||||
),
|
||||
)),
|
||||
protocol: VeilidConfigProtocol(
|
||||
udp: VeilidConfigUDP(
|
||||
enabled: !kIsWeb,
|
||||
socketPoolSize: 0,
|
||||
listenAddress: "",
|
||||
publicAddress: null,
|
||||
),
|
||||
leases: VeilidConfigLeases(
|
||||
maxServerSignalLeases: 256,
|
||||
maxServerRelayLeases: 8,
|
||||
maxClientSignalLeases: 2,
|
||||
maxClientRelayLeases: 2,
|
||||
)),
|
||||
tcp: VeilidConfigTCP(
|
||||
connect: !kIsWeb,
|
||||
listen: !kIsWeb,
|
||||
maxConnections: 32,
|
||||
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 {
|
||||
int connectionInitialTimeoutMs;
|
||||
int connectionInactivityTimeoutMs;
|
||||
@ -556,9 +526,12 @@ class VeilidConfigNetwork {
|
||||
int maxConnectionsPerIp6PrefixSize;
|
||||
int maxConnectionFrequencyPerMin;
|
||||
int clientWhitelistTimeoutMs;
|
||||
int reverseConnectionReceiptTimeMs;
|
||||
int holePunchReceiptTimeMs;
|
||||
String nodeId;
|
||||
String nodeIdSecret;
|
||||
List<String> bootstrap;
|
||||
List<String> bootstrapNodes;
|
||||
VeilidConfigRoutingTable routingTable;
|
||||
VeilidConfigRPC rpc;
|
||||
VeilidConfigDHT dht;
|
||||
@ -569,7 +542,6 @@ class VeilidConfigNetwork {
|
||||
VeilidConfigTLS tls;
|
||||
VeilidConfigApplication application;
|
||||
VeilidConfigProtocol protocol;
|
||||
VeilidConfigLeases leases;
|
||||
|
||||
VeilidConfigNetwork({
|
||||
required this.connectionInitialTimeoutMs,
|
||||
@ -579,9 +551,12 @@ class VeilidConfigNetwork {
|
||||
required this.maxConnectionsPerIp6PrefixSize,
|
||||
required this.maxConnectionFrequencyPerMin,
|
||||
required this.clientWhitelistTimeoutMs,
|
||||
required this.reverseConnectionReceiptTimeMs,
|
||||
required this.holePunchReceiptTimeMs,
|
||||
required this.nodeId,
|
||||
required this.nodeIdSecret,
|
||||
required this.bootstrap,
|
||||
required this.bootstrapNodes,
|
||||
required this.routingTable,
|
||||
required this.rpc,
|
||||
required this.dht,
|
||||
@ -592,7 +567,6 @@ class VeilidConfigNetwork {
|
||||
required this.tls,
|
||||
required this.application,
|
||||
required this.protocol,
|
||||
required this.leases,
|
||||
});
|
||||
|
||||
Map<String, dynamic> get json {
|
||||
@ -604,9 +578,12 @@ class VeilidConfigNetwork {
|
||||
'max_connections_per_ip6_prefix_size': maxConnectionsPerIp6PrefixSize,
|
||||
'max_connection_frequency_per_min': maxConnectionFrequencyPerMin,
|
||||
'client_whitelist_timeout_ms': clientWhitelistTimeoutMs,
|
||||
'reverse_connection_receipt_time_ms': reverseConnectionReceiptTimeMs,
|
||||
'hole_punch_receipt_time_ms': holePunchReceiptTimeMs,
|
||||
'node_id': nodeId,
|
||||
'node_id_secret': nodeIdSecret,
|
||||
'bootstrap': bootstrap,
|
||||
'bootstrap_nodes': bootstrapNodes,
|
||||
'routing_table': routingTable.json,
|
||||
'rpc': rpc.json,
|
||||
'dht': dht.json,
|
||||
@ -617,7 +594,6 @@ class VeilidConfigNetwork {
|
||||
'tls': tls.json,
|
||||
'application': application.json,
|
||||
'protocol': protocol.json,
|
||||
'leases': leases.json,
|
||||
};
|
||||
}
|
||||
|
||||
@ -631,9 +607,13 @@ class VeilidConfigNetwork {
|
||||
json['max_connections_per_ip6_prefix_size'],
|
||||
maxConnectionFrequencyPerMin = json['max_connection_frequency_per_min'],
|
||||
clientWhitelistTimeoutMs = json['client_whitelist_timeout_ms'],
|
||||
reverseConnectionReceiptTimeMs =
|
||||
json['reverse_connection_receipt_time_ms'],
|
||||
holePunchReceiptTimeMs = json['hole_punch_receipt_time_ms'],
|
||||
nodeId = json['node_id'],
|
||||
nodeIdSecret = json['node_id_secret'],
|
||||
bootstrap = json['bootstrap'],
|
||||
bootstrapNodes = json['bootstrap_nodes'],
|
||||
routingTable = VeilidConfigRoutingTable.fromJson(json['routing_table']),
|
||||
rpc = VeilidConfigRPC.fromJson(json['rpc']),
|
||||
dht = VeilidConfigDHT.fromJson(json['dht']),
|
||||
@ -643,8 +623,7 @@ class VeilidConfigNetwork {
|
||||
restrictedNatRetries = json['restricted_nat_retries'],
|
||||
tls = VeilidConfigTLS.fromJson(json['tls']),
|
||||
application = VeilidConfigApplication.fromJson(json['application']),
|
||||
protocol = VeilidConfigProtocol.fromJson(json['protocol']),
|
||||
leases = VeilidConfigLeases.fromJson(json['leases']);
|
||||
protocol = VeilidConfigProtocol.fromJson(json['protocol']);
|
||||
}
|
||||
|
||||
////////////
|
||||
@ -824,6 +803,11 @@ abstract class VeilidUpdate {
|
||||
{
|
||||
return VeilidUpdateAttachment(attachmentStateFromJson(json["state"]));
|
||||
}
|
||||
case "Network":
|
||||
{
|
||||
return VeilidUpdateNetwork(
|
||||
json["started"], json["bps_up"], json["bps_down"]);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw VeilidAPIExceptionInternal(
|
||||
@ -846,16 +830,50 @@ class VeilidUpdateAttachment implements VeilidUpdate {
|
||||
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
|
||||
|
||||
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)
|
||||
: attachment = attachmentStateFromJson(json['attachment']);
|
||||
: attachment = VeilidStateAttachment.fromJson(json['attachment']),
|
||||
network = VeilidStateNetwork.fromJson(json['network']);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
@ -33,12 +33,19 @@ ctrlc = "^3"
|
||||
lazy_static = "^1"
|
||||
bugsalot = "^0"
|
||||
flume = { version = "^0", features = ["async"] }
|
||||
rpassword = "^6"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-service = "^0"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
daemonize = "^0"
|
||||
signal-hook = "^0"
|
||||
signal-hook-async-std = "^0"
|
||||
nix = "^0"
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
systemd-journal-logger = "^0"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "^0"
|
||||
|
@ -11,19 +11,27 @@ enum AttachmentState {
|
||||
detaching @7;
|
||||
}
|
||||
|
||||
struct Attachment {
|
||||
state @0 :AttachmentState;
|
||||
struct VeilidStateAttachment {
|
||||
state @0 :AttachmentState;
|
||||
}
|
||||
|
||||
struct VeilidStateNetwork {
|
||||
started @0 :Bool;
|
||||
bpsDown @1 :UInt64;
|
||||
bpsUp @2 :UInt64;
|
||||
}
|
||||
|
||||
struct VeilidUpdate {
|
||||
union {
|
||||
attachment @0 :Attachment;
|
||||
shutdown @1 :Void;
|
||||
attachment @0 :VeilidStateAttachment;
|
||||
network @1 :VeilidStateNetwork;
|
||||
shutdown @2 :Void;
|
||||
}
|
||||
}
|
||||
|
||||
struct VeilidState {
|
||||
attachment @0 :Attachment;
|
||||
attachment @0 :VeilidStateAttachment;
|
||||
network @1 :VeilidStateNetwork;
|
||||
}
|
||||
|
||||
interface Registration {}
|
||||
|
@ -36,16 +36,26 @@ fn convert_update(
|
||||
mut rpc_update: crate::veilid_client_capnp::veilid_update::Builder,
|
||||
) {
|
||||
match update {
|
||||
veilid_core::VeilidUpdate::Log {
|
||||
veilid_core::VeilidUpdate::Log(veilid_core::VeilidStateLog {
|
||||
log_level: _,
|
||||
message: _,
|
||||
} => {
|
||||
}) => {
|
||||
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();
|
||||
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 => {
|
||||
rpc_update.set_shutdown(());
|
||||
}
|
||||
@ -54,11 +64,15 @@ fn convert_update(
|
||||
|
||||
fn convert_state(
|
||||
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
|
||||
.init_attachment()
|
||||
.set_state(convert_attachment_state(&state.attachment));
|
||||
let mut ab = rpc_state.reborrow().init_attachment();
|
||||
ab.set_state(convert_attachment_state(&state.attachment.state));
|
||||
|
||||
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 ---------------------------------
|
||||
|
@ -2,6 +2,7 @@ use crate::settings::*;
|
||||
use clap::{Arg, ArgMatches, Command};
|
||||
use std::ffi::OsStr;
|
||||
use std::str::FromStr;
|
||||
use veilid_core::{DHTKey, DHTKeySecret};
|
||||
|
||||
fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap::Error> {
|
||||
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"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("subnode_index")
|
||||
.long("subnode_index")
|
||||
Arg::new("subnode-index")
|
||||
.long("subnode-index")
|
||||
.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"),
|
||||
)
|
||||
@ -54,6 +55,14 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
||||
.long("generate-dht-key")
|
||||
.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::new("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")
|
||||
.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::new("bootstrap")
|
||||
.long("bootstrap")
|
||||
.takes_value(true)
|
||||
.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::new("local")
|
||||
@ -123,16 +145,16 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
|
||||
// Set config from command line
|
||||
if matches.occurrences_of("daemon") != 0 {
|
||||
settingsrw.daemon = true;
|
||||
settingsrw.daemon.enabled = true;
|
||||
settingsrw.logging.terminal.enabled = false;
|
||||
}
|
||||
if matches.occurrences_of("subnode_index") != 0 {
|
||||
let subnode_index = match matches.value_of("subnode_index") {
|
||||
if matches.occurrences_of("subnode-index") != 0 {
|
||||
let subnode_index = match matches.value_of("subnode-index") {
|
||||
Some(x) => x
|
||||
.parse()
|
||||
.map_err(|e| format!("couldn't parse subnode index: {}", e))?,
|
||||
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 {
|
||||
@ -164,16 +186,61 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
if matches.occurrences_of("delete-table-store") != 0 {
|
||||
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 {
|
||||
let bootstrap = match matches.value_of("bootstrap") {
|
||||
let bootstrap_list = match matches.value_of("bootstrap-list") {
|
||||
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();
|
||||
for x in x.split(',') {
|
||||
let x = x.trim();
|
||||
println!(" {}", x);
|
||||
out.push(ParsedNodeDialInfo::from_str(x).map_err(|e| {
|
||||
format!(
|
||||
"unable to parse dial info in bootstrap list: {} for {}",
|
||||
"unable to parse dial info in bootstrap node list: {} for {}",
|
||||
e, x
|
||||
)
|
||||
})?);
|
||||
@ -181,10 +248,10 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
out
|
||||
}
|
||||
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
|
||||
|
@ -28,7 +28,6 @@ fn main() -> Result<(), String> {
|
||||
|
||||
// --- Dump Config ---
|
||||
if matches.occurrences_of("dump-config") != 0 {
|
||||
//let cfg = config::Config::try_from(&*settingsr);
|
||||
return serde_yaml::to_writer(std::io::stdout(), &*settings.read())
|
||||
.map_err(|e| e.to_string());
|
||||
}
|
||||
@ -40,8 +39,37 @@ fn main() -> Result<(), String> {
|
||||
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 ----
|
||||
if settings.read().daemon {
|
||||
if settings.read().daemon.enabled {
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
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");
|
||||
|
||||
// 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 veilid_core::xx::SingleShotEventual;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ServerMode {
|
||||
Normal,
|
||||
ShutdownImmediate,
|
||||
DumpTXTRecord,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref SHUTDOWN_SWITCH: Mutex<Option<SingleShotEventual<()>>> =
|
||||
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();
|
||||
|
||||
// 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))?;
|
||||
|
||||
// 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());
|
||||
some_capi
|
||||
.clone()
|
||||
@ -55,16 +66,18 @@ pub async fn run_veilid_server(settings: Settings, logs: VeilidLogs) -> Result<(
|
||||
};
|
||||
|
||||
// Drop rwlock on settings
|
||||
let auto_attach = settingsr.auto_attach;
|
||||
let auto_attach = settingsr.auto_attach || !matches!(server_mode, ServerMode::Normal);
|
||||
drop(settingsr);
|
||||
|
||||
// Handle state changes on main thread for capnproto rpc
|
||||
let update_receiver_jh = capi.clone().map(|capi| {
|
||||
async_std::task::spawn_local(async move {
|
||||
while let Ok(change) = receiver.recv_async().await {
|
||||
// Process all updates
|
||||
let capi2 = capi.clone();
|
||||
let update_receiver_jh = async_std::task::spawn_local(async move {
|
||||
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);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
// Handle log messages on main thread for capnproto rpc
|
||||
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
|
||||
let mut out = Ok(());
|
||||
if auto_attach {
|
||||
info!("Auto-attach to the Veilid network");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
let shutdown_switch = {
|
||||
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
|
||||
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
|
||||
if let Some(client_log_receiver_jh) = client_log_receiver_jh {
|
||||
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> {
|
||||
let default_config = String::from(
|
||||
r#"---
|
||||
daemon: false
|
||||
daemon:
|
||||
enabled: false
|
||||
client_api:
|
||||
enabled: true
|
||||
listen_address: 'localhost:5959'
|
||||
auto_attach: true
|
||||
logging:
|
||||
logging:
|
||||
system:
|
||||
enabled: false
|
||||
level: 'info'
|
||||
terminal:
|
||||
enabled: true
|
||||
level: 'info'
|
||||
@ -31,14 +35,14 @@ logging:
|
||||
append: true
|
||||
level: 'info'
|
||||
client:
|
||||
enabled: true
|
||||
enabled: false
|
||||
level: 'info'
|
||||
testing:
|
||||
subnode_index: 0
|
||||
core:
|
||||
protected_store:
|
||||
allow_insecure_fallback: true
|
||||
always_use_insecure_storage: false
|
||||
always_use_insecure_storage: true
|
||||
insecure_fallback_directory: '%INSECURE_FALLBACK_DIRECTORY%'
|
||||
delete: false
|
||||
table_store:
|
||||
@ -55,9 +59,12 @@ core:
|
||||
max_connections_per_ip6_prefix_size: 56
|
||||
max_connection_frequency_per_min: 8
|
||||
client_whitelist_timeout_ms: 300000
|
||||
reverse_connection_receipt_time_ms: 5000
|
||||
hole_punch_receipt_time_ms: 5000
|
||||
node_id: ''
|
||||
node_id_secret: ''
|
||||
bootstrap: []
|
||||
bootstrap: ['bootstrap.veilid.net']
|
||||
bootstrap_nodes: []
|
||||
routing_table:
|
||||
limit_over_attached: 64
|
||||
limit_fully_attached: 32
|
||||
@ -90,8 +97,8 @@ core:
|
||||
enable_local_peer_scope: false
|
||||
restricted_nat_retries: 3
|
||||
tls:
|
||||
certificate_path: '/etc/veilid/server.crt'
|
||||
private_key_path: '/etc/veilid/private/server.key'
|
||||
certificate_path: '/etc/veilid-server/server.crt'
|
||||
private_key_path: '/etc/veilid-server/private/server.key'
|
||||
connection_initial_timeout_ms: 2000
|
||||
application:
|
||||
https:
|
||||
@ -130,11 +137,6 @@ core:
|
||||
listen_address: ':5150'
|
||||
path: 'ws'
|
||||
# url: ''
|
||||
leases:
|
||||
max_server_signal_leases: 256
|
||||
max_server_relay_leases: 8
|
||||
max_client_signal_leases: 2
|
||||
max_client_relay_leases: 2
|
||||
"#,
|
||||
)
|
||||
.replace(
|
||||
@ -402,6 +404,12 @@ pub struct File {
|
||||
pub level: LogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct System {
|
||||
pub enabled: bool,
|
||||
pub level: LogLevel,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Client {
|
||||
pub enabled: bool,
|
||||
@ -416,6 +424,7 @@ pub struct ClientApi {
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct Logging {
|
||||
pub system: System,
|
||||
pub terminal: Terminal,
|
||||
pub file: File,
|
||||
pub client: Client,
|
||||
@ -522,14 +531,6 @@ pub struct Dht {
|
||||
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)]
|
||||
pub struct RoutingTable {
|
||||
pub limit_over_attached: u32,
|
||||
@ -548,9 +549,12 @@ pub struct Network {
|
||||
pub max_connections_per_ip6_prefix_size: u32,
|
||||
pub max_connection_frequency_per_min: 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_secret: veilid_core::DHTKeySecret,
|
||||
pub bootstrap: Vec<ParsedNodeDialInfo>,
|
||||
pub bootstrap: Vec<String>,
|
||||
pub bootstrap_nodes: Vec<ParsedNodeDialInfo>,
|
||||
pub routing_table: RoutingTable,
|
||||
pub rpc: Rpc,
|
||||
pub dht: Dht,
|
||||
@ -561,7 +565,6 @@ pub struct Network {
|
||||
pub tls: Tls,
|
||||
pub application: Application,
|
||||
pub protocol: Protocol,
|
||||
pub leases: Leases,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
@ -597,9 +600,21 @@ pub struct Core {
|
||||
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)]
|
||||
pub struct SettingsInner {
|
||||
pub daemon: bool,
|
||||
pub daemon: Daemon,
|
||||
pub client_api: ClientApi,
|
||||
pub auto_attach: bool,
|
||||
pub logging: Logging,
|
||||
@ -708,56 +723,68 @@ impl Settings {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_default_config_path() -> PathBuf {
|
||||
// Get default configuration file location
|
||||
let mut default_config_path =
|
||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.config_dir())
|
||||
fn is_root() -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
use nix::unistd::Uid;
|
||||
Uid::effective().is_root()
|
||||
} 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
|
||||
}
|
||||
|
||||
pub fn get_default_table_store_path() -> PathBuf {
|
||||
// Get default configuration file location
|
||||
let mut default_config_path =
|
||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_config_path.push("table_store");
|
||||
let mut default_db_path = if Self::is_root() {
|
||||
PathBuf::from("/var/db/veilid-server")
|
||||
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_db_path.push("table_store");
|
||||
|
||||
default_config_path
|
||||
default_db_path
|
||||
}
|
||||
|
||||
pub fn get_default_block_store_path() -> PathBuf {
|
||||
// Get default configuration file location
|
||||
let mut default_config_path =
|
||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_config_path.push("block_store");
|
||||
let mut default_db_path = if Self::is_root() {
|
||||
PathBuf::from("/var/db/veilid-server")
|
||||
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_db_path.push("block_store");
|
||||
|
||||
default_config_path
|
||||
default_db_path
|
||||
}
|
||||
|
||||
pub fn get_default_protected_store_insecure_fallback_directory() -> PathBuf {
|
||||
// Get default configuration file location
|
||||
let mut default_config_path =
|
||||
if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_config_path.push("protected_store");
|
||||
let mut default_db_path = if Self::is_root() {
|
||||
PathBuf::from("/var/db/veilid-server")
|
||||
} else if let Some(my_proj_dirs) = ProjectDirs::from("org", "Veilid", "Veilid") {
|
||||
PathBuf::from(my_proj_dirs.data_local_dir())
|
||||
} else {
|
||||
PathBuf::from("./")
|
||||
};
|
||||
default_db_path.push("protected_store");
|
||||
|
||||
default_config_path
|
||||
default_db_path
|
||||
}
|
||||
|
||||
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(
|
||||
inner.core.network.max_connection_frequency_per_min,
|
||||
)),
|
||||
|
||||
"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_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
|
||||
.core
|
||||
.network
|
||||
.bootstrap
|
||||
.bootstrap_nodes
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|e| e.node_dial_info_string)
|
||||
@ -1112,18 +1145,6 @@ impl Settings {
|
||||
.as_ref()
|
||||
.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)),
|
||||
};
|
||||
out
|
||||
@ -1150,7 +1171,14 @@ mod tests {
|
||||
let settings = Settings::new(None).unwrap();
|
||||
|
||||
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.listen_address.name, "localhost:5959");
|
||||
assert_eq!(
|
||||
@ -1164,7 +1192,7 @@ mod tests {
|
||||
assert_eq!(s.logging.file.path, "");
|
||||
assert_eq!(s.logging.file.append, true);
|
||||
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.testing.subnode_index, 0);
|
||||
|
||||
@ -1181,7 +1209,7 @@ mod tests {
|
||||
assert_eq!(s.core.block_store.delete, false);
|
||||
|
||||
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!(
|
||||
s.core.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_connection_frequency_per_min, 8u32);
|
||||
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_secret,
|
||||
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.queue_size, 1024);
|
||||
@ -1234,11 +1268,11 @@ mod tests {
|
||||
//
|
||||
assert_eq!(
|
||||
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!(
|
||||
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);
|
||||
//
|
||||
@ -1317,9 +1351,5 @@ mod tests {
|
||||
);
|
||||
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::veilid_logs::*;
|
||||
use async_std::stream::StreamExt;
|
||||
use async_std::task;
|
||||
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> {
|
||||
eprintln!("Windows Service mode not implemented yet.");
|
||||
Ok(())
|
||||
async fn handle_signals(mut signals: Signals) {
|
||||
while let Some(signal) = signals.next().await {
|
||||
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::settings::*;
|
||||
use cfg_if::*;
|
||||
use log::*;
|
||||
use simplelog::*;
|
||||
use std::fs::OpenOptions;
|
||||
use std::path::Path;
|
||||
@ -9,6 +11,84 @@ pub struct VeilidLogs {
|
||||
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 {
|
||||
pub fn setup_normal_logs(settings: Settings) -> Result<VeilidLogs, String> {
|
||||
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))?;
|
||||
|
||||
Ok(VeilidLogs {
|
||||
|
Loading…
Reference in New Issue
Block a user