1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-05-03 12:19:26 +03:00

Compare commits

..

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] c7d906c01c Update README.md to reference Windows ARM64 build guide
Co-authored-by: chipitsine <2217296+chipitsine@users.noreply.github.com>
2026-02-04 16:40:48 +00:00
copilot-swe-agent[bot] 66119d1303 Add Windows ARM64 build and installation documentation
Co-authored-by: chipitsine <2217296+chipitsine@users.noreply.github.com>
2026-02-04 16:40:11 +00:00
copilot-swe-agent[bot] 486b9ed7c5 Initial plan 2026-02-04 16:37:45 +00:00
31 changed files with 711 additions and 1041 deletions
+1 -2
View File
@@ -4,7 +4,6 @@ name: Coverity
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
permissions:
contents: read
@@ -12,7 +11,7 @@ permissions:
jobs:
scan:
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'SoftEtherVPN' || github.event_name == 'workflow_dispatch' }}
if: ${{ github.repository_owner == 'SoftEtherVPN' }}
steps:
- uses: actions/checkout@v2
with:
-80
View File
@@ -1,80 +0,0 @@
name: Sanitizer
on: [push, pull_request]
permissions:
contents: read
jobs:
run_sanitizer:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sanitizer:
- "address,leak,undefined"
- "thread,undefined"
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt update
sudo apt-get -y install cmake gcc g++ ninja-build libncurses5-dev libreadline-dev libsodium-dev libssl-dev make zlib1g-dev liblz4-dev libnl-genl-3-dev
- name: Build
run: |
mkdir build
cd build
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-O1 -fsanitize=${{ matrix.sanitizer }} -fno-omit-frame-pointer" ..
cmake --build .
- name: Test
env:
ASAN_OPTIONS: halt_on_error=0:exitcode=0
TSAN_OPTIONS: halt_on_error=0:exitcode=0:suppressions=./tsan_suppressions.txt
UBSAN_OPTIONS: halt_on_error=0:exitcode=0
LSAN_OPTIONS: exitcode=0
run: |
.ci/vpntools-check.sh 2> sanitizer.log
- name: Make job summary
run: |
echo "### Sanitizer Report (${{ matrix.sanitizer }})" >> $GITHUB_STEP_SUMMARY
REPORTS=$(grep -E "SUMMARY:|runtime error:" sanitizer.log | sort | uniq)
REPORT_COUNT=$(echo "$REPORTS" | grep -c . || true)
echo "Found $REPORT_COUNT issues" >> $GITHUB_STEP_SUMMARY
echo "<details><summary>View Summary</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "$REPORTS" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
if [ "$REPORT_COUNT" -ne 0 ]; then
echo "HAS_ISSUES=true" >> $GITHUB_ENV
echo "REPORT_COUNT=$REPORT_COUNT" >> $GITHUB_ENV
fi
- name: Upload full sanitizer log
if: env.HAS_ISSUES == 'true'
uses: actions/upload-artifact@v4
with:
name: sanitizer-logs-${{ matrix.sanitizer }}
path: |
sanitizer.log
retention-days: 30
- name: Fail on sanitizer issues
if: env.HAS_ISSUES == 'true'
run: |
echo "Found ${{ env.REPORT_COUNT }} issues."
echo "Please check the Job Summary page for a quick overview."
echo "Full logs are available in the GitHub Artifacts."
exit 1
+4 -6
View File
@@ -8,11 +8,10 @@ jobs:
strategy:
matrix:
platform: [
{ ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat", RUNNER: "windows-latest", CMAKE_EXTRA_FLAGS: ""},
{ ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat", RUNNER: "windows-latest", CMAKE_EXTRA_FLAGS: ""},
{ ARCHITECTURE: arm64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/ARM64/bin/clang-cl.exe", VCPKG_TRIPLET: "arm64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsarm64.bat", RUNNER: "windows-11-arm", CMAKE_EXTRA_FLAGS: "-DOQS_PERMIT_UNSUPPORTED_ARCHITECTURE=ON"}
{ ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat"},
{ ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"}
]
runs-on: ${{ matrix.platform.RUNNER }}
runs-on: windows-latest
name: ${{ matrix.platform.ARCHITECTURE }}
steps:
- uses: actions/checkout@v4
@@ -34,13 +33,12 @@ jobs:
COMPILER_PATH: ${{ matrix.platform.COMPILER_PATH }}
VCPKG_TRIPLET: ${{ matrix.platform.VCPKG_TRIPLET }}
VCVARS_PATH: ${{ matrix.platform.VCVARS_PATH }}
CMAKE_EXTRA_FLAGS: ${{ matrix.platform.CMAKE_EXTRA_FLAGS }}
run: |
set BUILD_NUMBER=0
mkdir build
cd build
call "%VCVARS_PATH%"
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% %CMAKE_EXTRA_FLAGS% ..
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% ..
cmake --build .
mkdir installers
vpnsetup /SFXMODE:vpnclient /SFXOUT:"installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe"
+4 -6
View File
@@ -26,14 +26,13 @@ jobs:
uses: softprops/action-gh-release@v1
build-windows:
name: ${{ matrix.platform.ARCHITECTURE }}
runs-on: ${{ matrix.platform.RUNNER }}
runs-on: windows-latest
needs: ["release"]
strategy:
matrix:
platform: [
{ ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat", RUNNER: "windows-latest", CMAKE_EXTRA_FLAGS: ""},
{ ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat", RUNNER: "windows-latest", CMAKE_EXTRA_FLAGS: ""},
{ ARCHITECTURE: arm64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/ARM64/bin/clang-cl.exe", VCPKG_TRIPLET: "arm64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsarm64.bat", RUNNER: "windows-11-arm", CMAKE_EXTRA_FLAGS: "-DOQS_PERMIT_UNSUPPORTED_ARCHITECTURE=ON"}
{ ARCHITECTURE: x86, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/bin/clang-cl.exe", VCPKG_TRIPLET: "x86-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars32.bat"},
{ ARCHITECTURE: x64, COMPILER_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/Llvm/x64/bin/clang-cl.exe", VCPKG_TRIPLET: "x64-windows-static", VCVARS_PATH: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat"}
]
steps:
- name: "Checkout repository"
@@ -58,12 +57,11 @@ jobs:
COMPILER_PATH: ${{ matrix.platform.COMPILER_PATH }}
VCPKG_TRIPLET: ${{ matrix.platform.VCPKG_TRIPLET }}
VCVARS_PATH: ${{ matrix.platform.VCVARS_PATH }}
CMAKE_EXTRA_FLAGS: ${{ matrix.platform.CMAKE_EXTRA_FLAGS }}
run: |
mkdir build
cd build
call "%VCVARS_PATH%"
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% %CMAKE_EXTRA_FLAGS% ..
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER="%COMPILER_PATH%" -DCMAKE_CXX_COMPILER="%COMPILER_PATH%" -DBUILD_NUMBER=%BUILD_NUMBER% ..
cmake --build .
mkdir installers
vpnsetup /SFXMODE:vpnclient /SFXOUT:"installers\softether-vpnclient-%VERSION%.%BUILD_NUMBER%.%ARCHITECTURE%.exe"
+1 -1
View File
@@ -220,7 +220,7 @@ Please look at the [ContainerREADME.md](ContainerREADME.md)
## Build from Source code
see [BUILD_UNIX](src/BUILD_UNIX.md) or [BUILD_WINDOWS](src/BUILD_WINDOWS.md)
see [BUILD_UNIX](src/BUILD_UNIX.md), [BUILD_WINDOWS](src/BUILD_WINDOWS.md), or [BUILD_WINDOWS_ARM64](src/BUILD_WINDOWS_ARM64.md)
There are two flavours of SoftEtherVPN source code:
@@ -1,552 +1,430 @@
{
"name": "vpnrpc",
"version": "1.0.1",
"lockfileVersion": 3,
"lockfileVersion": 1,
"requires": true,
"packages": {
"": {
"version": "1.0.1",
"license": "Apache-2.0",
"devDependencies": {
"@types/node": "^12.0.2",
"ts-loader": "^9.4.2",
"tslint": "^5.16.0",
"typescript": "^3.4.5"
}
},
"node_modules/@babel/code-frame": {
"dependencies": {
"@babel/code-frame": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
"integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
"dev": true,
"dependencies": {
"requires": {
"@babel/highlight": "^7.0.0"
}
},
"node_modules/@babel/highlight": {
"@babel/highlight": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
"integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
"dev": true,
"dependencies": {
"requires": {
"chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0"
}
},
"node_modules/@types/node": {
"@types/node": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz",
"integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
"dev": true
},
"node_modules/ansi-styles": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"dependencies": {
"requires": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/argparse": {
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"dependencies": {
"requires": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/balanced-match": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"node_modules/brace-expansion": {
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
"requires": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/braces/node_modules/fill-range": {
"dependencies": {
"fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"requires": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
}
}
},
"node_modules/builtin-modules": {
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
"dev": true
},
"node_modules/chalk": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"dependencies": {
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/color-convert": {
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"dependencies": {
"requires": {
"color-name": "1.1.3"
}
},
"node_modules/color-name": {
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"node_modules/commander": {
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"dev": true
},
"node_modules/concat-map": {
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/diff": {
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
"dev": true
},
"node_modules/enhanced-resolve": {
"enhanced-resolve": {
"version": "5.12.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
"integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
"dev": true,
"dependencies": {
"requires": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/escape-string-regexp": {
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true,
"engines": {
"node": ">=0.8.0"
}
"dev": true
},
"node_modules/esprima": {
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
"dev": true
},
"engines": {
"node": ">=4"
}
},
"node_modules/esutils": {
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
"dev": true
},
"node_modules/fs.realpath": {
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/glob": {
"glob": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"dependencies": {
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
}
},
"node_modules/graceful-fs": {
"graceful-fs": {
"version": "4.2.10",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
"node_modules/has-flag": {
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true,
"engines": {
"node": ">=4"
}
"dev": true
},
"node_modules/inflight": {
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dev": true,
"dependencies": {
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
},
"node_modules/is-number": {
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
"dev": true
},
"node_modules/js-tokens": {
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/js-yaml": {
"js-yaml": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"dev": true,
"dependencies": {
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/lru-cache": {
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"requires": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/micromatch": {
"micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"dev": true,
"dependencies": {
"requires": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/minimatch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"license": "ISC",
"dependencies": {
"requires": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"minimist": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
"dev": true
},
"node_modules/mkdirp": {
"mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dev": true,
"dependencies": {
"requires": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/once": {
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"requires": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
"dev": true
},
"node_modules/path-parse": {
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/picomatch": {
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
"dev": true
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/resolve": {
"resolve": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
"integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
"dev": true,
"dependencies": {
"requires": {
"path-parse": "^1.0.6"
}
},
"node_modules/semver": {
"semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dev": true,
"dependencies": {
"requires": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sprintf-js": {
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"node_modules/supports-color": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"requires": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/tapable": {
"tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true,
"engines": {
"node": ">=6"
}
"dev": true
},
"node_modules/to-regex-range": {
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"requires": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/ts-loader": {
"ts-loader": {
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz",
"integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==",
"dev": true,
"dependencies": {
"requires": {
"chalk": "^4.1.0",
"enhanced-resolve": "^5.0.0",
"micromatch": "^4.0.0",
"semver": "^7.3.4"
},
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"typescript": "*",
"webpack": "^5.0.0"
}
},
"node_modules/ts-loader/node_modules/ansi-styles": {
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"requires": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/ts-loader/node_modules/chalk": {
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/ts-loader/node_modules/color-convert": {
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"requires": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/ts-loader/node_modules/color-name": {
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/ts-loader/node_modules/has-flag": {
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
"dev": true
},
"node_modules/ts-loader/node_modules/supports-color": {
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"requires": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
}
}
},
"node_modules/tslib": {
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
"dev": true
},
"node_modules/tslint": {
"tslint": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz",
"integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==",
"dev": true,
"dependencies": {
"requires": {
"@babel/code-frame": "^7.0.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
@@ -561,57 +439,37 @@
"tslib": "^1.8.0",
"tsutils": "^2.29.0"
},
"bin": {
"tslint": "bin/tslint"
},
"engines": {
"node": ">=4.8.0"
},
"peerDependencies": {
"typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
}
},
"node_modules/tslint/node_modules/semver": {
"dependencies": {
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true,
"bin": {
"semver": "bin/semver"
"dev": true
}
}
},
"node_modules/tsutils": {
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"dependencies": {
"requires": {
"tslib": "^1.8.1"
},
"peerDependencies": {
"typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
}
},
"node_modules/typescript": {
"typescript": {
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
"integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
"dev": true
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/wrappy": {
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"node_modules/yallist": {
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-4
View File
@@ -88,10 +88,6 @@ into it. So that is what will be described below.
Cross compile x86 executables with 64-bit compiler
- arm64-on-x64
Cross compile arm64 executables with x64t compiler
On 64-bit Windows, all four configurations can be used. 32-bit platforms can only use 32-bit compiler.
1. Visual Studio will try generating CMake cache. If not, click **Project -> Configure Cache** or **Generate Cache**.
+220
View File
@@ -0,0 +1,220 @@
# How to build SoftEther VPN for Windows ARM64
This guide explains how to build SoftEther VPN for Windows ARM64 architecture. Windows on ARM is becoming increasingly important, especially on modern laptops and virtualized environments. This allows SoftEther VPN to run **natively on Windows ARM64**, improving performance and compatibility compared to x86 emulation.
## Requirements
- **Windows x64 host machine** (ARM64 builds are cross-compiled from x64)
- Visual Studio 2019 or 2022 (Community Edition is fine)
https://visualstudio.microsoft.com/downloads
- Git for Windows (or other git tool)
https://gitforwindows.org/
- vcpkg
https://github.com/microsoft/vcpkg
## Installation
### Visual Studio
Download from the official site and run the installer.
Make sure to check:
- **Desktop development with C++** under *Workloads*
- **Clang C++ Tools for Windows** in *Optional* components
- **MSVC v142 - VS 2019 C++ ARM64 build tools** (or equivalent for VS 2022) in *Optional* components
### Git
Nothing special. Just follow the installer.
### vcpkg
Let's say you will install it to `C:\vcpkg`.
Open your preferred terminal and go to `C:\`. Then run these commands:
```
C:\> git clone https://github.com/microsoft/vcpkg
C:\> cd vcpkg
C:\vcpkg> bootstrap-vcpkg.bat
C:\vcpkg> vcpkg integrate install
```
## Update
### vcpkg
You are recommended to update vcpkg from time to time, so that the latest libraries are used in the build.
Go to the installation path, pull the latest repo and the binary:
```
C:\vcpkg> git pull
C:\vcpkg> bootstrap-vcpkg.bat
```
## Building
### Step 1: Build x64-native first
**Important:** For ARM64 builds, an existing `x64-native` build is required to generate `hamcore.se2`.
1. Launch Visual Studio
Choose either **Clone a repository** to clone from GitHub or **Open a local folder** if you already have a copy.
2. Open Terminal (*View -> Terminal*). Install the needed submodules to build the project:
`git submodule update --init --recursive`
**Note**: This step is not necessary if you have chosen **Clone a repository** as Visual Studio automatically takes care of it.
3. Switch to folder view in the solution explorer
4. Select **x64-native** configuration from the dropdown menu below the search box
5. Visual Studio will try generating CMake cache. If not, click **Project -> Configure Cache** or **Generate Cache**.
If CMake is busy, you will find **Generate Cache** greyed out. Wait until it finishes or click **Cancel CMake Cache Generation** to stop it.
The initial configuration will take a longer time since it needs to download and install dependencies.
6. When *CMake generation finished* is displayed, simply go to toolbar and click **Build -> Build All**.
7. Wait for the x64 build to complete. This creates the necessary `hamcorebuilder` executable that will be reused for the ARM64 build.
### Step 2: Build arm64-on-x64
1. Switch to the **arm64-on-x64** configuration from the dropdown menu
This configuration cross-compiles ARM64 executables using the 64-bit compiler on your x64 Windows host.
2. Click **Project -> Configure Cache** or **Generate Cache** to configure the ARM64 build.
The ARM64 build will reuse the `hamcorebuilder` executable from the x64-native build to generate `hamcore.se2`.
3. When *CMake generation finished* is displayed, click **Build -> Build All**.
4. Once building has finished, hopefully with no errors, look in the newly created `/build` directory in the project's folder.
## Installation on Windows ARM64 Devices
### Prerequisites
- Windows 10 or Windows 11 ARM64 device
- The compiled ARM64 binaries from the build process
- Administrator privileges
### Installing the VPN Client
1. Copy the ARM64 build output to your Windows ARM64 device
2. Run `vpnsetup.exe` from the ARM64 build output
3. Select the components you want to install (typically VPN Client)
4. Follow the installation wizard
### VPN Client Driver Installation
The ARM64 Neo6 VPN driver is included in the build and targets **Windows 10 ARM64** or later.
**Important Notes:**
- The ARM64 driver is **unsigned by default**
- To use the unsigned driver, you need to:
1. Enable Windows Test Mode by running in an Administrator Command Prompt:
```
bcdedit /set testsigning on
```
2. Restart your computer
3. Install the VPN Client as described above
- For production use, the driver should be properly signed with a valid code signing certificate
### Disabling Test Mode (Optional)
After you're done testing or if you have a signed driver, you can disable Test Mode:
```
bcdedit /set testsigning off
```
Then restart your computer.
## Build Configuration Details
The **arm64-on-x64** configuration includes:
- **Cross-compilation target**: Windows ARM64
- **Compiler**: clang-cl (LLVM)
- **Toolchain**: MSVC ARM64 toolchain
- **VCPKG triplet**: arm64-windows-static
- **CPU feature detection**: ARM64 crypto extensions (AES via `PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE`)
- **BLAKE2 optimization**: NEON implementation (instead of SSE2)
## Notes
### Build Number
You can change the build number in `CMakeSettings.json`. Use any integer no less than 5180.
Delete and regenerate CMake cache after the change.
### OpenSSL
The above instruction builds OpenSSL library statically in the SoftEther binaries. This means:
- When you distribute the installer, users will not need to install OpenSSL separately
- The OpenSSL library cannot be updated without a rebuild and reinstallation of SoftEther
It's also possible to build OpenSSL library dynamically, but this requires additional configuration and is beyond the scope of this ARM64-specific guide. Refer to `BUILD_WINDOWS.md` for details on dynamic OpenSSL linking.
### Driver Signing
For production deployments, you should sign the ARM64 driver with a valid code signing certificate:
1. Obtain a code signing certificate from a trusted Certificate Authority
2. Use the Windows Driver Kit (WDK) tools to sign the driver
3. Distribute the signed driver to users
Without driver signing, users will need to enable Test Mode which reduces system security.
### Tested Environments
This ARM64 build process has been tested on:
- Windows x64 host (cross-compiling ARM64)
- Windows 10 ARM64 (VPN Client driver load and basic functionality)
- Windows 11 ARM64 devices
## Troubleshooting
### Build Fails During hamcore.se2 Generation
Make sure you have completed the x64-native build first. The ARM64 build requires the x64 `hamcorebuilder` executable.
### Driver Installation Fails
Ensure you have:
- Enabled Test Mode (for unsigned drivers)
- Administrator privileges
- Windows 10 or later ARM64
### VPN Client Doesn't Start
Check that:
- All ARM64 binaries are in the correct installation directory
- The Neo6 ARM64 driver is properly installed
- Windows Event Viewer for any error messages
## References
- Main Windows build guide: `BUILD_WINDOWS.md`
- Pull Request #2209: Windows ARM64 support
- Issue #1331: Windows ARM64 support request
-52
View File
@@ -1,52 +0,0 @@
# How to build and install SoftEther VPN on Windows ARM64
This document describes how to build SoftEther VPN for Windows ARM64 and how to install the VPN Client and Neo6 virtual network adapter on Windows on ARM devices.
## Requirements
- Build host: Windows x64
- Target device: Windows 10 / Windows 11 ARM64
## Building
**Notes before building**: ARM64 builds are cross-compiled from an x64 Windows host. An existing x64-native build is required to generate hamcore.se2.
1. Follow [BUILD_WINDOWS.md](BUILD_WINDOWS.md##Building)
1. Build x64 (Native): From the build menu, select x64-on-x64. Complete the build successfully. This build is required to generate shared resources
1. Build ARM64 (Cross-Compiled): From the same build menu, select arm64-on-x64.
Build the ARM64 version of SoftEther VPN.
1. Building the Neo6 Virtual Network Adapter (ARM64)
Open the following project in Visual Studio:
```
.\src\Neo6\Neo6.vcxproj
```
SoftEther VPN Client uses the Neo6 virtual network adapter.
Driver Output Files
The ARM64 driver package includes:
```
Neo6_arm64_VPN.sys
Neo6_arm64_VPN.inf
```
Driver Signing and Installation (Windows ARM64)
```
Enable test-signing mode: bcdedit /set testsigning on
Reboot the system.
Testing signing:
Install the Neo6 ARM64 driver.
```
# Summary
SoftEther VPN can be cross-compiled for Windows ARM64 on an x64 host
VPN Client works natively on Windows on ARM
Neo6 ARM64 driver requires Microsoft signing for production use
Test-signing is suitable for local development only
+3 -5
View File
@@ -8739,7 +8739,7 @@ UINT StSetHubRadius(ADMIN *a, RPC_RADIUS *t)
}
//SetRadiusServer(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret);
SetRadiusServerEx2(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret, t->RadiusRetryInterval, t->RadiusRetryTimeout);
SetRadiusServerEx(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret, t->RadiusRetryInterval);
ALog(a, h, "LA_SET_HUB_RADIUS");
@@ -8778,8 +8778,8 @@ UINT StGetHubRadius(ADMIN *a, RPC_RADIUS *t)
Zero(t, sizeof(RPC_RADIUS));
//GetRadiusServer(h, t->RadiusServerName, sizeof(t->RadiusServerName),
// &t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret));
GetRadiusServerEx2(h, t->RadiusServerName, sizeof(t->RadiusServerName),
&t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret), &t->RadiusRetryInterval, &t->RadiusRetryTimeout);
GetRadiusServerEx(h, t->RadiusServerName, sizeof(t->RadiusServerName),
&t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret), &t->RadiusRetryInterval);
ReleaseHub(h);
@@ -13031,7 +13031,6 @@ void InRpcRadius(RPC_RADIUS *t, PACK *p)
PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
PackGetStr(p, "RadiusSecret", t->RadiusSecret, sizeof(t->RadiusSecret));
t->RadiusRetryInterval = PackGetInt(p, "RadiusRetryInterval");
t->RadiusRetryTimeout = PackGetInt(p, "RadiusRetryTimeout");
}
void OutRpcRadius(PACK *p, RPC_RADIUS *t)
{
@@ -13046,7 +13045,6 @@ void OutRpcRadius(PACK *p, RPC_RADIUS *t)
PackAddStr(p, "HubName", t->HubName);
PackAddStr(p, "RadiusSecret", t->RadiusSecret);
PackAddInt(p, "RadiusRetryInterval", t->RadiusRetryInterval);
PackAddInt(p, "RadiusRetryTimeout", t->RadiusRetryTimeout);
}
// RPC_HUB
-1
View File
@@ -259,7 +259,6 @@ struct RPC_RADIUS
UINT RadiusPort; // Radius port number
char RadiusSecret[MAX_PASSWORD_LEN + 1]; // Secret key
UINT RadiusRetryInterval; // Radius retry interval
UINT RadiusRetryTimeout; // Radius retry timeout
};
// Specify the HUB
-7
View File
@@ -11791,9 +11791,6 @@ UINT PsRadiusServerSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{"[server_name:port]", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_Host"), CmdEvalNotEmpty, NULL},
{"SECRET", CmdPromptChoosePassword, _UU("CMD_RadiusServerSet_Prompt_Secret"), NULL, NULL},
{"RETRY_INTERVAL", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_RetryInterval"), CmdEvalMinMax, &minmax},
// Support for setting timeout through commandline not added
// {"RETRY_TIMEOUT", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_RetryTimeout"), CmdEvalMinMax, &minmax},
};
// If virtual HUB is not selected, it's an error
@@ -11818,7 +11815,6 @@ UINT PsRadiusServerSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
StrCpy(t.RadiusServerName, sizeof(t.RadiusServerName), host);
StrCpy(t.RadiusSecret, sizeof(t.RadiusSecret), GetParamStr(o, "SECRET"));
t.RadiusRetryInterval = GetParamInt(o, "RETRY_INTERVAL");
// t.RadiusRetryTimeout = GetParamInt(o, "RETRY_TIMEOUT");
Free(host);
@@ -11942,9 +11938,6 @@ UINT PsRadiusServerGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
UniToStri(tmp, t.RadiusRetryInterval);
CtInsert(ct, _UU("CMD_RadiusServerGet_RetryInterval"), tmp);
UniToStri(tmp, t.RadiusRetryTimeout);
CtInsert(ct, _UU("CMD_RadiusServerGet_RetryTimeout"), tmp);
}
CtFree(ct, c);
+9 -30
View File
@@ -99,7 +99,6 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch
char radius_servers[MAX_PATH] = {0};
UINT radius_port = 0;
UINT radius_retry_interval = 0;
UINT radius_retry_timeout = 0;
char radius_secret[MAX_PATH] = {0};
char radius_suffix_filter[MAX_PATH] = {0};
if (cedar == NULL || hubname == NULL || client_ip_str == NULL || username == NULL)
@@ -116,8 +115,8 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch
if (hub != NULL)
{
if (GetRadiusServerEx3(hub, radius_servers, sizeof(radius_servers), &radius_port, radius_secret,
sizeof(radius_secret), &radius_retry_interval, &radius_retry_timeout, radius_suffix_filter, sizeof(radius_suffix_filter)))
if (GetRadiusServerEx2(hub, radius_servers, sizeof(radius_servers), &radius_port, radius_secret,
sizeof(radius_secret), &radius_retry_interval, radius_suffix_filter, sizeof(radius_suffix_filter)))
{
bool use_peap = hub->RadiusUsePeapInsteadOfEap;
@@ -6416,23 +6415,17 @@ void ReleaseHub(HUB *h)
bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size)
{
UINT interval;
return GetRadiusServerEx(hub, name, size, port, secret, secret_size, &interval);
}
bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval) {
UINT timeout;
return GetRadiusServerEx2(hub, name, size, port, secret, secret_size, interval, &timeout);
}
bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, UINT *timeout)
bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval)
{
return GetRadiusServerEx3(hub, name, size, port, secret, secret_size, interval, timeout, NULL, 0);
return GetRadiusServerEx2(hub, name, size, port, secret, secret_size, interval, NULL, 0);
}
bool GetRadiusServerEx3(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, UINT *timeout, char *suffix_filter, UINT suffix_filter_size)
bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, char *suffix_filter, UINT suffix_filter_size)
{
bool ret = false;
// Validate arguments
if (hub == NULL || name == NULL || port == NULL || secret == NULL || interval == NULL || timeout == NULL)
if (hub == NULL || name == NULL || port == NULL || secret == NULL || interval == NULL)
{
return false;
}
@@ -6446,7 +6439,6 @@ bool GetRadiusServerEx3(HUB *hub, char *name, UINT size, UINT *port, char *secre
StrCpy(name, size, hub->RadiusServerName);
*port = hub->RadiusServerPort;
*interval = hub->RadiusRetryInterval;
*timeout = hub->RadiusRetryTimeout;
tmp_size = hub->RadiusSecret->Size + 1;
tmp = ZeroMalloc(tmp_size);
@@ -6473,10 +6465,6 @@ void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret)
SetRadiusServerEx(hub, name, port, secret, RADIUS_RETRY_INTERVAL);
}
void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval)
{
SetRadiusServerEx2(hub, name, port, secret, interval, RADIUS_RETRY_TIMEOUT);
}
void SetRadiusServerEx2(HUB *hub, char *name, UINT port, char *secret, UINT interval, UINT timeout)
{
// Validate arguments
if (hub == NULL)
@@ -6496,28 +6484,19 @@ void SetRadiusServerEx2(HUB *hub, char *name, UINT port, char *secret, UINT inte
hub->RadiusServerName = NULL;
hub->RadiusServerPort = 0;
hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
hub->RadiusRetryTimeout = RADIUS_RETRY_TIMEOUT;
FreeBuf(hub->RadiusSecret);
}
else
{
hub->RadiusServerName = CopyStr(name);
hub->RadiusServerPort = port;
if (timeout == 0) {
timeout = RADIUS_RETRY_TIMEOUT;
}
hub->RadiusRetryTimeout = timeout;
if (interval == 0)
{
hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL; ///What happens here is that RADIUS_RETRY_TIMEOUT is not configurable, and RADIUS_RETRY_INTERVAL is set to the timeout if it's larger.
hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
}
if (interval > timeout)
else if (interval > RADIUS_RETRY_TIMEOUT)
{
hub->RadiusRetryInterval = timeout;
hub->RadiusRetryInterval = RADIUS_RETRY_TIMEOUT;
}
else
{
+1 -4
View File
@@ -341,7 +341,6 @@ struct HUB
char *RadiusServerName; // Radius server name
UINT RadiusServerPort; // Radius server port number
UINT RadiusRetryInterval; // Radius retry interval
UINT RadiusRetryTimeout; // Radius timeout, it will no longer retry
BUF *RadiusSecret; // Radius shared key
char RadiusSuffixFilter[MAX_SIZE]; // Radius suffix filter
char RadiusRealm[MAX_SIZE]; // Radius realm (optional)
@@ -483,11 +482,9 @@ void GetAccessListStr(char *str, UINT size, ACCESS *a);
void DeleteOldIpTableEntry(LIST *o);
void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret);
void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval);
void SetRadiusServerEx2(HUB *hub, char *name, UINT port, char *secret, UINT interval, UINT timeout);
bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size);
bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval);
bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, UINT *timeout);
bool GetRadiusServerEx3(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, UINT *timeout, char *suffix_filter, UINT suffix_filter_size);
bool GetRadiusServerEx2(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval, char *suffix_filter, UINT suffix_filter_size);
int CompareCert(void *p1, void *p2);
void GetHubLogSetting(HUB *h, HUB_LOG *setting);
void SetHubLogSetting(HUB *h, HUB_LOG *setting);
-7
View File
@@ -2562,16 +2562,9 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
Debug("OpenVPN Channel %u Failed.\n", j);
OvsLog(s, se, c, "LO_CHANNEL_FAILED");
if ((se->IpcAsync->ErrorCode == ERR_AUTHTYPE_NOT_SUPPORTED) ||
(se->IpcAsync->ErrorCode == ERR_AUTH_FAILED) ||
(se->IpcAsync->ErrorCode == ERR_PROXY_AUTH_FAILED) ||
(se->IpcAsync->ErrorCode == ERR_USER_AUTHTYPE_NOT_PASSWORD) ||
(se->IpcAsync->ErrorCode == ERR_NOT_SUPPORTED_AUTH_ON_OPENSOURCE))
{
// Return the AUTH_FAILED
str = "AUTH_FAILED";
WriteFifo(c->SslPipe->SslInOut->SendFifo, str, StrSize(str));
}
s->SessionEstablishedCount++;
+1 -19
View File
@@ -5429,7 +5429,7 @@ void ClientUploadNoop(CONNECTION *c)
}
p = PackError(0);
PackAddInt(p, "noop", NOOP);
PackAddInt(p, "noop", 1);
(void)HttpClientSend(c->FirstSock, p);
FreePack(p);
@@ -5440,24 +5440,6 @@ void ClientUploadNoop(CONNECTION *c)
}
}
void ServerUploadNoop(CONNECTION *c)
{
PACK *p;
// Validate arguments
if (c == NULL)
{
return;
}
p = PackError(0);
PackAddInt(p, "noop", NOOP_IGNORE);
(void)HttpServerSend(c->FirstSock, p);
FreePack(p);
// Client can't re-respond to an HTTP "response"
// so we don't wait for it on the server side
}
// Add client version information to the PACK
void PackAddClientVersion(PACK *p, CONNECTION *c)
{
-1
View File
@@ -169,7 +169,6 @@ bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32);
void CreateNodeInfo(NODE_INFO *info, CONNECTION *c);
UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin);
void ClientUploadNoop(CONNECTION *c);
void ServerUploadNoop(CONNECTION *c);
bool ClientCheckServerCert(CONNECTION *c, bool *expired);
void ClientCheckServerCertThread(THREAD *thread, void *param);
bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x);
+4 -15
View File
@@ -7,7 +7,6 @@
#include "Radius.h"
#include "Protocol.h"
#include "Connection.h"
#include "IPC.h"
#include "Server.h"
@@ -1768,7 +1767,7 @@ LABEL_ERROR:
////////// Classical implementation
// Attempts Radius authentication (with specifying retry interval and multiple server)
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UINT timeout, UCHAR *mschap_v2_server_response_20,
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20,
RADIUS_LOGIN_OPTION *opt, char *hubname)
{
UCHAR random[MD5_SIZE];
@@ -2073,22 +2072,14 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
// Transmission process start
start = Tick64();
// Limit timeout to be larger than hardcoded timeout
// Limit interval to be larger than the hardcoded interval and less than timeout
if (timeout < RADIUS_RETRY_TIMEOUT) {
timeout = RADIUS_RETRY_TIMEOUT;
}
if(interval < RADIUS_RETRY_INTERVAL)
{
interval = RADIUS_RETRY_INTERVAL;
}
else if(interval > timeout)
else if(interval > RADIUS_RETRY_TIMEOUT)
{
interval = timeout;
interval = RADIUS_RETRY_TIMEOUT;
}
next_send_time = start + (UINT64)interval;
while (true)
@@ -2108,8 +2099,6 @@ SEND_RETRY:
next_send_time = Tick64() + (UINT64)interval;
RECV_RETRY:
ServerUploadNoop(c);
now = Tick64();
if (next_send_time <= now)
{
@@ -2120,7 +2109,7 @@ RECV_RETRY:
goto SEND_RETRY;
}
if ((start + timeout) < now)
if ((start + RADIUS_RETRY_TIMEOUT) < now)
{
// Time-out
break;
+1 -1
View File
@@ -283,7 +283,7 @@ struct RADIUS_LOGIN_OPTION
};
// Function prototype
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UINT timeout, UCHAR *mschap_v2_server_response_20,
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20,
RADIUS_LOGIN_OPTION *opt, char *hubname);
BUF *RadiusEncryptPassword(char *password, UCHAR *random, UCHAR *secret, UINT secret_size);
BUF *RadiusCreateUserName(wchar_t *username);
+2 -3
View File
@@ -516,7 +516,6 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p
char suffix_filter[MAX_SIZE];
wchar_t suffix_filter_w[MAX_SIZE];
UINT interval;
UINT timeout;
EAP_CLIENT *eap = NULL;
char password1[MAX_SIZE];
UCHAR client_challenge[16];
@@ -587,7 +586,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p
}
// Get the Radius server information
if (GetRadiusServerEx3(hub, radius_server_addr, sizeof(radius_server_addr), &radius_server_port, radius_secret, sizeof(radius_secret), &interval, &timeout, suffix_filter, sizeof(suffix_filter)))
if (GetRadiusServerEx2(hub, radius_server_addr, sizeof(radius_server_addr), &radius_server_port, radius_secret, sizeof(radius_secret), &interval, suffix_filter, sizeof(suffix_filter)))
{
Unlock(hub->lock);
@@ -598,7 +597,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p
// Attempt to login
b = RadiusLogin(c, radius_server_addr, radius_server_port,
radius_secret, StrLen(radius_secret),
name, password, interval, timeout, mschap_v2_server_response_20, opt, hub->Name);
name, password, interval, mschap_v2_server_response_20, opt, hub->Name);
if (b)
{
+1 -8
View File
@@ -4855,7 +4855,6 @@ void SiWriteHubCfg(FOLDER *f, HUB *h)
}
CfgAddInt(f, "RadiusServerPort", h->RadiusServerPort);
CfgAddInt(f, "RadiusRetryInterval", h->RadiusRetryInterval);
CfgAddInt(f, "RadiusRetryTimeout", h->RadiusRetryTimeout);
CfgAddStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter);
CfgAddStr(f, "RadiusRealm", h->RadiusRealm);
@@ -5021,11 +5020,9 @@ void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
BUF *secret;
UINT port;
UINT interval;
UINT timeout;
port = CfgGetInt(f, "RadiusServerPort");
interval = CfgGetInt(f, "RadiusRetryInterval");
timeout = CfgGetInt(f, "RadiusRetryTimeout");
CfgGetStr(f, "RadiusSuffixFilter", h->RadiusSuffixFilter, sizeof(h->RadiusSuffixFilter));
CfgGetStr(f, "RadiusRealm", h->RadiusRealm, sizeof(h->RadiusRealm));
@@ -5038,10 +5035,6 @@ void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
interval = RADIUS_RETRY_INTERVAL;
}
if (timeout == 0) {
timeout = RADIUS_RETRY_TIMEOUT;
}
if (port != 0 && CfgGetStr(f, "RadiusServerName", name, sizeof(name)))
{
secret = CfgGetBuf(f, "RadiusSecret");
@@ -5055,7 +5048,7 @@ void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
}
secret_str[sizeof(secret_str) - 1] = 0;
//SetRadiusServer(h, name, port, secret_str);
SetRadiusServerEx2(h, name, port, secret_str, interval, timeout);
SetRadiusServerEx(h, name, port, secret_str, interval);
FreeBuf(secret);
}
}
+1 -1
View File
@@ -4761,7 +4761,7 @@ static void MY_SHA0_Transform(MY_SHA0_CTX* ctx) {
UCHAR* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
UINT tmp = (UINT)*p++ << 24;
UINT tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
+2 -26
View File
@@ -1207,14 +1207,12 @@ PACK *HttpClientRecv(SOCK *s)
UINT size;
UCHAR *tmp;
HTTP_VALUE *v;
UINT num_noop = 0;
// Validate arguments
if (s == NULL)
{
return NULL;
}
START:
h = RecvHttpHeader(s);
if (h == NULL)
{
@@ -1259,22 +1257,6 @@ START:
p = BufToPack(b);
FreeBuf(b);
// Client shouldn't receive a noop other than NOOP_IGNORE
// because it can't respond without a full new HTTP request
UINT noop = PackGetInt(p, "noop");
if (noop == NOOP_IGNORE) {
Debug("recv: noop ignore\n");
FreePack(p);
num_noop++;
if (num_noop > MAX_NOOP_PER_SESSION)
{
return NULL;
}
goto START;
}
return p;
}
@@ -1383,14 +1365,13 @@ START:
FreeBuf(b);
// Determine whether it's a NOOP
UINT noop = PackGetInt(p, "noop");
if (noop == NOOP)
if (PackGetInt(p, "noop") != 0)
{
Debug("recv: noop\n");
FreePack(p);
p = PackError(0);
PackAddInt(p, "noop", NOOP_IGNORE);
PackAddInt(p, "noop", 1);
if (HttpServerSend(s, p) == false)
{
FreePack(p);
@@ -1406,11 +1387,6 @@ START:
return NULL;
}
goto START;
} else if (noop == NOOP_IGNORE) {
Debug("recv: noop ignore\n");
FreePack(p);
goto START;
}
+5 -9
View File
@@ -63,7 +63,7 @@ static int ydays[] =
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
};
static COUNTER *current_num_thread = NULL;
static UINT current_num_thread = 0;
static UINT cached_number_of_cpus = 0;
@@ -776,7 +776,6 @@ void InitThreading()
{
thread_pool = NewSk();
thread_count = NewCounter();
current_num_thread = NewCounter();
}
// Release of thread pool
@@ -822,9 +821,6 @@ void FreeThreading()
DeleteCounter(thread_count);
thread_count = NULL;
DeleteCounter(current_num_thread);
current_num_thread = NULL;
}
// Thread pool procedure
@@ -1032,9 +1028,9 @@ THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
Wait(pd->InitFinishEvent, INFINITE);
Inc(current_num_thread);
current_num_thread++;
// Debug("current_num_thread = %u\n", Count(current_num_thread));
// Debug("current_num_thread = %u\n", current_num_thread);
return ret;
}
@@ -1059,8 +1055,8 @@ void CleanupThread(THREAD *t)
Free(t);
Dec(current_num_thread);
//Debug("current_num_thread = %u\n", Count(current_num_thread));
current_num_thread--;
//Debug("current_num_thread = %u\n", current_num_thread);
}
// Release thread (pool)
+1 -16
View File
@@ -72,26 +72,11 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
// Compiler dependent
#ifndef OS_WIN32
// GCC or Clang compiler
// Gcc compiler
#define GCC_PACKED __attribute__ ((__packed__))
// Clang compiler
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
#define ATTRIBUTE_NO_TSAN __attribute__((no_sanitize("thread")))
#endif // __has_feature(thread_sanitizer)
#endif // __has_feature
// GCC compiler
#if defined(__SANITIZE_THREAD__) && !defined(ATTRIBUTE_NO_TSAN)
#define ATTRIBUTE_NO_TSAN __attribute__((no_sanitize("thread")))
#endif // __SANITIZE_THREAD__
// Other or older Clang/GCC compiler
#ifndef ATTRIBUTE_NO_TSAN
#define ATTRIBUTE_NO_TSAN
#endif // ATTRIBUTE_NO_TSAN
#else // OS_WIN32
// VC++ compiler
#define GCC_PACKED
#define ATTRIBUTE_NO_TSAN
#endif // OS_WIN32
// Macro that displays the current file name and line number
+2
View File
@@ -881,6 +881,8 @@ struct SSL_VERIFY_OPTION
X *SavedCert; // Saved server certificate
};
#define SSL_DEFAULT_CONNECT_TIMEOUT (15 * 1000) // SSL default timeout
// Header for TCP Pair
struct TCP_PAIR_HEADER
{
-2
View File
@@ -38,8 +38,6 @@
// The number of allowable NOOP
#define MAX_NOOP_PER_SESSION 30
#define NOOP 1
#define NOOP_IGNORE 2 // A noop, but don't send a response noop
// VALUE object
struct VALUE
-1
View File
@@ -470,7 +470,6 @@ LIST *LoadLangList()
b = ReadDump(filename);
if (b == NULL)
{
FreeLangList(o);
return NULL;
}
-6
View File
@@ -1849,8 +1849,6 @@ void UnixUnlockEx(LOCK *lock, bool inner)
}
// Lock
// Recursive locking is implemented manually instead of using PTHREAD_MUTEX_RECURSIVE.
// See: https://github.com/SoftEtherVPN/SoftEtherVPN/pull/2219
bool UnixLock(LOCK *lock)
{
pthread_mutex_t *mutex;
@@ -2142,13 +2140,9 @@ void UnixMemoryFree(void *addr)
// SIGCHLD handler
void UnixSigChldHandler(int sig)
{
int old_errno = errno;
// Recall the zombie processes
while (waitpid(-1, NULL, WNOHANG) > 0);
signal(SIGCHLD, UnixSigChldHandler);
errno = old_errno;
}
// Disable core dump
File diff suppressed because it is too large Load Diff
-42
View File
@@ -1,42 +0,0 @@
# This file contains suppressions for Thread Sanitizer.
# For the specification, refer to: https://github.com/google/sanitizers/wiki/threadsanitizersuppressions
## Set/Wait
# This provides synchronization equivalent to a lock, but Thread Sanitizer cannot recognize it.
# Thread Sanitizer reports data race on Halt in TK64.
# https://github.com/SoftEtherVPN/SoftEtherVPN/pull/2221
race_top:FreeTick64
# Thread Sanitizer reports data races on Finished and NoDelayFlag in CONNECT_SERIAL_PARAM,
# shared between BindConnectThreadForIPv4, BindConnectThreadForIPv6, and BindConnectEx5.
# https://github.com/SoftEtherVPN/SoftEtherVPN/pull/2222
race_top:BindConnectThreadForIPv4
race_top:BindConnectThreadForIPv6
race_top:BindConnectEx5
# Thread Sanitizer reports data races on PoolHalting in THREAD, shared between ThreadPoolProc and WaitThread.
# But if WaitThread reads false, synchronization is ensured by Wait from the PoolWaitList. If it reads true,
# WaitThread simply returns.
race_top:ThreadPoolProc
## Accept/Disconnect cancellation
# Thread Sanitizer reports two data races on CancelAccept and CallingThread in SOCK, shared between
# Accept(Accept6) and Disconnect. These are used when interrupting an Accept operation from a Disconnect.
# They are race-safe because they work correctly even if both fields have old values.
race_top:^Accept$
race_top:^Accept6$
race_top:^Disconnect$
## Manual PTHREAD_MUTEX_RECURSIVE
# The Lock/Unlock mechanism on Unix is a manual, hand-coded implementation of PTHREAD_MUTEX_RECURSIVE.
# We avoid using the PTHREAD_MUTEX_RECURSIVE directly because it exhibits critical bugs, such as deadlocks
# on certain older systems(Linux, Solaris, or macOS). While Thread Sanitizer will report data races,
# these warnings should be ignored as the logic has been carefully implemented to ensure thread safety.
# https://github.com/SoftEtherVPN/SoftEtherVPN/pull/2219
race_top:UnixLock
race_top:UnixUnlockEx