Compare commits
228 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cca105e91d | ||
![]() |
3e52490d1b | ||
![]() |
d1293276ce | ||
![]() |
4a5e426730 | ||
![]() |
fdc2755291 | ||
![]() |
b4fbcd8d80 | ||
![]() |
2415cb211e | ||
![]() |
5e51784803 | ||
![]() |
5f0d71b0fe | ||
![]() |
71d41f0a70 | ||
![]() |
78f2804bad | ||
![]() |
0da09ec605 | ||
![]() |
02b5b5f3c7 | ||
![]() |
4a0adaa3f8 | ||
![]() |
d5bc15cf7a | ||
![]() |
4fea3a60d6 | ||
![]() |
7a2bc52ae0 | ||
![]() |
debc165326 | ||
![]() |
d5eef25ad1 | ||
![]() |
5451b52daa | ||
![]() |
fc9812dd54 | ||
![]() |
8858492fb4 | ||
![]() |
5987528f59 | ||
![]() |
a03fc04b1b | ||
![]() |
858ade2eee | ||
![]() |
4938e3ed2b | ||
![]() |
537f6ecf78 | ||
![]() |
24143cbf1c | ||
![]() |
513e4cacc9 | ||
![]() |
7cfa850d4c | ||
![]() |
571d4a6e8f | ||
![]() |
0f39bfcefa | ||
![]() |
34f832bbad | ||
![]() |
8aa57ebc22 | ||
![]() |
fede35cca4 | ||
![]() |
b2100b78d3 | ||
![]() |
70ad81f7bd | ||
![]() |
b43c078152 | ||
![]() |
6e77e6b5e7 | ||
![]() |
f9e6264f31 | ||
![]() |
df17a7bb68 | ||
![]() |
c1b725e64e | ||
![]() |
360691276c | ||
![]() |
f1e9864d08 | ||
![]() |
abf9d23d52 | ||
![]() |
bdbb1f02d6 | ||
![]() |
f64f58e2ae | ||
![]() |
6efbb5cb3d | ||
![]() |
0ead308392 | ||
![]() |
bad6a5946a | ||
![]() |
7532a7c1b2 | ||
![]() |
f665de9b18 | ||
![]() |
58d2ec475c | ||
![]() |
d5bf041834 | ||
![]() |
4e9b07f83b | ||
![]() |
fc4e3782bd | ||
![]() |
3e6b1ac384 | ||
![]() |
29365c39ed | ||
![]() |
09ebed157e | ||
![]() |
72f86025bd | ||
![]() |
51aa23b635 | ||
![]() |
43e076ef18 | ||
![]() |
29d8d4ba87 | ||
![]() |
1b1d76de99 | ||
![]() |
a5637003ad | ||
![]() |
65ac991d1c | ||
![]() |
0926820849 | ||
![]() |
518b6e277a | ||
![]() |
2deb867678 | ||
![]() |
e023c05440 | ||
![]() |
486286e497 | ||
![]() |
72701c9eb3 | ||
![]() |
b1153378c9 | ||
![]() |
ab0404bf6e | ||
![]() |
2a728482fa | ||
![]() |
bee9565225 | ||
![]() |
e07f760def | ||
![]() |
24e2f41260 | ||
![]() |
4da7f4ec20 | ||
![]() |
7d3b8e42fe | ||
![]() |
68c077820f | ||
![]() |
b4ebe7a481 | ||
![]() |
b1f8c5c175 | ||
![]() |
469187d0bb | ||
![]() |
770ab4a01b | ||
![]() |
e4146c3f92 | ||
![]() |
8e841bf5b5 | ||
![]() |
076f6cd965 | ||
![]() |
801104ca69 | ||
![]() |
5d5d8b122a | ||
![]() |
4387d49a42 | ||
![]() |
2d394acc47 | ||
![]() |
e1e10b24e6 | ||
![]() |
52fef9fd4f | ||
![]() |
e6ad308cd5 | ||
![]() |
bf6b46ec8e | ||
![]() |
da0777293f | ||
![]() |
4ca840239a | ||
![]() |
30ccfab288 | ||
![]() |
bde5b7f6ea | ||
![]() |
6448955e05 | ||
![]() |
0498b55d39 | ||
![]() |
c3df9ea7fa | ||
![]() |
6f437bf4c3 | ||
![]() |
74f01e9800 | ||
![]() |
5cbe59219d | ||
![]() |
1db1fbc03b | ||
![]() |
836a90e4d7 | ||
![]() |
bc64b05e18 | ||
![]() |
1170f758c1 | ||
![]() |
0b3ff3ced3 | ||
![]() |
060b11578f | ||
![]() |
d4d352a36f | ||
![]() |
c768e1d13b | ||
![]() |
5605d239ce | ||
![]() |
831ede7d35 | ||
![]() |
97e8cbb9ed | ||
![]() |
705c34623c | ||
![]() |
42f933dfc3 | ||
![]() |
d2f89bb0ac | ||
![]() |
114208081f | ||
![]() |
bd484eb7fe | ||
![]() |
d44b63d45f | ||
![]() |
307a0c7b3c | ||
![]() |
c66939249f | ||
![]() |
6f75dd72b9 | ||
![]() |
e6408f2582 | ||
![]() |
934cfce1b0 | ||
![]() |
76292a8377 | ||
![]() |
20c509da77 | ||
![]() |
584d924433 | ||
![]() |
740d2938f5 | ||
![]() |
7314309750 | ||
![]() |
af3e1634d1 | ||
![]() |
376d533527 | ||
![]() |
f583fea5e4 | ||
![]() |
14a391d4fc | ||
![]() |
14df3d3075 | ||
![]() |
0fa7895301 | ||
![]() |
b9c4cd25a6 | ||
![]() |
ecdf9f34ea | ||
![]() |
5b14fc05d2 | ||
![]() |
6089813da5 | ||
![]() |
189a073f05 | ||
![]() |
a6b8f2023c | ||
![]() |
9c390230f5 | ||
![]() |
36436b597f | ||
![]() |
f0c7b3a9bf | ||
![]() |
cbbd8a2b8c | ||
![]() |
3f44f48814 | ||
![]() |
1a1549cdc7 | ||
![]() |
eafff8439c | ||
![]() |
c37fc13404 | ||
![]() |
8b94b3cab0 | ||
![]() |
37f01f2898 | ||
![]() |
cd3387357b | ||
![]() |
59ccb38db2 | ||
![]() |
39fcbf91d5 | ||
![]() |
e3c82dbbc8 | ||
![]() |
be67330c24 | ||
![]() |
795b8ec1d0 | ||
![]() |
856cd33f26 | ||
![]() |
0b30bdf4a0 | ||
![]() |
11a3f786cb | ||
![]() |
0b389afd22 | ||
![]() |
1280e1dde2 | ||
![]() |
d10917d47d | ||
![]() |
fb2a6d9b17 | ||
![]() |
a8c4b1feac | ||
![]() |
c0dc9a493d | ||
![]() |
83baf2fdc7 | ||
![]() |
8188585edd | ||
![]() |
e9a625ec5f | ||
![]() |
8440eb842b | ||
![]() |
2e57599f41 | ||
![]() |
3abdca31f2 | ||
![]() |
8d1e99da05 | ||
![]() |
f72033e7f6 | ||
![]() |
57dce76363 | ||
![]() |
6c00ed4276 | ||
![]() |
9e5bdf74bc | ||
![]() |
893fba4adf | ||
![]() |
e7092bfcf6 | ||
![]() |
26c59d3507 | ||
![]() |
c6660986c4 | ||
![]() |
26d1482131 | ||
![]() |
9dd44038bc | ||
![]() |
06a0957734 | ||
![]() |
6428f23dce | ||
![]() |
8604724ff7 | ||
![]() |
fda056528b | ||
![]() |
e5b537267e | ||
![]() |
638013a93d | ||
![]() |
064a009cb4 | ||
![]() |
0af32526f7 | ||
![]() |
714667fdce | ||
![]() |
3a5332e31d | ||
![]() |
61d5e38cc9 | ||
![]() |
3763c959db | ||
![]() |
873851e6d0 | ||
![]() |
ebbed97ed5 | ||
![]() |
1be6db661e | ||
![]() |
d8446778cc | ||
![]() |
70dee329d1 | ||
![]() |
6595c2837e | ||
![]() |
577cef131b | ||
![]() |
b3717d974b | ||
![]() |
d8033a77b9 | ||
![]() |
3a965efab2 | ||
![]() |
a3e85a1270 | ||
![]() |
66b3241be7 | ||
![]() |
fcc73159b3 | ||
![]() |
69651ae3fd | ||
![]() |
096af6aa45 | ||
![]() |
57c9f11371 | ||
![]() |
3467890270 | ||
![]() |
39021d7b1b | ||
![]() |
0ddcda1b31 | ||
![]() |
50e14798d6 | ||
![]() |
727ef37ae4 | ||
![]() |
4eb7efe5fc | ||
![]() |
bb4ae71869 | ||
![]() |
892b06dfd3 | ||
![]() |
e4be86cf92 | ||
![]() |
25a7603990 | ||
![]() |
05cabb2651 | ||
![]() |
90110aa587 | ||
![]() |
ce889e990e |
@@ -1,7 +0,0 @@
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-musl-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
[target.'cfg(all(windows, target_env = "msvc"))']
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
77
.cargo/config.toml
Normal file
@@ -0,0 +1,77 @@
|
||||
[target.x86_64-unknown-linux-musl]
|
||||
linker = "rust-lld"
|
||||
rustflags = ["-C", "linker-flavor=ld.lld"]
|
||||
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-musl-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
[target.'cfg(all(windows, target_env = "msvc"))']
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
[target.mipsel-unknown-linux-musl]
|
||||
linker = "mipsel-linux-muslsf-gcc"
|
||||
rustflags = [
|
||||
"-C",
|
||||
"target-feature=+crt-static",
|
||||
"-L",
|
||||
"./musl_gcc/mipsel-linux-muslsf-cross/mipsel-linux-muslsf/lib",
|
||||
"-L",
|
||||
"./musl_gcc/mipsel-linux-muslsf-cross/lib/gcc/mipsel-linux-muslsf/11.2.1",
|
||||
"-l",
|
||||
"atomic",
|
||||
"-l",
|
||||
"ctz",
|
||||
]
|
||||
|
||||
[target.mips-unknown-linux-musl]
|
||||
linker = "mips-linux-muslsf-gcc"
|
||||
rustflags = [
|
||||
"-C",
|
||||
"target-feature=+crt-static",
|
||||
"-L",
|
||||
"./musl_gcc/mips-linux-muslsf-cross/mips-linux-muslsf/lib",
|
||||
"-L",
|
||||
"./musl_gcc/mips-linux-muslsf-cross/lib/gcc/mips-linux-muslsf/11.2.1",
|
||||
"-l",
|
||||
"atomic",
|
||||
"-l",
|
||||
"ctz",
|
||||
]
|
||||
|
||||
[target.armv7-unknown-linux-musleabihf]
|
||||
linker = "armv7l-linux-musleabihf-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
[target.armv7-unknown-linux-musleabi]
|
||||
linker = "armv7m-linux-musleabi-gcc"
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
|
||||
[target.arm-unknown-linux-musleabihf]
|
||||
linker = "arm-linux-musleabihf-gcc"
|
||||
rustflags = [
|
||||
"-C",
|
||||
"target-feature=+crt-static",
|
||||
"-L",
|
||||
"./musl_gcc/arm-linux-musleabihf-cross/arm-linux-musleabihf/lib",
|
||||
"-L",
|
||||
"./musl_gcc/arm-linux-musleabihf-cross/lib/gcc/arm-linux-musleabihf/11.2.1",
|
||||
"-l",
|
||||
"atomic",
|
||||
]
|
||||
|
||||
[target.arm-unknown-linux-musleabi]
|
||||
linker = "arm-linux-musleabi-gcc"
|
||||
rustflags = [
|
||||
"-C",
|
||||
"target-feature=+crt-static",
|
||||
"-L",
|
||||
"./musl_gcc/arm-linux-musleabi-cross/arm-linux-musleabi/lib",
|
||||
"-L",
|
||||
"./musl_gcc/arm-linux-musleabi-cross/lib/gcc/arm-linux-musleabi/11.2.1",
|
||||
"-l",
|
||||
"atomic",
|
||||
]
|
35
.github/workflows/Dockerfile
vendored
Normal file
@@ -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"]
|
174
.github/workflows/core.yml
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
name: EasyTier Core
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop", "main"]
|
||||
pull_request:
|
||||
branches: ["develop", "main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# necessary for windows
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
# continue-on-error: true # Uncomment once integration is finished
|
||||
runs-on: ubuntu-latest
|
||||
# Map a step output to a job output
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# 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", ".github/workflows/install_rust.sh"]'
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- TARGET: aarch64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-aarch64
|
||||
- TARGET: x86_64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-x86_64
|
||||
- TARGET: mips-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-mips
|
||||
- TARGET: mipsel-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-mipsel
|
||||
- TARGET: armv7-unknown-linux-musleabihf # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-armv7hf
|
||||
- TARGET: armv7-unknown-linux-musleabi # raspberry pi 2-3-4, not tested
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-armv7
|
||||
- TARGET: arm-unknown-linux-musleabihf # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-armhf
|
||||
- TARGET: arm-unknown-linux-musleabi # raspberry pi 0-1, not tested
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: linux-arm
|
||||
|
||||
- TARGET: x86_64-apple-darwin
|
||||
OS: macos-latest
|
||||
ARTIFACT_NAME: macos-x86_64
|
||||
- TARGET: aarch64-apple-darwin
|
||||
OS: macos-latest
|
||||
ARTIFACT_NAME: macos-aarch64
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
OS: windows-latest
|
||||
ARTIFACT_NAME: windows-x86_64
|
||||
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: easytier
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 21
|
||||
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Install rust target
|
||||
run: bash ./.github/workflows/install_rust.sh
|
||||
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Core & Cli
|
||||
run: |
|
||||
if [[ $OS =~ ^ubuntu.*$ && $TARGET =~ ^mips.*$ ]]; then
|
||||
cargo +nightly build -r --verbose --target $TARGET -Z build-std=std,panic_abort --no-default-features --features mips
|
||||
else
|
||||
cargo build --release --verbose --target $TARGET
|
||||
fi
|
||||
|
||||
- name: Install UPX
|
||||
if: ${{ matrix.OS != 'macos-latest' }}
|
||||
uses: crazy-max/ghaction-upx@v3
|
||||
with:
|
||||
version: latest
|
||||
install-only: true
|
||||
|
||||
- name: Compress
|
||||
run: |
|
||||
mkdir -p ./artifacts/objects/
|
||||
# windows is the only OS using a different convention for executable file name
|
||||
if [[ $OS =~ ^windows.*$ ]]; then
|
||||
SUFFIX=.exe
|
||||
cp easytier/third_party/Packet.dll ./artifacts/objects/
|
||||
cp easytier/third_party/wintun.dll ./artifacts/objects/
|
||||
fi
|
||||
if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then
|
||||
TAG=$GITHUB_REF_NAME
|
||||
else
|
||||
TAG=$GITHUB_SHA
|
||||
fi
|
||||
|
||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||
upx --lzma --best ./target/$TARGET/release/easytier-core"$SUFFIX"
|
||||
upx --lzma --best ./target/$TARGET/release/easytier-cli"$SUFFIX"
|
||||
fi
|
||||
|
||||
mv ./target/$TARGET/release/easytier-core"$SUFFIX" ./artifacts/objects/
|
||||
mv ./target/$TARGET/release/easytier-cli"$SUFFIX" ./artifacts/objects/
|
||||
|
||||
mv ./artifacts/objects/* ./artifacts/
|
||||
rm -rf ./artifacts/objects/
|
||||
|
||||
- name: Archive artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: easytier-${{ matrix.ARTIFACT_NAME }}
|
||||
path: |
|
||||
./artifacts/*
|
||||
|
||||
- name: Upload OSS
|
||||
if: ${{ env.OSS_BUCKET != '' }}
|
||||
uses: Menci/upload-to-oss@main
|
||||
with:
|
||||
access-key-id: ${{ secrets.ALIYUN_OSS_ACCESS_ID }}
|
||||
access-key-secret: ${{ secrets.ALIYUN_OSS_ACCESS_KEY }}
|
||||
endpoint: ${{ secrets.ALIYUN_OSS_ENDPOINT }}
|
||||
bucket: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
local-path: ./artifacts/
|
||||
remote-path: /easytier-releases/${{ github.sha }}/
|
||||
no-delete-remote-files: true
|
||||
retry: 5
|
||||
core-result:
|
||||
if: needs.pre_job.outputs.should_skip != 'true' && always()
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- pre_job
|
||||
- build
|
||||
steps:
|
||||
- name: Mark result as failed
|
||||
if: needs.build.result != 'success'
|
||||
run: exit 1
|
61
.github/workflows/docker.yml
vendored
Normal file
@@ -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' || '' }},
|
212
.github/workflows/gui.yml
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
name: EasyTier GUI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop", "main"]
|
||||
pull_request:
|
||||
branches: ["develop", "main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# necessary for windows
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
# continue-on-error: true # Uncomment once integration is finished
|
||||
runs-on: ubuntu-latest
|
||||
# Map a step output to a job output
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# 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", ".github/workflows/install_rust.sh"]'
|
||||
build-gui:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- TARGET: aarch64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
GUI_TARGET: aarch64-unknown-linux-gnu
|
||||
ARTIFACT_NAME: linux-aarch64
|
||||
- TARGET: x86_64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
GUI_TARGET: x86_64-unknown-linux-gnu
|
||||
ARTIFACT_NAME: linux-x86_64
|
||||
|
||||
- TARGET: x86_64-apple-darwin
|
||||
OS: macos-latest
|
||||
GUI_TARGET: x86_64-apple-darwin
|
||||
ARTIFACT_NAME: macos-x86_64
|
||||
- TARGET: aarch64-apple-darwin
|
||||
OS: macos-latest
|
||||
GUI_TARGET: aarch64-apple-darwin
|
||||
ARTIFACT_NAME: macos-aarch64
|
||||
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
OS: windows-latest
|
||||
GUI_TARGET: x86_64-pc-windows-msvc
|
||||
ARTIFACT_NAME: windows-x86_64
|
||||
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: easytier
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
GUI_TARGET: ${{ matrix.GUI_TARGET }}
|
||||
OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 21
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
(cd easytier-gui; pnpm install)
|
||||
(cd tauri-plugin-vpnservice; pnpm install; pnpm build)
|
||||
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Install rust target
|
||||
run: bash ./.github/workflows/install_rust.sh
|
||||
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install GUI cross compile (aarch64 only)
|
||||
if: ${{ matrix.TARGET == 'aarch64-unknown-linux-musl' }}
|
||||
run: |
|
||||
# see https://tauri.app/v1/guides/building/linux/
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted" | sudo tee /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security main restricted" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe" | sudo tee -a /etc/apt/sources.list
|
||||
echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse" | sudo tee -a /etc/apt/sources.list
|
||||
|
||||
sudo dpkg --add-architecture arm64
|
||||
sudo apt-get update && sudo apt-get upgrade -y
|
||||
sudo apt install gcc-aarch64-linux-gnu
|
||||
sudo apt install libwebkit2gtk-4.1-dev:arm64
|
||||
sudo apt install libssl-dev:arm64
|
||||
echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/" >> "$GITHUB_ENV"
|
||||
echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig/" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build GUI
|
||||
if: ${{ matrix.GUI_TARGET != '' }}
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
with:
|
||||
projectPath: ./easytier-gui
|
||||
# https://tauri.app/v1/guides/building/linux/#cross-compiling-tauri-applications-for-arm-based-devices
|
||||
args: --verbose --target ${{ matrix.GUI_TARGET }} ${{ matrix.OS == 'ubuntu-latest' && contains(matrix.TARGET, 'aarch64') && '--bundles deb' || '' }}
|
||||
|
||||
- name: Compress
|
||||
run: |
|
||||
mkdir -p ./artifacts/objects/
|
||||
|
||||
if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then
|
||||
TAG=$GITHUB_REF_NAME
|
||||
else
|
||||
TAG=$GITHUB_SHA
|
||||
fi
|
||||
# copy gui bundle, gui is built without specific target
|
||||
if [[ $OS =~ ^windows.*$ ]]; then
|
||||
mv ./target/$GUI_TARGET/release/bundle/nsis/*.exe ./artifacts/objects/
|
||||
elif [[ $OS =~ ^macos.*$ ]]; then
|
||||
mv ./target/$GUI_TARGET/release/bundle/dmg/*.dmg ./artifacts/objects/
|
||||
elif [[ $OS =~ ^ubuntu.*$ && ! $TARGET =~ ^mips.*$ ]]; then
|
||||
mv ./target/$GUI_TARGET/release/bundle/deb/*.deb ./artifacts/objects/
|
||||
if [[ $GUI_TARGET =~ ^x86_64.*$ ]]; then
|
||||
# currently only x86 appimage is supported
|
||||
mv ./target/$GUI_TARGET/release/bundle/appimage/*.AppImage ./artifacts/objects/
|
||||
fi
|
||||
fi
|
||||
|
||||
mv ./artifacts/objects/* ./artifacts/
|
||||
rm -rf ./artifacts/objects/
|
||||
|
||||
- name: Archive artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: easytier-gui-${{ matrix.ARTIFACT_NAME }}
|
||||
path: |
|
||||
./artifacts/*
|
||||
|
||||
- name: Upload OSS
|
||||
if: ${{ env.OSS_BUCKET != '' }}
|
||||
uses: Menci/upload-to-oss@main
|
||||
with:
|
||||
access-key-id: ${{ secrets.ALIYUN_OSS_ACCESS_ID }}
|
||||
access-key-secret: ${{ secrets.ALIYUN_OSS_ACCESS_KEY }}
|
||||
endpoint: ${{ secrets.ALIYUN_OSS_ENDPOINT }}
|
||||
bucket: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
local-path: ./artifacts/
|
||||
remote-path: /easytier-releases/${{ github.sha }}/gui
|
||||
no-delete-remote-files: true
|
||||
retry: 5
|
||||
gui-result:
|
||||
if: needs.pre_job.outputs.should_skip != 'true' && always()
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- pre_job
|
||||
- build-gui
|
||||
steps:
|
||||
- name: Mark result as failed
|
||||
if: needs.build-gui.result != 'success'
|
||||
run: exit 1
|
80
.github/workflows/install_rust.sh
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# env needed:
|
||||
# - TARGET
|
||||
# - GUI_TARGET
|
||||
# - OS
|
||||
|
||||
# dependencies are only needed on ubuntu as that's the only place where
|
||||
# we make cross-compilation
|
||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools libappindicator3-dev
|
||||
# for easytier-gui
|
||||
if [[ $GUI_TARGET != '' && $GUI_TARGET =~ ^x86_64.*$ ]]; then
|
||||
sudo apt install -qq libwebkit2gtk-4.1-dev \
|
||||
build-essential \
|
||||
curl \
|
||||
wget \
|
||||
file \
|
||||
libgtk-3-dev \
|
||||
librsvg2-dev \
|
||||
libxdo-dev \
|
||||
libssl-dev \
|
||||
patchelf
|
||||
fi
|
||||
# curl -s musl.cc | grep mipsel
|
||||
case $TARGET in
|
||||
mipsel-unknown-linux-musl)
|
||||
MUSL_URI=mipsel-linux-muslsf
|
||||
;;
|
||||
mips-unknown-linux-musl)
|
||||
MUSL_URI=mips-linux-muslsf
|
||||
;;
|
||||
aarch64-unknown-linux-musl)
|
||||
MUSL_URI=aarch64-linux-musl
|
||||
;;
|
||||
armv7-unknown-linux-musleabihf)
|
||||
MUSL_URI=armv7l-linux-musleabihf
|
||||
;;
|
||||
armv7-unknown-linux-musleabi)
|
||||
MUSL_URI=armv7m-linux-musleabi
|
||||
;;
|
||||
arm-unknown-linux-musleabihf)
|
||||
MUSL_URI=arm-linux-musleabihf
|
||||
;;
|
||||
arm-unknown-linux-musleabi)
|
||||
MUSL_URI=arm-linux-musleabi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -n "$MUSL_URI" ]; then
|
||||
mkdir -p ./musl_gcc
|
||||
wget -c https://musl.cc/${MUSL_URI}-cross.tgz -P ./musl_gcc/
|
||||
tar zxf ./musl_gcc/${MUSL_URI}-cross.tgz -C ./musl_gcc/
|
||||
sudo ln -s $(pwd)/musl_gcc/${MUSL_URI}-cross/bin/*gcc /usr/bin/
|
||||
fi
|
||||
fi
|
||||
|
||||
# see https://github.com/rust-lang/rustup/issues/3709
|
||||
rustup set auto-self-update disable
|
||||
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
|
||||
cd "$PWD/musl_gcc/${MUSL_URI}-cross/lib/gcc/${MUSL_URI}/11.2.1" || exit 255
|
||||
# for panic-abort
|
||||
cp libgcc_eh.a libunwind.a
|
||||
|
||||
# for mimalloc
|
||||
ar x libgcc.a _ctzsi2.o _clz.o _bswapsi2.o
|
||||
ar rcs libctz.a _ctzsi2.o _clz.o _bswapsi2.o
|
||||
|
||||
rustup toolchain install nightly-x86_64-unknown-linux-gnu
|
||||
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
|
||||
else
|
||||
rustup target add $TARGET
|
||||
if [[ $GUI_TARGET != '' ]]; then
|
||||
rustup target add $GUI_TARGET
|
||||
fi
|
||||
fi
|
165
.github/workflows/mobile.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
name: EasyTier Mobile
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop", "main"]
|
||||
pull_request:
|
||||
branches: ["develop", "main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# necessary for windows
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
# continue-on-error: true # Uncomment once integration is finished
|
||||
runs-on: ubuntu-latest
|
||||
# Map a step output to a job output
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# 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", ".github/workflows/install_rust.sh"]'
|
||||
build-mobile:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- TARGET: android
|
||||
OS: ubuntu-latest
|
||||
ARTIFACT_NAME: android
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: easytier
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'oracle'
|
||||
java-version: '20'
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
with:
|
||||
cmdline-tools-version: 11076708
|
||||
packages: 'build-tools;34.0.0 ndk;26.0.10792818 tools platform-tools platforms;android-34 '
|
||||
|
||||
- name: Setup Android Environment
|
||||
run: |
|
||||
echo "$ANDROID_HOME/platform-tools" >> $GITHUB_PATH
|
||||
echo "$ANDROID_HOME/ndk/26.0.10792818/toolchains/llvm/prebuilt/linux-x86_64/bin" >> $GITHUB_PATH
|
||||
echo "NDK_HOME=$ANDROID_HOME/ndk/26.0.10792818/" > $GITHUB_ENV
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 21
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v3
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
(cd easytier-gui; pnpm install)
|
||||
(cd tauri-plugin-vpnservice; pnpm install; pnpm build)
|
||||
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Install rust target
|
||||
run: |
|
||||
bash ./.github/workflows/install_rust.sh
|
||||
rustup target add aarch64-linux-android
|
||||
rustup target add armv7-linux-androideabi
|
||||
rustup target add i686-linux-android
|
||||
rustup target add x86_64-linux-android
|
||||
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Android
|
||||
run: |
|
||||
cd easytier-gui
|
||||
pnpm tauri android build
|
||||
|
||||
- name: Compress
|
||||
run: |
|
||||
mkdir -p ./artifacts/objects/
|
||||
mv easytier-gui/src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release.apk ./artifacts/objects/
|
||||
|
||||
if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then
|
||||
TAG=$GITHUB_REF_NAME
|
||||
else
|
||||
TAG=$GITHUB_SHA
|
||||
fi
|
||||
|
||||
mv ./artifacts/objects/* ./artifacts
|
||||
rm -rf ./artifacts/objects/
|
||||
|
||||
- name: Archive artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: easytier-gui-${{ matrix.ARTIFACT_NAME }}
|
||||
path: |
|
||||
./artifacts/*
|
||||
|
||||
- name: Upload OSS
|
||||
if: ${{ env.OSS_BUCKET != '' }}
|
||||
uses: Menci/upload-to-oss@main
|
||||
with:
|
||||
access-key-id: ${{ secrets.ALIYUN_OSS_ACCESS_ID }}
|
||||
access-key-secret: ${{ secrets.ALIYUN_OSS_ACCESS_KEY }}
|
||||
endpoint: ${{ secrets.ALIYUN_OSS_ENDPOINT }}
|
||||
bucket: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
local-path: ./artifacts/
|
||||
remote-path: /easytier-releases/${{ github.sha }}/mobile
|
||||
no-delete-remote-files: true
|
||||
retry: 5
|
||||
mobile-result:
|
||||
if: needs.pre_job.outputs.should_skip != 'true' && always()
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- pre_job
|
||||
- build-mobile
|
||||
steps:
|
||||
- name: Mark result as failed
|
||||
if: needs.build-mobile.result != 'success'
|
||||
run: exit 1
|
151
.github/workflows/rust.yml
vendored
@@ -1,151 +0,0 @@
|
||||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "develop", "main" ]
|
||||
pull_request:
|
||||
branches: [ "develop", "main" ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# necessary for windows
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- TARGET: aarch64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-unknown-linux-musl
|
||||
OS: ubuntu-latest
|
||||
- TARGET: x86_64-apple-darwin
|
||||
OS: macos-latest
|
||||
- TARGET: aarch64-apple-darwin
|
||||
OS: macos-latest
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
OS: windows-latest
|
||||
runs-on: ${{ matrix.OS }}
|
||||
env:
|
||||
NAME: easytier
|
||||
TARGET: ${{ matrix.TARGET }}
|
||||
OS: ${{ matrix.OS }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4.0.0
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: build-cargo-registry-${{matrix.TARGET}}
|
||||
- name: Install rust target
|
||||
run: |
|
||||
# dependencies are only needed on ubuntu as that's the only place where
|
||||
# we make cross-compilation
|
||||
if [[ $OS =~ ^ubuntu.*$ ]]; then
|
||||
sudo apt-get update && sudo apt-get install -qq crossbuild-essential-arm64 crossbuild-essential-armhf musl-tools
|
||||
# curl -s musl.cc | grep mipsel
|
||||
case $TARGET in
|
||||
mipsel-unknown-linux-musl)
|
||||
MUSL_URI=mipsel-linux-musl-cross
|
||||
;;
|
||||
aarch64-unknown-linux-musl)
|
||||
MUSL_URI=aarch64-linux-musl-cross
|
||||
;;
|
||||
armv7-unknown-linux-musleabihf)
|
||||
MUSL_URI=armv7l-linux-musleabihf-cross
|
||||
;;
|
||||
arm-unknown-linux-musleabihf)
|
||||
MUSL_URI=arm-linux-musleabihf-cross
|
||||
;;
|
||||
mips-unknown-linux-musl)
|
||||
MUSL_URI=mips-linux-musl-cross
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -n "$MUSL_URI" ]; then
|
||||
mkdir -p ./musl_gcc
|
||||
wget -c https://musl.cc/$MUSL_URI.tgz -P ./musl_gcc/
|
||||
tar zxf ./musl_gcc/$MUSL_URI.tgz -C ./musl_gcc/
|
||||
sudo ln -s $(pwd)/musl_gcc/$MUSL_URI/bin/*gcc /usr/bin/
|
||||
fi
|
||||
fi
|
||||
|
||||
# see https://github.com/rust-lang/rustup/issues/3709
|
||||
rustup set auto-self-update disable
|
||||
rustup install 1.75
|
||||
rustup default 1.75
|
||||
rustup target add $TARGET
|
||||
- name: Run build
|
||||
run: cargo build --release --verbose --target $TARGET
|
||||
- name: Compress
|
||||
run: |
|
||||
mkdir -p ./artifacts/objects/
|
||||
# windows is the only OS using a different convention for executable file name
|
||||
if [[ $OS =~ ^windows.*$ ]]; then
|
||||
SUFFIX=.exe
|
||||
cp third_party/Packet.dll ./artifacts/objects/
|
||||
cp third_party/wintun.dll ./artifacts/objects/
|
||||
fi
|
||||
if [[ $GITHUB_REF_TYPE =~ ^tag$ ]]; then
|
||||
TAG=$GITHUB_REF_NAME
|
||||
else
|
||||
TAG=$GITHUB_SHA
|
||||
fi
|
||||
mv ./target/$TARGET/release/easytier-core"$SUFFIX" ./artifacts/objects/
|
||||
mv ./target/$TARGET/release/easytier-cli"$SUFFIX" ./artifacts/objects/
|
||||
tar -cvf ./artifacts/$NAME-$TARGET-$TAG.tar -C ./artifacts/objects/ .
|
||||
rm -rf ./artifacts/objects/
|
||||
- name: Archive artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: easytier-${{ matrix.OS }}-${{ matrix.TARGET }}
|
||||
path: |
|
||||
./artifacts/*
|
||||
- name: Upload OSS
|
||||
uses: Menci/upload-to-oss@main
|
||||
with:
|
||||
access-key-id: ${{ secrets.ALIYUN_OSS_ACCESS_ID }}
|
||||
access-key-secret: ${{ secrets.ALIYUN_OSS_ACCESS_KEY }}
|
||||
endpoint: ${{ secrets.ALIYUN_OSS_ENDPOINT }}
|
||||
bucket: ${{ secrets.ALIYUN_OSS_BUCKET }}
|
||||
local-path: ./artifacts/
|
||||
remote-path: /easytier-releases/${{ github.sha }}/
|
||||
no-delete-remote-files: true
|
||||
retry: 5
|
||||
increment: true
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup tools for test
|
||||
run: sudo apt install bridge-utils
|
||||
- name: Setup system for test
|
||||
run: |
|
||||
sudo sysctl net.bridge.bridge-nf-call-iptables=0
|
||||
sudo sysctl net.bridge.bridge-nf-call-ip6tables=0
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4.0.0
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: build-cargo-registry-test
|
||||
- name: Run tests
|
||||
run: sudo -E env "PATH=$PATH" cargo test --verbose
|
67
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: EasyTier Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["develop", "main"]
|
||||
pull_request:
|
||||
branches: ["develop", "main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# necessary for windows
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
# continue-on-error: true # Uncomment once integration is finished
|
||||
runs-on: ubuntu-latest
|
||||
# Map a step output to a job output
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
steps:
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
# 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/test.yml"]'
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
with:
|
||||
# GitHub repo token to use to avoid rate limiter
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup tools for test
|
||||
run: sudo apt install bridge-utils
|
||||
|
||||
- name: Setup system for test
|
||||
run: |
|
||||
sudo sysctl net.bridge.bridge-nf-call-iptables=0
|
||||
sudo sysctl net.bridge.bridge-nf-call-ip6tables=0
|
||||
sudo sysctl net.ipv6.conf.lo.disable_ipv6=0
|
||||
sudo ip addr add 2001:db8::2/64 dev lo
|
||||
|
||||
- name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
./target
|
||||
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
sudo -E env "PATH=$PATH" cargo test --no-default-features --features=full --verbose
|
||||
sudo chown -R $USER:$USER ./target
|
||||
sudo chown -R $USER:$USER ~/.cargo
|
13
.gitignore
vendored
@@ -4,10 +4,6 @@ debug/
|
||||
target/
|
||||
target-*/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
@@ -24,3 +20,12 @@ flamegraph.svg
|
||||
root-target
|
||||
|
||||
nohup.out
|
||||
|
||||
.DS_Store
|
||||
|
||||
components.d.ts
|
||||
|
||||
musl_gcc
|
||||
|
||||
# log
|
||||
easytier-panic.log
|
||||
|
7595
Cargo.lock
generated
Normal file
145
Cargo.toml
@@ -1,144 +1,13 @@
|
||||
[package]
|
||||
name = "easytier"
|
||||
description = "A full meshed p2p VPN, connecting all your devices in one network with one command."
|
||||
homepage = "https://github.com/KKRainbow/EasyTier"
|
||||
repository = "https://github.com/KKRainbow/EasyTier"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
authors = ["kkrainbow"]
|
||||
keywords = ["vpn", "p2p", "network", "easytier"]
|
||||
categories = ["network-programming", "command-line-utilities"]
|
||||
rust-version = "1.75"
|
||||
license-file = "LICENSE"
|
||||
readme = "README.md"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[[bin]]
|
||||
name = "easytier-core"
|
||||
path = "src/easytier-core.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "easytier-cli"
|
||||
path = "src/easytier-cli.rs"
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
tracing-subscriber = { version = "0.3", features = [
|
||||
"env-filter",
|
||||
"local-time",
|
||||
"time",
|
||||
] }
|
||||
tracing-appender = "0.2.3"
|
||||
log = "0.4"
|
||||
thiserror = "1.0"
|
||||
auto_impl = "1.1.0"
|
||||
crossbeam = "0.8.4"
|
||||
time = "0.3"
|
||||
toml = "0.8.12"
|
||||
chrono = "0.4.35"
|
||||
|
||||
gethostname = "0.4.3"
|
||||
|
||||
futures = "0.3"
|
||||
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-stream = "0.1"
|
||||
tokio-util = { version = "0.7.9", features = ["codec", "net"] }
|
||||
|
||||
async-stream = "0.3.5"
|
||||
async-trait = "0.1.74"
|
||||
|
||||
dashmap = "5.5.3"
|
||||
timedmap = "1.0.1"
|
||||
|
||||
# for tap device
|
||||
tun = { version = "0.6.1", features = ["async"] }
|
||||
# for net ns
|
||||
nix = { version = "0.27", features = ["sched", "socket", "ioctl"] }
|
||||
|
||||
uuid = { version = "1.5.0", features = [
|
||||
"v4",
|
||||
"fast-rng",
|
||||
"macro-diagnostics",
|
||||
"serde",
|
||||
] }
|
||||
|
||||
# for ring tunnel
|
||||
crossbeam-queue = "0.3"
|
||||
once_cell = "1.18.0"
|
||||
|
||||
# for packet
|
||||
rkyv = { "version" = "0.7.42", features = [
|
||||
"validation",
|
||||
"archive_le",
|
||||
"strict",
|
||||
"copy_unsafe",
|
||||
"arbitrary_enum_discriminant",
|
||||
] }
|
||||
postcard = { "version" = "1.0.8", features = ["alloc"] }
|
||||
|
||||
# for rpc
|
||||
tonic = "0.10"
|
||||
prost = "0.12"
|
||||
anyhow = "1.0"
|
||||
tarpc = { version = "0.32", features = ["tokio1", "serde1"] }
|
||||
|
||||
url = { version = "2.5", features = ["serde"] }
|
||||
|
||||
# for tun packet
|
||||
byteorder = "1.5.0"
|
||||
|
||||
# for proxy
|
||||
cidr = "0.2.2"
|
||||
socket2 = "0.5.5"
|
||||
|
||||
# for hole punching
|
||||
stun_codec = "0.3.4"
|
||||
bytecodec = "0.4.15"
|
||||
rand = "0.8.5"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
pnet = { version = "0.34.0", features = ["serde"] }
|
||||
public-ip = { version = "0.2", features = ["default"] }
|
||||
|
||||
clap = { version = "4.4.8", features = ["unicode", "derive", "wrap_help"] }
|
||||
|
||||
async-recursion = "1.0.5"
|
||||
|
||||
network-interface = "1.1.1"
|
||||
|
||||
# for ospf route
|
||||
pathfinding = "4.9.1"
|
||||
|
||||
# for cli
|
||||
tabled = "0.15.*"
|
||||
humansize = "2.1.3"
|
||||
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.52", features = [
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
"Win32_Foundation",
|
||||
"Win32_System_IO",
|
||||
] }
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.10"
|
||||
|
||||
[target.'cfg(windows)'.build-dependencies]
|
||||
reqwest = { version = "0.11", features = ["blocking"] }
|
||||
zip = "0.6.6"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "3.0.0"
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["easytier", "easytier-gui/src-tauri"]
|
||||
default-members = ["easytier"]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
panic = "unwind"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
strip = true
|
||||
|
87
EasyTier.code-workspace
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "easytier-gui"
|
||||
},
|
||||
{
|
||||
"path": "easytier"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"eslint.experimental.useFlatConfig": true,
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"eslint.rules.customizations": [
|
||||
{
|
||||
"rule": "style/*",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "style/eol-last",
|
||||
"severity": "error"
|
||||
},
|
||||
{
|
||||
"rule": "format/*",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-indent",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-spacing",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-spaces",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-order",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-dangle",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*-newline",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*quotes",
|
||||
"severity": "off"
|
||||
},
|
||||
{
|
||||
"rule": "*semi",
|
||||
"severity": "off"
|
||||
}
|
||||
],
|
||||
"eslint.validate": [
|
||||
"code-workspace",
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"vue",
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml",
|
||||
"gql",
|
||||
"graphql"
|
||||
],
|
||||
"i18n-ally.localesPaths": [
|
||||
"easytier-gui/locales"
|
||||
]
|
||||
}
|
||||
}
|
119
README.md
@@ -1,17 +1,27 @@
|
||||
# EasyTier
|
||||
|
||||
[](https://github.com/KKRainbow/EasyTier/blob/main/LICENSE)
|
||||
[](https://github.com/KKRainbow/EasyTier/commits/main)
|
||||
[](https://github.com/KKRainbow/EasyTier/issues)
|
||||
[](https://github.com/KKRainbow/EasyTier/actions/)
|
||||
[](https://github.com/EasyTier/EasyTier/blob/main/LICENSE)
|
||||
[](https://github.com/EasyTier/EasyTier/commits/main)
|
||||
[](https://github.com/EasyTier/EasyTier/issues)
|
||||
[](https://github.com/EasyTier/EasyTier/actions/workflows/core.yml)
|
||||
[](https://github.com/EasyTier/EasyTier/actions/workflows/gui.yml)
|
||||
|
||||
[简体中文](/README_CN.md) | [English](/README.md)
|
||||
|
||||
EasyTier is a simple, plug-and-play, decentralized VPN networking solution implemented with the Rust language and Tokio framework.
|
||||
**Please visit the [EasyTier Official Website](https://www.easytier.top/en/) to view the full documentation.**
|
||||
|
||||
EasyTier is a simple, safe and decentralized VPN networking solution implemented with the Rust language and Tokio framework.
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/image-5.png" width="300">
|
||||
<img src="assets/image-4.png" width="300">
|
||||
</p>
|
||||
|
||||
## Features
|
||||
|
||||
- **Decentralized**: No need to rely on centralized services, nodes are equal and independent.
|
||||
- **Safe**: Use WireGuard protocol to encrypt data.
|
||||
- **High Performance**: Full-link zero-copy, with performance comparable to mainstream networking software.
|
||||
- **Cross-platform**: Supports MacOS/Linux/Windows, will support IOS and Android in the future. The executable file is statically linked, making deployment simple.
|
||||
- **Networking without public IP**: Supports networking using shared public nodes, refer to [Configuration Guide](#Networking-without-public-IP)
|
||||
- **NAT traversal**: Supports UDP-based NAT traversal, able to establish stable connections even in complex network environments.
|
||||
@@ -19,13 +29,15 @@
|
||||
- **Smart Routing**: Selects links based on traffic to reduce latency and increase throughput.
|
||||
- **TCP Support**: Provides reliable data transmission through concurrent TCP links when UDP is limited, optimizing performance.
|
||||
- **High Availability**: Supports multi-path and switches to healthy paths when high packet loss or network errors are detected.
|
||||
- **IPv6 Support**: Supports networking using IPv6.
|
||||
- **Multiple Protocol Types**: Supports communication between nodes using protocols such as WebSocket and QUIC.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Download the precompiled binary file**
|
||||
|
||||
Visit the [GitHub Release page](https://github.com/KKRainbow/EasyTier/releases) to download the binary file suitable for your operating system.
|
||||
Visit the [GitHub Release page](https://github.com/EasyTier/EasyTier/releases) to download the binary file suitable for your operating system. Release includes both command-line programs and GUI programs in the compressed package.
|
||||
|
||||
2. **Install via crates.io**
|
||||
```sh
|
||||
@@ -34,10 +46,12 @@
|
||||
|
||||
3. **Install from source code**
|
||||
```sh
|
||||
cargo install --git https://github.com/KKRainbow/EasyTier.git
|
||||
cargo install --git https://github.com/EasyTier/EasyTier.git
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
> The following text only describes the use of the command-line tool; the GUI program can be configured by referring to the following concepts.
|
||||
|
||||
Make sure EasyTier is installed according to the [Installation Guide](#Installation), and both easytier-core and easytier-cli commands are available.
|
||||
|
||||
@@ -66,7 +80,7 @@
|
||||
```
|
||||
Successful execution of the command will print the following.
|
||||
|
||||

|
||||

|
||||
|
||||
2. Execute on Node B
|
||||
```sh
|
||||
@@ -84,11 +98,11 @@
|
||||
```sh
|
||||
easytier-cli peer
|
||||
```
|
||||

|
||||

|
||||
```sh
|
||||
easytier-cli route
|
||||
```
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -138,7 +152,7 @@
|
||||
```sh
|
||||
easytier-cli route
|
||||
```
|
||||

|
||||

|
||||
|
||||
2. Test whether Node A can access nodes under the proxied subnet
|
||||
|
||||
@@ -157,17 +171,79 @@
|
||||
Taking two nodes as an example, Node A executes:
|
||||
|
||||
```sh
|
||||
sudo easytier-core -i 10.144.144.1 --network-name abc --network-secret abc -e 'tcp://easytier.public.kkrainbow.top:11010'
|
||||
sudo easytier-core -i 10.144.144.1 --network-name abc --network-secret abc -e tcp://easytier.public.kkrainbow.top:11010
|
||||
```
|
||||
|
||||
Node B executes
|
||||
|
||||
```sh
|
||||
sudo easytier-core --ipv4 10.144.144.2 --network-name abc --network-secret abc -e 'tcp://easytier.public.kkrainbow.top:11010'
|
||||
sudo easytier-core --ipv4 10.144.144.2 --network-name abc --network-secret abc -e tcp://easytier.public.kkrainbow.top:11010
|
||||
```
|
||||
|
||||
After the command is successfully executed, Node A can access Node B through the virtual IP 10.144.144.2.
|
||||
|
||||
### Use EasyTier with WireGuard Client
|
||||
|
||||
EasyTier can be used as a WireGuard server to allow any device with WireGuard client installed to access the EasyTier network. For platforms currently unsupported by EasyTier (such as iOS, Android, etc.), this method can be used to connect to the EasyTier network.
|
||||
|
||||
Assuming the network topology is as follows:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
||||
ios[[iPhone \n WireGuard Installed]]
|
||||
|
||||
subgraph Node A IP 22.1.1.1
|
||||
nodea[EasyTier\n10.144.144.1]
|
||||
end
|
||||
|
||||
subgraph Node B
|
||||
nodeb[EasyTier\n10.144.144.2]
|
||||
end
|
||||
|
||||
id1[[10.1.1.0/24]]
|
||||
|
||||
ios <-.-> nodea <--> nodeb <-.-> id1
|
||||
```
|
||||
|
||||
To enable an iPhone to access the EasyTier network through Node A, the following configuration can be applied:
|
||||
|
||||
Include the --vpn-portal parameter in the easytier-core command on Node A to specify the port that the WireGuard service listens on and the subnet used by the WireGuard network.
|
||||
|
||||
```
|
||||
# The following parameters mean: listen on port 0.0.0.0:11013, and use the 10.14.14.0/24 subnet for WireGuard
|
||||
sudo easytier-core --ipv4 10.144.144.1 --vpn-portal wg://0.0.0.0:11013/10.14.14.0/24
|
||||
```
|
||||
|
||||
After successfully starting easytier-core, use easytier-cli to obtain the WireGuard client configuration.
|
||||
|
||||
```
|
||||
$> easytier-cli vpn-portal
|
||||
portal_name: wireguard
|
||||
|
||||
############### client_config_start ###############
|
||||
|
||||
[Interface]
|
||||
PrivateKey = 9VDvlaIC9XHUvRuE06hD2CEDrtGF+0lDthgr9SZfIho=
|
||||
Address = 10.14.14.0/32 # should assign an ip from this cidr manually
|
||||
|
||||
[Peer]
|
||||
PublicKey = zhrZQg4QdPZs8CajT3r4fmzcNsWpBL9ImQCUsnlXyGM=
|
||||
AllowedIPs = 10.144.144.0/24,10.14.14.0/24
|
||||
Endpoint = 0.0.0.0:11013 # should be the public ip(or domain) of the vpn server
|
||||
PersistentKeepalive = 25
|
||||
|
||||
############### client_config_end ###############
|
||||
|
||||
connected_clients:
|
||||
[]
|
||||
```
|
||||
|
||||
Before using the Client Config, you need to modify the Interface Address and Peer Endpoint to the client's IP and the IP of the EasyTier node, respectively. Import the configuration file into the WireGuard client to access the EasyTier network.
|
||||
|
||||
# Self-Hosted Public Server
|
||||
|
||||
Each node can act as a relay node for other users' networks. Simply start EasyTier without any parameters.
|
||||
|
||||
### Configurations
|
||||
|
||||
@@ -183,20 +259,27 @@
|
||||
|
||||
# Community and Contribution
|
||||
|
||||
We welcome and encourage community contributions! If you want to get involved, please submit a [GitHub PR](https://github.com/KKRainbow/EasyTier/pulls). Detailed contribution guidelines can be found in [CONTRIBUTING.md](https://github.com/KKRainbow/EasyTier/blob/main/CONTRIBUTING.md).
|
||||
We welcome and encourage community contributions! If you want to get involved, please submit a [GitHub PR](https://github.com/EasyTier/EasyTier/pulls). Detailed contribution guidelines can be found in [CONTRIBUTING.md](https://github.com/EasyTier/EasyTier/blob/main/CONTRIBUTING.md).
|
||||
|
||||
# Related Projects and Resources
|
||||
|
||||
- [ZeroTier](https://www.zerotier.com/): A global virtual network for connecting devices.
|
||||
- [TailScale](https://tailscale.com/): A VPN solution aimed at simplifying network configuration.
|
||||
- [vpncloud](https://github.com/dswd/vpncloud): A P2P Mesh VPN
|
||||
- [Candy](https://github.com/lanthora/candy): A reliable, low-latency, and anti-censorship virtual private network
|
||||
|
||||
# License
|
||||
|
||||
EasyTier is released under the [Apache License 2.0](https://github.com/KKRainbow/EasyTier/blob/main/LICENSE).
|
||||
EasyTier is released under the [Apache License 2.0](https://github.com/EasyTier/EasyTier/blob/main/LICENSE).
|
||||
|
||||
# Contact
|
||||
|
||||
- Ask questions or report problems: [GitHub Issues](https://github.com/KKRainbow/EasyTier/issues)
|
||||
- Discussion and exchange: [GitHub Discussions](https://github.com/KKRainbow/EasyTier/discussions)
|
||||
- QQ Group: 949700262
|
||||
- Ask questions or report problems: [GitHub Issues](https://github.com/EasyTier/EasyTier/issues)
|
||||
- Discussion and exchange: [GitHub Discussions](https://github.com/EasyTier/EasyTier/discussions)
|
||||
- Telegram:https://t.me/easytier
|
||||
- QQ Group: 949700262
|
||||
|
||||
# Sponsor
|
||||
|
||||
<img src="assets/image-8.png" width="300">
|
||||
<img src="assets/image-9.png" width="300">
|
124
README_CN.md
@@ -1,17 +1,27 @@
|
||||
# EasyTier
|
||||
|
||||
[](https://github.com/KKRainbow/EasyTier/blob/main/LICENSE)
|
||||
[](https://github.com/KKRainbow/EasyTier/commits/main)
|
||||
[](https://github.com/KKRainbow/EasyTier/issues)
|
||||
[](https://github.com/KKRainbow/EasyTier/actions/)
|
||||
[](https://github.com/EasyTier/EasyTier/blob/main/LICENSE)
|
||||
[](https://github.com/EasyTier/EasyTier/commits/main)
|
||||
[](https://github.com/EasyTier/EasyTier/issues)
|
||||
[](https://github.com/EasyTier/EasyTier/actions/workflows/core.yml)
|
||||
[](https://github.com/EasyTier/EasyTier/actions/workflows/gui.yml)
|
||||
|
||||
[简体中文](/README_CN.md) | [English](/README.md)
|
||||
|
||||
一个简单、即插即用、去中心化的内网穿透 VPN 组网方案,使用 Rust 语言和 Tokio 框架实现。
|
||||
**请访问 [EasyTier 官网](https://www.easytier.top/) 以查看完整的文档。**
|
||||
|
||||
一个简单、安全、去中心化的内网穿透 VPN 组网方案,使用 Rust 语言和 Tokio 框架实现。
|
||||
|
||||
<p align="center">
|
||||
<img src="assets/image-6.png" width="300">
|
||||
<img src="assets/image-7.png" width="300">
|
||||
</p>
|
||||
|
||||
## 特点
|
||||
|
||||
- **去中心化**:无需依赖中心化服务,节点平等且独立。
|
||||
- **安全**:支持利用 WireGuard 加密通信,也支持 AES-GCM 加密保护中转流量。
|
||||
- **高性能**:全链路零拷贝,性能与主流组网软件相当。
|
||||
- **跨平台**:支持 MacOS/Linux/Windows,未来将支持 IOS 和 Android。可执行文件静态链接,部署简单。
|
||||
- **无公网 IP 组网**:支持利用共享的公网节点组网,可参考 [配置指南](#无公网IP组网)
|
||||
- **NAT 穿透**:支持基于 UDP 的 NAT 穿透,即使在复杂的网络环境下也能建立稳定的连接。
|
||||
@@ -19,12 +29,14 @@
|
||||
- **智能路由**:根据流量智能选择链路,减少延迟,提高吞吐量。
|
||||
- **TCP 支持**:在 UDP 受限的情况下,通过并发 TCP 链接提供可靠的数据传输,优化性能。
|
||||
- **高可用性**:支持多路径和在检测到高丢包率或网络错误时切换到健康路径。
|
||||
- **IPV6 支持**:支持利用 IPV6 组网。
|
||||
- **多协议类型**: 支持使用 WebSocket、QUIC 等协议进行节点间通信。
|
||||
|
||||
## 安装
|
||||
|
||||
1. **下载预编译的二进制文件**
|
||||
|
||||
访问 [GitHub Release 页面](https://github.com/KKRainbow/EasyTier/releases) 下载适用于您操作系统的二进制文件。
|
||||
访问 [GitHub Release 页面](https://github.com/EasyTier/EasyTier/releases) 下载适用于您操作系统的二进制文件。Release 压缩包中同时包含命令行程序和图形界面程序。
|
||||
|
||||
2. **通过 crates.io 安装**
|
||||
```sh
|
||||
@@ -34,11 +46,13 @@
|
||||
|
||||
3. **通过源码安装**
|
||||
```sh
|
||||
cargo install --git https://github.com/KKRainbow/EasyTier.git
|
||||
cargo install --git https://github.com/EasyTier/EasyTier.git
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
> 下文仅描述命令行工具的使用,图形界面程序可参考下述概念自行配置。
|
||||
|
||||
确保已按照 [安装指南](#安装) 安装 EasyTier,并且 easytier-core 和 easytier-cli 两个命令都已经可用。
|
||||
|
||||
### 双节点组网
|
||||
@@ -66,7 +80,7 @@ nodea <-----> nodeb
|
||||
```
|
||||
命令执行成功会有如下打印。
|
||||
|
||||

|
||||

|
||||
|
||||
2. 在节点 B 执行
|
||||
```sh
|
||||
@@ -84,11 +98,11 @@ nodea <-----> nodeb
|
||||
```sh
|
||||
easytier-cli peer
|
||||
```
|
||||

|
||||

|
||||
```sh
|
||||
easytier-cli route
|
||||
```
|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
@@ -138,7 +152,7 @@ sudo easytier-core --ipv4 10.144.144.2 -n 10.1.1.0/24
|
||||
```sh
|
||||
easytier-cli route
|
||||
```
|
||||

|
||||

|
||||
|
||||
2. 测试节点 A 是否可访问被代理子网下的节点
|
||||
|
||||
@@ -157,19 +171,84 @@ EasyTier 支持共享公网节点进行组网。目前已部署共享的公网
|
||||
以双节点为例,节点 A 执行:
|
||||
|
||||
```sh
|
||||
sudo easytier-core -i 10.144.144.1 --network-name abc --network-secret abc -e 'tcp://easytier.public.kkrainbow.top:11010'
|
||||
sudo easytier-core -i 10.144.144.1 --network-name abc --network-secret abc -e tcp://easytier.public.kkrainbow.top:11010
|
||||
```
|
||||
|
||||
节点 B 执行
|
||||
|
||||
```sh
|
||||
sudo easytier-core --ipv4 10.144.144.2 --network-name abc --network-secret abc -e 'tcp://easytier.public.kkrainbow.top:11010'
|
||||
sudo easytier-core --ipv4 10.144.144.2 --network-name abc --network-secret abc -e tcp://easytier.public.kkrainbow.top:11010
|
||||
```
|
||||
|
||||
命令执行成功后,节点 A 即可通过虚拟 IP 10.144.144.2 访问节点 B。
|
||||
|
||||
---
|
||||
|
||||
### 使用 WireGuard 客户端接入
|
||||
|
||||
EasyTier 可以用作 WireGuard 服务端,让任意安装了 WireGuard 客户端的设备访问 EasyTier 网络。对于目前 EasyTier 不支持的平台 (如 iOS、Android 等),可以使用这种方式接入 EasyTier 网络。
|
||||
|
||||
假设网络拓扑如下:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
|
||||
ios[[iPhone \n 安装 WireGuard]]
|
||||
|
||||
subgraph 节点 A IP 22.1.1.1
|
||||
nodea[EasyTier\n10.144.144.1]
|
||||
end
|
||||
|
||||
subgraph 节点 B
|
||||
nodeb[EasyTier\n10.144.144.2]
|
||||
end
|
||||
|
||||
id1[[10.1.1.0/24]]
|
||||
|
||||
ios <-.-> nodea <--> nodeb <-.-> id1
|
||||
```
|
||||
|
||||
我们需要 iPhone 通过节点 A 访问 EasyTier 网络,则可进行如下配置:
|
||||
|
||||
在节点 A 的 easytier-core 命令中,加入 --vpn-portal 参数,指定 WireGuard 服务监听的端口,以及 WireGuard 网络使用的网段。
|
||||
|
||||
```
|
||||
# 以下参数的含义为: 监听 0.0.0.0:11013 端口,WireGuard 使用 10.14.14.0/24 网段
|
||||
sudo easytier-core --ipv4 10.144.144.1 --vpn-portal wg://0.0.0.0:11013/10.14.14.0/24
|
||||
```
|
||||
|
||||
easytier-core 启动成功后,使用 easytier-cli 获取 WireGuard Client 的配置。
|
||||
|
||||
```
|
||||
$> easytier-cli vpn-portal
|
||||
portal_name: wireguard
|
||||
|
||||
############### client_config_start ###############
|
||||
|
||||
[Interface]
|
||||
PrivateKey = 9VDvlaIC9XHUvRuE06hD2CEDrtGF+0lDthgr9SZfIho=
|
||||
Address = 10.14.14.0/32 # should assign an ip from this cidr manually
|
||||
|
||||
[Peer]
|
||||
PublicKey = zhrZQg4QdPZs8CajT3r4fmzcNsWpBL9ImQCUsnlXyGM=
|
||||
AllowedIPs = 10.144.144.0/24,10.14.14.0/24
|
||||
Endpoint = 0.0.0.0:11013 # should be the public ip(or domain) of the vpn server
|
||||
PersistentKeepalive = 25
|
||||
|
||||
############### client_config_end ###############
|
||||
|
||||
connected_clients:
|
||||
[]
|
||||
```
|
||||
|
||||
使用 Client Config 前,需要将 Interface Address 和 Peer Endpoint 分别修改为客户端的 IP 和 EasyTier 节点的 IP。将配置文件导入 WireGuard 客户端,即可访问 EasyTier 网络。
|
||||
|
||||
---
|
||||
|
||||
### 自建公共中转服务器
|
||||
|
||||
每个节点都可作为其他用户网络的中转节点。不带任何参数直接启动 EasyTier 即可。
|
||||
|
||||
### 其他配置
|
||||
|
||||
可使用 ``easytier-core --help`` 查看全部配置项
|
||||
@@ -178,26 +257,33 @@ sudo easytier-core --ipv4 10.144.144.2 --network-name abc --network-secret abc -
|
||||
# 路线图
|
||||
|
||||
- [ ] 完善文档和用户指南。
|
||||
- [ ] 支持加密、TCP 打洞等特性。
|
||||
- [ ] 支持 TCP 打洞等特性。
|
||||
- [ ] 支持 Android、IOS 等移动平台。
|
||||
- [ ] 支持 Web 配置管理。
|
||||
|
||||
# 社区和贡献
|
||||
|
||||
我们欢迎并鼓励社区贡献!如果你想参与进来,请提交 [GitHub PR](https://github.com/KKRainbow/EasyTier/pulls)。详细的贡献指南可以在 [CONTRIBUTING.md](https://github.com/KKRainbow/EasyTier/blob/main/CONTRIBUTING.md) 中找到。
|
||||
我们欢迎并鼓励社区贡献!如果你想参与进来,请提交 [GitHub PR](https://github.com/EasyTier/EasyTier/pulls)。详细的贡献指南可以在 [CONTRIBUTING.md](https://github.com/EasyTier/EasyTier/blob/main/CONTRIBUTING.md) 中找到。
|
||||
|
||||
# 相关项目和资源
|
||||
|
||||
- [ZeroTier](https://www.zerotier.com/): 一个全球虚拟网络,用于连接设备。
|
||||
- [TailScale](https://tailscale.com/): 一个旨在简化网络配置的 VPN 解决方案。
|
||||
- [vpncloud](https://github.com/dswd/vpncloud): 一个 P2P Mesh VPN
|
||||
- [Candy](https://github.com/lanthora/candy): 可靠、低延迟、抗审查的虚拟专用网络
|
||||
|
||||
# 许可证
|
||||
|
||||
EasyTier 根据 [Apache License 2.0](https://github.com/KKRainbow/EasyTier/blob/main/LICENSE) 许可证发布。
|
||||
EasyTier 根据 [Apache License 2.0](https://github.com/EasyTier/EasyTier/blob/main/LICENSE) 许可证发布。
|
||||
|
||||
# 联系方式
|
||||
|
||||
- 提问或报告问题:[GitHub Issues](https://github.com/KKRainbow/EasyTier/issues)
|
||||
- 讨论和交流:[GitHub Discussions](https://github.com/KKRainbow/EasyTier/discussions)
|
||||
- QQ 群: 949700262
|
||||
- 提问或报告问题:[GitHub Issues](https://github.com/EasyTier/EasyTier/issues)
|
||||
- 讨论和交流:[GitHub Discussions](https://github.com/EasyTier/EasyTier/discussions)
|
||||
- QQ 群: 949700262
|
||||
- Telegram:https://t.me/easytier
|
||||
|
||||
# 赞助
|
||||
|
||||
<img src="assets/image-8.png" width="300">
|
||||
<img src="assets/image-9.png" width="300">
|
||||
|
BIN
assets/image-4.png
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
assets/image-5.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
assets/image-6.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
assets/image-7.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
assets/image-8.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
assets/image-9.png
Normal file
After Width: | Height: | Size: 218 KiB |
27
easytier-gui/.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
vite.config.ts.timestamp*
|
2
easytier-gui/.npmrc
Normal file
@@ -0,0 +1,2 @@
|
||||
shamefully-hoist=true
|
||||
strict-peer-dependencies=false
|
7
easytier-gui/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"vue.volar",
|
||||
"lokalise.i18n-ally"
|
||||
]
|
||||
}
|
5
easytier-gui/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"i18n-ally.localesPaths": [
|
||||
"locales"
|
||||
]
|
||||
}
|
46
easytier-gui/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# GUI for EasyTier
|
||||
|
||||
this is a GUI implementation for EasyTier, based on Tauri2.
|
||||
|
||||
## Compile
|
||||
|
||||
### Install prerequisites
|
||||
|
||||
```
|
||||
apt install npm
|
||||
npm install -g pnpm
|
||||
```
|
||||
|
||||
### For Desktop (Win/Mac/Linux)
|
||||
|
||||
```
|
||||
pnpm install
|
||||
pnpm tauri build
|
||||
```
|
||||
|
||||
### For Android
|
||||
|
||||
Need to install android SDK / emulator / NDK / Java (easy with android studio)
|
||||
|
||||
```
|
||||
# For ArchLinux
|
||||
sudo pacman -Sy sdkmanager
|
||||
sudo sdkmanager --install platform-tools platforms\;android-34 ndk\;r26 build-tools
|
||||
export PATH=/opt/android-sdk/platform-tools:$PATH
|
||||
export ANDROID_HOME=/opt/android-sdk/
|
||||
export NDK_HOME=/opt/android-sdk/ndk/26.0.10792818/
|
||||
rustup target add aarch64-linux-android
|
||||
|
||||
install java 20
|
||||
```
|
||||
|
||||
|
||||
Java version depend on gradle version specified in (easytier-gui\src-tauri\gen\android\build.gradle.kts)
|
||||
|
||||
See [Gradle compatibility matrix](https://docs.gradle.org/current/userguide/compatibility.html) for detail .
|
||||
|
||||
```
|
||||
pnpm install
|
||||
pnpm tauri android init
|
||||
pnpm tauri android build
|
||||
```
|
12
easytier-gui/eslint.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// @ts-check
|
||||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default antfu({
|
||||
formatters: true,
|
||||
rules: {
|
||||
'style/eol-last': ['error', 'always'],
|
||||
},
|
||||
ignores: [
|
||||
'src-tauri/**',
|
||||
],
|
||||
})
|
14
easytier-gui/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Tauri + Vue + TS</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
77
easytier-gui/locales/cn.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
network: 网络
|
||||
networking_method: 网络方式
|
||||
public_server: 公共服务器
|
||||
manual: 手动
|
||||
standalone: 独立
|
||||
virtual_ipv4: 虚拟IPv4地址
|
||||
virtual_ipv4_dhcp: DHCP
|
||||
network_name: 网络名称
|
||||
network_secret: 网络密码
|
||||
public_server_url: 公共服务器地址
|
||||
peer_urls: 对等节点地址
|
||||
proxy_cidrs: 子网代理CIDR
|
||||
enable_vpn_portal: 启用VPN门户
|
||||
vpn_portal_listen_port: 监听端口
|
||||
vpn_portal_client_network: 客户端子网
|
||||
advanced_settings: 高级设置
|
||||
basic_settings: 基础设置
|
||||
listener_urls: 监听地址
|
||||
rpc_port: RPC端口
|
||||
config_network: 配置网络
|
||||
running: 运行中
|
||||
error_msg: 错误信息
|
||||
detail: 详情
|
||||
add_new_network: 添加新网络
|
||||
del_cur_network: 删除当前网络
|
||||
select_network: 选择网络
|
||||
network_instances: 网络实例
|
||||
instance_id: 实例ID
|
||||
network_infos: 网络信息
|
||||
parse_network_config: 解析网络配置
|
||||
retain_network_instance: 保留网络实例
|
||||
collect_network_infos: 收集网络信息
|
||||
settings: 设置
|
||||
exchange_language: Switch to English
|
||||
logging: 日志
|
||||
logging_level_info: 信息
|
||||
logging_level_debug: 调试
|
||||
logging_level_warn: 警告
|
||||
logging_level_trace: 跟踪
|
||||
logging_level_off: 关闭
|
||||
logging_open_dir: 打开日志目录
|
||||
logging_copy_dir: 复制日志路径
|
||||
disable_auto_launch: 关闭开机自启
|
||||
enable_auto_launch: 开启开机自启
|
||||
exit: 退出
|
||||
chips_placeholder: 例如: {0}, 按回车添加
|
||||
hostname_placeholder: '留空默认为主机名: {0}'
|
||||
off_text: 点击关闭
|
||||
on_text: 点击开启
|
||||
show_config: 显示配置
|
||||
close: 关闭
|
||||
|
||||
my_node_info: 当前节点信息
|
||||
peer_count: 已连接
|
||||
upload: 上传
|
||||
download: 下载
|
||||
show_vpn_portal_config: 显示VPN门户配置
|
||||
vpn_portal_config: VPN门户配置
|
||||
show_event_log: 显示事件日志
|
||||
event_log: 事件日志
|
||||
peer_info: 节点信息
|
||||
hostname: 主机名
|
||||
route_cost: 路由
|
||||
latency: 延迟
|
||||
upload_bytes: 上传
|
||||
download_bytes: 下载
|
||||
loss_rate: 丢包率
|
||||
|
||||
run_network: 运行网络
|
||||
stop_network: 停止网络
|
||||
network_running: 运行中
|
||||
network_stopped: 已停止
|
||||
dhcp_experimental_warning: 实验性警告!使用DHCP时如果组网环境中发生IP冲突,将自动更改IP。
|
||||
|
||||
tray:
|
||||
show: 显示 / 隐藏
|
||||
exit: 退出
|
77
easytier-gui/locales/en.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
network: Network
|
||||
networking_method: Networking Method
|
||||
public_server: Public Server
|
||||
manual: Manual
|
||||
standalone: Standalone
|
||||
virtual_ipv4: Virtual IPv4
|
||||
virtual_ipv4_dhcp: DHCP
|
||||
network_name: Network Name
|
||||
network_secret: Network Secret
|
||||
public_server_url: Public Server URL
|
||||
peer_urls: Peer URLs
|
||||
proxy_cidrs: Subnet Proxy CIDRs
|
||||
enable_vpn_portal: Enable VPN Portal
|
||||
vpn_portal_listen_port: VPN Portal Listen Port
|
||||
vpn_portal_client_network: Client Sub Network
|
||||
advanced_settings: Advanced Settings
|
||||
basic_settings: Basic Settings
|
||||
listener_urls: Listener URLs
|
||||
rpc_port: RPC Port
|
||||
config_network: Config Network
|
||||
running: Running
|
||||
error_msg: Error Message
|
||||
detail: Detail
|
||||
add_new_network: New Network
|
||||
del_cur_network: Delete Current Network
|
||||
select_network: Select Network
|
||||
network_instances: Network Instances
|
||||
instance_id: Instance ID
|
||||
network_infos: Network Infos
|
||||
parse_network_config: Parse Network Config
|
||||
retain_network_instance: Retain Network Instance
|
||||
collect_network_infos: Collect Network Infos
|
||||
settings: Settings
|
||||
exchange_language: 切换中文
|
||||
logging: Logging
|
||||
logging_level_info: Info
|
||||
logging_level_debug: Debug
|
||||
logging_level_warn: Warn
|
||||
logging_level_trace: Trace
|
||||
logging_level_off: Off
|
||||
logging_open_dir: Open Log Directory
|
||||
logging_copy_dir: Copy Log Path
|
||||
disable_auto_launch: Disable Launch on Reboot
|
||||
enable_auto_launch: Enable Launch on Reboot
|
||||
exit: Exit
|
||||
|
||||
chips_placeholder: 'e.g: {0}, press Enter to add'
|
||||
hostname_placeholder: 'Leave blank and default to host name: {0}'
|
||||
off_text: Press to disable
|
||||
on_text: Press to enable
|
||||
show_config: Show Config
|
||||
close: Close
|
||||
my_node_info: My Node Info
|
||||
peer_count: Connected
|
||||
upload: Upload
|
||||
download: Download
|
||||
show_vpn_portal_config: Show VPN Portal Config
|
||||
vpn_portal_config: VPN Portal Config
|
||||
show_event_log: Show Event Log
|
||||
event_log: Event Log
|
||||
peer_info: Peer Info
|
||||
route_cost: Route Cost
|
||||
hostname: Hostname
|
||||
latency: Latency
|
||||
upload_bytes: Upload
|
||||
download_bytes: Download
|
||||
loss_rate: Loss Rate
|
||||
|
||||
run_network: Run Network
|
||||
stop_network: Stop Network
|
||||
network_running: running
|
||||
network_stopped: stopped
|
||||
dhcp_experimental_warning: Experimental warning! if there is an IP conflict in the network when using DHCP, the IP will be automatically changed.
|
||||
|
||||
tray:
|
||||
show: Show / Hide
|
||||
exit: Exit
|
58
easytier-gui/package.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "easytier-gui",
|
||||
"type": "module",
|
||||
"version": "1.2.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"preview": "vite preview",
|
||||
"tauri": "tauri",
|
||||
"lint": "eslint . --ignore-pattern src-tauri",
|
||||
"lint:fix": "eslint . --ignore-pattern src-tauri --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@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.2.1",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^7.0.0",
|
||||
"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.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.24.1",
|
||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||
"@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.1.2",
|
||||
"@vue-macros/volar": "^0.19.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.8.0",
|
||||
"eslint-plugin-format": "^0.1.2",
|
||||
"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.5",
|
||||
"vite-plugin-vue-devtools": "^7.3.7",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-tsc": "^2.0.29"
|
||||
}
|
||||
}
|
6714
easytier-gui/pnpm-lock.yaml
generated
Normal file
6
easytier-gui/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
4
easytier-gui/src-tauri/.cargo/config.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
[build]
|
||||
target = "x86_64-unknown-linux-gnu"
|
||||
|
||||
[target]
|
7
easytier-gui/src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
51
easytier-gui/src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,51 @@
|
||||
[package]
|
||||
name = "easytier-gui"
|
||||
version = "1.2.1"
|
||||
description = "EasyTier GUI"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-rc", features = [
|
||||
"tray-icon",
|
||||
"image-png",
|
||||
"image-ico",
|
||||
] }
|
||||
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
easytier = { path = "../../easytier" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
anyhow = "1.0"
|
||||
chrono = { version = "0.4.37", features = ["serde"] }
|
||||
|
||||
once_cell = "1.18.0"
|
||||
dashmap = "6.0"
|
||||
|
||||
privilege = "0.3"
|
||||
gethostname = "0.5"
|
||||
|
||||
auto-launch = "0.5.0"
|
||||
dunce = "1.0.4"
|
||||
|
||||
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-rc"
|
||||
|
||||
|
||||
[features]
|
||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
34
easytier-gui/src-tauri/build.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
fn main() {
|
||||
if !cfg!(debug_assertions) && cfg!(target_os = "windows") {
|
||||
let mut windows = tauri_build::WindowsAttributes::new();
|
||||
windows = windows.app_manifest(
|
||||
r#"
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
"#,
|
||||
);
|
||||
tauri_build::try_build(tauri_build::Attributes::new().windows_attributes(windows))
|
||||
.expect("failed to run build script");
|
||||
} else {
|
||||
tauri_build::build();
|
||||
}
|
||||
}
|
49
easytier-gui/src-tauri/capabilities/migrated.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"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",
|
||||
"clipboard-manager:allow-write-text",
|
||||
"shell:default",
|
||||
"process:default",
|
||||
"clipboard-manager:default",
|
||||
"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",
|
||||
"vpnservice:allow-stop-vpn",
|
||||
"vpnservice:allow-register-listener",
|
||||
"os:default",
|
||||
"os:allow-os-type",
|
||||
"os:allow-arch",
|
||||
"os:allow-hostname",
|
||||
"os:allow-platform",
|
||||
"os:allow-locale"
|
||||
]
|
||||
}
|
12
easytier-gui/src-tauri/gen/android/.editorconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
19
easytier-gui/src-tauri/gen/android/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
key.properties
|
||||
|
||||
/.tauri
|
||||
/tauri.settings.gradle
|
6
easytier-gui/src-tauri/gen/android/app/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/src/main/java/com/kkrainbow/easytier/generated
|
||||
/src/main/jniLibs/**/*.so
|
||||
/src/main/assets/tauri.conf.json
|
||||
/tauri.build.gradle.kts
|
||||
/proguard-tauri.pro
|
||||
/tauri.properties
|
85
easytier-gui/src-tauri/gen/android/app/build.gradle.kts
Normal file
@@ -0,0 +1,85 @@
|
||||
import java.util.Properties
|
||||
import java.io.FileInputStream
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("rust")
|
||||
}
|
||||
|
||||
val tauriProperties = Properties().apply {
|
||||
val propFile = file("tauri.properties")
|
||||
if (propFile.exists()) {
|
||||
propFile.inputStream().use { load(it) }
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = 34
|
||||
namespace = "com.kkrainbow.easytier"
|
||||
defaultConfig {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "false"
|
||||
applicationId = "com.kkrainbow.easytier"
|
||||
minSdk = 24
|
||||
targetSdk = 34
|
||||
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()
|
||||
versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0")
|
||||
}
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
storeFile = file(keystoreProperties["storeFile"] as String)
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
getByName("debug") {
|
||||
manifestPlaceholders["usesCleartextTraffic"] = "true"
|
||||
isDebuggable = true
|
||||
isJniDebuggable = true
|
||||
isMinifyEnabled = false
|
||||
packaging { jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86/*.so")
|
||||
jniLibs.keepDebugSymbols.add("*/x86_64/*.so")
|
||||
}
|
||||
}
|
||||
getByName("release") {
|
||||
isMinifyEnabled = true
|
||||
proguardFiles(
|
||||
*fileTree(".") { include("**/*.pro") }
|
||||
.plus(getDefaultProguardFile("proguard-android-optimize.txt"))
|
||||
.toList().toTypedArray()
|
||||
)
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
rust {
|
||||
rootDirRel = "../../../"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.webkit:webkit:1.6.1")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.8.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
||||
}
|
||||
|
||||
apply(from = "tauri.build.gradle.kts")
|
21
easytier-gui/src-tauri/gen/android/app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.easytier_gui"
|
||||
android:usesCleartextTraffic="${usesCleartextTraffic}">
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/main_activity_title"
|
||||
android:name=".MainActivity"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name="com.plugin.vpnservice.TauriVpnService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:label="@string/main_activity_title"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:foregroundServiceType="specialUse">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.VpnService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
@@ -0,0 +1,3 @@
|
||||
package com.kkrainbow.easytier
|
||||
|
||||
class MainActivity : TauriActivity()
|
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,6 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.easytier_gui" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">easytier-gui</string>
|
||||
<string name="main_activity_title">easytier-gui</string>
|
||||
</resources>
|
@@ -0,0 +1,6 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.easytier_gui" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<external-path name="my_images" path="." />
|
||||
<cache-path name="my_cache_images" path="." />
|
||||
</paths>
|
BIN
easytier-gui/src-tauri/gen/android/app/upload-keystore.jks
Normal file
22
easytier-gui/src-tauri/gen/android/build.gradle.kts
Normal file
@@ -0,0 +1,22 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:8.3.2")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("clean").configure {
|
||||
delete("build")
|
||||
}
|
||||
|
23
easytier-gui/src-tauri/gen/android/buildSrc/build.gradle.kts
Normal file
@@ -0,0 +1,23 @@
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("pluginsForCoolKids") {
|
||||
id = "rust"
|
||||
implementationClass = "RustPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(gradleApi())
|
||||
implementation("com.android.tools.build:gradle:8.3.2")
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
import java.io.File
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
open class BuildTask : DefaultTask() {
|
||||
@Input
|
||||
var rootDirRel: String? = null
|
||||
@Input
|
||||
var target: String? = null
|
||||
@Input
|
||||
var release: Boolean? = null
|
||||
|
||||
@TaskAction
|
||||
fun assemble() {
|
||||
val executable = """pnpm""";
|
||||
try {
|
||||
runTauriCli(executable)
|
||||
} catch (e: Exception) {
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
runTauriCli("$executable.cmd")
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun runTauriCli(executable: String) {
|
||||
val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null")
|
||||
val target = target ?: throw GradleException("target cannot be null")
|
||||
val release = release ?: throw GradleException("release cannot be null")
|
||||
val args = listOf("tauri", "android", "android-studio-script");
|
||||
|
||||
project.exec {
|
||||
workingDir(File(project.projectDir, rootDirRel))
|
||||
executable(executable)
|
||||
args(args)
|
||||
if (project.logger.isEnabled(LogLevel.DEBUG)) {
|
||||
args("-vv")
|
||||
} else if (project.logger.isEnabled(LogLevel.INFO)) {
|
||||
args("-v")
|
||||
}
|
||||
if (release) {
|
||||
args("--release")
|
||||
}
|
||||
args(listOf("--target", target))
|
||||
}.assertNormalExitValue()
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
import com.android.build.api.dsl.ApplicationExtension
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.get
|
||||
|
||||
const val TASK_GROUP = "rust"
|
||||
|
||||
open class Config {
|
||||
lateinit var rootDirRel: String
|
||||
}
|
||||
|
||||
open class RustPlugin : Plugin<Project> {
|
||||
private lateinit var config: Config
|
||||
|
||||
override fun apply(project: Project) = with(project) {
|
||||
config = extensions.create("rust", Config::class.java)
|
||||
|
||||
val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64");
|
||||
val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList
|
||||
|
||||
val defaultArchList = listOf("arm64", "arm", "x86", "x86_64");
|
||||
val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList
|
||||
|
||||
val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64")
|
||||
|
||||
extensions.configure<ApplicationExtension> {
|
||||
@Suppress("UnstableApiUsage")
|
||||
flavorDimensions.add("abi")
|
||||
productFlavors {
|
||||
create("universal") {
|
||||
dimension = "abi"
|
||||
ndk {
|
||||
abiFilters += abiList
|
||||
}
|
||||
}
|
||||
defaultArchList.forEachIndexed { index, arch ->
|
||||
create(arch) {
|
||||
dimension = "abi"
|
||||
ndk {
|
||||
abiFilters.add(defaultAbiList[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
for (profile in listOf("debug", "release")) {
|
||||
val profileCapitalized = profile.replaceFirstChar { it.uppercase() }
|
||||
val buildTask = tasks.maybeCreate(
|
||||
"rustBuildUniversal$profileCapitalized",
|
||||
DefaultTask::class.java
|
||||
).apply {
|
||||
group = TASK_GROUP
|
||||
description = "Build dynamic library in $profile mode for all targets"
|
||||
}
|
||||
|
||||
tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask)
|
||||
|
||||
for (targetPair in targetsList.withIndex()) {
|
||||
val targetName = targetPair.value
|
||||
val targetArch = archList[targetPair.index]
|
||||
val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() }
|
||||
val targetBuildTask = project.tasks.maybeCreate(
|
||||
"rustBuild$targetArchCapitalized$profileCapitalized",
|
||||
BuildTask::class.java
|
||||
).apply {
|
||||
group = TASK_GROUP
|
||||
description = "Build dynamic library in $profile mode for $targetArch"
|
||||
rootDirRel = config.rootDirRel
|
||||
target = targetName
|
||||
release = profile == "release"
|
||||
}
|
||||
|
||||
buildTask.dependsOn(targetBuildTask)
|
||||
tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn(
|
||||
targetBuildTask
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
easytier-gui/src-tauri/gen/android/gradle.properties
Normal file
@@ -0,0 +1,24 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app"s APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.nonFinalResIds=false
|
BIN
easytier-gui/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar
vendored
Executable file
6
easytier-gui/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Tue May 10 19:22:52 CST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
185
easytier-gui/src-tauri/gen/android/gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
89
easytier-gui/src-tauri/gen/android/gradlew.bat
vendored
Executable file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
4
easytier-gui/src-tauri/gen/android/keystore.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
storePassword=EasyTier
|
||||
keyPassword=EasyTier
|
||||
keyAlias=upload
|
||||
storeFile=upload-keystore.jks
|
3
easytier-gui/src-tauri/gen/android/settings.gradle
Normal file
@@ -0,0 +1,3 @@
|
||||
include ':app'
|
||||
|
||||
apply from: 'tauri.settings.gradle'
|
BIN
easytier-gui/src-tauri/icons/128x128.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
easytier-gui/src-tauri/icons/128x128@2x.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
easytier-gui/src-tauri/icons/32x32.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
easytier-gui/src-tauri/icons/Square107x107Logo.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
easytier-gui/src-tauri/icons/Square142x142Logo.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
easytier-gui/src-tauri/icons/Square150x150Logo.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
easytier-gui/src-tauri/icons/Square284x284Logo.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
easytier-gui/src-tauri/icons/Square30x30Logo.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
easytier-gui/src-tauri/icons/Square310x310Logo.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
easytier-gui/src-tauri/icons/Square44x44Logo.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
easytier-gui/src-tauri/icons/Square71x71Logo.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
easytier-gui/src-tauri/icons/Square89x89Logo.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
easytier-gui/src-tauri/icons/StoreLogo.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
easytier-gui/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 5.3 KiB |
BIN
easytier-gui/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 16 KiB |