mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-15 10:25:40 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cca105e91d | |||
| 3e52490d1b | |||
| d1293276ce | |||
| 4a5e426730 | |||
| fdc2755291 | |||
| b4fbcd8d80 | |||
| 2415cb211e | |||
| 5e51784803 | |||
| 5f0d71b0fe | |||
| 71d41f0a70 |
@@ -0,0 +1,35 @@
|
||||
FROM alpine:latest AS builder
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
COPY . /tmp/artifacts
|
||||
RUN mkdir -p /tmp/output; \
|
||||
cd /tmp/artifacts; \
|
||||
ARTIFACT_ARCH=""; \
|
||||
if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
|
||||
ARTIFACT_ARCH="x86_64"; \
|
||||
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
|
||||
ARTIFACT_ARCH="aarch64"; \
|
||||
else \
|
||||
echo "Unsupported architecture: $TARGETARCH"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
cp /tmp/artifacts/easytier-linux-${ARTIFACT_ARCH}/* /tmp/output;
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder --chmod=755 /tmp/output/* /usr/local/bin
|
||||
|
||||
# tcp
|
||||
EXPOSE 11010/tcp
|
||||
# udp
|
||||
EXPOSE 11010/udp
|
||||
# wg
|
||||
EXPOSE 11011/udp
|
||||
# ws
|
||||
EXPOSE 11011/tcp
|
||||
# wss
|
||||
EXPOSE 11012/tcp
|
||||
|
||||
ENTRYPOINT ["easytier-core"]
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
# All of these options are optional, so you can remove them if you are happy with the defaults
|
||||
concurrent_skipping: 'never'
|
||||
skip_after_successful_duplicate: 'true'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", ".github/workflows/core.yml"]'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", ".github/workflows/core.yml", ".github/workflows/install_rust.sh"]'
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
name: EasyTier Docker
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_id:
|
||||
description: 'The run id of EasyTier-Core Action in EasyTier repo'
|
||||
type: number
|
||||
default: 10228239965
|
||||
required: true
|
||||
image_tag:
|
||||
description: 'Tag for this image build'
|
||||
type: string
|
||||
default: 'v1.2.0'
|
||||
required: true
|
||||
mark_latest:
|
||||
description: 'Mark this image as latest'
|
||||
type: boolean
|
||||
default: false
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
if: contains('["KKRainbow"]', github.actor)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Download artifact
|
||||
id: download-artifact
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
run_id: ${{ inputs.run_id }}
|
||||
repo: EasyTier/EasyTier
|
||||
path: docker_context
|
||||
- name: List files
|
||||
run: |
|
||||
ls -l -R .
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./docker_context
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: .github/workflows/Dockerfile
|
||||
tags: easytier/easytier:${{ inputs.image_tag }}${{ inputs.mark_latest && ',easytier/easytier:latest' || '' }},
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
# All of these options are optional, so you can remove them if you are happy with the defaults
|
||||
concurrent_skipping: 'never'
|
||||
skip_after_successful_duplicate: 'true'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", "easytier-gui/**", ".github/workflows/gui.yml"]'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", "easytier-gui/**", ".github/workflows/gui.yml", ".github/workflows/install_rust.sh"]'
|
||||
build-gui:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
@@ -57,8 +57,8 @@ fi
|
||||
|
||||
# see https://github.com/rust-lang/rustup/issues/3709
|
||||
rustup set auto-self-update disable
|
||||
rustup install 1.79
|
||||
rustup default 1.79
|
||||
rustup install 1.77
|
||||
rustup default 1.77
|
||||
|
||||
# mips/mipsel cannot add target from rustup, need compile by ourselves
|
||||
if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
|
||||
@@ -72,7 +72,6 @@ if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
|
||||
|
||||
rustup toolchain install nightly-x86_64-unknown-linux-gnu
|
||||
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
|
||||
cd -
|
||||
else
|
||||
rustup target add $TARGET
|
||||
if [[ $GUI_TARGET != '' ]]; then
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
# All of these options are optional, so you can remove them if you are happy with the defaults
|
||||
concurrent_skipping: 'never'
|
||||
skip_after_successful_duplicate: 'true'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", "easytier-gui/**", "tauri-plugin-vpnservice/**", ".github/workflows/mobile.yml"]'
|
||||
paths: '["Cargo.toml", "Cargo.lock", "easytier/**", "easytier-gui/**", "tauri-plugin-vpnservice/**", ".github/workflows/mobile.yml", ".github/workflows/install_rust.sh"]'
|
||||
build-mobile:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
Generated
+694
-526
File diff suppressed because it is too large
Load Diff
+29
-29
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "easytier-gui",
|
||||
"type": "module",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -12,47 +12,47 @@
|
||||
"lint:fix": "eslint . --ignore-pattern src-tauri --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@primevue/themes": "^4.0.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.4",
|
||||
"@tauri-apps/plugin-os": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-process": "2.0.0-beta.6",
|
||||
"@tauri-apps/plugin-shell": "2.0.0-beta.7",
|
||||
"@primevue/themes": "^4.0.4",
|
||||
"@tauri-apps/plugin-clipboard-manager": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-os": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-process": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-shell": "2.0.0-rc.0",
|
||||
"aura": "link:@primevue/themes/aura",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia": "^2.2.1",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^7.0.0",
|
||||
"primevue": "^4.0.0",
|
||||
"tauri-plugin-vpnservice-api": "link:../tauri-plugin-vpnservice/",
|
||||
"vue": "^3.4.31",
|
||||
"primevue": "^4.0.4",
|
||||
"tauri-plugin-vpnservice-api": "link:../tauri-plugin-vpnservice",
|
||||
"vue": "^3.4.36",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-router": "^4.4.0"
|
||||
"vue-router": "^4.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.21.3",
|
||||
"@antfu/eslint-config": "^2.24.1",
|
||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||
"@primevue/auto-import-resolver": "^4.0.0",
|
||||
"@tauri-apps/api": "2.0.0-beta.14",
|
||||
"@tauri-apps/cli": "2.0.0-beta.21",
|
||||
"@types/node": "^20.14.10",
|
||||
"@primevue/auto-import-resolver": "^4.0.4",
|
||||
"@tauri-apps/api": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli": "2.0.0-rc.1",
|
||||
"@types/node": "^20.14.14",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"@vitejs/plugin-vue": "^5.1.2",
|
||||
"@vue-macros/volar": "^0.19.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^9.6.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.8.0",
|
||||
"eslint-plugin-format": "^0.1.2",
|
||||
"postcss": "^8.4.39",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.5.3",
|
||||
"unplugin-auto-import": "^0.17.6",
|
||||
"unplugin-vue-components": "^0.27.2",
|
||||
"unplugin-vue-macros": "^2.9.5",
|
||||
"postcss": "^8.4.41",
|
||||
"tailwindcss": "^3.4.7",
|
||||
"typescript": "^5.5.4",
|
||||
"unplugin-auto-import": "^0.17.8",
|
||||
"unplugin-vue-components": "^0.27.3",
|
||||
"unplugin-vue-macros": "^2.11.4",
|
||||
"unplugin-vue-markdown": "^0.26.2",
|
||||
"unplugin-vue-router": "^0.8.8",
|
||||
"uuid": "^9.0.1",
|
||||
"vite": "^5.3.3",
|
||||
"vite-plugin-vue-devtools": "^7.3.5",
|
||||
"vite": "^5.3.5",
|
||||
"vite-plugin-vue-devtools": "^7.3.7",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-tsc": "^2.0.26"
|
||||
"vue-tsc": "^2.0.29"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+1789
-1316
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "easytier-gui"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
description = "EasyTier GUI"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
@@ -12,10 +12,14 @@ name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta", features = [ "tray-icon", "image-png", "image-ico"] }
|
||||
tauri = { version = "2.0.0-rc", features = [
|
||||
"tray-icon",
|
||||
"image-png",
|
||||
"image-ico",
|
||||
] }
|
||||
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
@@ -26,20 +30,20 @@ anyhow = "1.0"
|
||||
chrono = { version = "0.4.37", features = ["serde"] }
|
||||
|
||||
once_cell = "1.18.0"
|
||||
dashmap = "5.5.3"
|
||||
dashmap = "6.0"
|
||||
|
||||
privilege = "0.3"
|
||||
gethostname = "0.4.3"
|
||||
gethostname = "0.5"
|
||||
|
||||
auto-launch = "0.5.0"
|
||||
dunce = "1.0.4"
|
||||
|
||||
tauri-plugin-shell = "2.0.0-beta.8"
|
||||
tauri-plugin-process = "2.0.0-beta.7"
|
||||
tauri-plugin-clipboard-manager = "2.1.0-beta.5"
|
||||
tauri-plugin-positioner = { version = "2.0.0-beta", features = ["tray-icon"] }
|
||||
tauri-plugin-shell = "2.0.0-rc"
|
||||
tauri-plugin-process = "2.0.0-rc"
|
||||
tauri-plugin-clipboard-manager = "2.0.0-rc"
|
||||
tauri-plugin-positioner = { version = "2.0.0-rc", features = ["tray-icon"] }
|
||||
tauri-plugin-vpnservice = { path = "../../tauri-plugin-vpnservice" }
|
||||
tauri-plugin-os = "2.0.0-beta.7"
|
||||
tauri-plugin-os = "2.0.0-rc"
|
||||
|
||||
|
||||
[features]
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
"window:default",
|
||||
"window:allow-is-visible",
|
||||
"window:allow-show",
|
||||
"window:allow-hide",
|
||||
"window:allow-set-focus",
|
||||
"app:default",
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default",
|
||||
"core:path:default",
|
||||
"core:event:default",
|
||||
"core:window:default",
|
||||
"core:window:allow-is-visible",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-set-focus",
|
||||
"core:app:default",
|
||||
"core:resources:default",
|
||||
"core:menu:default",
|
||||
"core:tray:default",
|
||||
"shell:allow-open",
|
||||
"process:allow-exit",
|
||||
"clipboard-manager:allow-read-text",
|
||||
@@ -24,16 +24,16 @@
|
||||
"shell:default",
|
||||
"process:default",
|
||||
"clipboard-manager:default",
|
||||
"tray:default",
|
||||
"tray:allow-new",
|
||||
"tray:allow-set-menu",
|
||||
"tray:allow-set-title",
|
||||
"tray:allow-remove-by-id",
|
||||
"tray:allow-get-by-id",
|
||||
"tray:allow-set-icon",
|
||||
"tray:allow-set-icon-as-template",
|
||||
"tray:allow-set-show-menu-on-left-click",
|
||||
"tray:allow-set-tooltip",
|
||||
"core:tray:default",
|
||||
"core:tray:allow-new",
|
||||
"core:tray:allow-set-menu",
|
||||
"core:tray:allow-set-title",
|
||||
"core:tray:allow-remove-by-id",
|
||||
"core:tray:allow-get-by-id",
|
||||
"core:tray:allow-set-icon",
|
||||
"core:tray:allow-set-icon-as-template",
|
||||
"core:tray:allow-set-show-menu-on-left-click",
|
||||
"core:tray:allow-set-tooltip",
|
||||
"vpnservice:allow-ping",
|
||||
"vpnservice:allow-prepare-vpn",
|
||||
"vpnservice:allow-start-vpn",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"createUpdaterArtifacts": false
|
||||
},
|
||||
"productName": "easytier-gui",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.1",
|
||||
"identifier": "com.kkrainbow.easytier",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
|
||||
Vendored
-95
@@ -201,98 +201,3 @@ declare module 'vue' {
|
||||
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
|
||||
}
|
||||
}
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly MenuItemExit: UnwrapRef<typeof import('./composables/tray')['MenuItemExit']>
|
||||
readonly MenuItemShow: UnwrapRef<typeof import('./composables/tray')['MenuItemShow']>
|
||||
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
|
||||
readonly collectNetworkInfos: UnwrapRef<typeof import('./composables/network')['collectNetworkInfos']>
|
||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
|
||||
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
|
||||
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
|
||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||
readonly definePage: UnwrapRef<typeof import('unplugin-vue-router/runtime')['definePage']>
|
||||
readonly defineStore: UnwrapRef<typeof import('pinia')['defineStore']>
|
||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||
readonly generateMenuItem: UnwrapRef<typeof import('./composables/tray')['generateMenuItem']>
|
||||
readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
|
||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||
readonly getOsHostname: UnwrapRef<typeof import('./composables/network')['getOsHostname']>
|
||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly initMobileVpnService: UnwrapRef<typeof import('./composables/mobile_vpn')['initMobileVpnService']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
|
||||
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
||||
readonly loadRunningInstanceIdsFromLocalStorage: UnwrapRef<typeof import('./stores/network')['loadRunningInstanceIdsFromLocalStorage']>
|
||||
readonly mapActions: UnwrapRef<typeof import('pinia')['mapActions']>
|
||||
readonly mapGetters: UnwrapRef<typeof import('pinia')['mapGetters']>
|
||||
readonly mapState: UnwrapRef<typeof import('pinia')['mapState']>
|
||||
readonly mapStores: UnwrapRef<typeof import('pinia')['mapStores']>
|
||||
readonly mapWritableState: UnwrapRef<typeof import('pinia')['mapWritableState']>
|
||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
|
||||
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
|
||||
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteLeave']>
|
||||
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router/auto')['onBeforeRouteUpdate']>
|
||||
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
|
||||
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
|
||||
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
|
||||
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
|
||||
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
|
||||
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
|
||||
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
|
||||
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
|
||||
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
|
||||
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly parseNetworkConfig: UnwrapRef<typeof import('./composables/network')['parseNetworkConfig']>
|
||||
readonly prepareVpnService: UnwrapRef<typeof import('./composables/mobile_vpn')['prepareVpnService']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
|
||||
readonly ref: UnwrapRef<typeof import('vue')['ref']>
|
||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||
readonly retainNetworkInstance: UnwrapRef<typeof import('./composables/network')['retainNetworkInstance']>
|
||||
readonly runNetworkInstance: UnwrapRef<typeof import('./composables/network')['runNetworkInstance']>
|
||||
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
||||
readonly setAutoLaunchStatus: UnwrapRef<typeof import('./composables/network')['setAutoLaunchStatus']>
|
||||
readonly setLoggingLevel: UnwrapRef<typeof import('./composables/network')['setLoggingLevel']>
|
||||
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
||||
readonly setTrayMenu: UnwrapRef<typeof import('./composables/tray')['setTrayMenu']>
|
||||
readonly setTrayRunState: UnwrapRef<typeof import('./composables/tray')['setTrayRunState']>
|
||||
readonly setTrayTooltip: UnwrapRef<typeof import('./composables/tray')['setTrayTooltip']>
|
||||
readonly setTunFd: UnwrapRef<typeof import('./composables/network')['setTunFd']>
|
||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
||||
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
|
||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||
readonly unref: UnwrapRef<typeof import('vue')['unref']>
|
||||
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
|
||||
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
|
||||
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
|
||||
readonly useI18n: UnwrapRef<typeof import('vue-i18n')['useI18n']>
|
||||
readonly useLink: UnwrapRef<typeof import('vue-router/auto')['useLink']>
|
||||
readonly useNetworkStore: UnwrapRef<typeof import('./stores/network')['useNetworkStore']>
|
||||
readonly useRoute: UnwrapRef<typeof import('vue-router/auto')['useRoute']>
|
||||
readonly useRouter: UnwrapRef<typeof import('vue-router/auto')['useRouter']>
|
||||
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
|
||||
readonly useTray: UnwrapRef<typeof import('./composables/tray')['useTray']>
|
||||
readonly watch: UnwrapRef<typeof import('vue')['watch']>
|
||||
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
|
||||
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
|
||||
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,14 +159,11 @@ async function watchNetworkInstance() {
|
||||
if (subscribe_running) {
|
||||
return
|
||||
}
|
||||
console.log('network instance change')
|
||||
|
||||
subscribe_running = true
|
||||
try {
|
||||
await onNetworkInstanceChange()
|
||||
} catch (_) {
|
||||
}
|
||||
console.log('network instance change done')
|
||||
subscribe_running = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getCurrent } from '@tauri-apps/api/window'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { Menu, MenuItem, PredefinedMenuItem } from '@tauri-apps/api/menu'
|
||||
import { TrayIcon } from '@tauri-apps/api/tray'
|
||||
import pkg from '~/../package.json'
|
||||
@@ -6,11 +6,11 @@ import pkg from '~/../package.json'
|
||||
const DEFAULT_TRAY_NAME = 'main'
|
||||
|
||||
async function toggleVisibility() {
|
||||
if (await getCurrent().isVisible()) {
|
||||
await getCurrent().hide()
|
||||
if (await getCurrentWindow().isVisible()) {
|
||||
await getCurrentWindow().hide()
|
||||
} else {
|
||||
await getCurrent().show()
|
||||
await getCurrent().setFocus()
|
||||
await getCurrentWindow().show()
|
||||
await getCurrentWindow().setFocus()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ export async function generateMenuItem() {
|
||||
await MenuItemExit('Exit'),
|
||||
await PredefinedMenuItem.new({ item: 'Separator' }),
|
||||
await MenuItemShow('Show / Hide'),
|
||||
] || []
|
||||
]
|
||||
}
|
||||
|
||||
export async function MenuItemExit(text: string) {
|
||||
|
||||
+26
-15
@@ -3,7 +3,7 @@ name = "easytier"
|
||||
description = "A full meshed p2p VPN, connecting all your devices in one network with one command."
|
||||
homepage = "https://github.com/EasyTier/EasyTier"
|
||||
repository = "https://github.com/EasyTier/EasyTier"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
edition = "2021"
|
||||
authors = ["kkrainbow"]
|
||||
keywords = ["vpn", "p2p", "network", "easytier"]
|
||||
@@ -43,7 +43,7 @@ time = "0.3"
|
||||
toml = "0.8.12"
|
||||
chrono = { version = "0.4.37", features = ["serde"] }
|
||||
|
||||
gethostname = "0.4.3"
|
||||
gethostname = "0.5.0"
|
||||
|
||||
futures = { version = "0.3", features = ["bilock", "unstable"] }
|
||||
|
||||
@@ -54,7 +54,7 @@ tokio-util = { version = "0.7.9", features = ["codec", "net"] }
|
||||
async-stream = "0.3.5"
|
||||
async-trait = "0.1.74"
|
||||
|
||||
dashmap = "5.5.3"
|
||||
dashmap = "6.0"
|
||||
timedmap = "=1.0.1"
|
||||
|
||||
# for full-path zero-copy
|
||||
@@ -62,7 +62,7 @@ zerocopy = { version = "0.7.32", features = ["derive", "simd"] }
|
||||
bytes = "1.5.0"
|
||||
pin-project-lite = "0.2.13"
|
||||
atomicbox = "0.4.0"
|
||||
tachyonix = "0.2.1"
|
||||
tachyonix = "0.3.0"
|
||||
|
||||
quinn = { version = "0.11.0", optional = true, features = ["ring"] }
|
||||
rustls = { version = "0.23.0", features = [
|
||||
@@ -71,7 +71,7 @@ rustls = { version = "0.23.0", features = [
|
||||
rcgen = { version = "0.11.1", optional = true }
|
||||
|
||||
# for websocket
|
||||
tokio-websockets = { version = "0.8.2", optional = true, features = [
|
||||
tokio-websockets = { version = "0.8", optional = true, features = [
|
||||
"rustls-webpki-roots",
|
||||
"client",
|
||||
"server",
|
||||
@@ -84,7 +84,7 @@ http = { version = "1", default-features = false, features = [
|
||||
tokio-rustls = { version = "0.26", default-features = false, optional = true }
|
||||
|
||||
# for tap device
|
||||
tun = { package = "tun-easytier", version = "0.7.1", features = [
|
||||
tun = { package = "tun-easytier", version = "1.1.1", features = [
|
||||
"async",
|
||||
], optional = true }
|
||||
# for net ns
|
||||
@@ -105,8 +105,8 @@ once_cell = "1.18.0"
|
||||
postcard = { "version" = "1.0.8", features = ["alloc"] }
|
||||
|
||||
# for rpc
|
||||
tonic = "0.10"
|
||||
prost = "0.12"
|
||||
tonic = "0.12"
|
||||
prost = "0.13"
|
||||
anyhow = "1.0"
|
||||
tarpc = { version = "0.32", features = ["tokio1", "serde1"] }
|
||||
|
||||
@@ -126,13 +126,18 @@ bytecodec = "0.4.15"
|
||||
rand = "0.8.5"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
pnet = { version = "0.34.0", features = ["serde"] }
|
||||
pnet = { version = "0.35.0", features = ["serde"] }
|
||||
|
||||
clap = { version = "4.4.8", features = ["unicode", "derive", "wrap_help"] }
|
||||
clap = { version = "4.4.8", features = [
|
||||
"string",
|
||||
"unicode",
|
||||
"derive",
|
||||
"wrap_help",
|
||||
] }
|
||||
|
||||
async-recursion = "1.0.5"
|
||||
|
||||
network-interface = "1.1.1"
|
||||
network-interface = "2.0"
|
||||
|
||||
# for ospf route
|
||||
petgraph = "0.6.5"
|
||||
@@ -143,15 +148,16 @@ bitflags = "2.5"
|
||||
aes-gcm = { version = "0.10.3", optional = true }
|
||||
|
||||
# for cli
|
||||
tabled = "0.15.*"
|
||||
tabled = "0.16"
|
||||
humansize = "2.1.3"
|
||||
|
||||
base64 = "0.21.7"
|
||||
base64 = "0.22"
|
||||
|
||||
derivative = "2.2.0"
|
||||
|
||||
mimalloc-rust = { version = "0.2.1", optional = true }
|
||||
|
||||
# for mips
|
||||
indexmap = { version = "~1.9.3", optional = false, features = ["std"] }
|
||||
|
||||
atomic-shim = "0.2.0"
|
||||
@@ -168,6 +174,9 @@ parking_lot = { version = "0.12.0", optional = true }
|
||||
|
||||
wildmatch = "2.3.4"
|
||||
|
||||
rust-i18n = "3"
|
||||
sys-locale = "0.3"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.52", features = [
|
||||
"Win32_Networking_WinSock",
|
||||
@@ -176,10 +185,12 @@ windows-sys = { version = "0.52", features = [
|
||||
"Win32_System_IO",
|
||||
] }
|
||||
encoding = "0.2"
|
||||
winreg = "0.11"
|
||||
winreg = "0.52"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.10"
|
||||
tonic-build = "0.12"
|
||||
globwalk = "0.8.1"
|
||||
regex = "1"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
reqwest = { version = "0.11", features = ["blocking"] }
|
||||
|
||||
@@ -86,6 +86,45 @@ impl WindowsBuild {
|
||||
}
|
||||
}
|
||||
|
||||
fn workdir() -> Option<String> {
|
||||
if let Ok(cargo_manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
|
||||
return Some(cargo_manifest_dir);
|
||||
}
|
||||
|
||||
let dest = std::env::var("OUT_DIR");
|
||||
if dest.is_err() {
|
||||
return None;
|
||||
}
|
||||
let dest = dest.unwrap();
|
||||
|
||||
let seperator = regex::Regex::new(r"(/target/(.+?)/build/)|(\\target\\(.+?)\\build\\)")
|
||||
.expect("Invalid regex");
|
||||
let parts = seperator.split(dest.as_str()).collect::<Vec<_>>();
|
||||
|
||||
if parts.len() >= 2 {
|
||||
return Some(parts[0].to_string());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn check_locale() {
|
||||
let workdir = workdir().unwrap_or("./".to_string());
|
||||
|
||||
let locale_path = format!("{workdir}/**/locales/**/*");
|
||||
if let Ok(globs) = globwalk::glob(locale_path) {
|
||||
for entry in globs {
|
||||
if let Err(e) = entry {
|
||||
println!("cargo:i18n-error={}", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
let entry = entry.unwrap().into_path();
|
||||
println!("cargo:rerun-if-changed={}", entry.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[cfg(target_os = "windows")]
|
||||
WindowsBuild::check_for_win();
|
||||
@@ -98,5 +137,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.compile(&["proto/cli.proto"], &["proto/"])
|
||||
.unwrap();
|
||||
// tonic_build::compile_protos("proto/cli.proto")?;
|
||||
check_locale();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
_version: 2
|
||||
|
||||
core_clap:
|
||||
config_file:
|
||||
en: "path to the config file, NOTE: if this is set, all other options will be ignored"
|
||||
zh-CN: "配置文件路径,注意:如果设置了这个选项,其他所有选项都将被忽略"
|
||||
network_name:
|
||||
en: "network name to identify this vpn network"
|
||||
zh-CN: "用于标识此VPN网络的网络名称"
|
||||
network_secret:
|
||||
en: "network secret to verify this node belongs to the vpn network"
|
||||
zh-CN: "网络密钥,用于验证此节点属于VPN网络"
|
||||
ipv4:
|
||||
en: "ipv4 address of this vpn node, if empty, this node will only forward packets and no TUN device will be created"
|
||||
zh-CN: "此VPN节点的IPv4地址,如果为空,则此节点将仅转发数据包,不会创建TUN设备"
|
||||
dhcp:
|
||||
en: "automatically determine and set IP address by Easytier, and the IP address starts from 10.0.0.1 by default. Warning, if there is an IP conflict in the network when using DHCP, the IP will be automatically changed."
|
||||
zh-CN: "由Easytier自动确定并设置IP地址,默认从10.0.0.1开始。警告:在使用DHCP时,如果网络中出现IP冲突,IP将自动更改。"
|
||||
peers:
|
||||
en: "peers to connect initially"
|
||||
zh-CN: "最初要连接的对等节点"
|
||||
external_node:
|
||||
en: "use a public shared node to discover peers"
|
||||
zh-CN: "使用公共共享节点来发现对等节点"
|
||||
proxy_networks:
|
||||
en: "export local networks to other peers in the vpn"
|
||||
zh-CN: "将本地网络导出到VPN中的其他对等节点"
|
||||
rpc_portal:
|
||||
en: "rpc portal address to listen for management. 0 means random port, 12345 means listen on 12345 of localhost, 0.0.0.0:12345 means listen on 12345 of all interfaces. default is 0 and will try 15888 first"
|
||||
zh-CN: "用于管理的RPC门户地址。0表示随机端口,12345表示在localhost的12345上监听,0.0.0.0:12345表示在所有接口的12345上监听。默认是0,首先尝试15888"
|
||||
listeners:
|
||||
en: |+
|
||||
listeners to accept connections, allow format:
|
||||
port number: <11010>. means tcp/udp will listen on 11010, ws/wss will listen on 11010 and 11011, wg will listen on 11011
|
||||
url: <tcp://0.0.0.0:11010>. tcp can be tcp, udp, ring, wg, ws, wss\n
|
||||
proto & port pair: <proto:port>. wg:11011, means listen on 11011 with wireguard protocol url and proto:port can occur multiple times.
|
||||
zh-CN: |+
|
||||
监听器用于接受连接,允许以下格式:
|
||||
端口号:<11010>,意味着tcp/udp将在11010端口监听,ws/wss将在11010和11011端口监听,wg将在11011端口监听。
|
||||
url:<tcp://0.0.0.0:11010>,其中tcp可以是tcp、udp、ring、wg、ws、wss协议。
|
||||
协议和端口对:<proto:port>,例如wg:11011,表示使用WireGuard协议在11011端口监听。URL 和 协议端口对 可以多次出现。
|
||||
no_listener:
|
||||
en: "do not listen on any port, only connect to peers"
|
||||
zh-CN: "不监听任何端口,只连接到对等节点"
|
||||
console_log_level:
|
||||
en: "console log level"
|
||||
zh-CN: "控制台日志级别"
|
||||
file_log_level:
|
||||
en: "file log level"
|
||||
zh-CN: "文件日志级别"
|
||||
file_log_dir:
|
||||
en: "directory to store log files"
|
||||
zh-CN: "存储日志文件的目录"
|
||||
hostname:
|
||||
en: "host name to identify this device"
|
||||
zh-CN: "用于标识此设备的主机名"
|
||||
instance_name:
|
||||
en: "instance name to identify this vpn node in same machine"
|
||||
zh-CN: "实例名称,用于在同一台机器上标识此VPN节点"
|
||||
vpn_portal:
|
||||
en: "url that defines the vpn portal, allow other vpn clients to connect. example: wg://0.0.0.0:11010/10.14.14.0/24, means the vpn portal is a wireguard server listening on vpn.example.com:11010, and the vpn client is in network of 10.14.14.0/24"
|
||||
zh-CN: "定义VPN门户的URL,允许其他VPN客户端连接。示例:wg://0.0.0.0:11010/10.14.14.0/24,表示VPN门户是监听在vpn.example.com:11010的wireguard服务器,VPN客户端在10.14.14.0/24网络中"
|
||||
default_protocol:
|
||||
en: "default protocol to use when connecting to peers"
|
||||
zh-CN: "连接到对等节点时使用的默认协议"
|
||||
disable_encryption:
|
||||
en: "disable encryption for peers communication, default is false, must be same with peers"
|
||||
zh-CN: "禁用对等节点通信的加密,默认为false,必须与对等节点相同"
|
||||
multi_thread:
|
||||
en: "use multi-thread runtime, default is single-thread"
|
||||
zh-CN: "使用多线程运行时,默认为单线程"
|
||||
disable_ipv6:
|
||||
en: "do not use ipv6"
|
||||
zh-CN: "不使用IPv6"
|
||||
dev_name:
|
||||
en: "optional tun interface name"
|
||||
zh-CN: "可选的TUN接口名称"
|
||||
mtu:
|
||||
en: "mtu of the TUN device, default is 1420 for non-encryption, 1400 for encryption"
|
||||
zh-CN: "TUN设备的MTU,默认为非加密时为1420,加密时为1400"
|
||||
latency_first:
|
||||
en: "latency first mode, will try to relay traffic with lowest latency path, default is using shortest path"
|
||||
zh-CN: "延迟优先模式,将尝试使用最低延迟路径转发流量,默认使用最短路径"
|
||||
exit_nodes:
|
||||
en: "exit nodes to forward all traffic to, a virtual ipv4 address, priority is determined by the order of the list"
|
||||
zh-CN: "转发所有流量的出口节点,虚拟IPv4地址,优先级由列表顺序决定"
|
||||
enable_exit_node:
|
||||
en: "allow this node to be an exit node"
|
||||
zh-CN: "允许此节点成为出口节点"
|
||||
no_tun:
|
||||
en: "do not create TUN device, can use subnet proxy to access node"
|
||||
zh-CN: "不创建TUN设备,可以使用子网代理访问节点"
|
||||
use_smoltcp:
|
||||
en: "enable smoltcp stack for subnet proxy"
|
||||
zh-CN: "为子网代理启用smoltcp堆栈"
|
||||
manual_routes:
|
||||
en: "assign routes cidr manually, will disable subnet proxy and wireguard routes propagated from peers. e.g.: 192.168.0.0/16"
|
||||
zh-CN: "手动分配路由CIDR,将禁用子网代理和从对等节点传播的wireguard路由。例如:192.168.0.0/16"
|
||||
relay_network_whitelist:
|
||||
en: "only relay traffic of whitelisted networks, input is a wildcard string, e.g.: '*' (all networks), 'def*' (network prefixed with def), can specify multiple networks disable relay if arg is empty. default is allowing all networks"
|
||||
zh-CN: "仅转发白名单网络的流量,输入是通配符字符串,例如:'*'(所有网络),'def*'(以def为前缀的网络),可以指定多个网络。如果参数为空,则禁用转发。默认允许所有网络"
|
||||
@@ -258,21 +258,15 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
|
||||
match hostname {
|
||||
Some(hostname) => {
|
||||
let hostname = hostname
|
||||
.chars()
|
||||
.filter(|c| !c.is_control())
|
||||
.take(32)
|
||||
.collect::<String>();
|
||||
|
||||
if !hostname.is_empty() {
|
||||
let mut name = hostname
|
||||
.chars()
|
||||
.filter(|c| c.is_ascii_alphanumeric() || *c == '-' || *c == '_')
|
||||
.take(32)
|
||||
.collect::<String>();
|
||||
|
||||
if name.len() > 32 {
|
||||
name = name.chars().take(32).collect::<String>();
|
||||
}
|
||||
|
||||
if hostname != name {
|
||||
self.set_hostname(Some(name.clone()));
|
||||
}
|
||||
name
|
||||
self.set_hostname(Some(hostname.clone()));
|
||||
hostname
|
||||
} else {
|
||||
self.set_hostname(None);
|
||||
gethostname::gethostname().to_string_lossy().to_string()
|
||||
|
||||
@@ -316,6 +316,7 @@ impl ManualConnectorManager {
|
||||
ip_versions.push(IpVersion::Both);
|
||||
} else {
|
||||
let addrs = u.socket_addrs(|| Some(1000))?;
|
||||
tracing::info!(?addrs, ?dead_url, "get ip from url done");
|
||||
let mut has_ipv4 = false;
|
||||
let mut has_ipv6 = false;
|
||||
for addr in addrs {
|
||||
|
||||
@@ -10,6 +10,9 @@ use std::{
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
extern crate rust_i18n;
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
|
||||
@@ -52,19 +55,20 @@ struct Cli {
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "path to the config file, NOTE: if this is set, all other options will be ignored"
|
||||
help = t!("core_clap.config_file").to_string()
|
||||
)]
|
||||
config_file: Option<PathBuf>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "network name to identify this vpn network",
|
||||
help = t!("core_clap.network_name").to_string(),
|
||||
default_value = "default"
|
||||
)]
|
||||
network_name: String,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "network secret to verify this node belongs to the vpn network",
|
||||
help = t!("core_clap.network_secret").to_string(),
|
||||
default_value = ""
|
||||
)]
|
||||
network_secret: String,
|
||||
@@ -72,171 +76,193 @@ struct Cli {
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "ipv4 address of this vpn node, if empty, this node will only forward packets and no TUN device will be created"
|
||||
help = t!("core_clap.ipv4").to_string()
|
||||
)]
|
||||
ipv4: Option<String>,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = "automatically determine and set IP address by Easytier, and the
|
||||
IP address starts from 10.0.0.1 by default. Warning, if there is an IP
|
||||
conflict in the network when using DHCP, the IP will be automatically
|
||||
changed."
|
||||
help = t!("core_clap.dhcp").to_string()
|
||||
)]
|
||||
dhcp: bool,
|
||||
|
||||
#[arg(short, long, help = "peers to connect initially", num_args = 0..)]
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = t!("core_clap.peers").to_string(),
|
||||
num_args = 0..
|
||||
)]
|
||||
peers: Vec<String>,
|
||||
|
||||
#[arg(short, long, help = "use a public shared node to discover peers")]
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = t!("core_clap.external_node").to_string()
|
||||
)]
|
||||
external_node: Option<String>,
|
||||
|
||||
#[arg(
|
||||
short = 'n',
|
||||
long,
|
||||
help = "export local networks to other peers in the vpn"
|
||||
help = t!("core_clap.proxy_networks").to_string()
|
||||
)]
|
||||
proxy_networks: Vec<String>,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
default_value = "0",
|
||||
help = "rpc portal address to listen for management. 0 means random
|
||||
port, 12345 means listen on 12345 of localhost, 0.0.0.0:12345 means
|
||||
listen on 12345 of all interfaces. default is 0 and will try 15888 first"
|
||||
help = t!("core_clap.rpc_portal").to_string(),
|
||||
default_value = "0"
|
||||
)]
|
||||
rpc_portal: String,
|
||||
|
||||
#[arg(short, long, help = "listeners to accept connections, allow format:
|
||||
a port number: 11010, means tcp/udp will listen on 11010, ws/wss will listen on 11010 and 11011, wg will listen on 11011
|
||||
url: tcp://0.0.0.0:11010, tcp can be tcp, udp, ring, wg, ws, wss,
|
||||
proto:port: wg:11011, means listen on 11011 with wireguard protocol
|
||||
url and proto:port can occur multiple times.
|
||||
", default_values_t = ["11010".to_string()],
|
||||
num_args = 0..)]
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
help = t!("core_clap.listeners").to_string(),
|
||||
default_values_t = ["11010".to_string()],
|
||||
num_args = 0..
|
||||
)]
|
||||
listeners: Vec<String>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "do not listen on any port, only connect to peers",
|
||||
help = t!("core_clap.no_listener").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
no_listener: bool,
|
||||
|
||||
#[arg(long, help = "console log level",
|
||||
value_parser = clap::builder::PossibleValuesParser::new(["trace", "debug", "info", "warn", "error", "off"]))]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.console_log_level").to_string()
|
||||
)]
|
||||
console_log_level: Option<String>,
|
||||
|
||||
#[arg(long, help = "file log level",
|
||||
value_parser = clap::builder::PossibleValuesParser::new(["trace", "debug", "info", "warn", "error", "off"]))]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.file_log_level").to_string()
|
||||
)]
|
||||
file_log_level: Option<String>,
|
||||
#[arg(long, help = "directory to store log files")]
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.file_log_dir").to_string()
|
||||
)]
|
||||
file_log_dir: Option<String>,
|
||||
|
||||
#[arg(long, help = "host name to identify this device")]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.hostname").to_string()
|
||||
)]
|
||||
hostname: Option<String>,
|
||||
|
||||
#[arg(
|
||||
short = 'm',
|
||||
long,
|
||||
default_value = "default",
|
||||
help = "instance name to identify this vpn node in same machine"
|
||||
help = t!("core_clap.instance_name").to_string(),
|
||||
default_value = "default"
|
||||
)]
|
||||
instance_name: String,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "url that defines the vpn portal, allow other vpn clients to connect.
|
||||
example: wg://0.0.0.0:11010/10.14.14.0/24, means the vpn portal is a wireguard server listening on vpn.example.com:11010,
|
||||
and the vpn client is in network of 10.14.14.0/24"
|
||||
help = t!("core_clap.vpn_portal").to_string()
|
||||
)]
|
||||
vpn_portal: Option<String>,
|
||||
|
||||
#[arg(long, help = "default protocol to use when connecting to peers")]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.default_protocol").to_string()
|
||||
)]
|
||||
default_protocol: Option<String>,
|
||||
|
||||
#[arg(
|
||||
short = 'u',
|
||||
long,
|
||||
help = "disable encryption for peers communication, default is false, must be same with peers",
|
||||
help = t!("core_clap.disable_encryption").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
disable_encryption: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "use multi-thread runtime, default is single-thread",
|
||||
help = t!("core_clap.multi_thread").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
multi_thread: bool,
|
||||
|
||||
#[arg(long, help = "do not use ipv6", default_value = "false")]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.disable_ipv6").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
disable_ipv6: bool,
|
||||
|
||||
#[arg(long, help = "optional tun interface name")]
|
||||
#[arg(
|
||||
long,
|
||||
help = t!("core_clap.dev_name").to_string()
|
||||
)]
|
||||
dev_name: Option<String>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "mtu of the TUN device, default is 1420 for non-encryption, 1400 for encryption"
|
||||
help = t!("core_clap.mtu").to_string()
|
||||
)]
|
||||
mtu: Option<u16>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "latency first mode, will try to relay traffic with lowest latency path, default is using shortest path",
|
||||
help = t!("core_clap.latency_first").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
latency_first: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "exit nodes to forward all traffic to, a virtual ipv4 address, priority is determined by the order of the list",
|
||||
help = t!("core_clap.exit_nodes").to_string(),
|
||||
num_args = 0..
|
||||
)]
|
||||
exit_nodes: Vec<Ipv4Addr>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "allow this node to be an exit node, default is false",
|
||||
help = t!("core_clap.enable_exit_node").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
enable_exit_node: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "do not create TUN device, can use subnet proxy to access node",
|
||||
help = t!("core_clap.no_tun").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
no_tun: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "enable smoltcp stack for subnet proxy",
|
||||
help = t!("core_clap.use_smoltcp").to_string(),
|
||||
default_value = "false"
|
||||
)]
|
||||
use_smoltcp: bool,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "assign routes cidr manually, will disable subnet proxy and
|
||||
wireguard routes propogated from peers. e.g.: 192.168.0.0/16",
|
||||
help = t!("core_clap.manual_routes").to_string(),
|
||||
num_args = 0..
|
||||
)]
|
||||
manual_routes: Option<Vec<String>>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
help = "only relay traffic of whitelisted networks, input is a wildcard
|
||||
string, e.g.: '*' (all networks), 'def*' (network prefixed with def), can specify multiple networks
|
||||
disable relay if arg is empty. default is allowing all networks",
|
||||
num_args = 0..,
|
||||
help = t!("core_clap.relay_network_whitelist").to_string(),
|
||||
num_args = 0..
|
||||
)]
|
||||
relay_network_whitelist: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
rust_i18n::i18n!("locales");
|
||||
|
||||
impl Cli {
|
||||
fn parse_listeners(&self) -> Vec<String> {
|
||||
println!("parsing listeners: {:?}", self.listeners);
|
||||
@@ -628,6 +654,9 @@ pub async fn async_main(cli: Cli) {
|
||||
fn main() {
|
||||
setup_panic_handler();
|
||||
|
||||
let locale = sys_locale::get_locale().unwrap_or_else(|| String::from("en-US"));
|
||||
rust_i18n::set_locale(&locale);
|
||||
|
||||
let cli = Cli::parse();
|
||||
tracing::info!(cli = ?cli, "cli args parsed");
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::any::Any;
|
||||
use std::collections::HashSet;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -91,7 +92,7 @@ impl NicCtx {
|
||||
}
|
||||
}
|
||||
|
||||
type ArcNicCtx = Arc<Mutex<Option<NicCtx>>>;
|
||||
type ArcNicCtx = Arc<Mutex<Option<Box<dyn Any + 'static + Send>>>>;
|
||||
|
||||
pub struct Instance {
|
||||
inst_name: String,
|
||||
@@ -197,14 +198,28 @@ impl Instance {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn clear_nic_ctx(arc_nic_ctx: ArcNicCtx) {
|
||||
// use a mock nic ctx to consume packets.
|
||||
async fn clear_nic_ctx(
|
||||
arc_nic_ctx: ArcNicCtx,
|
||||
packet_recv: Arc<Mutex<PacketRecvChanReceiver>>,
|
||||
) {
|
||||
let _ = arc_nic_ctx.lock().await.take();
|
||||
|
||||
let mut tasks = JoinSet::new();
|
||||
tasks.spawn(async move {
|
||||
let mut packet_recv = packet_recv.lock().await;
|
||||
while let Some(packet) = packet_recv.recv().await {
|
||||
tracing::trace!("packet consumed by mock nic ctx: {:?}", packet);
|
||||
}
|
||||
});
|
||||
arc_nic_ctx.lock().await.replace(Box::new(tasks));
|
||||
|
||||
tracing::debug!("nic ctx cleared.");
|
||||
}
|
||||
|
||||
async fn use_new_nic_ctx(arc_nic_ctx: ArcNicCtx, nic_ctx: NicCtx) {
|
||||
let mut g = arc_nic_ctx.lock().await;
|
||||
*g = Some(nic_ctx);
|
||||
*g = Some(Box::new(nic_ctx));
|
||||
tracing::debug!("nic ctx updated.");
|
||||
}
|
||||
|
||||
@@ -274,7 +289,7 @@ impl Instance {
|
||||
"dhcp start changing ip"
|
||||
);
|
||||
|
||||
Self::clear_nic_ctx(nic_ctx.clone()).await;
|
||||
Self::clear_nic_ctx(nic_ctx.clone(), _peer_packet_receiver.clone()).await;
|
||||
|
||||
if let Some(ip) = candidate_ipv4_addr {
|
||||
if global_ctx_c.no_tun() {
|
||||
@@ -329,9 +344,9 @@ impl Instance {
|
||||
self.listener_manager.lock().await.run().await?;
|
||||
self.peer_manager.run().await?;
|
||||
|
||||
if self.global_ctx.config.get_flags().no_tun {
|
||||
self.peer_packet_receiver.lock().await.close();
|
||||
} else {
|
||||
Self::clear_nic_ctx(self.nic_ctx.clone(), self.peer_packet_receiver.clone()).await;
|
||||
|
||||
if !self.global_ctx.config.get_flags().no_tun {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
if let Some(ipv4_addr) = self.global_ctx.get_ipv4() {
|
||||
let mut new_nic_ctx = NicCtx::new(
|
||||
@@ -532,7 +547,7 @@ impl Instance {
|
||||
fd: i32,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
println!("setup_nic_ctx_for_android, fd: {}", fd);
|
||||
Self::clear_nic_ctx(nic_ctx.clone()).await;
|
||||
Self::clear_nic_ctx(nic_ctx.clone(), peer_packet_receiver.clone()).await;
|
||||
if fd <= 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ use tokio::{
|
||||
task::JoinSet,
|
||||
};
|
||||
use tokio_util::bytes::Bytes;
|
||||
use tun::{create_as_async, AsyncDevice, Configuration, Device as _, Layer};
|
||||
use tun::{AbstractDevice, AsyncDevice, Configuration, Layer};
|
||||
use zerocopy::{NativeEndian, NetworkEndian};
|
||||
|
||||
pin_project! {
|
||||
@@ -237,9 +237,6 @@ impl AsyncWrite for TunAsyncWrite {
|
||||
}
|
||||
|
||||
pub struct VirtualNic {
|
||||
dev_name: String,
|
||||
queue_num: usize,
|
||||
|
||||
global_ctx: ArcGlobalCtx,
|
||||
|
||||
ifname: Option<String>,
|
||||
@@ -247,10 +244,8 @@ pub struct VirtualNic {
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn checkreg() -> io::Result<()> {
|
||||
use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey,enums::KEY_ALL_ACCESS};
|
||||
// 打开根键
|
||||
use winreg::{enums::HKEY_LOCAL_MACHINE, enums::KEY_ALL_ACCESS, RegKey};
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
// 打开指定的子键
|
||||
let profiles_key = hklm.open_subkey_with_flags(
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles",
|
||||
KEY_ALL_ACCESS,
|
||||
@@ -259,21 +254,19 @@ pub fn checkreg() -> io::Result<()> {
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged",
|
||||
KEY_ALL_ACCESS,
|
||||
)?;
|
||||
// 收集要删除的子键名称
|
||||
// collect subkeys to delete
|
||||
let mut keys_to_delete = Vec::new();
|
||||
let mut keys_to_delete_unmanaged = Vec::new();
|
||||
for subkey_name in profiles_key.enum_keys().filter_map(Result::ok) {
|
||||
let subkey = profiles_key.open_subkey(&subkey_name)?;
|
||||
// 尝试读取 ProfileName 值
|
||||
// check if ProfileName contains "et"
|
||||
match subkey.get_value::<String, _>("ProfileName") {
|
||||
Ok(profile_name) => {
|
||||
// 检查 ProfileName 是否包含 "et"
|
||||
if profile_name.contains("et_") {
|
||||
keys_to_delete.push(subkey_name);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// 打印错误信息
|
||||
tracing::error!(
|
||||
"Failed to read ProfileName for subkey {}: {}",
|
||||
subkey_name,
|
||||
@@ -284,16 +277,14 @@ pub fn checkreg() -> io::Result<()> {
|
||||
}
|
||||
for subkey_name in unmanaged_key.enum_keys().filter_map(Result::ok) {
|
||||
let subkey = unmanaged_key.open_subkey(&subkey_name)?;
|
||||
// 尝试读取 ProfileName 值
|
||||
// check if ProfileName contains "et"
|
||||
match subkey.get_value::<String, _>("Description") {
|
||||
Ok(profile_name) => {
|
||||
// 检查 ProfileName 是否包含 "et"
|
||||
if profile_name.contains("et_") {
|
||||
keys_to_delete_unmanaged.push(subkey_name);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// 打印错误信息
|
||||
tracing::error!(
|
||||
"Failed to read ProfileName for subkey {}: {}",
|
||||
subkey_name,
|
||||
@@ -302,7 +293,7 @@ pub fn checkreg() -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
//删除收集到的子键
|
||||
// delete collected subkeys
|
||||
if !keys_to_delete.is_empty() {
|
||||
for subkey_name in keys_to_delete {
|
||||
match profiles_key.delete_subkey_all(&subkey_name) {
|
||||
@@ -325,25 +316,13 @@ pub fn checkreg() -> io::Result<()> {
|
||||
impl VirtualNic {
|
||||
pub fn new(global_ctx: ArcGlobalCtx) -> Self {
|
||||
Self {
|
||||
dev_name: "".to_owned(),
|
||||
queue_num: 1,
|
||||
global_ctx,
|
||||
ifname: None,
|
||||
ifcfg: Box::new(IfConfiger {}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_dev_name(mut self, dev_name: &str) -> Result<Self, Error> {
|
||||
self.dev_name = dev_name.to_owned();
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn set_queue_num(mut self, queue_num: usize) -> Result<Self, Error> {
|
||||
self.queue_num = queue_num;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
async fn create_tun(&mut self) -> Result<AsyncDevice, Error> {
|
||||
async fn create_tun(&mut self) -> Result<tun::platform::Device, Error> {
|
||||
let mut config = Configuration::default();
|
||||
config.layer(Layer::L3);
|
||||
|
||||
@@ -351,22 +330,23 @@ impl VirtualNic {
|
||||
{
|
||||
let dev_name = self.global_ctx.get_flags().dev_name;
|
||||
if !dev_name.is_empty() {
|
||||
config.name(format!("{}", dev_name));
|
||||
config.tun_name(format!("{}", dev_name));
|
||||
}
|
||||
config.platform(|config| {
|
||||
// detect protocol by ourselves for cross platform
|
||||
config.packet_information(false);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
config.platform_config(|config| {
|
||||
// disable packet information so we can process the header by ourselves, see tun2 impl for more details
|
||||
config.packet_information(false);
|
||||
});
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
match checkreg(){
|
||||
match checkreg() {
|
||||
Ok(_) => tracing::trace!("delete successful!"),
|
||||
Err(e) => tracing::error!("An error occurred: {}", e),
|
||||
}
|
||||
use rand::distributions::Distribution as _;
|
||||
use std::net::IpAddr;
|
||||
let c = crate::arch::windows::interface_count()?;
|
||||
let mut rng = rand::thread_rng();
|
||||
let s: String = rand::distributions::Alphanumeric
|
||||
@@ -376,13 +356,15 @@ impl VirtualNic {
|
||||
.collect::<String>()
|
||||
.to_lowercase();
|
||||
|
||||
config.name(format!("et{}_{}_{}", self.dev_name, c, s));
|
||||
// set a temporary address
|
||||
config.address(format!("172.0.{}.3", c).parse::<IpAddr>().unwrap());
|
||||
let dev_name = self.global_ctx.get_flags().dev_name;
|
||||
if !dev_name.is_empty() {
|
||||
config.tun_name(format!("{}", dev_name));
|
||||
} else {
|
||||
config.tun_name(format!("et{}_{}", c, s));
|
||||
}
|
||||
|
||||
config.platform(|config| {
|
||||
config.platform_config(|config| {
|
||||
config.skip_config(true);
|
||||
config.guid(None);
|
||||
config.ring_cap(Some(std::cmp::min(
|
||||
config.min_ring_cap() * 32,
|
||||
config.max_ring_cap(),
|
||||
@@ -390,14 +372,10 @@ impl VirtualNic {
|
||||
});
|
||||
}
|
||||
|
||||
if self.queue_num != 1 {
|
||||
todo!("queue_num != 1")
|
||||
}
|
||||
config.queues(self.queue_num);
|
||||
config.up();
|
||||
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
Ok(create_as_async(&config)?)
|
||||
Ok(tun::create(&config)?)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -409,12 +387,11 @@ impl VirtualNic {
|
||||
let mut config = Configuration::default();
|
||||
config.layer(Layer::L3);
|
||||
config.raw_fd(tun_fd);
|
||||
config.platform(|config| {
|
||||
config.no_close_fd_on_drop(true);
|
||||
});
|
||||
config.close_fd_on_drop(false);
|
||||
config.up();
|
||||
|
||||
let dev = create_as_async(&config)?;
|
||||
let dev = tun::create(&config)?;
|
||||
let dev = AsyncDevice::new(dev)?;
|
||||
let (a, b) = BiLock::new(dev);
|
||||
let ft = TunnelWrapper::new(
|
||||
TunStream::new(a, false),
|
||||
@@ -432,9 +409,11 @@ impl VirtualNic {
|
||||
|
||||
pub async fn create_dev(&mut self) -> Result<Box<dyn Tunnel>, Error> {
|
||||
let dev = self.create_tun().await?;
|
||||
let ifname = dev.get_ref().name()?;
|
||||
let ifname = dev.tun_name()?;
|
||||
self.ifcfg.wait_interface_show(ifname.as_str()).await?;
|
||||
|
||||
let dev = AsyncDevice::new(dev)?;
|
||||
|
||||
let flags = self.global_ctx.config.get_flags();
|
||||
let mut mtu_in_config = flags.mtu;
|
||||
if flags.enable_encryption {
|
||||
|
||||
@@ -205,7 +205,7 @@ impl FromUrl for SocketAddr {
|
||||
fn from_url(url: url::Url, ip_version: IpVersion) -> Result<Self, TunnelError> {
|
||||
let addrs = url.socket_addrs(|| None)?;
|
||||
tracing::debug!(?addrs, ?ip_version, ?url, "convert url to socket addrs");
|
||||
let mut addrs = addrs
|
||||
let addrs = addrs
|
||||
.into_iter()
|
||||
.filter(|addr| match ip_version {
|
||||
IpVersion::V4 => addr.is_ipv4(),
|
||||
@@ -213,7 +213,13 @@ impl FromUrl for SocketAddr {
|
||||
IpVersion::Both => true,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
addrs.pop().ok_or(TunnelError::NoDnsRecordFound(ip_version))
|
||||
|
||||
use rand::seq::SliceRandom;
|
||||
// randomly select one address
|
||||
addrs
|
||||
.choose(&mut rand::thread_rng())
|
||||
.copied()
|
||||
.ok_or(TunnelError::NoDnsRecordFound(ip_version))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tauri-plugin-vpnservice"
|
||||
version = "0.0.0"
|
||||
authors = [ "You" ]
|
||||
authors = ["You"]
|
||||
description = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
@@ -9,9 +9,9 @@ exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"]
|
||||
links = "tauri-plugin-vpnservice"
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta.23" }
|
||||
tauri = { version = "2.0.0-rc" }
|
||||
serde = "1.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-plugin = { version = "2.0.0-beta.18", features = ["build"] }
|
||||
tauri-plugin = { version = "2.0.0-rc", features = ["build"] }
|
||||
|
||||
@@ -88,9 +88,9 @@ class TauriVpnService : VpnService() {
|
||||
builder.addDnsServer(dns)
|
||||
|
||||
for (route in routes) {
|
||||
val ipParts = ipv4Addr.split("/")
|
||||
val ipParts = route.split("/")
|
||||
if (ipParts.size != 2) throw IllegalArgumentException("Invalid IP addr string")
|
||||
builder.addAddress(ipParts[0], ipParts[1].toInt())
|
||||
builder.addRoute(ipParts[0], ipParts[1].toInt())
|
||||
}
|
||||
|
||||
for (app in disallowedApplications) {
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
"pretest": "yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": ">=2.0.0-beta.6"
|
||||
"@tauri-apps/api": "2.0.0-rc.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"rollup": "^4.9.6",
|
||||
"typescript": "^5.3.3",
|
||||
"tslib": "^2.6.2"
|
||||
"rollup": "^4.20.0",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.5.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+91
-91
@@ -9,21 +9,21 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@tauri-apps/api':
|
||||
specifier: '>=2.0.0-beta.6'
|
||||
version: 2.0.0-beta.14
|
||||
specifier: 2.0.0-rc.0
|
||||
version: 2.0.0-rc.0
|
||||
devDependencies:
|
||||
'@rollup/plugin-typescript':
|
||||
specifier: ^11.1.6
|
||||
version: 11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3)
|
||||
version: 11.1.6(rollup@4.20.0)(tslib@2.6.3)(typescript@5.5.4)
|
||||
rollup:
|
||||
specifier: ^4.9.6
|
||||
version: 4.18.1
|
||||
specifier: ^4.20.0
|
||||
version: 4.20.0
|
||||
tslib:
|
||||
specifier: ^2.6.2
|
||||
specifier: ^2.6.3
|
||||
version: 2.6.3
|
||||
typescript:
|
||||
specifier: ^5.3.3
|
||||
version: 5.5.3
|
||||
specifier: ^5.5.4
|
||||
version: 5.5.4
|
||||
|
||||
packages:
|
||||
|
||||
@@ -49,88 +49,88 @@ packages:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.18.1':
|
||||
resolution: {integrity: sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==}
|
||||
'@rollup/rollup-android-arm-eabi@4.20.0':
|
||||
resolution: {integrity: sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.18.1':
|
||||
resolution: {integrity: sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==}
|
||||
'@rollup/rollup-android-arm64@4.20.0':
|
||||
resolution: {integrity: sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.18.1':
|
||||
resolution: {integrity: sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==}
|
||||
'@rollup/rollup-darwin-arm64@4.20.0':
|
||||
resolution: {integrity: sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.18.1':
|
||||
resolution: {integrity: sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==}
|
||||
'@rollup/rollup-darwin-x64@4.20.0':
|
||||
resolution: {integrity: sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
|
||||
resolution: {integrity: sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==}
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.20.0':
|
||||
resolution: {integrity: sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
|
||||
resolution: {integrity: sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==}
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.20.0':
|
||||
resolution: {integrity: sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==}
|
||||
'@rollup/rollup-linux-arm64-gnu@4.20.0':
|
||||
resolution: {integrity: sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.18.1':
|
||||
resolution: {integrity: sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==}
|
||||
'@rollup/rollup-linux-arm64-musl@4.20.0':
|
||||
resolution: {integrity: sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==}
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
|
||||
resolution: {integrity: sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==}
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.20.0':
|
||||
resolution: {integrity: sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==}
|
||||
'@rollup/rollup-linux-s390x-gnu@4.20.0':
|
||||
resolution: {integrity: sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.18.1':
|
||||
resolution: {integrity: sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==}
|
||||
'@rollup/rollup-linux-x64-gnu@4.20.0':
|
||||
resolution: {integrity: sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.18.1':
|
||||
resolution: {integrity: sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==}
|
||||
'@rollup/rollup-linux-x64-musl@4.20.0':
|
||||
resolution: {integrity: sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==}
|
||||
'@rollup/rollup-win32-arm64-msvc@4.20.0':
|
||||
resolution: {integrity: sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==}
|
||||
'@rollup/rollup-win32-ia32-msvc@4.20.0':
|
||||
resolution: {integrity: sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.18.1':
|
||||
resolution: {integrity: sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==}
|
||||
'@rollup/rollup-win32-x64-msvc@4.20.0':
|
||||
resolution: {integrity: sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@tauri-apps/api@2.0.0-beta.14':
|
||||
resolution: {integrity: sha512-YLYgHqdwWswr4Y70+hRzaLD6kLIUgHhE3shLXNquPiTaQ9+cX3Q2dB0AFfqsua6NXYFNe7LfkmMzaqEzqv3yQg==}
|
||||
'@tauri-apps/api@2.0.0-rc.0':
|
||||
resolution: {integrity: sha512-v454Qs3REHc3Za59U+/eSmBsdmF+3NE5+76+lFDaitVqN4ZglDHENDaMARYKGJVZuxiSkzyqG0SeG7lLQjVkPA==}
|
||||
engines: {node: '>= 18.18', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||
|
||||
'@types/estree@1.0.5':
|
||||
@@ -151,8 +151,8 @@ packages:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-core-module@2.14.0:
|
||||
resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==}
|
||||
is-core-module@2.15.0:
|
||||
resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
path-parse@1.0.7:
|
||||
@@ -166,8 +166,8 @@ packages:
|
||||
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
|
||||
hasBin: true
|
||||
|
||||
rollup@4.18.1:
|
||||
resolution: {integrity: sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==}
|
||||
rollup@4.20.0:
|
||||
resolution: {integrity: sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -178,79 +178,79 @@ packages:
|
||||
tslib@2.6.3:
|
||||
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
||||
|
||||
typescript@5.5.3:
|
||||
resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==}
|
||||
typescript@5.5.4:
|
||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@rollup/plugin-typescript@11.1.6(rollup@4.18.1)(tslib@2.6.3)(typescript@5.5.3)':
|
||||
'@rollup/plugin-typescript@11.1.6(rollup@4.20.0)(tslib@2.6.3)(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.18.1)
|
||||
'@rollup/pluginutils': 5.1.0(rollup@4.20.0)
|
||||
resolve: 1.22.8
|
||||
typescript: 5.5.3
|
||||
typescript: 5.5.4
|
||||
optionalDependencies:
|
||||
rollup: 4.18.1
|
||||
rollup: 4.20.0
|
||||
tslib: 2.6.3
|
||||
|
||||
'@rollup/pluginutils@5.1.0(rollup@4.18.1)':
|
||||
'@rollup/pluginutils@5.1.0(rollup@4.20.0)':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
optionalDependencies:
|
||||
rollup: 4.18.1
|
||||
rollup: 4.20.0
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.18.1':
|
||||
'@rollup/rollup-android-arm-eabi@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.18.1':
|
||||
'@rollup/rollup-android-arm64@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.18.1':
|
||||
'@rollup/rollup-darwin-arm64@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.18.1':
|
||||
'@rollup/rollup-darwin-x64@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.18.1':
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.18.1':
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.18.1':
|
||||
'@rollup/rollup-linux-arm64-gnu@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.18.1':
|
||||
'@rollup/rollup-linux-arm64-musl@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.18.1':
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.18.1':
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.18.1':
|
||||
'@rollup/rollup-linux-s390x-gnu@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.18.1':
|
||||
'@rollup/rollup-linux-x64-gnu@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.18.1':
|
||||
'@rollup/rollup-linux-x64-musl@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.18.1':
|
||||
'@rollup/rollup-win32-arm64-msvc@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.18.1':
|
||||
'@rollup/rollup-win32-ia32-msvc@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.18.1':
|
||||
'@rollup/rollup-win32-x64-msvc@4.20.0':
|
||||
optional: true
|
||||
|
||||
'@tauri-apps/api@2.0.0-beta.14': {}
|
||||
'@tauri-apps/api@2.0.0-rc.0': {}
|
||||
|
||||
'@types/estree@1.0.5': {}
|
||||
|
||||
@@ -265,7 +265,7 @@ snapshots:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
is-core-module@2.14.0:
|
||||
is-core-module@2.15.0:
|
||||
dependencies:
|
||||
hasown: 2.0.2
|
||||
|
||||
@@ -275,34 +275,34 @@ snapshots:
|
||||
|
||||
resolve@1.22.8:
|
||||
dependencies:
|
||||
is-core-module: 2.14.0
|
||||
is-core-module: 2.15.0
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
|
||||
rollup@4.18.1:
|
||||
rollup@4.20.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.18.1
|
||||
'@rollup/rollup-android-arm64': 4.18.1
|
||||
'@rollup/rollup-darwin-arm64': 4.18.1
|
||||
'@rollup/rollup-darwin-x64': 4.18.1
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.18.1
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.18.1
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-arm64-musl': 4.18.1
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-x64-gnu': 4.18.1
|
||||
'@rollup/rollup-linux-x64-musl': 4.18.1
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.18.1
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.18.1
|
||||
'@rollup/rollup-win32-x64-msvc': 4.18.1
|
||||
'@rollup/rollup-android-arm-eabi': 4.20.0
|
||||
'@rollup/rollup-android-arm64': 4.20.0
|
||||
'@rollup/rollup-darwin-arm64': 4.20.0
|
||||
'@rollup/rollup-darwin-x64': 4.20.0
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.20.0
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.20.0
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.20.0
|
||||
'@rollup/rollup-linux-arm64-musl': 4.20.0
|
||||
'@rollup/rollup-linux-powerpc64le-gnu': 4.20.0
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.20.0
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.20.0
|
||||
'@rollup/rollup-linux-x64-gnu': 4.20.0
|
||||
'@rollup/rollup-linux-x64-musl': 4.20.0
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.20.0
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.20.0
|
||||
'@rollup/rollup-win32-x64-msvc': 4.20.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
tslib@2.6.3: {}
|
||||
|
||||
typescript@5.5.3: {}
|
||||
typescript@5.5.4: {}
|
||||
|
||||
Reference in New Issue
Block a user