Compare commits
10 Commits
7495c9a861
...
afe7019f4f
| Author | SHA1 | Date | |
|---|---|---|---|
| afe7019f4f | |||
| a7738d9a5d | |||
| 23bb6c784d | |||
| a30cf1b39b | |||
| 20ce2c897c | |||
| eb81e5d573 | |||
| c952b7015d | |||
| 48c2bfd551 | |||
| aaa3e5104d | |||
| 216c9ce306 |
581
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
name: Build
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths-ignore: [README.md]
|
||||
release:
|
||||
types: [published]
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: src
|
||||
env:
|
||||
CACHE_EPOCH: 1
|
||||
CCACHE_MAXSIZE: 200M
|
||||
CCACHE_MAXFILES: 0
|
||||
SCCACHE_CACHE_SIZE: 200M
|
||||
jobs:
|
||||
cache-toolchains-posix:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains (Linux, OpenWrt, Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
src/qemu-user*.deb
|
||||
key: toolchains-posix-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (Linux, OpenWrt)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/
|
||||
key: pgo-linux-openwrt-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache AFDO (Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/android/profiles/
|
||||
key: afdo-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache Android NDK (Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/third_party/android_toolchain/ndk/
|
||||
key: android-ndk-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- run: ./get-clang.sh
|
||||
- run: EXTRA_FLAGS='target_os="android"' ./get-clang.sh
|
||||
- run: |
|
||||
if [ ! -f qemu-user*.deb ]; then
|
||||
wget https://snapshot.debian.org/archive/debian/20250405T083429Z/pool/main/q/qemu/qemu-user_9.2.2%2Bds-1%2Bb2_amd64.deb
|
||||
fi
|
||||
cache-toolchains-win:
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
~/.cargo/bin/
|
||||
~/bin/ninja.exe
|
||||
key: toolchains-win-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (win64)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/chrome-win64-*
|
||||
key: pgo-win64-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (win32)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/chrome-win32-*
|
||||
key: pgo-win32-arm64-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- run: EXTRA_FLAGS='target_cpu="x64"' ./get-clang.sh
|
||||
- run: EXTRA_FLAGS='target_cpu="x86"' ./get-clang.sh
|
||||
- run: |
|
||||
if [ ! -f ~/bin/ninja.exe ]; then
|
||||
curl -LO https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip
|
||||
unzip ninja-win.zip -d ~/bin
|
||||
fi
|
||||
cache-toolchains-mac:
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/chrome/build/pgo_profiles/chrome-mac-*
|
||||
src/gn/
|
||||
key: toolchains-pgo-mac-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- run: EXTRA_FLAGS='target_cpu="x64"' ./get-clang.sh
|
||||
- run: EXTRA_FLAGS='target_cpu="arm64"' ./get-clang.sh
|
||||
linux:
|
||||
needs: cache-toolchains-posix
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, x86, arm64, arm, mipsel, mips64el, riscv64, loong64]
|
||||
env:
|
||||
EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"'
|
||||
BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains (Linux, OpenWrt, Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
src/qemu-user*.deb
|
||||
key: toolchains-posix-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (Linux, OpenWrt)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/
|
||||
key: pgo-linux-openwrt-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Regenerate Debian keyring
|
||||
run: |
|
||||
rm -f ./build/linux/sysroot_scripts/keyring.gpg
|
||||
GPG_TTY=/dev/null ./build/linux/sysroot_scripts/generate_keyring.sh
|
||||
- name: Cache sysroot
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/out/sysroot-build/bullseye/bullseye_*
|
||||
src/out/sysroot-build/trixie/trixie_*
|
||||
src/out/sysroot-build/sid/sid_*
|
||||
key: sysroot-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- id: ccache-timestamp
|
||||
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
|
||||
- name: Cache ccache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ccache
|
||||
key: ccache-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
|
||||
restore-keys: ccache-linux-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
|
||||
- name: Install APT packages
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ninja-build pkg-config ccache bubblewrap
|
||||
sudo apt remove -y qemu-user-binfmt
|
||||
sudo dpkg -i qemu-user*.deb
|
||||
# libc6-i386 interferes with x86 build
|
||||
sudo apt remove libc6-i386
|
||||
- run: ./get-clang.sh
|
||||
- run: ccache -z
|
||||
- run: ./build.sh
|
||||
- run: ccache -s && ccache --evict-older-than 1d
|
||||
- run: ../tests/basic.sh out/Release/naive
|
||||
- name: Pack naiveproxy assets
|
||||
run: |
|
||||
mkdir ${{ env.BUNDLE }}
|
||||
cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }}
|
||||
tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }}
|
||||
openssl sha256 out/Release/naive >sha256sum.txt
|
||||
echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUNDLE }}.tar.xz naive executable sha256 ${{ env.SHA256SUM }}
|
||||
path: src/sha256sum.txt
|
||||
- name: Upload naiveproxy assets
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.tar.xz --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
android:
|
||||
needs: cache-toolchains-posix
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
abi: x86_64
|
||||
- arch: x86
|
||||
abi: x86
|
||||
- arch: arm64
|
||||
abi: arm64-v8a
|
||||
- arch: arm
|
||||
abi: armeabi-v7a
|
||||
env:
|
||||
EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}" target_os="android"'
|
||||
BUNDLE: naiveproxy-plugin-${{ github.event.release.tag_name || 'v1.1.1.1-1' }}-${{ matrix.abi }}.apk
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Cache toolchains (Linux, OpenWrt, Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
src/qemu-user*.deb
|
||||
key: toolchains-posix-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache AFDO (Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/android/profiles/
|
||||
key: afdo-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache Android NDK (Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/third_party/android_toolchain/ndk/
|
||||
key: android-ndk-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache sysroot
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/out/sysroot-build/android/
|
||||
key: sysroot-android-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- id: ccache-timestamp
|
||||
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
|
||||
- name: Cache ccache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ccache
|
||||
key: ccache-android-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
|
||||
restore-keys: ccache-android-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
|
||||
- name: Install APT packages
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ninja-build pkg-config ccache bubblewrap
|
||||
sudo apt remove -y qemu-user-binfmt
|
||||
sudo dpkg -i qemu-user*.deb
|
||||
# libc6-i386 interferes with x86 build
|
||||
sudo apt remove libc6-i386
|
||||
- run: ./get-clang.sh
|
||||
- run: ccache -z
|
||||
- run: ./build.sh
|
||||
- run: ccache -s && ccache --evict-older-than 1d
|
||||
- run: ./get-android-sys.sh
|
||||
- run: ../tests/basic.sh out/Release/naive
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.gradle
|
||||
key: gradle-${{ hashFiles('**/*.gradle.kts') }}
|
||||
- name: Create APK
|
||||
working-directory: apk
|
||||
env:
|
||||
APK_ABI: ${{ matrix.abi }}
|
||||
APK_VERSION_NAME: ${{ github.event.release.tag_name || 'v1.1.1.1-1' }}
|
||||
KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }}
|
||||
run: |
|
||||
mkdir -p app/libs/$APK_ABI
|
||||
cp ../src/out/Release/naive app/libs/$APK_ABI/libnaive.so
|
||||
./gradlew :app:assembleRelease
|
||||
openssl sha256 app/build/outputs/apk/release/${{ env.BUNDLE }} >sha256sum.txt
|
||||
echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUNDLE }} sha256 ${{ env.SHA256SUM }}
|
||||
path: apk/sha256sum.txt
|
||||
- name: Upload naiveproxy assets
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
working-directory: apk/app/build/outputs/apk/release
|
||||
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }} --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
win:
|
||||
needs: cache-toolchains-win
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, x86, arm64]
|
||||
env:
|
||||
EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"'
|
||||
BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
~/.cargo/bin/
|
||||
~/bin/ninja.exe
|
||||
key: toolchains-win-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (win64)
|
||||
if: ${{ matrix.arch == 'x64' }}
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/chrome-win64-*
|
||||
key: pgo-win64-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (win32)
|
||||
if: ${{ matrix.arch != 'x64' }}
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/chrome-win32-*
|
||||
key: pgo-win32-arm64-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- id: ccache-timestamp
|
||||
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
|
||||
- name: Cache ccache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/AppData/Local/Mozilla/sccache
|
||||
key: ccache-win-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
|
||||
restore-keys: ccache-win-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
|
||||
- run: ./get-clang.sh
|
||||
- run: ~/.cargo/bin/sccache -z
|
||||
- run: ./build.sh
|
||||
- run: ~/.cargo/bin/sccache -s
|
||||
- run: ../tests/basic.sh out/Release/naive
|
||||
# No real or emulated environment is available to test this.
|
||||
if: ${{ matrix.arch != 'arm64' }}
|
||||
- name: Pack naiveproxy assets
|
||||
run: |
|
||||
mkdir ${{ env.BUNDLE }}
|
||||
cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }}
|
||||
7z a ${{ env.BUNDLE }}.zip ${{ env.BUNDLE }}
|
||||
openssl sha256 out/Release/naive.exe >sha256sum.txt
|
||||
echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUNDLE }}.zip naive executable sha256 ${{ env.SHA256SUM }}
|
||||
path: src/sha256sum.txt
|
||||
- name: Upload naiveproxy assets
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.zip --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
mac:
|
||||
needs: cache-toolchains-mac
|
||||
runs-on: macos-15
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, arm64]
|
||||
env:
|
||||
EXTRA_FLAGS: 'target_cpu="${{ matrix.arch }}"'
|
||||
BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains and PGO
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/chrome/build/pgo_profiles/chrome-mac-*
|
||||
src/gn/
|
||||
key: toolchains-pgo-mac-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- id: ccache-timestamp
|
||||
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
|
||||
- name: Cache ccache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/Library/Caches/ccache
|
||||
key: ccache-mac-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
|
||||
restore-keys: ccache-mac-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
|
||||
- run: brew install ninja ccache
|
||||
- run: pip install setuptools
|
||||
- run: ./get-clang.sh
|
||||
- run: ccache -z
|
||||
- run: ./build.sh
|
||||
- run: ccache -s && ccache --evict-older-than 1d
|
||||
- run: ../tests/basic.sh out/Release/naive
|
||||
# No real or emulated environment is available to test this.
|
||||
if: ${{ matrix.arch != 'arm64' }}
|
||||
- name: Pack naiveproxy assets
|
||||
run: |
|
||||
mkdir ${{ env.BUNDLE }}
|
||||
cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }}
|
||||
tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }}
|
||||
openssl sha256 out/Release/naive >sha256sum.txt
|
||||
echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUNDLE }}.tar.xz naive executable sha256 ${{ env.SHA256SUM }}
|
||||
path: src/sha256sum.txt
|
||||
- name: Upload naiveproxy assets
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.tar.xz --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
openwrt:
|
||||
needs: cache-toolchains-posix
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
openwrt: "target=x86 subtarget=64"
|
||||
target_cpu: x64
|
||||
- arch: x86
|
||||
openwrt: "target=x86 subtarget=geode"
|
||||
target_cpu: x86
|
||||
- arch: aarch64_cortex-a53
|
||||
openwrt: "target=sunxi subtarget=cortexa53"
|
||||
target_cpu: arm64
|
||||
extra: 'arm_cpu="cortex-a53"'
|
||||
- arch: aarch64_cortex-a53-static
|
||||
openwrt: "target=sunxi subtarget=cortexa53"
|
||||
target_cpu: arm64
|
||||
extra: 'arm_cpu="cortex-a53" build_static=true use_allocator_shim=false use_partition_alloc=false'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: aarch64_cortex-a72
|
||||
openwrt: "target=mvebu subtarget=cortexa72"
|
||||
target_cpu: arm64
|
||||
extra: 'arm_cpu="cortex-a72"'
|
||||
- arch: aarch64_cortex-a72-static
|
||||
openwrt: "target=mvebu subtarget=cortexa72"
|
||||
target_cpu: arm64
|
||||
extra: 'arm_cpu="cortex-a72" build_static=true use_allocator_shim=false use_partition_alloc=false'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: aarch64_cortex-a76
|
||||
openwrt: "target=bcm27xx subtarget=bcm2712"
|
||||
target_cpu: arm64
|
||||
extra: 'arm_cpu="cortex-a76"'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: aarch64_generic
|
||||
openwrt: "target=layerscape subtarget=armv8_64b"
|
||||
target_cpu: arm64
|
||||
- arch: aarch64_generic-static
|
||||
openwrt: "target=layerscape subtarget=armv8_64b"
|
||||
target_cpu: arm64
|
||||
extra: "build_static=true use_allocator_shim=false use_partition_alloc=false"
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: arm_arm1176jzf-s_vfp
|
||||
openwrt: "target=brcm2708 subtarget=bcm2708"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="arm1176jzf-s" arm_fpu="vfp" arm_float_abi="hard" arm_use_neon=false arm_use_thumb=false'
|
||||
- arch: arm_arm926ej-s
|
||||
openwrt: "target=mxs subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="arm926ej-s" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false'
|
||||
- arch: arm_cortex-a15_neon-vfpv4
|
||||
openwrt: "target=ipq806x subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a15" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true'
|
||||
- arch: arm_cortex-a5_vfpv4
|
||||
openwrt: "target=at91 subtarget=sama5d3"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a5" arm_fpu="vfpv4" arm_float_abi="hard" arm_use_neon=false'
|
||||
- arch: arm_cortex-a7
|
||||
openwrt: "target=mediatek subtarget=mt7629"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a7" arm_float_abi="soft" arm_use_neon=false'
|
||||
openwrt_release: '21.02.0'
|
||||
openwrt_gcc_ver: '8.4.0'
|
||||
- arch: arm_cortex-a7_neon-vfpv4
|
||||
openwrt: "target=sunxi subtarget=cortexa7"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true'
|
||||
- arch: arm_cortex-a7_neon-vfpv4-static
|
||||
openwrt: "target=sunxi subtarget=cortexa7"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="neon-vfpv4" arm_float_abi="hard" arm_use_neon=true build_static=true use_allocator_shim=false use_partition_alloc=false'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: arm_cortex-a7_vfpv4
|
||||
openwrt: "target=at91 subtarget=sama7"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a7" arm_fpu="vfpv4" arm_float_abi="hard" arm_use_neon=false'
|
||||
openwrt_release: '22.03.0'
|
||||
openwrt_gcc_ver: '11.2.0'
|
||||
- arch: arm_cortex-a8_vfpv3
|
||||
openwrt: "target=sunxi subtarget=cortexa8"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a8" arm_fpu="vfpv3" arm_float_abi="hard" arm_use_neon=false'
|
||||
- arch: arm_cortex-a9
|
||||
openwrt: "target=bcm53xx subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false'
|
||||
- arch: arm_cortex-a9-static
|
||||
openwrt: "target=bcm53xx subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false build_static=true use_allocator_shim=false use_partition_alloc=false'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: arm_cortex-a9_neon
|
||||
openwrt: "target=imx6 subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a9" arm_fpu="neon" arm_float_abi="hard" arm_use_neon=true'
|
||||
- arch: arm_cortex-a9_vfpv3-d16
|
||||
openwrt: "target=mvebu subtarget=cortexa9"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="cortex-a9" arm_fpu="vfpv3-d16" arm_float_abi="hard" arm_use_neon=false'
|
||||
- arch: arm_mpcore
|
||||
openwrt: "target=oxnas subtarget=ox820"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="mpcore" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false'
|
||||
- arch: arm_xscale
|
||||
openwrt: "target=kirkwood subtarget=generic"
|
||||
target_cpu: arm
|
||||
extra: 'arm_version=0 arm_cpu="xscale" arm_float_abi="soft" arm_use_neon=false arm_use_thumb=false'
|
||||
- arch: mipsel_24kc
|
||||
openwrt: "target=ramips subtarget=rt305x"
|
||||
target_cpu: mipsel
|
||||
extra: 'mips_arch_variant="r2" mips_float_abi="soft"'
|
||||
- arch: mipsel_24kc-static
|
||||
openwrt: "target=ramips subtarget=rt305x"
|
||||
target_cpu: mipsel
|
||||
extra: 'mips_arch_variant="r2" mips_float_abi="soft" build_static=true use_allocator_shim=false use_partition_alloc=false'
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
- arch: mipsel_mips32
|
||||
openwrt: "target=brcm47xx subtarget=legacy"
|
||||
target_cpu: mipsel
|
||||
extra: 'mips_arch_variant="r1" mips_float_abi="soft"'
|
||||
- arch: riscv64
|
||||
openwrt: "target=sifiveu subtarget=generic"
|
||||
target_cpu: riscv64
|
||||
openwrt_release: '23.05.0'
|
||||
openwrt_gcc_ver: '12.3.0'
|
||||
- arch: loongarch64
|
||||
openwrt: "target=loongarch64 subtarget=generic"
|
||||
target_cpu: loong64
|
||||
openwrt_release: '24.10.0'
|
||||
openwrt_gcc_ver: '13.3.0'
|
||||
env:
|
||||
EXTRA_FLAGS: target_cpu="${{ matrix.target_cpu }}" target_os="openwrt" ${{ matrix.extra }}
|
||||
OPENWRT_FLAGS: arch=${{ matrix.arch }} release=${{ matrix.openwrt_release || '18.06.0' }} gcc_ver=${{ matrix.openwrt_gcc_ver || '7.3.0' }} ${{ matrix.openwrt }}
|
||||
BUNDLE: naiveproxy-${{ github.event.release.tag_name }}-${{ github.job }}-${{ matrix.arch }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache toolchains (Linux, OpenWrt, Android)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
src/third_party/llvm-build/Release+Asserts/
|
||||
src/gn/
|
||||
src/qemu-user*.deb
|
||||
key: toolchains-posix-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache PGO (Linux, OpenWrt)
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/chrome/build/pgo_profiles/
|
||||
key: pgo-linux-openwrt-${{ hashFiles('CHROMIUM_VERSION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache sysroot
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src/out/sysroot-build/openwrt
|
||||
key: sysroot-openwrt-23.05.0-${{ matrix.arch }}-v${{ env.CACHE_EPOCH }}
|
||||
- id: ccache-timestamp
|
||||
run: echo "CCACHE_TIMESTAMP=$(date +%s)" >>$GITHUB_OUTPUT
|
||||
- name: Cache ccache files
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ccache
|
||||
key: ccache-openwrt-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-${{ steps.ccache-timestamp.outputs.CCACHE_TIMESTAMP }}
|
||||
restore-keys: ccache-openwrt-${{ matrix.arch }}-${{ hashFiles('CHROMIUM_VERSION') }}-
|
||||
- name: Install APT packages
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ninja-build pkg-config ccache bubblewrap
|
||||
sudo apt remove -y qemu-user-binfmt
|
||||
sudo dpkg -i qemu-user*.deb
|
||||
# libc6-i386 interferes with x86 build
|
||||
sudo apt remove libc6-i386
|
||||
- run: ./get-clang.sh
|
||||
- run: ccache -z
|
||||
- run: ./build.sh
|
||||
- run: ccache -s && ccache --evict-older-than 1d
|
||||
- run: ../tests/basic.sh out/Release/naive
|
||||
- name: Pack naiveproxy assets
|
||||
run: |
|
||||
mkdir ${{ env.BUNDLE }}
|
||||
cp out/Release/naive config.json ../LICENSE ../USAGE.txt ${{ env.BUNDLE }}
|
||||
tar cJf ${{ env.BUNDLE }}.tar.xz ${{ env.BUNDLE }}
|
||||
openssl sha256 out/Release/naive >sha256sum.txt
|
||||
echo "SHA256SUM=$(cut -d' ' -f2 sha256sum.txt)" >>$GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.BUNDLE }}.tar.xz naive executable sha256 ${{ env.SHA256SUM }}
|
||||
path: src/sha256sum.txt
|
||||
- name: Upload naiveproxy assets
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
run: gh release upload "${GITHUB_REF##*/}" ${{ env.BUNDLE }}.tar.xz --clobber
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@ -1 +1 @@
|
||||
140.0.7339.123
|
||||
143.0.7499.41
|
||||
|
||||
12
USAGE.txt
@ -64,8 +64,12 @@ Options:
|
||||
SOCKS-PROXY = "socks://"<HOSTNAME>[":"<PORT>]
|
||||
|
||||
Routes traffic via the proxy chain.
|
||||
The default proxy is directly connection without proxying.
|
||||
The default proxy is a direct connection without proxying.
|
||||
The last PROXY-URI is negotiated automatically for Naive padding.
|
||||
|
||||
Can be specified multiple times, but they must match the number of specified
|
||||
LISTEN-URIs, and each LISTEN-URI is routed to the PROXY matched by position.
|
||||
|
||||
Limitations:
|
||||
* QUIC proxies cannot follow TCP-based proxies in a proxy chain.
|
||||
* The user needs to ensure there is no loop in the proxy chain.
|
||||
@ -89,6 +93,7 @@ Options:
|
||||
--host-resolver-rules="MAP proxy.example.com 1.2.3.4"
|
||||
|
||||
Statically resolves a domain name to an IP address.
|
||||
Multiple rules are comma separated.
|
||||
|
||||
--resolver-range=CIDR
|
||||
|
||||
@ -110,3 +115,8 @@ Options:
|
||||
--no-post-quantum
|
||||
|
||||
Overrides the default and disables post-quantum key agreement.
|
||||
|
||||
--env=NAME=VALUE
|
||||
|
||||
Sets the environment variable NAME to the value VALUE. Can be specified
|
||||
multiple times.
|
||||
|
||||
7
apk/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
.gradle/
|
||||
app/build/
|
||||
app/libs/
|
||||
build/
|
||||
.idea/
|
||||
local.properties
|
||||
.kotlin/
|
||||
73
apk/app/build.gradle.kts
Normal file
@ -0,0 +1,73 @@
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.nekohasekai.sagernet.plugin.naive"
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
storeFile = rootProject.file("release.keystore")
|
||||
storePassword = System.getenv("KEYSTORE_PASS")
|
||||
keyAlias = "release"
|
||||
keyPassword = System.getenv("KEYSTORE_PASS")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
isMinifyEnabled = true
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
}
|
||||
}
|
||||
|
||||
buildToolsVersion = "36.0.0"
|
||||
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
|
||||
applicationId = "io.nekohasekai.sagernet.plugin.naive"
|
||||
versionCode = System.getenv("APK_VERSION_NAME").removePrefix("v").split(".")[0].toInt() * 10 + System.getenv("APK_VERSION_NAME").removePrefix("v").split("-")[1].toInt()
|
||||
versionName = System.getenv("APK_VERSION_NAME").removePrefix("v")
|
||||
splits.abi {
|
||||
isEnable = true
|
||||
isUniversalApk = false
|
||||
reset()
|
||||
include(System.getenv("APK_ABI"))
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
lint {
|
||||
showAll = true
|
||||
checkAllWarnings = true
|
||||
checkReleaseBuilds = false
|
||||
warningsAsErrors = true
|
||||
}
|
||||
|
||||
packaging {
|
||||
jniLibs.useLegacyPackaging = true
|
||||
}
|
||||
|
||||
applicationVariants.all {
|
||||
outputs.all {
|
||||
this as com.android.build.gradle.internal.api.BaseVariantOutputImpl
|
||||
outputFileName =
|
||||
outputFileName.replace(project.name, "naiveproxy-plugin-v$versionName")
|
||||
.replace("-release", "")
|
||||
.replace("-oss", "")
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets.getByName("main") {
|
||||
jniLibs.srcDir("libs")
|
||||
}
|
||||
}
|
||||
45
apk/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="internalOnly"
|
||||
tools:ignore="MissingLeanbackLauncher">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="Naïve Plugin"
|
||||
android:roundIcon="@mipmap/ic_launcher_round">
|
||||
<provider
|
||||
android:name=".BinaryProvider"
|
||||
android:authorities="io.nekohasekai.sagernet.plugin.naive.BinaryProvider"
|
||||
android:directBootAware="true"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedContentProvider">
|
||||
<intent-filter>
|
||||
<action android:name="io.nekohasekai.sagernet.plugin.ACTION_NATIVE_PLUGIN" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="io.nekohasekai.sagernet.plugin.ACTION_NATIVE_PLUGIN" />
|
||||
<data
|
||||
android:host="io.nekohasekai.sagernet"
|
||||
android:path="/naive-plugin"
|
||||
android:scheme="plugin" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="io.nekohasekai.sagernet.plugin.id"
|
||||
android:value="naive-plugin" />
|
||||
<meta-data
|
||||
android:name="io.nekohasekai.sagernet.plugin.executable_path"
|
||||
android:value="libnaive.so" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -0,0 +1,98 @@
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2021 by nekohasekai <contact-sagernet@sekai.icu> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
package io.nekohasekai.sagernet.plugin
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.ParcelFileDescriptor
|
||||
|
||||
abstract class NativePluginProvider : ContentProvider() {
|
||||
override fun getType(uri: Uri): String? = "application/x-elf"
|
||||
|
||||
override fun onCreate(): Boolean = true
|
||||
|
||||
/**
|
||||
* Provide all files needed for native plugin.
|
||||
*
|
||||
* @param provider A helper object to use to add files.
|
||||
*/
|
||||
protected abstract fun populateFiles(provider: PathProvider)
|
||||
|
||||
override fun query(
|
||||
uri: Uri,
|
||||
projection: Array<out String>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?,
|
||||
sortOrder: String?,
|
||||
): Cursor? {
|
||||
check(selection == null && selectionArgs == null && sortOrder == null)
|
||||
val result = MatrixCursor(projection)
|
||||
populateFiles(PathProvider(uri, result))
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns executable entry absolute path.
|
||||
* This is used for fast mode initialization where ss-local launches your native binary at the path given directly.
|
||||
* In order for this to work, plugin app is encouraged to have the following in its AndroidManifest.xml:
|
||||
* - android:installLocation="internalOnly" for <manifest>
|
||||
* - android:extractNativeLibs="true" for <application>
|
||||
*
|
||||
* Default behavior is throwing UnsupportedOperationException. If you don't wish to use this feature, use the
|
||||
* default behavior.
|
||||
*
|
||||
* @return Absolute path for executable entry.
|
||||
*/
|
||||
open fun getExecutable(): String = throw UnsupportedOperationException()
|
||||
|
||||
abstract fun openFile(uri: Uri): ParcelFileDescriptor
|
||||
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor {
|
||||
check(mode == "r")
|
||||
return openFile(uri)
|
||||
}
|
||||
|
||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? = when (method) {
|
||||
PluginContract.METHOD_GET_EXECUTABLE -> {
|
||||
Bundle().apply {
|
||||
putString(PluginContract.EXTRA_ENTRY, getExecutable())
|
||||
}
|
||||
}
|
||||
else -> super.call(method, arg, extras)
|
||||
}
|
||||
|
||||
// Methods that should not be used
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? =
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
override fun update(
|
||||
uri: Uri,
|
||||
values: ContentValues?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<out String>?,
|
||||
): Int =
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int =
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2021 by nekohasekai <contact-sagernet@sekai.icu> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
package io.nekohasekai.sagernet.plugin
|
||||
|
||||
import android.database.MatrixCursor
|
||||
import android.net.Uri
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Helper class to provide relative paths of files to copy.
|
||||
*/
|
||||
class PathProvider internal constructor(baseUri: Uri, private val cursor: MatrixCursor) {
|
||||
private val basePath = baseUri.path?.trim('/') ?: ""
|
||||
|
||||
fun addPath(path: String, mode: Int = 0b110100100): PathProvider {
|
||||
val trimmed = path.trim('/')
|
||||
if (trimmed.startsWith(basePath)) cursor.newRow()
|
||||
.add(PluginContract.COLUMN_PATH, trimmed)
|
||||
.add(PluginContract.COLUMN_MODE, mode)
|
||||
return this
|
||||
}
|
||||
fun addTo(file: File, to: String = "", mode: Int = 0b110100100): PathProvider {
|
||||
var sub = to + file.name
|
||||
if (basePath.startsWith(sub)) if (file.isDirectory) {
|
||||
sub += '/'
|
||||
file.listFiles()!!.forEach { addTo(it, sub, mode) }
|
||||
} else addPath(sub, mode)
|
||||
return this
|
||||
}
|
||||
fun addAt(file: File, at: String = "", mode: Int = 0b110100100): PathProvider {
|
||||
if (basePath.startsWith(at)) {
|
||||
if (file.isDirectory) file.listFiles()!!.forEach { addTo(it, at, mode) } else addPath(at, mode)
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2021 by nekohasekai <contact-sagernet@sekai.icu> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
package io.nekohasekai.sagernet.plugin
|
||||
|
||||
object PluginContract {
|
||||
|
||||
const val ACTION_NATIVE_PLUGIN = "io.nekohasekai.sagernet.plugin.ACTION_NATIVE_PLUGIN"
|
||||
const val EXTRA_ENTRY = "io.nekohasekai.sagernet.plugin.EXTRA_ENTRY"
|
||||
const val METADATA_KEY_ID = "io.nekohasekai.sagernet.plugin.id"
|
||||
const val METADATA_KEY_EXECUTABLE_PATH = "io.nekohasekai.sagernet.plguin.executable_path"
|
||||
const val METHOD_GET_EXECUTABLE = "sagernet:getExecutable"
|
||||
|
||||
const val COLUMN_PATH = "path"
|
||||
const val COLUMN_MODE = "mode"
|
||||
const val SCHEME = "plugin"
|
||||
const val AUTHORITY = "io.nekohasekai.sagernet"
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/******************************************************************************
|
||||
* *
|
||||
* Copyright (C) 2021 by nekohasekai <contact-sagernet@sekai.icu> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
package io.nekohasekai.sagernet.plugin.naive
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.ParcelFileDescriptor
|
||||
import io.nekohasekai.sagernet.plugin.NativePluginProvider
|
||||
import io.nekohasekai.sagernet.plugin.PathProvider
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
class BinaryProvider : NativePluginProvider() {
|
||||
override fun populateFiles(provider: PathProvider) {
|
||||
provider.addPath("naive-plugin", 0b111101101)
|
||||
}
|
||||
|
||||
override fun getExecutable() = context!!.applicationInfo.nativeLibraryDir + "/libnaive.so"
|
||||
override fun openFile(uri: Uri): ParcelFileDescriptor = when (uri.path) {
|
||||
"/naive-plugin" -> ParcelFileDescriptor.open(
|
||||
File(getExecutable()),
|
||||
ParcelFileDescriptor.MODE_READ_ONLY
|
||||
)
|
||||
else -> throw FileNotFoundException()
|
||||
}
|
||||
}
|
||||
25
apk/app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?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"
|
||||
android:tint="#FFFFFF">
|
||||
<group android:scaleX="0.13877095"
|
||||
android:scaleY="0.13877095"
|
||||
android:translateX="29.16"
|
||||
android:translateY="42.010185">
|
||||
<group android:translateY="138.67206">
|
||||
<path android:pathData="M4.171875,-0L34.546875,-0L34.546875,-5.890625L25.90625,-7.046875L23.3125,-9.796875L23.3125,-82.125L78.1875,-0L87.6875,-0L87.6875,-87.328125L90.28125,-89.9375L98.921875,-91.234375L98.921875,-97L68.671875,-97L68.671875,-91.234375L77.3125,-89.9375L79.90625,-87.328125L79.90625,-19.34375L30.8125,-93.390625L30.8125,-97L3.734375,-97L3.734375,-91.234375L12.953125,-90.359375L15.546875,-88.34375L15.546875,-9.796875L12.953125,-7.046875L4.171875,-5.890625L4.171875,-0Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path android:pathData="M151.09375,-8.375L152.95312,0L173.26562,0L173.26562,-5.171875L165.625,-5.90625L163.03125,-8.234375L163.03125,-50.3125C163.03125,-64.796875,156.70312,-71,141.57812,-71C123.4375,-71,112.5,-63.5,112.5,-54.75C112.5,-51.3125,113.640625,-50.3125,116.953125,-50.3125L126.890625,-50.3125L126.890625,-62.359375C130.78125,-63.9375,134.23438,-64.65625,137.84375,-64.65625C148.20312,-64.65625,151.09375,-59.921875,151.09375,-48.578125L151.09375,-44C122.28125,-37.0625,109.046875,-32.6875,109.046875,-17.546875C109.046875,-6.625,116.09375,1,127.46875,1C134.39062,1.015625,142.01562,-2.15625,151.09375,-8.375ZM151.09375,-13.328125C143.89062,-9.09375,137.98438,-6.765625,133.23438,-6.765625C126.03125,-6.765625,121.71875,-11.578125,121.71875,-18.703125C121.71875,-29.34375,130.78125,-33.265625,151.09375,-38.953125L151.09375,-13.328125Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path android:pathData="M197.59375,-70L181.03125,-65L181.03125,-60.53125L191.10938,-60.53125L191.10938,-8.203125L188.65625,-5.90625L181.03125,-5.171875L181.03125,0L213.4375,0L213.4375,-5.171875L205.65625,-5.90625L203.20312,-8.203125L203.20312,-70L197.59375,-70ZM182.76562,-99.53125C178.73438,-99.53125,175.42188,-96.375,175.42188,-92.1875C175.42188,-88.15625,178.73438,-85,182.76562,-85C186.79688,-85,189.95312,-88.15625,189.95312,-92.1875C189.95312,-96.375,186.79688,-99.53125,182.76562,-99.53125ZM209.54688,-99.53125C205.51562,-99.53125,202.20312,-96.375,202.20312,-92.1875C202.20312,-88.15625,205.51562,-85,209.54688,-85C213.57812,-85,216.75,-88.15625,216.75,-92.1875C216.75,-96.375,213.57812,-99.53125,209.54688,-99.53125Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path android:pathData="M215.26562,-69L215.26562,-63.671875L224.0625,-62.796875L247.23438,0L255.29688,0L280.5,-62.515625L289,-63.671875L289,-69L263.51562,-69L263.51562,-63.671875L271.28125,-63.09375L272.4375,-60.796875L254,-13.90625L237.15625,-60.796875L238.89062,-63.09375L246.51562,-63.671875L246.51562,-69L215.26562,-69Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path android:pathData="M351.5,-15.5C343.29688,-10.0625,336.09375,-7.203125,328.89062,-7.203125C314.35938,-7.203125,304.70312,-18.078125,304.70312,-36.421875C304.70312,-36.84375,304.70312,-37.421875,304.70312,-38L351.35938,-38C351.5,-39.578125,351.5,-41.015625,351.5,-42.453125C351.5,-60.296875,341.28125,-71,325.57812,-71C306.28125,-71,292.3125,-56.09375,292.3125,-34.265625C292.3125,-13.21875,305.42188,1,324.4375,1C333.5,1,342.85938,-1.875,351.5,-7.625L351.5,-15.5ZM338.6875,-44.046875L305.42188,-44.046875C306.28125,-56.375,314.5,-64.515625,323.71875,-64.515625C333.35938,-64.515625,338.6875,-58.125,338.6875,-46.359375C338.6875,-45.640625,338.6875,-44.765625,338.6875,-44.046875Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
6
apk/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
apk/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apk/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
apk/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
apk/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
apk/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
apk/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
apk/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
apk/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
apk/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
4
apk/app/src/main/res/values/ic_launcher_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#E91E63</color>
|
||||
</resources>
|
||||
18
apk/build.gradle
Normal file
@ -0,0 +1,18 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.11.0'
|
||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('clean', Delete) {
|
||||
delete rootProject.layout.buildDirectory
|
||||
}
|
||||
21
apk/gradle.properties
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
BIN
apk/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
7
apk/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
251
apk/gradlew
vendored
Executable file
@ -0,0 +1,251 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original 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.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# 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 ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# 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
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
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
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# 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"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
94
apk/gradlew.bat
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
@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
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@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=.
|
||||
@rem This is normally unused
|
||||
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% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 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!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
BIN
apk/release.keystore
Normal file
10
apk/settings.gradle
Normal file
@ -0,0 +1,10 @@
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
rootProject.name = "Naive Plugin"
|
||||
|
||||
include ':app'
|
||||
@ -2165,7 +2165,7 @@ component("base") {
|
||||
"process/set_process_title_linux.h",
|
||||
"system/sys_info_linux.cc",
|
||||
]
|
||||
if (!is_cronet_build) {
|
||||
if (!is_android) {
|
||||
# These dependencies are not required on Android.
|
||||
sources += [
|
||||
"nix/mime_util_xdg.cc",
|
||||
|
||||
118
src/build.sh
Executable file
@ -0,0 +1,118 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
export TMPDIR="$PWD/tmp"
|
||||
rm -rf "$TMPDIR"
|
||||
mkdir -p "$TMPDIR"
|
||||
|
||||
if [ "$1" = debug ]; then
|
||||
out=out/Debug
|
||||
flags="
|
||||
chrome_pgo_phase=0
|
||||
is_debug=true
|
||||
is_component_build=true"
|
||||
else
|
||||
out=out/Release
|
||||
flags="
|
||||
is_official_build=true
|
||||
exclude_unwind_tables=true
|
||||
enable_resource_allowlist_generation=false
|
||||
chrome_pgo_phase=2
|
||||
symbol_level=0"
|
||||
fi
|
||||
|
||||
. ./get-sysroot.sh
|
||||
|
||||
# ccache
|
||||
case "$host_os" in
|
||||
linux|mac)
|
||||
if which ccache >/dev/null 2>&1; then
|
||||
export CCACHE_SLOPPINESS=time_macros
|
||||
export CCACHE_BASEDIR="$PWD"
|
||||
export CCACHE_CPP2=yes
|
||||
CCACHE=ccache
|
||||
fi
|
||||
;;
|
||||
win)
|
||||
if [ -f "$HOME"/.cargo/bin/sccache* ]; then
|
||||
export PATH="$PATH:$HOME/.cargo/bin"
|
||||
CCACHE=sccache
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if [ "$CCACHE" ]; then
|
||||
flags="$flags
|
||||
cc_wrapper=\"$CCACHE\""
|
||||
fi
|
||||
|
||||
flags="$flags"'
|
||||
is_clang=true
|
||||
use_sysroot=false
|
||||
|
||||
fatal_linker_warnings=false
|
||||
treat_warnings_as_errors=false
|
||||
|
||||
is_cronet_build=true
|
||||
|
||||
use_udev=false
|
||||
use_aura=false
|
||||
use_ozone=false
|
||||
use_gio=false
|
||||
use_platform_icu_alternatives=true
|
||||
use_glib=false
|
||||
is_perfetto_embedder=true
|
||||
|
||||
disable_file_support=true
|
||||
enable_websockets=false
|
||||
use_kerberos=false
|
||||
disable_file_support=true
|
||||
disable_zstd_filter=false
|
||||
enable_mdns=false
|
||||
enable_reporting=false
|
||||
include_transport_security_state_preload_list=false
|
||||
enable_device_bound_sessions=false
|
||||
enable_bracketed_proxy_uris=true
|
||||
enable_quic_proxy_support=true
|
||||
enable_disk_cache_sql_backend=false
|
||||
|
||||
use_nss_certs=false
|
||||
|
||||
enable_backup_ref_ptr_support=false
|
||||
enable_dangling_raw_ptr_checks=false
|
||||
'
|
||||
|
||||
if [ "$WITH_SYSROOT" ]; then
|
||||
flags="$flags
|
||||
target_sysroot=\"//$WITH_SYSROOT\""
|
||||
fi
|
||||
|
||||
if [ "$host_os" = "mac" ]; then
|
||||
flags="$flags"'
|
||||
enable_dsyms=false'
|
||||
fi
|
||||
|
||||
case "$EXTRA_FLAGS" in
|
||||
*target_os=\"android\"*)
|
||||
# default_min_sdk_version=24: 26 introduces unnecessary snew symbols
|
||||
# is_high_end_android=true: Does not optimize for size, Uses PGO profiles
|
||||
flags="$flags"'
|
||||
default_min_sdk_version=24
|
||||
is_high_end_android=true'
|
||||
;;
|
||||
esac
|
||||
|
||||
# See https://github.com/llvm/llvm-project/issues/86430
|
||||
if [ "$target_os" = "linux" -a "$target_cpu" = "x64" ]; then
|
||||
flags="$flags"'
|
||||
use_cfi_icall=false'
|
||||
fi
|
||||
|
||||
|
||||
rm -rf "./$out"
|
||||
mkdir -p out
|
||||
|
||||
export DEPOT_TOOLS_WIN_TOOLCHAIN=0
|
||||
|
||||
./gn/out/gn gen "$out" --args="$flags $EXTRA_FLAGS"
|
||||
|
||||
ninja -C "$out" naive
|
||||
19
src/get-android-sys.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
. ./get-sysroot.sh
|
||||
|
||||
if [ "$WITH_ANDROID_IMG" -a ! -d out/sysroot-build/android/"$WITH_ANDROID_IMG"/system ]; then
|
||||
curl -O https://dl.google.com/android/repository/sys-img/android/$WITH_ANDROID_IMG.zip
|
||||
mkdir -p $WITH_ANDROID_IMG/mount
|
||||
unzip $WITH_ANDROID_IMG.zip '*/system.img' -d $WITH_ANDROID_IMG
|
||||
# Need mount -t ext4 -o ro,loop,offset=0x100000 for API level of 26+
|
||||
sudo mount $WITH_ANDROID_IMG/*/system.img $WITH_ANDROID_IMG/mount
|
||||
rootfs=out/sysroot-build/android/$WITH_ANDROID_IMG
|
||||
mkdir -p $rootfs/system/bin $rootfs/system/etc
|
||||
cp $WITH_ANDROID_IMG/mount/bin/linker* $rootfs/system/bin
|
||||
cp $WITH_ANDROID_IMG/mount/etc/hosts $rootfs/system/etc
|
||||
cp -r $WITH_ANDROID_IMG/mount/lib* $rootfs/system
|
||||
sudo umount $WITH_ANDROID_IMG/mount
|
||||
rm -rf $WITH_ANDROID_IMG $WITH_ANDROID_IMG.zip
|
||||
fi
|
||||
117
src/get-clang.sh
Executable file
@ -0,0 +1,117 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
|
||||
. ./get-sysroot.sh
|
||||
|
||||
if [ "$SYSROOT_ARCH" -a ! -d ./"$WITH_SYSROOT/lib" ]; then
|
||||
./build/linux/sysroot_scripts/sysroot_creator.py build "$SYSROOT_ARCH"
|
||||
fi
|
||||
|
||||
if [ "$OPENWRT_FLAGS" ]; then
|
||||
./get-openwrt.sh
|
||||
fi
|
||||
|
||||
# Clang
|
||||
# See src/tools/clang/scripts/update.py
|
||||
case "$host_os" in
|
||||
linux) WITH_CLANG=Linux_x64;;
|
||||
win) WITH_CLANG=Win;;
|
||||
mac) WITH_CLANG=Mac;;
|
||||
esac
|
||||
if [ "$host_os" = mac -a "$host_cpu" = arm64 ]; then
|
||||
WITH_CLANG=Mac_arm64
|
||||
fi
|
||||
mkdir -p third_party/llvm-build/Release+Asserts
|
||||
cd tools/clang/scripts
|
||||
CLANG_REVISION=$($PYTHON -c 'import update; print(update.PACKAGE_VERSION)')
|
||||
cd -
|
||||
echo $CLANG_REVISION >third_party/llvm-build/Release+Asserts/cr_build_revision
|
||||
if [ ! -d third_party/llvm-build/Release+Asserts/bin ]; then
|
||||
mkdir -p third_party/llvm-build/Release+Asserts
|
||||
clang_path="clang-$CLANG_REVISION.tar.xz"
|
||||
clang_url="https://commondatastorage.googleapis.com/chromium-browser-clang/$WITH_CLANG/$clang_path"
|
||||
curl "$clang_url" | tar xJf - -C third_party/llvm-build/Release+Asserts
|
||||
fi
|
||||
|
||||
# sccache
|
||||
if [ "$host_os" = win -a ! -f ~/.cargo/bin/sccache.exe ]; then
|
||||
sccache_url="https://github.com/mozilla/sccache/releases/download/0.2.12/sccache-0.2.12-x86_64-pc-windows-msvc.tar.gz"
|
||||
mkdir -p ~/.cargo/bin
|
||||
curl -L "$sccache_url" | tar xzf - --strip=1 -C ~/.cargo/bin
|
||||
fi
|
||||
|
||||
# GN
|
||||
# See src/DEPS
|
||||
case "$host_os" in
|
||||
linux) WITH_GN=linux-amd64;;
|
||||
win) WITH_GN=windows-amd64;;
|
||||
mac) WITH_GN=mac-amd64;;
|
||||
esac
|
||||
if [ "$host_os" = mac -a "$host_cpu" = arm64 ]; then
|
||||
WITH_GN=mac-arm64
|
||||
fi
|
||||
if [ ! -f gn/out/gn ]; then
|
||||
gn_version=$(grep "'gn_version':" DEPS | cut -d"'" -f4)
|
||||
mkdir -p gn/out
|
||||
curl -L "https://chrome-infra-packages.appspot.com/dl/gn/gn/$WITH_GN/+/$gn_version" -o gn.zip
|
||||
unzip gn.zip -d gn/out
|
||||
rm gn.zip
|
||||
fi
|
||||
|
||||
# See src/build/config/compiler/pgo/BUILD.gn
|
||||
case "$target_os" in
|
||||
win)
|
||||
case "$target_cpu" in
|
||||
arm64) WITH_PGO=win-arm64;;
|
||||
x64) WITH_PGO=win64;;
|
||||
*) WITH_PGO=win32;;
|
||||
esac
|
||||
;;
|
||||
mac)
|
||||
case "$target_cpu" in
|
||||
arm64) WITH_PGO=mac-arm;;
|
||||
*) WITH_PGO=mac;;
|
||||
esac
|
||||
;;
|
||||
linux|openwrt)
|
||||
WITH_PGO=linux
|
||||
;;
|
||||
android)
|
||||
case "$target_cpu" in
|
||||
arm64) WITH_PGO=android-arm64;;
|
||||
*) WITH_PGO=android-arm32;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
if [ "$WITH_PGO" ]; then
|
||||
PGO_PATH=$(cat chrome/build/$WITH_PGO.pgo.txt)
|
||||
fi
|
||||
if [ "$WITH_PGO" -a ! -f chrome/build/pgo_profiles/"$PGO_PATH" ]; then
|
||||
mkdir -p chrome/build/pgo_profiles
|
||||
cd chrome/build/pgo_profiles
|
||||
curl --limit-rate 10M -LO "https://storage.googleapis.com/chromium-optimization-profiles/pgo_profiles/$PGO_PATH"
|
||||
cd ../../..
|
||||
fi
|
||||
|
||||
if [ "$target_os" = android -a ! -d third_party/android_toolchain/ndk ]; then
|
||||
# https://dl.google.com/android/repository/android-ndk-r25c-linux.zip
|
||||
android_ndk_version=$(grep 'default_android_ndk_version = ' build/config/android/config.gni | cut -d'"' -f2)
|
||||
curl -LO https://dl.google.com/android/repository/android-ndk-$android_ndk_version-linux.zip
|
||||
unzip android-ndk-$android_ndk_version-linux.zip
|
||||
mkdir -p third_party/android_toolchain/ndk
|
||||
cd android-ndk-$android_ndk_version
|
||||
cp -r --parents sources/android/cpufeatures ../third_party/android_toolchain/ndk
|
||||
cp -r --parents toolchains/llvm/prebuilt ../third_party/android_toolchain/ndk
|
||||
cd ..
|
||||
cd third_party/android_toolchain/ndk
|
||||
find toolchains -type f -regextype egrep \! -regex \
|
||||
'.*(lib(atomic|gcc|gcc_real|compiler_rt-extras|android_support|unwind).a|crt.*o|lib(android|c|dl|log|m).so|usr/local.*|usr/include.*)' -delete
|
||||
# Works around https://github.com/android/ndk/issues/2082
|
||||
# .../android/hardware_buffer.h:322:42: error: expression is not an integral constant expression
|
||||
# 322 | AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1UL << 32,
|
||||
# .../android/hardware_buffer.h:322:46: note: shift count 32 >= width of type 'unsigned long' (32 bits)
|
||||
# 322 | AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1UL << 32,
|
||||
sed -i 's/AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1UL /AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1ULL /' toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/hardware_buffer.h
|
||||
cd -
|
||||
rm -rf android-ndk-$android_ndk_version android-ndk-$android_ndk_version-linux.zip
|
||||
fi
|
||||
111
src/get-openwrt.sh
Executable file
@ -0,0 +1,111 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
eval "$OPENWRT_FLAGS"
|
||||
|
||||
sysroot=$PWD/out/sysroot-build/openwrt/$release/$arch
|
||||
if [ -d $sysroot/lib ]; then
|
||||
exit 0
|
||||
fi
|
||||
mkdir -p $sysroot
|
||||
|
||||
case "$arch" in
|
||||
arm_*) abi=musl_eabi;;
|
||||
*) abi=musl;;
|
||||
esac
|
||||
|
||||
major=${release%%.*}
|
||||
if [ "$major" -ge 22 ]; then
|
||||
path_suffix=toolchain
|
||||
else
|
||||
path_suffix=sdk
|
||||
fi
|
||||
|
||||
if [ "$major" -ge 24 ]; then
|
||||
tarball_suffix=zst
|
||||
else
|
||||
tarball_suffix=xz
|
||||
fi
|
||||
|
||||
if [ ! "$subtarget" ]; then
|
||||
subtarget=generic
|
||||
fi
|
||||
|
||||
if [ "$subtarget" != generic -o "$major" -ge 22 ]; then
|
||||
SDK_PATH=openwrt-$path_suffix-$release-$target-${subtarget}_gcc-${gcc_ver}_${abi}.Linux-x86_64
|
||||
else
|
||||
SDK_PATH=openwrt-$path_suffix-$release-${target}_gcc-${gcc_ver}_${abi}.Linux-x86_64
|
||||
fi
|
||||
SDK_URL=https://downloads.openwrt.org/releases/$release/targets/$target/$subtarget/$SDK_PATH.tar.$tarball_suffix
|
||||
rm -rf $SDK_PATH
|
||||
if [ $tarball_suffix = xz ]; then
|
||||
curl $SDK_URL | tar xJf -
|
||||
elif [ $tarball_suffix = zst ]; then
|
||||
curl $SDK_URL | tar --zstd -xf -
|
||||
fi
|
||||
|
||||
full_root=toolchain-*_gcc-${gcc_ver}_${abi}
|
||||
|
||||
if [ "$major" -lt 22 ]; then
|
||||
mv $SDK_PATH/staging_dir/$full_root $SDK_PATH
|
||||
fi
|
||||
|
||||
cd $SDK_PATH
|
||||
cat >include.txt <<EOF
|
||||
./include
|
||||
./lib/*.o
|
||||
./lib/gcc/*/libgcc.a
|
||||
./lib/gcc/*/libgcc_eh.a
|
||||
./lib/libatomic.so*
|
||||
./lib/libatomic.a
|
||||
./lib/libc.so
|
||||
./lib/libc.a
|
||||
./lib/libdl.a
|
||||
./lib/ld-*
|
||||
./lib/libgcc_s.*
|
||||
./lib/libm.a
|
||||
./lib/libpthread.a
|
||||
./lib/libresolv.a
|
||||
./lib/librt.a
|
||||
./usr
|
||||
EOF
|
||||
tar cf - -C $full_root --hard-dereference . | tar xf - -C $sysroot --wildcards --wildcards-match-slash -T include.txt
|
||||
rm -rf include.txt
|
||||
cd ..
|
||||
rm -rf $SDK_PATH
|
||||
|
||||
# LLVM does not accept muslgnueabi as the target triple environment
|
||||
if [ -d "$sysroot/lib/gcc/arm-openwrt-linux-muslgnueabi" ]; then
|
||||
mv "$sysroot/lib/gcc/arm-openwrt-linux-muslgnueabi" "$sysroot/lib/gcc/arm-openwrt-linux-musleabi"
|
||||
fi
|
||||
|
||||
if [ "$arch" = "loongarch64" ]; then
|
||||
if grep HWCAP_LOONGARCH_LSX "$sysroot/include/bits/hwcap.h"; then
|
||||
echo "$sysroot/include/bits/hwcap.h" is already populated
|
||||
exit 1
|
||||
fi
|
||||
# https://www.openwall.com/lists/musl/2025/04/03/3
|
||||
cat >"$sysroot/include/bits/hwcap.h" <<EOF
|
||||
/* The following must match the kernel's <asm/hwcap.h>. */
|
||||
/* HWCAP flags */
|
||||
#define HWCAP_LOONGARCH_CPUCFG (1 << 0)
|
||||
#define HWCAP_LOONGARCH_LAM (1 << 1)
|
||||
#define HWCAP_LOONGARCH_UAL (1 << 2)
|
||||
#define HWCAP_LOONGARCH_FPU (1 << 3)
|
||||
#define HWCAP_LOONGARCH_LSX (1 << 4)
|
||||
#define HWCAP_LOONGARCH_LASX (1 << 5)
|
||||
#define HWCAP_LOONGARCH_CRC32 (1 << 6)
|
||||
#define HWCAP_LOONGARCH_COMPLEX (1 << 7)
|
||||
#define HWCAP_LOONGARCH_CRYPTO (1 << 8)
|
||||
#define HWCAP_LOONGARCH_LVZ (1 << 9)
|
||||
#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
|
||||
#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
|
||||
#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
|
||||
#define HWCAP_LOONGARCH_PTW (1 << 13)
|
||||
EOF
|
||||
|
||||
# https://www.openwall.com/lists/musl/2022/03/22/4
|
||||
# But this breaks C++.
|
||||
sed -i 's/extcontext\[\] /extcontext\[0\] /' "$sysroot/include/bits/signal.h"
|
||||
fi
|
||||
72
src/get-sysroot.sh
Normal file
@ -0,0 +1,72 @@
|
||||
eval "$EXTRA_FLAGS"
|
||||
|
||||
case "$(uname)" in
|
||||
MINGW*|MSYS*) host_os=win;;
|
||||
Linux) host_os=linux;;
|
||||
Darwin) host_os=mac;;
|
||||
*) echo "Unsupported host OS" >&2; exit 1;;
|
||||
esac
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64|x64) host_cpu=x64;;
|
||||
x86|i386|i686) host_cpu=x86;;
|
||||
arm) host_cpu=arm;;
|
||||
arm64|aarch64|armv8b|armv8l) host_cpu=arm64;;
|
||||
*) echo "Unsupported host CPU" >&2; exit 1;;
|
||||
esac
|
||||
|
||||
# See src/build/config/BUILDCONFIG.gn
|
||||
if [ ! "$target_os" ]; then
|
||||
target_os="$host_os"
|
||||
fi
|
||||
|
||||
if [ ! "$target_cpu" ]; then
|
||||
target_cpu="$host_cpu"
|
||||
fi
|
||||
|
||||
if which python3 >/dev/null 2>/dev/null; then
|
||||
PYTHON=python3
|
||||
else
|
||||
PYTHON=python
|
||||
fi
|
||||
|
||||
# sysroot
|
||||
case "$target_os" in
|
||||
linux)
|
||||
RELEASE=bullseye
|
||||
case "$target_cpu" in
|
||||
x64) SYSROOT_ARCH=amd64;;
|
||||
x86) SYSROOT_ARCH=i386;;
|
||||
arm64) SYSROOT_ARCH=arm64;;
|
||||
arm) SYSROOT_ARCH=armhf;;
|
||||
mipsel) SYSROOT_ARCH=mipsel;;
|
||||
mips64el) SYSROOT_ARCH=mips64el;;
|
||||
riscv64) SYSROOT_ARCH=riscv64; RELEASE=trixie;;
|
||||
loong64) SYSROOT_ARCH=loong64; RELEASE=sid;;
|
||||
esac
|
||||
if [ "$SYSROOT_ARCH" ]; then
|
||||
WITH_SYSROOT="out/sysroot-build/${RELEASE}/${RELEASE}_${SYSROOT_ARCH}_staging"
|
||||
fi
|
||||
# This is the case where running ./build.sh without EXTRA_FLAGS
|
||||
# wants to avoid downloading sysroots.
|
||||
if [ ! "$EXTRA_FLAGS" -a "$target_cpu" = "$host_cpu" ]; then
|
||||
SYSROOT_ARCH=
|
||||
WITH_SYSROOT=
|
||||
fi
|
||||
;;
|
||||
openwrt)
|
||||
eval "$OPENWRT_FLAGS"
|
||||
WITH_SYSROOT="out/sysroot-build/openwrt/$release/$arch"
|
||||
;;
|
||||
android)
|
||||
WITH_SYSROOT=
|
||||
# https://dl.google.com/android/repository/sys-img/android/sys-img.xml
|
||||
# https://dl.google.com/android/repository/sys-img/google_apis/sys-img.xml
|
||||
case "$target_cpu" in
|
||||
x64) WITH_ANDROID_IMG=x86_64-24_r08;;
|
||||
x86) WITH_ANDROID_IMG=x86-24_r08;;
|
||||
arm64) WITH_ANDROID_IMG=arm64-v8a-24_r07;;
|
||||
arm) WITH_ANDROID_IMG=armeabi-v7a-24_r07;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
@ -14,6 +14,7 @@
|
||||
#include "build/build_config.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/base/load_flags.h"
|
||||
#include "net/base/net_export.h"
|
||||
#include "net/base/proxy_chain.h"
|
||||
#include "net/base/proxy_server.h"
|
||||
#include "net/dns/public/secure_dns_policy.h"
|
||||
@ -228,7 +229,7 @@ base::TimeDelta ClientSocketPoolManager::unused_idle_socket_timeout(
|
||||
return base::Seconds(kPreconnectIntervalSec);
|
||||
}
|
||||
|
||||
int InitSocketHandleForHttpRequest(
|
||||
int NET_EXPORT InitSocketHandleForHttpRequest(
|
||||
url::SchemeHostPort endpoint,
|
||||
int request_load_flags,
|
||||
RequestPriority request_priority,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "base/environment.h"
|
||||
#include "base/strings/escape.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_tokenizer.h"
|
||||
@ -76,17 +77,13 @@ NaiveConfig::~NaiveConfig() = default;
|
||||
|
||||
bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
if (const base::Value* v = value.Find("listen")) {
|
||||
listen.clear();
|
||||
std::vector<std::string> listen_strs;
|
||||
if (const std::string* str = v->GetIfString()) {
|
||||
if (!listen.emplace_back().Parse(*str)) {
|
||||
return false;
|
||||
}
|
||||
listen_strs.push_back(*str);
|
||||
} else if (const base::Value::List* strs = v->GetIfList()) {
|
||||
for (const auto& str_e : *strs) {
|
||||
if (const std::string* s = str_e.GetIfString()) {
|
||||
if (!listen.emplace_back().Parse(*s)) {
|
||||
return false;
|
||||
}
|
||||
listen_strs.push_back(*s);
|
||||
} else {
|
||||
std::cerr << "Invalid listen element" << std::endl;
|
||||
return false;
|
||||
@ -96,6 +93,14 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
std::cerr << "Invalid listen" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!listen_strs.empty()) {
|
||||
listen.clear();
|
||||
}
|
||||
for (const std::string& str : listen_strs) {
|
||||
if (!listen.emplace_back().Parse(str)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (const base::Value* v = value.Find("insecure-concurrency")) {
|
||||
@ -126,8 +131,24 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
}
|
||||
|
||||
if (const base::Value* v = value.Find("proxy")) {
|
||||
std::vector<std::string> proxy_strs;
|
||||
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
|
||||
base::StringTokenizer proxy_uri_list(*str, ",");
|
||||
proxy_strs.push_back(*str);
|
||||
} else if (const base::Value::List* strs = v->GetIfList()) {
|
||||
for (const auto& str_e : *strs) {
|
||||
if (const std::string* s = str_e.GetIfString(); s && !s->empty()) {
|
||||
proxy_strs.push_back(*s);
|
||||
} else {
|
||||
std::cerr << "Invalid proxy element" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Invalid proxy argument" << std::endl;
|
||||
return false;
|
||||
}
|
||||
for (const std::string& str : proxy_strs) {
|
||||
base::StringTokenizer proxy_uri_list(str, ",");
|
||||
std::vector<ProxyServer> proxy_servers;
|
||||
bool seen_tcp = false;
|
||||
while (proxy_uri_list.GetNext()) {
|
||||
@ -187,6 +208,7 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
ProxyChain proxy_chain;
|
||||
if (std::any_of(proxy_servers.begin(), proxy_servers.end(),
|
||||
[](const ProxyServer& s) { return s.is_quic(); })) {
|
||||
proxy_chain = ProxyChain::ForIpProtection(proxy_servers);
|
||||
@ -198,9 +220,7 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
std::cerr << "Invalid proxy chain" << std::endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Invalid proxy argument" << std::endl;
|
||||
return false;
|
||||
proxy_chains.push_back(proxy_chain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,6 +286,39 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
|
||||
no_post_quantum = true;
|
||||
}
|
||||
|
||||
if (const base::Value* v = value.Find("env")) {
|
||||
std::vector<std::string> env_strs;
|
||||
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
|
||||
env_strs.push_back(*str);
|
||||
} else if (const base::Value::List* strs = v->GetIfList()) {
|
||||
for (const auto& str_e : *strs) {
|
||||
if (const std::string* s = str_e.GetIfString(); s && !s->empty()) {
|
||||
env_strs.push_back(*s);
|
||||
} else {
|
||||
std::cerr << "Invalid env element" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Invalid env argument" << std::endl;
|
||||
return false;
|
||||
}
|
||||
auto env = base::Environment::Create();
|
||||
for (const std::string& str : env_strs) {
|
||||
size_t equal_pos = str.find_first_of('=');
|
||||
if (equal_pos != std::string::npos && equal_pos > 0 &&
|
||||
equal_pos + 1 < str.size()) {
|
||||
std::string env_name = str.substr(0, equal_pos);
|
||||
std::string env_value = str.substr(equal_pos + 1);
|
||||
if (!env->SetVar(env_name, env_value)) {
|
||||
std::cerr << "Invalid env element " << str << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Invalid env element " << str << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ struct NaiveConfig {
|
||||
HttpRequestHeaders extra_headers;
|
||||
|
||||
// The last server is assumed to be Naive.
|
||||
ProxyChain proxy_chain = ProxyChain::Direct();
|
||||
std::vector<ProxyChain> proxy_chains;
|
||||
std::set<HostPortPair> origins_to_force_quic_on;
|
||||
std::map<url::SchemeHostPort, AuthCredentials> auth_store;
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "base/at_exit.h"
|
||||
#include "base/check.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/json/json_file_value_serializer.h"
|
||||
@ -172,7 +173,8 @@ std::unique_ptr<URLRequestContext> BuildCertURLRequestContext(NetLog* net_log) {
|
||||
std::unique_ptr<URLRequestContext> BuildURLRequestContext(
|
||||
const NaiveConfig& config,
|
||||
scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher,
|
||||
NetLog* net_log) {
|
||||
NetLog* net_log,
|
||||
int proxy_chain_index = 0) {
|
||||
URLRequestContextBuilder builder;
|
||||
|
||||
builder.DisableHttpCache();
|
||||
@ -212,8 +214,13 @@ std::unique_ptr<URLRequestContext> BuildURLRequestContext(
|
||||
ProxyConfig proxy_config;
|
||||
proxy_config.proxy_rules().type =
|
||||
net::ProxyConfig::ProxyRules::Type::PROXY_LIST;
|
||||
proxy_config.proxy_rules().single_proxies.SetSingleProxyChain(
|
||||
config.proxy_chain);
|
||||
if (config.proxy_chains.empty()) {
|
||||
proxy_config.proxy_rules().single_proxies.SetSingleProxyChain(
|
||||
ProxyChain::Direct());
|
||||
} else {
|
||||
proxy_config.proxy_rules().single_proxies.SetSingleProxyChain(
|
||||
config.proxy_chains.at(proxy_chain_index));
|
||||
}
|
||||
LOG(INFO) << "Proxying via "
|
||||
<< proxy_config.proxy_rules().single_proxies.ToDebugString();
|
||||
auto proxy_service =
|
||||
@ -456,14 +463,20 @@ int main(int argc, char* argv[]) {
|
||||
cert_net_fetcher = base::MakeRefCounted<net::CertNetFetcherURLRequest>();
|
||||
cert_net_fetcher->SetURLRequestContext(cert_context.get());
|
||||
#endif
|
||||
auto context =
|
||||
net::BuildURLRequestContext(config, std::move(cert_net_fetcher), net_log);
|
||||
auto* session = context->http_transaction_factory()->GetSession();
|
||||
|
||||
if (config.proxy_chains.size() >= 2 &&
|
||||
config.proxy_chains.size() != config.listen.size()) {
|
||||
std::cerr << "Listen addresses do not match multiple proxy chains"
|
||||
<< std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<net::NaiveProxy>> naive_proxies;
|
||||
std::vector<std::unique_ptr<net::URLRequestContext>> contexts;
|
||||
std::unique_ptr<net::RedirectResolver> resolver;
|
||||
|
||||
for (const net::NaiveListenConfig& listen_config : config.listen) {
|
||||
for (size_t listen_i = 0; listen_i < config.listen.size(); ++listen_i) {
|
||||
const net::NaiveListenConfig& listen_config = config.listen[listen_i];
|
||||
auto listen_socket =
|
||||
std::make_unique<net::TCPServerSocket>(net_log, net::NetLogSource());
|
||||
|
||||
@ -503,6 +516,15 @@ int main(int argc, char* argv[]) {
|
||||
config.resolver_prefix);
|
||||
}
|
||||
|
||||
if (config.proxy_chains.size() >= 2) {
|
||||
contexts.push_back(net::BuildURLRequestContext(
|
||||
config, std::move(cert_net_fetcher), net_log, listen_i));
|
||||
} else if (contexts.empty()) {
|
||||
contexts.push_back(net::BuildURLRequestContext(
|
||||
config, std::move(cert_net_fetcher), net_log));
|
||||
}
|
||||
auto& context = contexts.back();
|
||||
auto* session = context->http_transaction_factory()->GetSession();
|
||||
auto naive_proxy = std::make_unique<net::NaiveProxy>(
|
||||
std::move(listen_socket), listen_config.protocol, listen_config.user,
|
||||
listen_config.pass, config.insecure_concurrency, resolver.get(),
|
||||
@ -512,6 +534,9 @@ int main(int argc, char* argv[]) {
|
||||
naive_proxies.push_back(std::move(naive_proxy));
|
||||
}
|
||||
|
||||
if (base::Environment::Create()->HasVar("TEST_MARK_STARTUP")) {
|
||||
LOG(INFO) << "TEST_MARK_STARTUP";
|
||||
}
|
||||
base::RunLoop().Run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@ -105,12 +105,6 @@ def _get_profile_path(args):
|
||||
"""
|
||||
if args.override_filename:
|
||||
profile_path = os.path.join(_PGO_PROFILE_DIR, args.override_filename)
|
||||
elif args.target == 'android-arm64':
|
||||
# By default on android for arm64 we use the PGO profile that is generated
|
||||
# at the same commit as the orderfile. See https://crbug.com/372686816 for
|
||||
# more context on why this is necessary.
|
||||
profile_path = os.path.join(_ANDROID_ARM64_PROFILE_DIR,
|
||||
'pgo_profile.arm64.profdata')
|
||||
else:
|
||||
profile_path = os.path.join(_PGO_PROFILE_DIR,
|
||||
_read_profile_name(args.target))
|
||||
|
||||
332
tests/basic.py
Normal file
@ -0,0 +1,332 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import http.server
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import ssl
|
||||
import subprocess
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--naive', required=True)
|
||||
parser.add_argument('--rootfs')
|
||||
parser.add_argument('--target_cpu')
|
||||
parser.add_argument('--server_protocol',
|
||||
choices=['http', 'https'], default='https')
|
||||
argv = parser.parse_args()
|
||||
|
||||
if argv.rootfs:
|
||||
try:
|
||||
os.remove(os.path.join(argv.rootfs, 'naive'))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
server_protocol = argv.server_protocol
|
||||
|
||||
_, certfile = tempfile.mkstemp()
|
||||
|
||||
result = subprocess.run(
|
||||
f'openssl req -new -x509 -keyout {certfile} -out {certfile} -days 1 -nodes -subj /C=XX'.split(), capture_output=True)
|
||||
result.check_returncode()
|
||||
|
||||
HTTPS_SERVER_HOSTNAME = '127.0.0.1'
|
||||
HTTP_SERVER_PORT = 60443 if server_protocol == 'https' else 60080
|
||||
|
||||
httpd = http.server.HTTPServer(
|
||||
(HTTPS_SERVER_HOSTNAME, HTTP_SERVER_PORT), http.server.SimpleHTTPRequestHandler)
|
||||
httpd.timeout = 1
|
||||
httpd.allow_reuse_address = True
|
||||
if server_protocol == 'https':
|
||||
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
ssl_context.load_cert_chain(certfile=certfile)
|
||||
httpd.socket = ssl_context.wrap_socket(httpd.socket, server_side=True)
|
||||
|
||||
httpd_thread = threading.Thread(
|
||||
target=lambda httpd: httpd.serve_forever(), args=(httpd,), daemon=True)
|
||||
httpd_thread.start()
|
||||
|
||||
|
||||
def test_https_server(hostname, port, proxy=None):
|
||||
url = f'{server_protocol}://{hostname}:{port}/404'
|
||||
cmdline = ['curl', '-k', '-s']
|
||||
if proxy:
|
||||
cmdline.extend(['--proxy', proxy])
|
||||
cmdline.append(url)
|
||||
print('subprocess.run', ' '.join(cmdline))
|
||||
result = subprocess.run(cmdline, capture_output=True,
|
||||
timeout=10, text=True, encoding='utf-8')
|
||||
print(result.stderr, end='')
|
||||
return 'Error code: 404' in result.stdout
|
||||
|
||||
|
||||
assert test_https_server(HTTPS_SERVER_HOSTNAME,
|
||||
HTTP_SERVER_PORT), 'https server not up'
|
||||
|
||||
|
||||
def start_naive(naive_args, config_file):
|
||||
with_qemu = None
|
||||
if argv.target_cpu == 'arm64':
|
||||
with_qemu = 'aarch64'
|
||||
elif argv.target_cpu == 'arm':
|
||||
with_qemu = 'arm'
|
||||
elif argv.target_cpu == 'mipsel':
|
||||
with_qemu = 'mipsel'
|
||||
elif argv.target_cpu == 'mips64el':
|
||||
with_qemu = 'mips64el'
|
||||
elif argv.target_cpu == 'riscv64':
|
||||
with_qemu = 'riscv64'
|
||||
elif argv.target_cpu == 'loong64':
|
||||
with_qemu = 'loong64'
|
||||
|
||||
if argv.rootfs:
|
||||
if not with_qemu:
|
||||
if not os.path.exists(os.path.join(argv.rootfs, 'naive')):
|
||||
shutil.copy2(argv.naive, argv.rootfs)
|
||||
# bwrap isolates filesystem, config_file needs a copy inside.
|
||||
if config_file is not None:
|
||||
shutil.copy2(config_file, argv.rootfs)
|
||||
cmdline = ['bwrap', '--die-with-parent', '--bind', argv.rootfs, '/',
|
||||
'--proc', '/proc', '--dev', '/dev', '--chdir', '/', '/naive']
|
||||
else:
|
||||
cmdline = [f'qemu-{with_qemu}',
|
||||
'-L', argv.rootfs, argv.naive]
|
||||
else:
|
||||
cmdline = [argv.naive]
|
||||
cmdline.extend(naive_args)
|
||||
|
||||
env = os.environ.copy()
|
||||
env["TEST_MARK_STARTUP"] = "yes"
|
||||
proc = subprocess.Popen(cmdline, stdout=subprocess.DEVNULL, env=env,
|
||||
stderr=subprocess.PIPE, text=True, encoding='utf-8')
|
||||
print('subprocess.Popen', ' '.join(cmdline), 'pid:', proc.pid)
|
||||
|
||||
def terminate(proc):
|
||||
print('proc has timed out')
|
||||
print('terminate pid', proc.pid)
|
||||
proc.terminate()
|
||||
|
||||
# Some qemu-user tests take a while to start.
|
||||
# See https://gitlab.com/qemu-project/qemu/-/issues/1729
|
||||
timeout = threading.Timer(20, terminate, args=(proc,))
|
||||
timeout.start()
|
||||
while True:
|
||||
if proc.poll() is not None:
|
||||
timeout.cancel()
|
||||
return proc.poll() == 0
|
||||
|
||||
line = proc.stderr.readline().strip()
|
||||
print(line)
|
||||
if 'Failed to listen' in line:
|
||||
timeout.cancel()
|
||||
print('terminate pid', proc.pid)
|
||||
proc.terminate()
|
||||
return 'Failed to listen'
|
||||
elif 'TEST_MARK_STARTUP' in line:
|
||||
timeout.cancel()
|
||||
return proc
|
||||
|
||||
|
||||
port = 10000
|
||||
|
||||
|
||||
def allocate_port_number():
|
||||
global port
|
||||
port += 1
|
||||
if port > 60000:
|
||||
port = 10000
|
||||
return port
|
||||
|
||||
|
||||
def test_naive_once(proxy, *args, **kwargs):
|
||||
port_map = {}
|
||||
|
||||
class PortDict(dict):
|
||||
def __init__(self, port_map):
|
||||
self._port_map = port_map
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key.startswith('PORT'):
|
||||
if key not in self._port_map:
|
||||
self._port_map[key] = str(allocate_port_number())
|
||||
return self._port_map[key]
|
||||
return key
|
||||
port_dict = PortDict(port_map)
|
||||
|
||||
proxy = proxy.format_map(port_dict)
|
||||
|
||||
config_file = kwargs.get('config_file')
|
||||
config_content = kwargs.get('config_content')
|
||||
if config_content is not None:
|
||||
config_content = config_content.format_map(port_dict)
|
||||
print(f"Writing {repr(config_content)} to {config_file}")
|
||||
with open(config_file, 'w') as f:
|
||||
f.write('{')
|
||||
f.write(config_content)
|
||||
f.write('}')
|
||||
|
||||
naive_procs = []
|
||||
|
||||
def cleanup():
|
||||
if config_file is not None:
|
||||
os.remove(config_file)
|
||||
for naive_proc in naive_procs:
|
||||
print('terminate pid', naive_proc.pid)
|
||||
naive_proc.terminate()
|
||||
|
||||
for args_instance in args:
|
||||
naive_args = args_instance.format_map(port_dict).split()
|
||||
naive_proc = start_naive(naive_args, config_file)
|
||||
if naive_proc == 'Failed to listen':
|
||||
cleanup()
|
||||
return 'Failed to listen'
|
||||
if not naive_proc:
|
||||
cleanup()
|
||||
return False
|
||||
naive_procs.append(naive_proc)
|
||||
|
||||
result = test_https_server(HTTPS_SERVER_HOSTNAME, HTTP_SERVER_PORT, proxy)
|
||||
|
||||
cleanup()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def test_naive(label, proxy, *args, **kwargs):
|
||||
RETRIES = 5
|
||||
result = None
|
||||
if argv.target_cpu == 'arm' and not label.startswith('Default'):
|
||||
# Arm tests are too slow in qemu-user
|
||||
# due to https://www.openwall.com/lists/musl/2017/06/15/9
|
||||
print('** SKIP TEST:', label, end='\n\n')
|
||||
return
|
||||
|
||||
for i in range(RETRIES):
|
||||
result = test_naive_once(proxy, *args, **kwargs)
|
||||
if result == 'Failed to listen':
|
||||
result = False
|
||||
print('Retrying...')
|
||||
time.sleep(1)
|
||||
continue
|
||||
break
|
||||
if result is True:
|
||||
print('** TEST PASS:', label, end='\n\n')
|
||||
else:
|
||||
print('** TEST FAIL:', label, end='\n\n')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
test_naive('Default config', 'socks5h://127.0.0.1:1080',
|
||||
'--log')
|
||||
|
||||
test_naive('Default config file', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'',
|
||||
config_content='"listen":"socks://127.0.0.1:{PORT1}","log":""',
|
||||
config_file='config.json')
|
||||
|
||||
test_naive('Custom config file', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'custom.json',
|
||||
config_content='"listen":"socks://127.0.0.1:{PORT1}","log":""',
|
||||
config_file='custom.json')
|
||||
|
||||
test_naive('Multiple listens - command line', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --listen=http://:{PORT2}')
|
||||
|
||||
test_naive('Multiple listens - command line', 'http://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT1} --listen=http://:{PORT2}')
|
||||
|
||||
test_naive('Multiple listens - config file', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'multiple-listen.json',
|
||||
config_content='"listen":["socks://:{PORT1}", "http://:{PORT2}"],"log":""',
|
||||
config_file='multiple-listen.json')
|
||||
|
||||
test_naive('Multiple listens - config file', 'http://127.0.0.1:{PORT2}',
|
||||
'multiple-listen.json',
|
||||
config_content='"listen":["socks://:{PORT1}", "http://:{PORT2}"],"log":""',
|
||||
config_file='multiple-listen.json')
|
||||
|
||||
test_naive('Multiple proxies - command line', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --listen=socks://:{PORT2} --proxy=http://127.0.0.1:{PORT3} --proxy=http://127.0.0.1:{PORT4}',
|
||||
'--log --listen=http://:{PORT3} --listen=http://:{PORT4} --proxy=socks://127.0.0.1:{PORT5}',
|
||||
'--log --listen=socks://:{PORT5}')
|
||||
|
||||
test_naive('Multiple proxies - command line', 'socks5h://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT1} --listen=socks://:{PORT2} --proxy=http://127.0.0.1:{PORT3} --proxy=http://127.0.0.1:{PORT4}',
|
||||
'--log --listen=http://:{PORT3} --listen=http://:{PORT4} --proxy=socks://127.0.0.1:{PORT5}',
|
||||
'--log --listen=socks://:{PORT5}')
|
||||
|
||||
test_naive('Trivial - listen scheme only', 'socks5h://127.0.0.1:1080',
|
||||
'--log --listen=socks://')
|
||||
|
||||
test_naive('Trivial - listen no host', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1}')
|
||||
|
||||
test_naive('Trivial - listen no port', 'socks5h://127.0.0.1:1080',
|
||||
'--log --listen=socks://127.0.0.1')
|
||||
|
||||
test_naive('Trivial - auth', 'socks5h://user:pass@127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://user:pass@127.0.0.1:{PORT1}')
|
||||
|
||||
test_naive('Trivial - auth with special chars', 'socks5h://user:^@127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://user:^@127.0.0.1:{PORT1}')
|
||||
|
||||
test_naive('Trivial - auth with special chars', 'socks5h://^:^@127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://^:^@127.0.0.1:{PORT1}')
|
||||
|
||||
test_naive('Trivial - auth with empty pass', 'socks5h://user:@127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://user:@127.0.0.1:{PORT1}')
|
||||
|
||||
test_naive('SOCKS-SOCKS', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --proxy=socks://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT2}')
|
||||
|
||||
test_naive('SOCKS-SOCKS - proxy no port', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --proxy=socks://127.0.0.1',
|
||||
'--log --listen=socks://:1080')
|
||||
|
||||
test_naive('SOCKS-HTTP', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --proxy=http://127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://:{PORT2}')
|
||||
|
||||
test_naive('HTTP-HTTP', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT1} --proxy=http://127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://:{PORT2}')
|
||||
|
||||
test_naive('HTTP-SOCKS', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT1} --proxy=socks://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT2}')
|
||||
|
||||
test_naive('SOCKS-SOCKS-SOCKS', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --proxy=socks://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT2} --proxy=socks://127.0.0.1:{PORT3}',
|
||||
'--log --listen=socks://:{PORT3}')
|
||||
|
||||
test_naive('SOCKS-HTTP-SOCKS', 'socks5h://127.0.0.1:{PORT1}',
|
||||
'--log --listen=socks://:{PORT1} --proxy=http://127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://:{PORT2} --proxy=socks://127.0.0.1:{PORT3}',
|
||||
'--log --listen=socks://:{PORT3}')
|
||||
|
||||
test_naive('HTTP-SOCKS-HTTP', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT1} --proxy=socks://127.0.0.1:{PORT2}',
|
||||
'--log --listen=socks://:{PORT2} --proxy=http://127.0.0.1:{PORT3}',
|
||||
'--log --listen=http://:{PORT3}')
|
||||
|
||||
test_naive('HTTP-HTTP-HTTP', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT1} --proxy=http://127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://:{PORT2} --proxy=http://127.0.0.1:{PORT3}',
|
||||
'--log --listen=http://:{PORT3}')
|
||||
|
||||
test_naive('HTTP-HTTP (with auth)', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT1} --proxy=http://hello:world@127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://hello:world@127.0.0.1:{PORT2}')
|
||||
|
||||
test_naive('HTTPa-HTTPb,HTTPc (chaining with remote loop)', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://:{PORT2}',
|
||||
'--log --listen=http://:{PORT1} --proxy=http://127.0.0.1:{PORT2},http://127.0.0.1:{PORT2}')
|
||||
|
||||
test_naive('HTTPa-HTTPb,HTTPc (chaining with multiple auth)', 'http://127.0.0.1:{PORT1}',
|
||||
'--log --listen=http://hello:world2@127.0.0.1:{PORT2}',
|
||||
'--log --listen=http://hello:world3@127.0.0.1:{PORT3}',
|
||||
'--log --listen=http://127.0.0.1:{PORT1} --proxy=http://hello:world2@127.0.0.1:{PORT2},http://hello:world3@127.0.0.1:{PORT3}')
|
||||
20
tests/basic.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
script_dir=$(dirname "$PWD/$0")
|
||||
|
||||
[ "$1" ] || exit 1
|
||||
naive="$PWD/$1"
|
||||
|
||||
. ./get-sysroot.sh
|
||||
|
||||
if [ "$WITH_ANDROID_IMG" ]; then
|
||||
rootfs="$PWD/out/sysroot-build/android/$WITH_ANDROID_IMG"
|
||||
elif [ "$WITH_SYSROOT" ]; then
|
||||
rootfs="$PWD/$WITH_SYSROOT"
|
||||
fi
|
||||
|
||||
cd /tmp
|
||||
python3 "$script_dir"/basic.py --naive="$naive" --rootfs="$rootfs" --target_cpu="$target_cpu" --server_protocol=https
|
||||
python3 "$script_dir"/basic.py --naive="$naive" --rootfs="$rootfs" --target_cpu="$target_cpu" --server_protocol=http
|
||||
95
tests/qemu-howto.md
Normal file
@ -0,0 +1,95 @@
|
||||
# Debug ARM Cortex-A9 static in QEMU
|
||||
|
||||
```
|
||||
export EXTRA_FLAGS='target_cpu="arm" target_os="openwrt" arm_version=0 arm_cpu="cortex-a9" arm_float_abi="soft" arm_use_neon=false build_static=true no_madvise_syscall=true'
|
||||
export OPENWRT_FLAGS='arch=arm_cortex-a9-static release=23.05.0 gcc_ver=12.3.0 target=bcm53xx subtarget=generic'
|
||||
./get-clang.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
See https://wiki.qemu.org/Documentation/Networking for example.
|
||||
|
||||
```
|
||||
$ wget https://downloads.openwrt.org/releases/23.05.2/targets/armsr/armv7/openwrt-23.05.2-armsr-armv7-generic-initramfs-kernel.bin
|
||||
|
||||
$ qemu-system-arm -nographic -M virt -m 1024 -kernel openwrt-23.05.2-armsr-armv7-generic-initramfs-kernel.bin -device virtio-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::5555-:1080
|
||||
...
|
||||
|
||||
root@OpenWrt:/# ip link del br-lan
|
||||
root@OpenWrt:/# ip addr add 10.0.2.15/24 dev eth0
|
||||
root@OpenWrt:/# ip route add default via 10.0.2.2
|
||||
root@OpenWrt:/# nft flush ruleset
|
||||
root@OpenWrt:/# echo nameserver 10.0.2.3 >/etc/resolv.conf
|
||||
root@OpenWrt:/# scp user@10.0.2.2:/tmp/naive .
|
||||
root@OpenWrt:/# ./naive --listen=socks://0.0.0.0:1080 --proxy=https://user:pass@example.com --log
|
||||
|
||||
user@host:/tmp$ curl -v --proxy socks5h://127.0.0.1:5555 example.com
|
||||
```
|
||||
|
||||
Install GDB
|
||||
```
|
||||
root@OpenWrt:/# sed -i -e "s/https/http/" /etc/opkg/distfeeds.conf
|
||||
root@OpenWrt:/# echo option http_proxy http://10.0.2.2:8080/ >>/etc/opkg.conf
|
||||
root@OpenWrt:/# opkg update
|
||||
root@OpenWrt:/# opkg install gdb
|
||||
```
|
||||
|
||||
# Debug ARM64 static in QEMU
|
||||
|
||||
```
|
||||
export EXTRA_FLAGS='target_cpu="arm64" target_os="openwrt" arm_cpu="cortex-a53" build_static=true no_madvise_syscall=true'
|
||||
export OPENWRT_FLAGS='arch=aarch64_cortex-a53-static release=23.05.0 gcc_ver=12.3.0 target=sunxi subtarget=cortexa53'
|
||||
./get-clang.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
```
|
||||
$ wget https://downloads.openwrt.org/releases/23.05.2/targets/armsr/armv8/openwrt-23.05.2-armsr-armv8-generic-initramfs-kernel.bin
|
||||
|
||||
$ qemu-system-aarch64 -m 1024 -M virt -cpu cortex-a53 -nographic -kernel openwrt-23.05.2-armsr-armv8-generic-initramfs-kernel.bin -device virtio-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::5555-:1080
|
||||
...
|
||||
|
||||
root@OpenWrt:/# ip link del br-lan
|
||||
root@OpenWrt:/# ip addr add 10.0.2.15/24 dev eth0
|
||||
root@OpenWrt:/# ip route add default via 10.0.2.2
|
||||
root@OpenWrt:/# nft flush ruleset
|
||||
root@OpenWrt:/# echo nameserver 10.0.2.3 >/etc/resolv.conf
|
||||
root@OpenWrt:/# scp user@10.0.2.2:/tmp/naive .
|
||||
root@OpenWrt:/# ./naive --listen=socks://0.0.0.0:1080 --proxy=https://user:pass@example.com --log
|
||||
user@host:/tmp$ curl -v --proxy socks5h://127.0.0.1:5555 example.com
|
||||
```
|
||||
|
||||
# Debug MIPSEL static in QEMU
|
||||
|
||||
```
|
||||
export EXTRA_FLAGS='target_cpu="mipsel" target_os="openwrt" mips_arch_variant="r2" mips_float_abi="soft" build_static=true no_madvise_syscall=true'
|
||||
export OPENWRT_FLAGS='arch=mipsel_24kc-static release=23.05.0 gcc_ver=12.3.0 target=ramips subtarget=rt305x'
|
||||
./get-clang.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
```
|
||||
$ wget https://downloads.openwrt.org/snapshots/targets/malta/le/lede-malta-le-vmlinux-initramfs.elf
|
||||
|
||||
$ qemu-system-mipsel -nographic -M malta -kernel lede-malta-le-vmlinux-initramfs.elf -m 64 -device pcnet,netdev=net0 -netdev user,id=net0,hostfwd=tcp::5555-:1080
|
||||
...
|
||||
(eth0 is set up by DHCP)
|
||||
|
||||
root@LEDE:/# iptables -F
|
||||
(scp is too old)
|
||||
user@host:/tmp$ nc -l -p 2222 <./naive
|
||||
root@LEDE:/# nc 10.0.2.2 2222 >naive
|
||||
^C
|
||||
root@LEDE:/# chmod +x ./naive
|
||||
user@host:/tmp$ nc -l -p2222 </etc/ssl/certs/ca-certificates.crt
|
||||
root@LEDE:/# mkdir -p /etc/ssl/certs/
|
||||
root@LEDE:/# nc 10.0.2.2 2222 >/etc/ssl/certs/ca-certificates.crt
|
||||
^C
|
||||
root@LEDE:/# ./naive --listen=socks://0.0.0.0:1080 --proxy=https://user:pass@example.com --log
|
||||
user@host:/tmp$ curl -v --proxy socks5h://127.0.0.1:5555 example.com
|
||||
```
|
||||
|
||||
## To exit QEMU in -nographic:
|
||||
|
||||
Press Ctrl-A
|
||||
Press X
|
||||