mirror of
https://github.com/Windscribe/Desktop-App.git
synced 2026-05-07 20:12:44 +00:00
v2.22.4
This commit is contained in:
+176
-59
@@ -18,10 +18,23 @@ variables:
|
||||
NEXUS_PATH_TAGGED_UPLOAD: '${NEXUS_PATH_ROOT}/tagged-builds'
|
||||
ARCH_LINUX_BUILD_PATH: '/home/build/windscribe'
|
||||
RHEL_CMAKE_BUILD_PATH: '/home/build/windscribe'
|
||||
BUILD_LIBS_FOLDER: 'build-libs'
|
||||
BUILD_LIBS_FOLDER: 'build-libs/windscribe'
|
||||
BUILD_LIBS_FOLDER_X64: 'build-libs/windscribe'
|
||||
BUILD_LIBS_FOLDER_ARM64: 'build-libs-arm64/windscribe'
|
||||
VCPKG_ROOT_WINDOWS: 'c:\vcpkg'
|
||||
VCPKG_DEFAULT_BINARY_CACHE_WINDOWS: 'c:\vcpkg_cache'
|
||||
|
||||
.check_translations:
|
||||
script:
|
||||
- $Diff = git diff src/client/frontend/gui/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed desktop strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $Diff = git diff src/installer/gui/installer-gui-common/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed installer strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $Diff = git diff src/installer/gui/windows/uninstaller/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed uninstaller strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $Diff = git diff src/windscribe-cli/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed CLI strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
|
||||
.template_win10_build: &template_win10_build
|
||||
tags: [win10qty6]
|
||||
before_script:
|
||||
@@ -53,6 +66,10 @@ variables:
|
||||
.template_mac_build: &template_mac_build
|
||||
tags: [macos-arm64-qt6]
|
||||
before_script:
|
||||
- export DEVELOPER_DIR=/Applications/Xcode15.4.app/Contents/Developer
|
||||
- export PYENV_ROOT="${HOME}/.pyenv"
|
||||
- export PATH="${PYENV_ROOT}/bin:${PYENV_ROOT}/shims:${PATH}"
|
||||
- eval "$(pyenv init --path)"
|
||||
- brew install pkg-config
|
||||
- export VCPKG_ROOT="${HOME}/vcpkg"
|
||||
- export VCPKG_INSTALL_OPTIONS="--clean-after-build"
|
||||
@@ -60,7 +77,6 @@ variables:
|
||||
- git clone https://github.com/Windscribe/ws-vcpkg-registry.git
|
||||
- ./ws-vcpkg-registry/install-vcpkg/vcpkg_install.sh "${VCPKG_ROOT}" --configure-git
|
||||
- python3 -m pip install -r tools/requirements.txt
|
||||
- python3 -m pip install dmgbuild
|
||||
- python3 -m pip install gcovr
|
||||
interruptible: true
|
||||
|
||||
@@ -70,7 +86,7 @@ variables:
|
||||
before_script:
|
||||
- python3 -m pip install --user -r tools/requirements.txt
|
||||
# hack to fix 777 file permissions, which breaks the dpkg-deb command in the build_all script.
|
||||
- chmod -R o-w src/installer/linux
|
||||
- chmod -R o-w src/installer/gui/linux src/installer/cli/linux
|
||||
# vcpkg settings
|
||||
- export VCPKG_ROOT="${HOME}/vcpkg"
|
||||
- export VCPKG_FORCE_SYSTEM_BINARIES=1
|
||||
@@ -88,7 +104,7 @@ variables:
|
||||
image: registry.gitlab.int.windscribe.com:5005/ws/client/desktop/client-desktop/fedora36
|
||||
before_script:
|
||||
# hack to fix 777 file permissions, which breaks the dpkg-deb command in the build_all script.
|
||||
- chmod -R o-w src/installer/linux
|
||||
- chmod -R o-w src/installer/gui/linux src/installer/cli/linux
|
||||
# vcpkg settings
|
||||
- export VCPKG_ROOT="${HOME}/vcpkg"
|
||||
- export PATH=${RHEL_CMAKE_BUILD_PATH}/bin:$PATH
|
||||
@@ -145,7 +161,7 @@ variables:
|
||||
# Backup OS identifier/build libs values. Set flags to get the x86 Qt libs if on arm64.
|
||||
- Set-Variable -name OS_IDENTIFIER_BAK -value "${OS_IDENTIFIER}"
|
||||
- Set-Variable -name BUILD_LIBS_FOLDER_BAK -value "${BUILD_LIBS_FOLDER}"
|
||||
- if ("${ARCH_FLAG}" -eq "--arm64") { Set-Variable -name OS_IDENTIFIER -value "windows"; Set-Variable -name BUILD_LIBS_FOLDER -value "build-libs" }
|
||||
- if ("${ARCH_FLAG}" -eq "--arm64") { Set-Variable -name OS_IDENTIFIER -value "windows"; Set-Variable -name BUILD_LIBS_FOLDER -value "${BUILD_LIBS_FOLDER_X64}" }
|
||||
- if ("${ARCH_FLAG}" -ne "--arm64") { Set-Variable -name SKIP_DOWNLOAD -value "1" }
|
||||
- IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}
|
||||
# Reset to original values
|
||||
@@ -155,13 +171,9 @@ variables:
|
||||
- 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}'
|
||||
- $env:VCPKG_ROOT = $env:VCPKG_ROOT_WINDOWS
|
||||
- $env:VCPKG_DEFAULT_BINARY_CACHE = $env:VCPKG_DEFAULT_BINARY_CACHE_WINDOWS
|
||||
- tools/build_all ${BUILD_FLAG} ${ARCH_FLAG} --ci-mode
|
||||
- $Diff = git diff src/client/frontend/gui/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed desktop strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $Diff = git diff src/installer/common/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed installer strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $Diff = git diff src/installer/windows/uninstaller/translations
|
||||
- if ( $Diff.Count -ne 0 ) { echo "You have changed uninstaller strings which are not in ts files. Update your ts files by building locally, run the translation script on them, and add them to the commit."; exit 1 }
|
||||
- $buildSymbolsFlag = if ($CI_COMMIT_TAG) { "--build-symbols" } else { "" }
|
||||
- tools/build_all ${BUILD_FLAG} ${ARCH_FLAG} --ci-mode $buildSymbolsFlag
|
||||
- !reference [.check_translations, script]
|
||||
artifacts:
|
||||
paths:
|
||||
- build/temp/
|
||||
@@ -181,14 +193,13 @@ variables:
|
||||
artifacts:
|
||||
paths:
|
||||
- build/temp/
|
||||
- build/src/installer/windows/bootstrap/
|
||||
- build/src/installer/gui/windows/bootstrap/
|
||||
expire_in: 1 day
|
||||
|
||||
build:win:x64:app:
|
||||
<<: *template_win_build_app
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows"
|
||||
BUILD_LIBS_FOLDER: "build-libs"
|
||||
ARCH_FLAG: ""
|
||||
BUILD_FLAG: "--build-app"
|
||||
rules:
|
||||
@@ -206,6 +217,7 @@ build:win:x64:mr:
|
||||
- !reference [.download_dependencies_win, script]
|
||||
- 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}'
|
||||
- tools/build_all --ci-mode
|
||||
- !reference [.check_translations, script]
|
||||
rules:
|
||||
- if: $BUILD_WIN == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -241,7 +253,6 @@ build:win:x64:installer:
|
||||
<<: *template_win_build_app
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows"
|
||||
BUILD_LIBS_FOLDER: "build-libs"
|
||||
ARCH_FLAG: ""
|
||||
BUILD_FLAG: "--build-installer"
|
||||
artifacts:
|
||||
@@ -298,7 +309,6 @@ build:win:x64:bootstrap:
|
||||
<<: *template_win_build_bootstrap
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows"
|
||||
BUILD_LIBS_FOLDER: "build-libs"
|
||||
ARCH_FLAG: ""
|
||||
needs:
|
||||
- job: sign:win:x64:installer
|
||||
@@ -313,13 +323,11 @@ sign:win:x64:bootstrap:
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- tools/build_all --sign-bootstrap --ci-mode
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}_amd64.exe "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/Windscribe_${VERSION}_amd64.exe"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/WindscribeSymbols_${VERSION}_amd64.zip "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/WindscribeSymbols_${VERSION}_amd64.zip"
|
||||
artifacts:
|
||||
paths: []
|
||||
needs:
|
||||
@@ -335,13 +343,11 @@ sign:win:arm64:bootstrap:
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- tools/build_all --sign-bootstrap --arm64 --ci-mode
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows-arm64"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}_arm64.exe "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/Windscribe_${VERSION}_arm64.exe"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/WindscribeSymbols_${VERSION}_arm64.zip "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/WindscribeSymbols_${VERSION}_arm64.zip"
|
||||
artifacts:
|
||||
paths: []
|
||||
needs:
|
||||
@@ -357,9 +363,9 @@ sign:win:x64:bootstrap:tagged:
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- Set-Variable -name TAG -value $($CI_COMMIT_TAG -replace '^v([0-9].*)','$1')
|
||||
- tools/build_all --sign-bootstrap --ci-mode
|
||||
- tools/build_all --sign-bootstrap --ci-mode --build-symbols
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}_amd64.exe "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/Windscribe_${VERSION}_amd64.exe"
|
||||
@@ -380,9 +386,9 @@ sign:win:arm64:bootstrap:tagged:
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- Set-Variable -name TAG -value $($CI_COMMIT_TAG -replace '^v([0-9].*)','$1')
|
||||
- tools/build_all --sign-bootstrap --arm64 --ci-mode
|
||||
- tools/build_all --sign-bootstrap --arm64 --ci-mode --build-symbols
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows-arm64"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}_arm64.exe "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/Windscribe_${VERSION}_arm64.exe"
|
||||
@@ -401,7 +407,7 @@ build:win:arm64:app:
|
||||
<<: *template_win_build_app
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows-arm64"
|
||||
BUILD_LIBS_FOLDER: "build-libs-arm64"
|
||||
BUILD_LIBS_FOLDER: "$BUILD_LIBS_FOLDER_ARM64"
|
||||
ARCH_FLAG: "--arm64"
|
||||
BUILD_FLAG: "--build-app"
|
||||
rules:
|
||||
@@ -417,13 +423,14 @@ build:win:arm64:mr:
|
||||
script:
|
||||
# Need the x64 Qt package so we can reference it as the QT_HOST_PATH in build_all.
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows"
|
||||
- Set-Variable -name BUILD_LIBS_FOLDER -value "build-libs"
|
||||
- Set-Variable -name BUILD_LIBS_FOLDER -value "${BUILD_LIBS_FOLDER_X64}"
|
||||
- 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}'
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows-arm64"
|
||||
- Set-Variable -name BUILD_LIBS_FOLDER -value "build-libs-arm64"
|
||||
- Set-Variable -name BUILD_LIBS_FOLDER -value "${BUILD_LIBS_FOLDER_ARM64}"
|
||||
- !reference [.download_dependencies_win, script]
|
||||
- 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}'
|
||||
- tools/build_all --arm64 --ci-mode
|
||||
- !reference [.check_translations, script]
|
||||
rules:
|
||||
- if: $BUILD_WIN_ARM64 == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -431,7 +438,7 @@ build:win:arm64:installer:
|
||||
<<: *template_win_build_app
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows-arm64"
|
||||
BUILD_LIBS_FOLDER: "build-libs-arm64"
|
||||
BUILD_LIBS_FOLDER: "$BUILD_LIBS_FOLDER_ARM64"
|
||||
ARCH_FLAG: "--arm64"
|
||||
BUILD_FLAG: "--build-installer"
|
||||
artifacts:
|
||||
@@ -450,7 +457,7 @@ build:win:arm64:bootstrap:
|
||||
<<: *template_win_build_bootstrap
|
||||
variables:
|
||||
OS_IDENTIFIER: "windows-arm64"
|
||||
BUILD_LIBS_FOLDER: "build-libs-arm64"
|
||||
BUILD_LIBS_FOLDER: "$BUILD_LIBS_FOLDER_ARM64"
|
||||
ARCH_FLAG: "--arm64"
|
||||
needs:
|
||||
- job: sign:win:arm64:installer
|
||||
@@ -467,7 +474,7 @@ build:win:arm64:bootstrap:
|
||||
# Download the provisioning profiles from Nexus
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem --create-dirs -o data/provisioning_profile/embedded.provisionprofile "$NEXUS_PATH_ROOT/secrets/embedded.provisionprofile"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem --create-dirs -o data/provisioning_profile/splittunnelextension.provisionprofile "$NEXUS_PATH_ROOT/secrets/splittunnelextension.provisionprofile"
|
||||
- VERSION=$(python3 tools/base/extract.py)
|
||||
- VERSION=$(cmake -P cmake/print_version.cmake 2>&1)
|
||||
|
||||
build:mac:installer:
|
||||
<<: *template_mac_build
|
||||
@@ -479,6 +486,10 @@ build:mac:installer:
|
||||
- tools/build_all --ci-mode
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}.dmg "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/Windscribe_${VERSION}_universal.dmg"
|
||||
artifacts:
|
||||
paths:
|
||||
- build/src/helper/macos/com.windscribe.helper.macos
|
||||
expire_in: 1 day
|
||||
rules:
|
||||
- if: $BUILD_MAC == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH != null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -491,6 +502,10 @@ build:mac:installer:mr:
|
||||
script:
|
||||
- !reference [.build_mac_installer_common, script]
|
||||
- tools/build_all --ci-mode
|
||||
artifacts:
|
||||
paths:
|
||||
- build/src/helper/macos/com.windscribe.helper.macos
|
||||
expire_in: 1 day
|
||||
rules:
|
||||
- if: $BUILD_MAC == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -503,7 +518,7 @@ build:mac:installer:tagged:
|
||||
- !reference [.build_mac_installer_common, script]
|
||||
# Only tagged builds are notarized
|
||||
- tools/build_all --ci-mode --notarize
|
||||
- VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/Windscribe_${VERSION}.dmg "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/Windscribe_${VERSION}_universal.dmg"
|
||||
@@ -514,7 +529,7 @@ build:mac:installer:tagged:
|
||||
script:
|
||||
- !reference [.download_dependencies_posix, script]
|
||||
- if [ -d ./${BUILD_LIBS_FOLDER}/ ]; then for z in ./${BUILD_LIBS_FOLDER}/*.zip; do unzip -qod ./${BUILD_LIBS_FOLDER} $z; done; fi
|
||||
- VERSION=$(python3 tools/base/extract.py)
|
||||
- VERSION=$(cmake -P cmake/print_version.cmake 2>&1)
|
||||
|
||||
build:aarch64_ubuntu:installer:
|
||||
<<: *template_aarch64_ubuntu_build
|
||||
@@ -540,7 +555,7 @@ build:aarch64_ubuntu_cli:installer:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux-arm64"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --arm64 --build-cli-only --build-deb --build-rpm
|
||||
- tools/build_all --ci-mode --arm64 --integration=cli --build-deb --build-rpm
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe-cli_${VERSION}_arm64.deb "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/windscribe-cli_${VERSION}_arm64.deb"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
@@ -569,7 +584,7 @@ build:aarch64_ubuntu_cli:installer:mr:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux-arm64"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --arm64 --build-cli-only --build-deb --build-rpm
|
||||
- tools/build_all --ci-mode --arm64 --integration=cli --build-deb --build-rpm
|
||||
rules:
|
||||
- if: $BUILD_LINUX_ARM64 == "y" && $BUILD_LINUX_CLI == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -582,7 +597,7 @@ build:aarch64_ubuntu:installer:tagged:
|
||||
- OS_IDENTIFIER="linux-arm64"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --arm64 --build-deb --build-rpm
|
||||
- VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe_${VERSION}_arm64.deb "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe_${VERSION}_arm64.deb"
|
||||
@@ -599,8 +614,8 @@ build:aarch64_ubuntu_cli:installer:tagged:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux-arm64"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --arm64 --build-cli-only --build-deb --build-rpm
|
||||
- VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- tools/build_all --ci-mode --arm64 --integration=cli --build-deb --build-rpm
|
||||
- VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe-cli_${VERSION}_arm64.deb "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe-cli_${VERSION}_arm64.deb"
|
||||
@@ -635,7 +650,7 @@ build:rhel_cli:installer:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --build-cli-only
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --integration=cli
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe-cli_${VERSION}_amd64_fedora.rpm "${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/windscribe-cli_${VERSION}_amd64_fedora.rpm"
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
@@ -666,7 +681,7 @@ build:rhel_cli:installer:mr:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --build-cli-only
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --integration=cli
|
||||
rules:
|
||||
- if: $BUILD_LINUX == "y" && $BUILD_LINUX_CLI == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -679,7 +694,7 @@ build:rhel:installer:tagged:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse
|
||||
- VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe_${VERSION}_amd64_fedora.rpm "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe_${VERSION}_amd64_fedora.rpm"
|
||||
@@ -698,8 +713,8 @@ build:rhel_cli:installer:tagged:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --build-cli-only
|
||||
- VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- tools/build_all --ci-mode --build-deb --build-rpm --build-rpm-opensuse --integration=cli
|
||||
- VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
--upload-file build-exe/windscribe-cli_${VERSION}_amd64_fedora.rpm "${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe-cli_${VERSION}_amd64_fedora.rpm"
|
||||
@@ -721,8 +736,8 @@ build:rhel_cli:installer:tagged:
|
||||
- chmod g+ws ${ARCH_LINUX_BUILD_PATH}
|
||||
- setfacl -m u::rwx,g::rwx ${ARCH_LINUX_BUILD_PATH}
|
||||
- setfacl -d --set u::rwx,g::rwx,o::- ${ARCH_LINUX_BUILD_PATH}
|
||||
- export VERSION=$(python3 tools/base/extract.py)
|
||||
- export VERSION_NO_SUFFIX=$(python3 tools/base/extract.py --no-suffix)
|
||||
- export VERSION=$(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- export VERSION_NO_SUFFIX=$(cmake -DNO_SUFFIX=1 -P cmake/print_version.cmake 2>&1)
|
||||
|
||||
.build_archlinux_installer_makepkg:
|
||||
script:
|
||||
@@ -739,7 +754,7 @@ build:archlinux:installer:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_archlinux_installer_prep_build_dir, script]
|
||||
- cp src/installer/linux/gui/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- cp src/installer/gui/linux/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- export APP_DOWNLOAD_URL="${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/windscribe_${VERSION}_amd64.deb"
|
||||
- !reference [.build_archlinux_installer_makepkg, script]
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
@@ -759,7 +774,7 @@ build:archlinux_cli:installer:
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_archlinux_installer_prep_build_dir, script]
|
||||
- cp src/installer/linux/cli/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- cp src/installer/cli/linux/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- export APP_DOWNLOAD_URL="${NEXUS_PATH_BRANCH_UPLOAD}/${OS_IDENTIFIER}/windscribe-cli_${VERSION}_amd64.deb"
|
||||
- !reference [.build_archlinux_installer_makepkg, script]
|
||||
- curl --silent --show-error --fail -u "${NEXUS_USERNAME}:${NEXUS_PASSWORD}" --cacert tools/cacert.pem
|
||||
@@ -778,7 +793,7 @@ build:archlinux:installer:tagged:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- !reference [.build_archlinux_installer_prep_build_dir, script]
|
||||
- cp src/installer/linux/gui/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- cp src/installer/gui/linux/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- export APP_DOWNLOAD_URL=${NEXUS_PATH_TAGGED_UPLOAD}/$VERSION_NO_SUFFIX/windscribe_${VERSION}_amd64.deb
|
||||
- !reference [.build_archlinux_installer_makepkg, script]
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
@@ -798,7 +813,7 @@ build:archlinux_cli:installer:tagged:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- !reference [.build_archlinux_installer_prep_build_dir, script]
|
||||
- cp src/installer/linux/cli/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- cp src/installer/cli/linux/arch_package/* ${ARCH_LINUX_BUILD_PATH}
|
||||
- export APP_DOWNLOAD_URL=${NEXUS_PATH_TAGGED_UPLOAD}/$VERSION_NO_SUFFIX/windscribe-cli_${VERSION}_amd64.deb
|
||||
- !reference [.build_archlinux_installer_makepkg, script]
|
||||
- if [[ $CI_COMMIT_TAG =~ ^v[0-9] ]]; then TAG=${CI_COMMIT_TAG:1}; else TAG=${CI_COMMIT_TAG}; fi
|
||||
@@ -815,7 +830,7 @@ build:artifact:links:
|
||||
tags: [win10qty6]
|
||||
stage: Artifact Links
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/windows/Windscribe_${VERSION}_amd64.exe
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/windows-arm64/Windscribe_${VERSION}_arm64.exe
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/macos/Windscribe_${VERSION}_universal.dmg
|
||||
@@ -829,7 +844,7 @@ build:artifact:links:
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/linux/windscribe-cli_${VERSION}_amd64_opensuse.rpm
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/linux/windscribe_${VERSION}_amd64.pkg.tar.zst
|
||||
- echo ${NEXUS_PATH_BRANCH_UPLOAD}/linux/windscribe-cli_${VERSION}_amd64.pkg.tar.zst
|
||||
dependencies: []
|
||||
needs: []
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH != null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
@@ -837,7 +852,7 @@ build:artifact:links:tagged:
|
||||
tags: [win10qty6]
|
||||
stage: Artifact Links
|
||||
script:
|
||||
- Set-Variable -name VERSION -value $(python3 tools/base/extract.py)
|
||||
- Set-Variable -name VERSION -value $(cmake -P cmake/print_version.cmake 2>&1)
|
||||
- Set-Variable -name TAG -value $($CI_COMMIT_TAG -replace '^v([0-9].*)','$1')
|
||||
- echo ${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/Windscribe_${VERSION}_amd64.exe
|
||||
- echo ${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/Windscribe_${VERSION}_arm64.exe
|
||||
@@ -852,10 +867,63 @@ build:artifact:links:tagged:
|
||||
- echo ${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe-cli_${VERSION}_amd64_opensuse.rpm
|
||||
- echo ${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe_${VERSION}_amd64.pkg.tar.zst
|
||||
- echo ${NEXUS_PATH_TAGGED_UPLOAD}/${TAG}/windscribe-cli_${VERSION}_amd64.pkg.tar.zst
|
||||
dependencies: []
|
||||
needs: []
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG != null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
test:signature_check:win:
|
||||
<<: *template_win10_build
|
||||
stage: Test
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- Write-Host "Verifying USE_SIGNATURE_CHECK is enabled in helper binary..."
|
||||
- if (-not (Test-Path "build\temp\InstallerFiles\WindscribeService.exe")) {
|
||||
Write-Error "Helper binary not found - build artifacts may be missing!"; exit 1 }
|
||||
- if (-not (findstr /M /C:"verifyAppProcessPath" build\temp\InstallerFiles\WindscribeService.exe)) {
|
||||
Write-Error "FATAL - USE_SIGNATURE_CHECK is not compiled into the helper binary!"; exit 1 }
|
||||
- Write-Host "Signature check verification passed."
|
||||
needs:
|
||||
- job: build:win:x64:app
|
||||
optional: true
|
||||
artifacts: true
|
||||
- job: build:nightly:win
|
||||
optional: true
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $BUILD_WIN == "y" && ($CI_COMMIT_BRANCH != null || $NIGHTLY_TEST_BUILD == "y")
|
||||
|
||||
test:signature_check:mac:
|
||||
<<: *template_mac_build
|
||||
stage: Test
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- echo "Verifying USE_SIGNATURE_CHECK is enabled in helper binary..."
|
||||
- |
|
||||
HELPER="build/src/helper/macos/com.windscribe.helper.macos"
|
||||
if [ ! -f "$HELPER" ]; then
|
||||
echo "Helper binary not found - build artifacts may be missing!"
|
||||
exit 1
|
||||
fi
|
||||
if ! nm -u "$HELPER" | grep -q "SecCodeCreateWithXPCMessage"; then
|
||||
echo "FATAL - USE_SIGNATURE_CHECK is not compiled into the helper binary!"
|
||||
exit 1
|
||||
fi
|
||||
echo "Signature check verification passed."
|
||||
needs:
|
||||
- job: build:mac:installer
|
||||
optional: true
|
||||
artifacts: true
|
||||
- job: build:mac:installer:mr
|
||||
optional: true
|
||||
artifacts: true
|
||||
- job: build:nightly:mac
|
||||
optional: true
|
||||
artifacts: true
|
||||
rules:
|
||||
- if: $BUILD_MAC == "y" && ($CI_COMMIT_BRANCH != null || $NIGHTLY_TEST_BUILD == "y")
|
||||
|
||||
lint:flake8:
|
||||
<<: *template_win10_build
|
||||
stage: Test
|
||||
@@ -864,7 +932,7 @@ lint:flake8:
|
||||
script:
|
||||
- python3 -m pip install flake8
|
||||
- flake8 --ignore=E402,E501 tools
|
||||
dependencies: []
|
||||
needs: []
|
||||
rules:
|
||||
- if: $BUILD_WIN == "y"
|
||||
|
||||
@@ -874,11 +942,11 @@ test:translations:
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- $Unfinished = Select-String -Path src\client\frontend\gui\translations\*,src\installer\common\translations\*,src\installer\windows\uninstaller\translations\* -Pattern 'type="unfinished"'
|
||||
- $Unfinished = Select-String -Path src\client\frontend\gui\translations\*,src\installer\gui\installer-gui-common\translations\*,src\installer\gui\windows\uninstaller\translations\*,src\windscribe-cli\translations\* -Pattern 'type="unfinished"'
|
||||
- if ( $Unfinished.Matches.Count -ne 0 ) { echo "You have untranslated strings in your ts files. Run the translation script on the ts files and add them to the commit."; exit 1 }
|
||||
- $Vanished = Select-String -Path src\client\frontend\gui\translations\*,src\installer\common\translations\*,src\installer\windows\uninstaller\translations\* -Pattern 'type="vanished"'
|
||||
- $Vanished = Select-String -Path src\client\frontend\gui\translations\*,src\installer\gui\installer-gui-common\translations\*,src\installer\gui\windows\uninstaller\translations\*,src\windscribe-cli\translations\* -Pattern 'type="vanished"'
|
||||
- if ( $Vanished.Matches.Count -ne 0 ) { echo "You have vanished strings in your ts files. Run the translation script on the ts files with --remove-vanished and add them to the commit."; exit 1 }
|
||||
dependencies: []
|
||||
needs: []
|
||||
rules:
|
||||
- if: $BUILD_WIN == "y"
|
||||
|
||||
@@ -900,6 +968,55 @@ test:version:mac:
|
||||
echo "Files in src/splittunneling/macos were changed, but src/splittunneling/macos/Info.plist was not updated"
|
||||
exit 1
|
||||
fi
|
||||
dependencies: []
|
||||
needs: []
|
||||
rules:
|
||||
- if: $BUILD_MAC == "y" && $CI_COMMIT_TAG == null && $CI_COMMIT_BRANCH == null && $NIGHTLY_TEST_BUILD != "y"
|
||||
|
||||
build:nightly:win:
|
||||
<<: *template_win10_build
|
||||
stage: Build
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
VCPKG_ROOT: '%VCPKG_ROOT_WINDOWS%'
|
||||
VCPKG_DEFAULT_BINARY_CACHE: '%VCPKG_DEFAULT_BINARY_CACHE_WINDOWS%'
|
||||
script:
|
||||
- Set-Variable -name OS_IDENTIFIER -value "windows"
|
||||
- !reference [.download_dependencies_win, script]
|
||||
- 'IF(Test-Path .\$BUILD_LIBS_FOLDER\) {Get-ChildItem .\$BUILD_LIBS_FOLDER\*.zip | Foreach {.\tools\bin\7z.exe x $_.FullName -o"$BUILD_LIBS_FOLDER\"}}'
|
||||
- tools/build_all --ci-mode
|
||||
artifacts:
|
||||
paths:
|
||||
- build/temp/
|
||||
expire_in: 1 day
|
||||
rules:
|
||||
- if: $BUILD_WIN == "y" && $NIGHTLY_TEST_BUILD == "y"
|
||||
|
||||
build:nightly:mac:
|
||||
<<: *template_mac_build
|
||||
stage: Build
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- OS_IDENTIFIER="macos"
|
||||
- !reference [.build_mac_installer_common, script]
|
||||
- tools/build_all --ci-mode
|
||||
artifacts:
|
||||
paths:
|
||||
- build/src/helper/macos/com.windscribe.helper.macos
|
||||
expire_in: 1 day
|
||||
rules:
|
||||
- if: $BUILD_MAC == "y" && $NIGHTLY_TEST_BUILD == "y"
|
||||
|
||||
build:nightly:rhel:
|
||||
<<: *template_rhel_build
|
||||
stage: Build
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
script:
|
||||
- OS_IDENTIFIER="linux"
|
||||
- !reference [.build_linux_installer_common, script]
|
||||
- python3 -m pip install "clang-tidy<21"
|
||||
- tools/build_all --ci-mode --static-analysis
|
||||
rules:
|
||||
- if: $BUILD_LINUX == "y" && $NIGHTLY_TEST_BUILD == "y"
|
||||
|
||||
|
||||
+61
-1
@@ -1,3 +1,64 @@
|
||||
2.22.4 (10/04/2026)
|
||||
All:
|
||||
* Improved WireGuard PersistentKeepalive to use a value of 25 on all platforms. #1741
|
||||
* Fixed server sub-menus for the locations list in the OS tray menu should have a delay before being displayed. #1737
|
||||
* Fixed protocol indicates "WireGuard" while disconnected and selected location is an OpenVPN custom config. #1740
|
||||
* Fixed WireGuard key limit dialog overlaps notification banners on app launch. #1742
|
||||
Windows:
|
||||
* Fixed IKEv2 connection process may fail. Regression introduced in 2.22.2. #1739
|
||||
* Fixed third-party custom config may no longer passes tunnel test. 1743
|
||||
macOS:
|
||||
* Fixed factory reset does not fully reset preferences. #1744
|
||||
Linux:
|
||||
* Fixed third-party custom config may no longer passes tunnel test. 1743
|
||||
|
||||
|
||||
2.22.3 (08/04/2026)
|
||||
All:
|
||||
* Added a 'ports' command to the CLI. #1731
|
||||
* Improved filtering of potentially malicious directives in OpenVPN custom configs, which could lead to a privilege escalation. #1729
|
||||
* Fixed standard/hashed login text overlaps when language set to Belarusian. #1736
|
||||
* Updated c-ares back to 1.34.5 due to DNS resoluton issues with 1.34.6. #1733
|
||||
macOS:
|
||||
* Fixed network connectivity lost after disconnecting due to regression caused by #1720 in the 2.22.2 release. #1735
|
||||
|
||||
|
||||
2.22.2 (02/04/2026)
|
||||
All:
|
||||
* Added Belarusian (Taraškievica) localization. Community contribution by dubovy-achvelak. #1723
|
||||
* Improved "No P2P" icon to display per-city (datacenter) instead of per-country in the locations list. #1594
|
||||
* Fixed wsnet receiving system language rather than user's preferred language. #1716
|
||||
* Fixed news feed title is clipped and entry height miscalculated when entry is expanded. #1721
|
||||
* Fixed location list hover states broken after clicking main window. #1600
|
||||
* Fixed executable signature verification mechanism disabled by #1678. #1728
|
||||
* Updated to Qt 6.11.0. #1692
|
||||
* Updated to c-ares 1.34.6, cURL 8.18.0, and OpenSSL 3.6.1. #1710
|
||||
Windows:
|
||||
* Fixed WireGuard service may start then terminate immediately in a loop after wake from sleep. #1720
|
||||
* Updated OpenVPN DCO driver to 2.8.2. #1717
|
||||
macOS:
|
||||
* Fixed call continuity doesn't work with firewall enabled. #1724
|
||||
|
||||
|
||||
2.22.1 (26/03/2026)
|
||||
All:
|
||||
* Added support for the new server list v2 API. #1594
|
||||
* Improved build system for future flexibility. #1678
|
||||
* Fixed nightly tests. #1696
|
||||
* Fixed incorrect code organization. #1711
|
||||
* Fixed Manage Account and other browser links opening production website in staging mode. #1713
|
||||
* Updated ctrld to 1.5.0. #1689
|
||||
Windows:
|
||||
* Improved BFE service status detection on Windows when SCM access is restricted from unelevated processes. #1699
|
||||
* Fixed possible app crash when initiating an IKEv2 connection. #1100
|
||||
* Fixed potential deadlock at app start. #1712
|
||||
macOS:
|
||||
* Improved installer dmg generation by switching back to dmgbuild. #1715
|
||||
* Fixed OpenVPN TCP fails to connect when LAN proxy feature is enabled. #1695
|
||||
* Fixed multicast traffic not working on split tunneled apps. #1709
|
||||
* Fixed potential deadlock at app start. #1712
|
||||
|
||||
|
||||
2.21.7 (23/03/2026)
|
||||
All:
|
||||
* Fixed e-mail field should not show for hashed accounts. #1704
|
||||
@@ -16,7 +77,6 @@ All:
|
||||
* Fixed rotating the MAC address causing the tunnel test phase to get stuck. #1686
|
||||
Windows:
|
||||
* Fixed IP pinning and rotation features may be disabled when using Circumvent Censorship. #1654
|
||||
* Fixed WireGuard may fail to reconnect on PC wake when using Circumvent Censorship. #1688
|
||||
|
||||
|
||||
2.21.5 (09/03/2026)
|
||||
|
||||
@@ -14,7 +14,7 @@ This application provides secure, private internet access by routing your traffi
|
||||
|
||||
**Supported Platforms**:
|
||||
- Windows 10/11 (amd64, arm64), Windows Server 2022
|
||||
- macOS 12+ (amd64, arm64)
|
||||
- macOS 13+ (amd64, arm64)
|
||||
- Ubuntu 22.04+, Fedora 36+, openSUSE Leap 15.6, Arch, immutable distros (amd64, arm64)
|
||||
|
||||
### Key Features
|
||||
@@ -170,7 +170,7 @@ Most components have separate implementations:
|
||||
- **vcpkg** - C++ package manager
|
||||
- **Ninja** - Build backend (Windows)
|
||||
- **Visual Studio 2022** - Windows compiler
|
||||
- **Xcode 14.2** - macOS compiler
|
||||
- **Xcode 15+** - macOS compiler
|
||||
- **GCC** - Linux compiler
|
||||
|
||||
### VPN Protocols & Implementations
|
||||
|
||||
+104
-78
@@ -1,6 +1,6 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Windscribe Build System
|
||||
# Copyright (c) 2020-2025, Windscribe Limited. All rights reserved.
|
||||
# Copyright (c) 2020-2026, Windscribe Limited. All rights reserved.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
@@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.23)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # option() honors normal variables
|
||||
|
||||
# Set macOS deployment target and architecture before project()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "Minimum OS X deployment version")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "13" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
# Detect and set macOS architecture to match host unless in CI mode (which builds universal)
|
||||
if(APPLE AND NOT CI_MODE AND NOT DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
@@ -30,35 +30,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# MSVC runtime library (static linkage)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# Read version from header file
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/src/client/client-common/version/windscribe_version.h"
|
||||
VERSION_MAJOR_LINE REGEX "^#define WINDSCRIBE_MAJOR_VERSION")
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/src/client/client-common/version/windscribe_version.h"
|
||||
VERSION_MINOR_LINE REGEX "^#define WINDSCRIBE_MINOR_VERSION")
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/src/client/client-common/version/windscribe_version.h"
|
||||
VERSION_BUILD_LINE REGEX "^#define WINDSCRIBE_BUILD_VERSION")
|
||||
|
||||
string(REGEX REPLACE "^#define WINDSCRIBE_MAJOR_VERSION ([0-9]+).*" "\\1"
|
||||
WINDSCRIBE_VERSION_MAJOR "${VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define WINDSCRIBE_MINOR_VERSION ([0-9]+).*" "\\1"
|
||||
WINDSCRIBE_VERSION_MINOR "${VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define WINDSCRIBE_BUILD_VERSION ([0-9]+).*" "\\1"
|
||||
WINDSCRIBE_VERSION_BUILD "${VERSION_BUILD_LINE}")
|
||||
|
||||
# Detect build type (guinea pig, beta, or stable)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/src/client/client-common/version/windscribe_version.h" VERSION_FILE_CONTENTS)
|
||||
if(VERSION_FILE_CONTENTS MATCHES "^[^/]*#define WINDSCRIBE_IS_GUINEA_PIG" OR
|
||||
VERSION_FILE_CONTENTS MATCHES "\n[^/]*#define WINDSCRIBE_IS_GUINEA_PIG")
|
||||
set(WINDSCRIBE_BUILD_TYPE "guinea_pig")
|
||||
set(WINDSCRIBE_BUILD_SUFFIX "_guinea_pig")
|
||||
elseif(VERSION_FILE_CONTENTS MATCHES "^[^/]*#define WINDSCRIBE_IS_BETA" OR
|
||||
VERSION_FILE_CONTENTS MATCHES "\n[^/]*#define WINDSCRIBE_IS_BETA")
|
||||
set(WINDSCRIBE_BUILD_TYPE "beta")
|
||||
set(WINDSCRIBE_BUILD_SUFFIX "_beta")
|
||||
else()
|
||||
set(WINDSCRIBE_BUILD_TYPE "stable")
|
||||
set(WINDSCRIBE_BUILD_SUFFIX "")
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Build Options (defaults match build_all.py behavior)
|
||||
@@ -66,16 +37,22 @@ endif()
|
||||
|
||||
option(BUILD_APP "Build the main GUI application" ON)
|
||||
option(BUILD_INSTALLER "Build the installer" ON)
|
||||
option(BUILD_CLI_ONLY "Build CLI-only version (Linux)" OFF)
|
||||
option(BUILD_TESTS "Build test executables" OFF)
|
||||
set(INTEGRATION_TYPE "gui" CACHE STRING "Integration type to build (e.g. gui, cli)")
|
||||
option(SIGN_APP "Enable app code signing" OFF)
|
||||
option(SIGN_INSTALLER "Enable installer code signing" OFF)
|
||||
option(SIGN_BOOTSTRAP "Enable bootstrap code signing" OFF)
|
||||
option(ENABLE_NOTARIZE "Enable macOS notarization" OFF)
|
||||
option(CI_MODE "CI-specific behavior" OFF)
|
||||
if(CI_MODE)
|
||||
set(DEFINE_USE_SIGNATURE_CHECK_MACRO ON CACHE BOOL "Add define USE_SIGNATURE_CHECK to project" FORCE)
|
||||
endif()
|
||||
option(BUILD_SYMBOLS "Collect PDB symbol files" OFF)
|
||||
option(STATIC_ANALYSIS "Run clang-tidy static analysis" OFF)
|
||||
option(UPDATE_TRANSLATIONS "Run lupdate to regenerate .ts translation files" OFF)
|
||||
|
||||
# Platform-specific build options
|
||||
# Platform-specific build options (these use WIN32/APPLE which are set before project()
|
||||
# when using a platform-native generator, e.g. Visual Studio on Windows)
|
||||
if(WIN32)
|
||||
option(BUILD_BOOTSTRAP "Build the bootstrap (Windows only)" ON)
|
||||
option(BUILD_ARM64 "Build for ARM64 architecture" OFF)
|
||||
@@ -101,14 +78,13 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
|
||||
include(cmake/architectures.cmake)
|
||||
|
||||
# Static Analysis Configuration
|
||||
if(STATIC_ANALYSIS)
|
||||
set(CMAKE_CXX_CLANG_TIDY
|
||||
"clang-tidy"
|
||||
"--checks=-clang-analyzer-optin.cplusplus.VirtualCall,-clang-diagnostic-deprecated-declarations,-clang-analyzer-osx.cocoa.RetainCount"
|
||||
"--allow-no-checks"
|
||||
"--checks=clang-analyzer-*,-clang-analyzer-optin.cplusplus.VirtualCall,-clang-diagnostic-deprecated-declarations,-clang-analyzer-osx.cocoa.RetainCount"
|
||||
"--header-filter=.*/(src|libs)/.*"
|
||||
"--exclude-header-filter=.*vcpkg/.*"
|
||||
"--warnings-as-errors=*"
|
||||
)
|
||||
endif()
|
||||
@@ -122,11 +98,79 @@ if(BUILD_APP OR BUILD_INSTALLER OR BUILD_BOOTSTRAP)
|
||||
include(cmake/vcpkg.cmake)
|
||||
endif()
|
||||
|
||||
project(Windscribe
|
||||
VERSION ${WINDSCRIBE_VERSION_MAJOR}.${WINDSCRIBE_VERSION_MINOR}.${WINDSCRIBE_VERSION_BUILD}
|
||||
DESCRIPTION "Windscribe VPN Client"
|
||||
LANGUAGES CXX C
|
||||
project(WS LANGUAGES CXX C)
|
||||
|
||||
include(cmake/architectures.cmake)
|
||||
|
||||
# Load integration configuration (after architectures.cmake so that
|
||||
# WINDSCRIBE_BUILD_LIBS_PATH and PACKAGE_ARCH are available)
|
||||
set(WS_INTEGRATION_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/cmake/integrations/${INTEGRATION_TYPE}.cmake")
|
||||
if(NOT EXISTS "${WS_INTEGRATION_CONFIG}")
|
||||
message(FATAL_ERROR "Integration config not found: ${WS_INTEGRATION_CONFIG}")
|
||||
endif()
|
||||
include("${WS_INTEGRATION_CONFIG}")
|
||||
|
||||
set(PROJECT_VERSION "${WS_VERSION_MAJOR}.${WS_VERSION_MINOR}.${WS_VERSION_BUILD}" CACHE STRING "" FORCE)
|
||||
|
||||
include(cmake/utilities.cmake)
|
||||
|
||||
# Derive build suffix from build type (empty for stable releases)
|
||||
if(WS_BUILD_TYPE STREQUAL "stable")
|
||||
set(WS_BUILD_SUFFIX "")
|
||||
else()
|
||||
set(WS_BUILD_SUFFIX "${WS_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
# Expose branding to C++ code
|
||||
add_compile_definitions(
|
||||
WS_APP_EXECUTABLE_NAME="${WS_APP_EXECUTABLE_NAME}"
|
||||
WS_CLI_EXECUTABLE_NAME="${WS_CLI_EXECUTABLE_NAME}"
|
||||
WS_APP_IDENTIFIER="${WS_APP_IDENTIFIER}"
|
||||
WS_COPYRIGHT="${WS_COPYRIGHT}"
|
||||
WS_EXTRA_CONFIG_NAME="${WS_EXTRA_CONFIG_NAME}"
|
||||
WS_LINUX_INSTALL_DIR="${WS_LINUX_INSTALL_DIR}"
|
||||
WS_LINUX_LOG_DIR="${WS_LINUX_LOG_DIR}"
|
||||
WS_LINUX_TMP_DIR="${WS_LINUX_TMP_DIR}"
|
||||
WS_MAC_APP_DIR="${WS_MAC_APP_DIR}"
|
||||
WS_MAC_GID="${WS_MAC_GID}"
|
||||
WS_MAC_GUI_BUNDLE_ID="${WS_MAC_GUI_BUNDLE_ID}"
|
||||
WS_MAC_HELPER_BUNDLE_ID="${WS_MAC_HELPER_BUNDLE_ID}"
|
||||
WS_MAC_HELPER_BUNDLE_ID_PATH="Contents/Library/LaunchServices/${WS_MAC_HELPER_BUNDLE_ID}"
|
||||
WS_MAC_IKEV2_KEYCHAIN_SERVICE="${WS_MAC_IKEV2_KEYCHAIN_SERVICE}"
|
||||
WS_MAC_INSTALLER_BUNDLE_ID="${WS_MAC_INSTALLER_BUNDLE_ID}"
|
||||
WS_MAC_INSTALLER_BUNDLE_NAME="${WS_MAC_INSTALLER_BUNDLE_NAME}"
|
||||
WS_MAC_INSTALLER_INNER_BINARY="Contents/MacOS/${WS_MAC_INSTALLER_TARGET}"
|
||||
WS_MAC_LAUNCHER_BUNDLE_ID="${WS_MAC_LAUNCHER_BUNDLE_ID}"
|
||||
WS_MAC_SPLIT_TUNNEL_BUNDLE_ID="${WS_MAC_SPLIT_TUNNEL_BUNDLE_ID}"
|
||||
WS_MAC_UID="${WS_MAC_UID}"
|
||||
WS_MAC_VPN_DESCRIPTION="${WS_MAC_VPN_DESCRIPTION}"
|
||||
WS_POSIX_CONFIG_DIR="${WS_POSIX_CONFIG_DIR}"
|
||||
WS_POSIX_RUN_DIR="${WS_POSIX_RUN_DIR}"
|
||||
WS_PRODUCT_NAME="${WS_PRODUCT_NAME}"
|
||||
WS_PRODUCT_NAME_LOWER="${WS_PRODUCT_NAME_LOWER}"
|
||||
WS_PRODUCT_NAME_UPPER="${WS_PRODUCT_NAME_UPPER}"
|
||||
WS_SETTINGS_APP="${WS_SETTINGS_APP}"
|
||||
WS_SETTINGS_ORG="${WS_SETTINGS_ORG}"
|
||||
WS_VERSION="${WS_VERSION_MAJOR}.${WS_VERSION_MINOR}.${WS_VERSION_BUILD}"
|
||||
WS_VERSION_BUILD=${WS_VERSION_BUILD}
|
||||
WS_VERSION_MAJOR=${WS_VERSION_MAJOR}
|
||||
WS_VERSION_MAJOR_MINOR="${WS_VERSION_MAJOR}.${WS_VERSION_MINOR}"
|
||||
WS_VERSION_MINOR=${WS_VERSION_MINOR}
|
||||
WS_WIN_CONFIG_SUBDIR="${WS_WIN_CONFIG_SUBDIR}"
|
||||
WS_WIN_IKEV2_CONNECTION_NAME="${WS_WIN_IKEV2_CONNECTION_NAME}"
|
||||
)
|
||||
if(DEFINED WS_COMPILE_DEFINITIONS)
|
||||
add_compile_definitions(${WS_COMPILE_DEFINITIONS})
|
||||
endif()
|
||||
if(WS_BUILD_TYPE STREQUAL "guinea_pig")
|
||||
add_compile_definitions(WINDSCRIBE_IS_GUINEA_PIG)
|
||||
elseif(WS_BUILD_TYPE STREQUAL "beta")
|
||||
add_compile_definitions(WINDSCRIBE_IS_BETA)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_SYSTEM_NAME IN_LIST WS_SUPPORTED_PLATFORMS)
|
||||
message(FATAL_ERROR "Integration '${INTEGRATION_TYPE}' does not support ${CMAKE_SYSTEM_NAME}. Supported: ${WS_SUPPORTED_PLATFORMS}")
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Build Configuration Summary
|
||||
@@ -137,7 +181,7 @@ message(STATUS "==================================================")
|
||||
message(STATUS "Windscribe Build Configuration Summary")
|
||||
message(STATUS "==================================================")
|
||||
message(STATUS "Version: ${PROJECT_VERSION}")
|
||||
message(STATUS "Build Variant: ${WINDSCRIBE_BUILD_TYPE}")
|
||||
message(STATUS "Build Variant: ${WS_BUILD_TYPE}")
|
||||
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "Platform: ${CMAKE_SYSTEM_NAME}")
|
||||
if(APPLE)
|
||||
@@ -148,13 +192,14 @@ endif()
|
||||
message(STATUS "CI Mode: ${CI_MODE}")
|
||||
message(STATUS "")
|
||||
message(STATUS "Build Options:")
|
||||
message(STATUS " Integration: ${INTEGRATION_TYPE}")
|
||||
if(UNIX AND NOT APPLE)
|
||||
message(STATUS " CLI Only: ${BUILD_CLI_ONLY}")
|
||||
message(STATUS " Build DEB: ${BUILD_DEB}")
|
||||
message(STATUS " Build RPM: Fedora ${BUILD_RPM} OpenSUSE ${BUILD_RPM_OPENSUSE}")
|
||||
endif()
|
||||
message(STATUS " Build Tests: ${BUILD_TESTS}")
|
||||
message(STATUS " Static Analysis: ${STATIC_ANALYSIS}")
|
||||
message(STATUS " Translations: ${UPDATE_TRANSLATIONS}")
|
||||
if(APPLE)
|
||||
message(STATUS " Notarization: ${ENABLE_NOTARIZE}")
|
||||
endif()
|
||||
@@ -179,6 +224,10 @@ if(NOT EXISTS "${WINDSCRIBE_BUILD_LIBS_PATH}")
|
||||
message(WARNING "Dependencies directory not found: ${WINDSCRIBE_BUILD_LIBS_PATH}")
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
ws_resolve_bundled_helpers()
|
||||
ws_resolve_shared_libs()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Code Signing Configuration
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -194,24 +243,11 @@ if(BUILD_APP)
|
||||
set(IS_BUILD_TESTS ON)
|
||||
endif()
|
||||
|
||||
# Utility programs
|
||||
if(WIN32)
|
||||
add_subdirectory(src/utils/windows/windscribe_install_helper)
|
||||
add_subdirectory(src/utils/windows/wireguard_service)
|
||||
add_subdirectory(src/installer/windows/uninstaller)
|
||||
elseif(APPLE)
|
||||
add_subdirectory(src/utils/macos/launcher)
|
||||
add_subdirectory(src/splittunneling/macos)
|
||||
elseif(UNIX)
|
||||
add_subdirectory(src/utils/linux/authhelper)
|
||||
endif()
|
||||
# Additional components from integration config
|
||||
foreach(_subdir ${WS_ADDITIONAL_SUBDIRS})
|
||||
add_subdirectory(${_subdir})
|
||||
endforeach()
|
||||
|
||||
if(BUILD_CLI_ONLY)
|
||||
set(DEFINE_CLI_ONLY_MACRO ON CACHE BOOL "Build GUI-less client" FORCE)
|
||||
endif()
|
||||
|
||||
# Main GUI application
|
||||
add_subdirectory(src/windscribe-cli)
|
||||
add_subdirectory(src/helper)
|
||||
add_subdirectory(src/client)
|
||||
|
||||
@@ -219,38 +255,28 @@ if(BUILD_APP)
|
||||
include("${CMAKE_SOURCE_DIR}/cmake/fetch_wsnet.cmake")
|
||||
|
||||
if(WIN32)
|
||||
add_custom_target(build-app ALL
|
||||
DEPENDS Windscribe windscribe-cli WindscribeService WindscribeInstallHelper WireguardService uninstall
|
||||
)
|
||||
add_custom_target(build-app ALL DEPENDS ${WS_WIN_APP_TARGETS})
|
||||
elseif(APPLE)
|
||||
add_custom_target(build-app ALL
|
||||
DEPENDS Windscribe windscribe-cli com.windscribe.helper.macos WindscribeLauncher com.windscribe.client.splittunnelextension
|
||||
)
|
||||
add_custom_target(build-app ALL DEPENDS ${WS_MAC_APP_TARGETS})
|
||||
elseif(UNIX)
|
||||
add_custom_target(build-app ALL
|
||||
DEPENDS Windscribe windscribe-cli helper windscribe-authhelper
|
||||
)
|
||||
add_custom_target(build-app ALL DEPENDS ${WS_LINUX_APP_TARGETS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Installers
|
||||
if(BUILD_INSTALLER)
|
||||
if(WIN32)
|
||||
add_subdirectory(src/installer/windows/installer)
|
||||
add_subdirectory(src/installer/${INSTALLER_TYPE}/windows/installer)
|
||||
elseif(APPLE)
|
||||
add_subdirectory(src/installer/mac/installer)
|
||||
add_subdirectory(src/installer/${INSTALLER_TYPE}/macos/installer)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_BOOTSTRAP)
|
||||
if(WIN32)
|
||||
if(BUILD_ARM64)
|
||||
set(WINDSCRIBE_ARCH_SUFFIX "_arm64")
|
||||
else()
|
||||
set(WINDSCRIBE_ARCH_SUFFIX "_amd64")
|
||||
endif()
|
||||
set(WINDSCRIBE_INSTALLER_NAME "Windscribe_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}${WINDSCRIBE_ARCH_SUFFIX}.exe" CACHE STRING "Name of internal installer exe")
|
||||
add_subdirectory(src/installer/windows/bootstrap)
|
||||
ws_resolve_output_name("${WS_WIN_OUTPUT_NAME}" _resolved_installer_name)
|
||||
set(WINDSCRIBE_INSTALLER_NAME "${_resolved_installer_name}.exe" CACHE STRING "Name of internal installer exe")
|
||||
add_subdirectory(src/installer/${INSTALLER_TYPE}/windows/bootstrap)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ The Windscribe VPN desktop application hides your physical location, blocks ads
|
||||
- Windows 10/11 amd64 (minimum build 17763)
|
||||
- Windows 11 arm64
|
||||
- Windows Server 2022 amd64
|
||||
- macOS 12+ (amd64, arm64)
|
||||
- macOS 13+ (amd64, arm64)
|
||||
- Ubuntu 22.04+ (amd64, arm64)
|
||||
- Fedora 36+ (amd64, arm64)
|
||||
- openSUSE Leap 15.6 amd64
|
||||
@@ -113,13 +113,12 @@ See `build_all --help` for other build options.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- macOS Big Sur or newer, but preferably at least Monterey.
|
||||
- Install Xcode 14.2 (If on MacOS 11 Big Sur, you may use Xcode 13.2.1, but this is deprecated and not maintained going forward)
|
||||
- Xcode 15 is not currently supported. You may install a copy of Xcode 14.2 and use `sudo xcode-select --switch /path/to/your/xcode` to have both Xcode 13/14 and 15 simultaneously.
|
||||
- macOS Ventura (13) or newer.
|
||||
- Install Xcode 15 or newer.
|
||||
- You must agree to the Xcode license (`sudo xcodebuild -license`)
|
||||
- You may need to run `xcodebuild -runFirstLaunch` or the Xcode GUI once if CMake complains that it can't find the compiler when building using the Xcode generator.
|
||||
- Note: these downloads will require you to first login to your Apple account.
|
||||
- https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_14.2/Xcode_14.2.xip
|
||||
- https://xcodereleases.com
|
||||
- Install brew (brew.sh)
|
||||
```bash
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
@@ -141,11 +140,6 @@ See `build_all --help` for other build options.
|
||||
pyenv install 3.11.6
|
||||
pyenv global 3.11.6
|
||||
```
|
||||
- Install create-dmg:
|
||||
```bash
|
||||
brew install create-dmg
|
||||
```
|
||||
|
||||
- Install CMake v3.28.x or newer from [here](https://cmake.org/download/) and make sure that the cmake executable is in the path and available for execution. The project will build with older versions of CMake, but you may encounter some warnings.
|
||||
- Clone the [ws-vcpkg-registry](https://github.com/Windscribe/ws-vcpkg-registry) and run its installation script to set up vcpkg. Then set the `VCPKG_ROOT` environment variable to the path you chose:
|
||||
```bash
|
||||
|
||||
+16
-16
@@ -3,46 +3,46 @@
|
||||
# Handles multi-architecture builds and platform-specific settings
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Product subdirectory under build-libs/ for dependency artifacts.
|
||||
# Defaults to "windscribe"; override with -DWS_BUILD_LIBS_SUBDIR=<product> for whitelabel builds.
|
||||
# Also set in each integration file (e.g. windscribe.cmake) for documentation.
|
||||
if(NOT DEFINED WS_BUILD_LIBS_SUBDIR)
|
||||
set(WS_BUILD_LIBS_SUBDIR "windscribe" CACHE STRING "Product subdirectory under build-libs")
|
||||
endif()
|
||||
|
||||
# Windows architecture handling
|
||||
if(WIN32)
|
||||
if(BUILD_ARM64)
|
||||
set(WINDSCRIBE_ARCH "arm64")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs-arm64" CACHE PATH "Custom build libraries path")
|
||||
message(STATUS "Building for ARM64 architecture")
|
||||
set(PACKAGE_ARCH "arm64")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs-arm64/${WS_BUILD_LIBS_SUBDIR}" CACHE PATH "Custom build libraries path")
|
||||
else()
|
||||
set(WINDSCRIBE_ARCH "x86_64")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs" CACHE PATH "Custom build libraries path")
|
||||
message(STATUS "Building for x86_64 architecture")
|
||||
set(PACKAGE_ARCH "amd64")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs/${WS_BUILD_LIBS_SUBDIR}" CACHE PATH "Custom build libraries path")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# macOS architecture handling
|
||||
if(APPLE)
|
||||
if(CI_MODE)
|
||||
# Universal binary on CI
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "macOS architectures" FORCE)
|
||||
message(STATUS "Building universal binary (arm64 + x86_64)")
|
||||
elseif(NOT DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
# Native architecture
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "macOS architectures" FORCE)
|
||||
else()
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "macOS architectures" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs" CACHE PATH "Custom build libraries path")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs/${WS_BUILD_LIBS_SUBDIR}" CACHE PATH "Custom build libraries path")
|
||||
endif()
|
||||
|
||||
# Linux architecture handling
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(WINDSCRIBE_ARCH "aarch64")
|
||||
set(PACKAGE_ARCH "arm64")
|
||||
else()
|
||||
set(WINDSCRIBE_ARCH "x86_64")
|
||||
set(PACKAGE_ARCH "amd64")
|
||||
endif()
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs" CACHE PATH "Custom build libraries path")
|
||||
message(STATUS "Building for ${WINDSCRIBE_ARCH} architecture")
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-libs/${WS_BUILD_LIBS_SUBDIR}" CACHE PATH "Custom build libraries path")
|
||||
endif()
|
||||
|
||||
# Export WINDSCRIBE_BUILD_LIBS_PATH for use in component CMakeLists.txt files
|
||||
message(STATUS "Custom build libraries path: ${WINDSCRIBE_BUILD_LIBS_PATH}")
|
||||
message(STATUS "Build libraries path: ${WINDSCRIBE_BUILD_LIBS_PATH}")
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configure a single dependency template file with integration-specific values.
|
||||
# This is used to configure dependencies in tools/deps with custom branding.
|
||||
#
|
||||
# Invoked as:
|
||||
# cmake -DPRODUCT=windscribe -DINPUT_FILE=<template.in> -DOUTPUT_FILE=<output>
|
||||
# -P cmake/configure_dependency.cmake
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
if(NOT DEFINED PRODUCT)
|
||||
message(FATAL_ERROR "PRODUCT is not defined")
|
||||
endif()
|
||||
if(NOT DEFINED INPUT_FILE)
|
||||
message(FATAL_ERROR "INPUT_FILE is not defined")
|
||||
endif()
|
||||
if(NOT DEFINED OUTPUT_FILE)
|
||||
message(FATAL_ERROR "OUTPUT_FILE is not defined")
|
||||
endif()
|
||||
|
||||
set(WS_INTEGRATION_CONFIG "${CMAKE_CURRENT_LIST_DIR}/integrations/${PRODUCT}.cmake")
|
||||
if(NOT EXISTS "${WS_INTEGRATION_CONFIG}")
|
||||
message(FATAL_ERROR "Integration config not found: ${WS_INTEGRATION_CONFIG}")
|
||||
endif()
|
||||
include("${WS_INTEGRATION_CONFIG}")
|
||||
|
||||
configure_file("${INPUT_FILE}" "${OUTPUT_FILE}" @ONLY)
|
||||
@@ -1,8 +1,8 @@
|
||||
if(NOT TARGET wsnet::wsnet)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(wsnet
|
||||
GIT_REPOSITORY git@github.com:Windscribe/wsnet.git
|
||||
GIT_TAG 1.4.8
|
||||
GIT_REPOSITORY https://github.com/Windscribe/wsnet.git
|
||||
GIT_TAG 1.5.6
|
||||
)
|
||||
FetchContent_MakeAvailable(wsnet)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Integration Configuration: Windscribe CLI
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/windscribe.cmake)
|
||||
|
||||
set(WS_SUPPORTED_PLATFORMS Linux)
|
||||
|
||||
set(FRONTEND_TYPE "cli")
|
||||
set(INSTALLER_TYPE "cli")
|
||||
|
||||
list(APPEND WS_COMPILE_DEFINITIONS CLI_ONLY)
|
||||
set(WS_SETTINGS_CLI "${WS_PRODUCT_NAME_LOWER}_cli")
|
||||
|
||||
list(APPEND WS_COMPILE_DEFINITIONS WS_SETTINGS_CLI="${WS_SETTINGS_CLI}")
|
||||
set(WS_QT_COMPONENTS Network LinguistTools Test)
|
||||
|
||||
set(WS_LINUX_PACKAGE_NAME "windscribe-cli")
|
||||
set(WS_LINUX_OUTPUT_NAME "windscribe-cli_@VERSION@_@SUFFIX@_@ARCH@")
|
||||
@@ -0,0 +1,125 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Integration Configuration: Windscribe GUI
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/windscribe.cmake)
|
||||
|
||||
set(WS_SUPPORTED_PLATFORMS Windows Darwin Linux)
|
||||
|
||||
set(FRONTEND_TYPE "gui")
|
||||
set(INSTALLER_TYPE "gui")
|
||||
|
||||
set(WS_CLIENT_EXTRA_LIBS Qt6::Widgets)
|
||||
set(WS_QT_COMPONENTS Widgets Network LinguistTools Test)
|
||||
# For convenience, since many paths are relative to the installer directory
|
||||
set(WS_INSTALLER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}")
|
||||
|
||||
|
||||
###
|
||||
### Windows
|
||||
###
|
||||
|
||||
set(WS_WIN_APP_ICON "frontend/gui/resources/icons/win/windscribe.ico")
|
||||
|
||||
# User-visible IKEv2 connection name shown in Windows network settings.
|
||||
set(WS_WIN_IKEV2_CONNECTION_NAME "Windscribe IKEv2")
|
||||
|
||||
set(WS_WIN_INSTALLER_TARGET "installer")
|
||||
set(WS_WIN_BOOTSTRAP_TARGET "bootstrap")
|
||||
|
||||
# build-app dependencies
|
||||
set(WS_WIN_APP_TARGETS
|
||||
${WS_APP_TARGET} ${WS_CLI_TARGET} ${WS_APP_IDENTIFIER}Service InstallHelper WireguardService uninstall)
|
||||
set(WS_WIN_PDB_TARGETS
|
||||
${WS_APP_TARGET} ${WS_CLI_TARGET} ${WS_APP_IDENTIFIER}Service InstallHelper WireguardService)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND WS_ADDITIONAL_SUBDIRS
|
||||
src/windscribe-cli
|
||||
src/utils/windows/install_helper
|
||||
src/utils/windows/wireguard_service
|
||||
src/installer/${INSTALLER_TYPE}/windows/uninstaller)
|
||||
endif()
|
||||
|
||||
# Windows additional files to copy into the installer package.
|
||||
# Each entry is "source_path|dest_path". Use DIR: prefix for directory copies.
|
||||
set(WS_WIN_ADDITIONAL_FILES
|
||||
"DIR:${WS_INSTALLER_DIR}/windows/additional_files/qt|qt"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wintun/bin/wintun.dll|wintun.dll"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.cat|openvpndco/win10/ovpn-dco.cat"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.inf|openvpndco/win10/ovpn-dco.inf"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.sys|openvpndco/win10/ovpn-dco.sys"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.cat|openvpndco/win11/ovpn-dco.cat"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.inf|openvpndco/win11/ovpn-dco.inf"
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.sys|openvpndco/win11/ovpn-dco.sys"
|
||||
"${WS_INSTALLER_DIR}/windows/additional_files/driver_utils/${PACKAGE_ARCH}/devcon.exe|devcon.exe"
|
||||
"${WS_INSTALLER_DIR}/windows/additional_files/driver_utils/${PACKAGE_ARCH}/tapctl.exe|tapctl.exe"
|
||||
"${WS_INSTALLER_DIR}/windows/additional_files/splittunnel/${PACKAGE_ARCH}/windscribesplittunnel.cat|splittunnel/windscribesplittunnel.cat"
|
||||
"${WS_INSTALLER_DIR}/windows/additional_files/splittunnel/${PACKAGE_ARCH}/windscribesplittunnel.inf|splittunnel/windscribesplittunnel.inf"
|
||||
"${WS_INSTALLER_DIR}/windows/additional_files/splittunnel/${PACKAGE_ARCH}/windscribesplittunnel.sys|splittunnel/windscribesplittunnel.sys"
|
||||
)
|
||||
|
||||
###
|
||||
### macOS
|
||||
###
|
||||
|
||||
set(WS_MAC_APP_ICON "frontend/gui/resources/icons/Mac/windscribe.icns")
|
||||
|
||||
# Bundle IDs for the various components of the macOS application.
|
||||
set(WS_MAC_GUI_BUNDLE_ID "com.windscribe.client")
|
||||
set(WS_MAC_HELPER_BUNDLE_ID "com.windscribe.helper.macos")
|
||||
set(WS_MAC_LAUNCHER_BUNDLE_ID "com.windscribe.launcher.macos")
|
||||
set(WS_MAC_INSTALLER_BUNDLE_ID "com.windscribe.installer.macos")
|
||||
set(WS_MAC_SPLIT_TUNNEL_BUNDLE_ID "com.windscribe.client.splittunnelextension")
|
||||
|
||||
# This is the service name/label for the IKEv2 password in the keychain.
|
||||
set(WS_MAC_IKEV2_KEYCHAIN_SERVICE "aaa.windscribe.com.password.ikev2")
|
||||
|
||||
# User-visible VPN description shown in macOS Network preferences for IKEv2.
|
||||
set(WS_MAC_VPN_DESCRIPTION "Windscribe VPN")
|
||||
|
||||
# Name of the main .app bundle (e.g. "Windscribe.app").
|
||||
set(WS_MAC_APP_BUNDLE_NAME "${WS_PRODUCT_NAME}.app")
|
||||
|
||||
# Full path to the installed .app bundle.
|
||||
set(WS_MAC_APP_DIR "/Applications/${WS_MAC_APP_BUNDLE_NAME}")
|
||||
# Arbitrary GID/UID for the application's macOS user and group.
|
||||
set(WS_MAC_GID "518")
|
||||
set(WS_MAC_UID "1639")
|
||||
|
||||
set(WS_MAC_LAUNCHER_TARGET "WindscribeLauncher")
|
||||
set(WS_MAC_INSTALLER_TARGET "installer")
|
||||
|
||||
set(WS_MAC_INSTALLER_APP_NAME "${WS_PRODUCT_NAME}Installer")
|
||||
set(WS_MAC_INSTALLER_BUNDLE_NAME "${WS_MAC_INSTALLER_APP_NAME}.app")
|
||||
|
||||
# macOS helpers that need openssl dylib paths fixed to @executable_path/../Frameworks/.
|
||||
set(WS_MAC_RPATH_BINARIES openvpn)
|
||||
|
||||
# Qt frameworks to remove from macOS bundles after macdeployqt
|
||||
set(WS_MAC_UNUSED_FRAMEWORKS QtQml QtQuick)
|
||||
|
||||
# macOS entitlements file for the main app executable (empty string to skip)
|
||||
set(WS_MAC_ENTITLEMENTS "${CMAKE_BINARY_DIR}/src/client/engine.entitlements.configured")
|
||||
|
||||
# dmgbuild settings file and background image for macOS DMG creation.
|
||||
set(WS_MAC_DMGBUILD_SETTINGS "${WS_INSTALLER_DIR}/macos/dmgbuild/dmgbuild_settings.py")
|
||||
set(WS_MAC_DMGBUILD_BACKGROUND "${WS_INSTALLER_DIR}/macos/dmg/installer_background.png")
|
||||
|
||||
# build-app dependencies
|
||||
set(WS_MAC_APP_TARGETS
|
||||
${WS_APP_TARGET} ${WS_CLI_TARGET} ${WS_MAC_HELPER_BUNDLE_ID} ${WS_MAC_LAUNCHER_TARGET} ${WS_MAC_SPLIT_TUNNEL_BUNDLE_ID})
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND WS_ADDITIONAL_SUBDIRS
|
||||
src/windscribe-cli
|
||||
src/utils/macos/launcher
|
||||
src/splittunneling/macos)
|
||||
endif()
|
||||
|
||||
###
|
||||
### Linux
|
||||
###
|
||||
|
||||
set(WS_LINUX_PACKAGE_NAME "windscribe")
|
||||
set(WS_LINUX_OUTPUT_NAME "windscribe_@VERSION@_@SUFFIX@_@ARCH@")
|
||||
@@ -0,0 +1,109 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Common Windscribe Branding
|
||||
# Included by gui.cmake and cli.cmake integrations.
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
set(WS_VERSION_MAJOR 2)
|
||||
set(WS_VERSION_MINOR 22)
|
||||
set(WS_VERSION_BUILD 4)
|
||||
set(WS_BUILD_TYPE "guinea_pig")
|
||||
|
||||
# WS_APP_IDENTIFIER: Internal identifier, no spaces. Used for service names,
|
||||
# adapter names, pipe names, and other system identifiers.
|
||||
set(WS_APP_IDENTIFIER "Windscribe")
|
||||
# WS_PRODUCT_NAME: User-facing product name. May contain spaces.
|
||||
# Used in UI strings, registry keys, log messages, macOS .app bundle paths.
|
||||
set(WS_PRODUCT_NAME "Windscribe")
|
||||
# WS_PRODUCT_NAME_LOWER: Lowercase identifier, no spaces. Used for filesystem paths,
|
||||
# binary name prefixes, user/group names, and config directories.
|
||||
set(WS_PRODUCT_NAME_LOWER "windscribe")
|
||||
# WS_PRODUCT_NAME_UPPER: Uppercase identifier, no spaces. Used for all-caps identifiers.
|
||||
set(WS_PRODUCT_NAME_UPPER "WINDSCRIBE")
|
||||
|
||||
# WS_APP_TARGET: CMake target name for the main application executable.
|
||||
set(WS_APP_TARGET "Windscribe")
|
||||
# WS_APP_EXECUTABLE_NAME: Name of the main application binary.
|
||||
set(WS_APP_EXECUTABLE_NAME "Windscribe")
|
||||
# WS_CLI_TARGET: CMake target name for the CLI executable. Empty if no CLI.
|
||||
set(WS_CLI_TARGET "windscribe-cli")
|
||||
# WS_CLI_EXECUTABLE_NAME: Name of the CLI binary.
|
||||
set(WS_CLI_EXECUTABLE_NAME "windscribe-cli")
|
||||
# WS_EXTRA_CONFIG_NAME: Filename for the advanced parameters config file.
|
||||
set(WS_EXTRA_CONFIG_NAME "${WS_PRODUCT_NAME_LOWER}_extra.conf")
|
||||
|
||||
# WS_BUILD_LIBS_SUBDIR: Subdirectory of build-libs/ where dependency install scripts
|
||||
# place compiled artifacts.
|
||||
set(WS_BUILD_LIBS_SUBDIR "windscribe")
|
||||
|
||||
set(WS_OUTPUT_PREFIX "Windscribe")
|
||||
|
||||
# Output filename templates for final packaged artifacts.
|
||||
# Available placeholders: @VERSION@, @SUFFIX@, @ARCH@
|
||||
# @SUFFIX@ resolves to the build type (e.g. "guinea_pig"), empty for stable.
|
||||
# @ARCH@ resolves to the architecture (e.g. "amd64", "arm64").
|
||||
set(WS_WIN_OUTPUT_NAME "${WS_OUTPUT_PREFIX}_@VERSION@_@SUFFIX@_@ARCH@")
|
||||
set(WS_WIN_SYMBOLS_NAME "${WS_OUTPUT_PREFIX}Symbols_@VERSION@_@SUFFIX@_@ARCH@")
|
||||
set(WS_MAC_OUTPUT_NAME "${WS_OUTPUT_PREFIX}_@VERSION@_@SUFFIX@")
|
||||
|
||||
# WS_COMPILE_DEFINITIONS: Extra preprocessor definitions to expose to C++ code.
|
||||
# Allows code in common components to add integration-specific behaviour.
|
||||
set(WS_COMPILE_DEFINITIONS WS_IS_WINDSCRIBE)
|
||||
|
||||
# QSettings organization and application names.
|
||||
set(WS_SETTINGS_ORG "Windscribe")
|
||||
set(WS_SETTINGS_APP "Windscribe2")
|
||||
|
||||
# Branding information, primarily for Windows .rc files
|
||||
set(WS_VENDOR "Windscribe Limited")
|
||||
set(WS_VENDOR_URL "https://www.windscribe.com")
|
||||
set(WS_SUPPORT_EMAIL "hello@windscribe.com")
|
||||
set(WS_COPYRIGHT "Copyright (C) 2026 Windscribe Limited")
|
||||
|
||||
# Which helper binaries to bundle.
|
||||
set(WS_BUNDLED_HELPER_NAMES openvpn ctrld wstunnel amneziawg)
|
||||
|
||||
# Shared libraries to bundle.
|
||||
set(WS_SHARED_LIB_NAMES wsnet openssl)
|
||||
|
||||
# Common directories for macOS and Linux.
|
||||
set(WS_POSIX_RUN_DIR "/var/run/windscribe")
|
||||
set(WS_POSIX_CONFIG_DIR "/etc/windscribe")
|
||||
|
||||
###
|
||||
### Windows
|
||||
###
|
||||
|
||||
# This variable is here here instead of gui.cmake because it is used when templating dependencies from tools/deps. It is not used in the cli integration.
|
||||
# WS_WIN_CONFIG_SUBDIR: Subdirectory under Program Files used for config storage.
|
||||
# e.g. "Windscribe" -> "C:\Program Files\Windscribe\config"
|
||||
set(WS_WIN_CONFIG_SUBDIR "${WS_PRODUCT_NAME}")
|
||||
|
||||
###
|
||||
### Linux
|
||||
###
|
||||
|
||||
set(WS_LINUX_INSTALL_DIR "/opt/windscribe")
|
||||
set(WS_LINUX_TMP_DIR "/var/tmp/windscribe")
|
||||
set(WS_LINUX_LOG_DIR "/var/log/windscribe")
|
||||
set(WS_LINUX_USER_GROUP "windscribe")
|
||||
|
||||
set(WS_LINUX_APP_TARGETS
|
||||
${WS_APP_TARGET} ${WS_CLI_TARGET} helper ${WS_PRODUCT_NAME_LOWER}-authhelper)
|
||||
|
||||
# Additional subdirectories to build (beyond client and helper which are always built).
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(WS_ADDITIONAL_SUBDIRS src/windscribe-cli src/utils/linux/authhelper)
|
||||
endif()
|
||||
|
||||
# Binaries that need RPATH set to ${WS_LINUX_INSTALL_DIR}/lib.
|
||||
# Paths are relative to ${WS_LINUX_INSTALL_DIR}.
|
||||
set(WS_LINUX_RPATH_BINARIES
|
||||
${WS_APP_EXECUTABLE_NAME}
|
||||
${WS_CLI_EXECUTABLE_NAME}
|
||||
helper
|
||||
${WS_PRODUCT_NAME_LOWER}-authhelper
|
||||
${WS_PRODUCT_NAME_LOWER}openvpn
|
||||
lib/libssl.so.3
|
||||
lib/libcrypto.so.3
|
||||
lib/libwsnet.so
|
||||
)
|
||||
+53
-94
@@ -4,107 +4,64 @@
|
||||
|
||||
# Common macro to copy Linux binaries and dependencies
|
||||
macro(linux_copy_files DEST_DIR TARGET_NAME)
|
||||
# Copy binaries
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying binaries to package..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:Windscribe>"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:windscribe-cli>"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:helper>"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:windscribe-authhelper>"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
)
|
||||
# Copy app target binaries
|
||||
foreach(_target ${WS_LINUX_APP_TARGETS})
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:${_target}>" "${DEST_DIR}${WS_LINUX_INSTALL_DIR}/"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Copy shared libraries
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"$<TARGET_FILE:wsnet>"
|
||||
"${DEST_DIR}/opt/windscribe/lib/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/lib/libssl.so.3"
|
||||
"${DEST_DIR}/opt/windscribe/lib/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/lib/libcrypto.so.3"
|
||||
"${DEST_DIR}/opt/windscribe/lib/"
|
||||
)
|
||||
foreach(_entry ${WS_SHARED_LIBS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}" "${DEST_DIR}${WS_LINUX_INSTALL_DIR}/lib/${_dest}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Copy custom dependencies
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/windscribeamneziawg"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wstunnel/windscribewstunnel"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
)
|
||||
|
||||
# Copy OpenVPN and ctrld binaries from vcpkg
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/tools/openvpn/sbin/openvpn"
|
||||
"${DEST_DIR}/opt/windscribe/windscribeopenvpn"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/tools/ctrld/ctrld"
|
||||
"${DEST_DIR}/opt/windscribe/windscribectrld"
|
||||
)
|
||||
# Copy bundled helper binaries
|
||||
foreach(_entry ${WS_BUNDLED_HELPERS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}" "${DEST_DIR}${WS_LINUX_INSTALL_DIR}/${_dest}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Copy open source licenses
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/client/client-common/licenses/open_source_licenses.txt"
|
||||
"${DEST_DIR}/opt/windscribe/"
|
||||
"${DEST_DIR}${WS_LINUX_INSTALL_DIR}/"
|
||||
)
|
||||
|
||||
# Fix RPATH for binaries and libraries
|
||||
find_program(PATCHELF_EXECUTABLE patchelf)
|
||||
if(PATCHELF_EXECUTABLE)
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Fixing RPATH for binaries..."
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/Windscribe"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/windscribe-cli"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/helper"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/windscribe-authhelper"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/windscribeopenvpn"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Fixing RPATH for shared libs..."
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/lib/libssl.so.3"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/lib/libcrypto.so.3"
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "/opt/windscribe/lib"
|
||||
"${DEST_DIR}/opt/windscribe/lib/libwsnet.so"
|
||||
)
|
||||
foreach(_bin ${WS_LINUX_RPATH_BINARIES})
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${PATCHELF_EXECUTABLE} --set-rpath "${WS_LINUX_INSTALL_DIR}/lib"
|
||||
"${DEST_DIR}${WS_LINUX_INSTALL_DIR}/${_bin}"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(PACKAGE_ARCH "amd64")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(PACKAGE_ARCH "arm64")
|
||||
set(INSTALLER_LINUX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}/linux")
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}/linux/common")
|
||||
set(INSTALLER_LINUX_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}/linux/common")
|
||||
else()
|
||||
set(INSTALLER_LINUX_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${WS_PRODUCT_NAME_LOWER}/linux")
|
||||
endif()
|
||||
|
||||
set(PACKAGE_TYPE "gui")
|
||||
set(PACKAGE_NAME "windscribe")
|
||||
if(BUILD_CLI_ONLY)
|
||||
set(PACKAGE_TYPE "cli")
|
||||
set(PACKAGE_NAME "windscribe-cli")
|
||||
endif()
|
||||
|
||||
set(INSTALLER_LINUX_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/linux")
|
||||
|
||||
# DEB Packaging
|
||||
if(BUILD_DEB)
|
||||
set(DEB_PACKAGE_DIR "${CMAKE_BINARY_DIR}/debian_package")
|
||||
set(DEB_PACKAGE_NAME "${PACKAGE_NAME}_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}_${PACKAGE_ARCH}")
|
||||
ws_resolve_output_name("${WS_LINUX_OUTPUT_NAME}" DEB_PACKAGE_NAME)
|
||||
|
||||
add_custom_target(package-deb
|
||||
DEPENDS build-app
|
||||
@@ -114,14 +71,14 @@ if(BUILD_DEB)
|
||||
add_custom_command(TARGET package-deb PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEB_PACKAGE_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}/opt/windscribe"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}/opt/windscribe/lib"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}${WS_LINUX_INSTALL_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}${WS_LINUX_INSTALL_DIR}/lib"
|
||||
)
|
||||
|
||||
# Copy DEBIAN control files and scripts
|
||||
add_custom_command(TARGET package-deb PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${INSTALLER_LINUX_DIR}/${PACKAGE_TYPE}/debian_package/DEBIAN"
|
||||
"${INSTALLER_LINUX_DIR}/debian_package/DEBIAN"
|
||||
"${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}/DEBIAN"
|
||||
COMMAND chmod +x "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}/DEBIAN/preinst"
|
||||
COMMAND chmod +x "${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}/DEBIAN/postinst"
|
||||
@@ -139,14 +96,14 @@ if(BUILD_DEB)
|
||||
# Copy common files (systemd services, scripts, polkit policy, etc.)
|
||||
add_custom_command(TARGET package-deb PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${INSTALLER_LINUX_DIR}/common"
|
||||
"${INSTALLER_LINUX_COMMON_DIR}"
|
||||
"${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}"
|
||||
)
|
||||
|
||||
# Copy overlay files (package-specific systemd units, scripts)
|
||||
add_custom_command(TARGET package-deb PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${INSTALLER_LINUX_DIR}/${PACKAGE_TYPE}/overlay"
|
||||
"${INSTALLER_LINUX_DIR}/overlay"
|
||||
"${DEB_PACKAGE_DIR}/${DEB_PACKAGE_NAME}"
|
||||
)
|
||||
|
||||
@@ -195,26 +152,26 @@ macro(build_rpm_package TARGET_NAME RPM_TYPE_DIR DISTRO_SUFFIX DISTRO_NAME)
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/BUILDROOT"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/RPMS"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/SOURCES"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/BUILD/opt/windscribe"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/BUILD/opt/windscribe/lib"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/BUILD${WS_LINUX_INSTALL_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${RPM_BUILD_ROOT}/BUILD${WS_LINUX_INSTALL_DIR}/lib"
|
||||
)
|
||||
|
||||
# Copy spec file and update version
|
||||
add_custom_command(TARGET ${TARGET_NAME} PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${INSTALLER_LINUX_DIR}/${PACKAGE_TYPE}/${RPM_TYPE_DIR}/SPECS/windscribe_rpm.spec"
|
||||
"${INSTALLER_LINUX_DIR}/${RPM_TYPE_DIR}/SPECS/rpm.spec"
|
||||
"${RPM_BUILD_ROOT}/SPECS/"
|
||||
COMMAND sed -i "s/Version:.*/Version: ${PROJECT_VERSION}/"
|
||||
"${RPM_BUILD_ROOT}/SPECS/windscribe_rpm.spec"
|
||||
"${RPM_BUILD_ROOT}/SPECS/rpm.spec"
|
||||
)
|
||||
|
||||
# Copy files to BUILD directory
|
||||
add_custom_command(TARGET ${TARGET_NAME} PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${INSTALLER_LINUX_DIR}/common"
|
||||
"${INSTALLER_LINUX_COMMON_DIR}"
|
||||
"${RPM_BUILD_ROOT}/BUILD"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${INSTALLER_LINUX_DIR}/${PACKAGE_TYPE}/overlay"
|
||||
"${INSTALLER_LINUX_DIR}/overlay"
|
||||
"${RPM_BUILD_ROOT}/BUILD"
|
||||
)
|
||||
|
||||
@@ -224,11 +181,13 @@ macro(build_rpm_package TARGET_NAME RPM_TYPE_DIR DISTRO_SUFFIX DISTRO_NAME)
|
||||
# Build RPM package
|
||||
find_program(RPMBUILD_EXECUTABLE rpmbuild)
|
||||
if(RPMBUILD_EXECUTABLE)
|
||||
set(RPM_SOURCE_NAME "${PACKAGE_NAME}-${PROJECT_VERSION}-0.${RPM_BUILD_ARCH}.rpm")
|
||||
set(RPM_FINAL_NAME "${PACKAGE_NAME}_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}_${RPM_FILENAME_ARCH}${DISTRO_SUFFIX}.rpm")
|
||||
set(RPM_SOURCE_NAME "${WS_LINUX_PACKAGE_NAME}-${PROJECT_VERSION}-0.${RPM_BUILD_ARCH}.rpm")
|
||||
set(PACKAGE_ARCH "${RPM_FILENAME_ARCH}${DISTRO_SUFFIX}")
|
||||
ws_resolve_output_name("${WS_LINUX_OUTPUT_NAME}" _rpm_resolved_name)
|
||||
set(RPM_FINAL_NAME "${_rpm_resolved_name}.rpm")
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Building ${DISTRO_NAME} RPM package..."
|
||||
COMMAND ${RPMBUILD_EXECUTABLE} -bb "${RPM_BUILD_ROOT}/SPECS/windscribe_rpm.spec"
|
||||
COMMAND ${RPMBUILD_EXECUTABLE} -bb "${RPM_BUILD_ROOT}/SPECS/rpm.spec"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${RPM_BUILD_ROOT}/RPMS/${RPM_BUILD_ARCH}/${RPM_SOURCE_NAME}"
|
||||
"${BUILD_EXE_DIR}/${RPM_FINAL_NAME}"
|
||||
|
||||
+56
-66
@@ -2,101 +2,102 @@
|
||||
# macOS Packaging Configuration
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Resolve output name template
|
||||
ws_resolve_output_name("${WS_MAC_OUTPUT_NAME}" WS_MAC_RESOLVED_NAME)
|
||||
|
||||
add_custom_target(prep-installer-macos
|
||||
DEPENDS build-app
|
||||
)
|
||||
|
||||
# Run macdeployqt on Windscribe.app
|
||||
# Run macdeployqt on main application bundle
|
||||
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${Qt6_DIR}/../../../bin")
|
||||
if(MACDEPLOYQT_EXECUTABLE)
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running macdeployqt on Windscribe.app..."
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} "$<TARGET_BUNDLE_DIR:Windscribe>" -always-overwrite
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running macdeployqt on ${WS_MAC_APP_BUNDLE_NAME}..."
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} "$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>" -always-overwrite
|
||||
)
|
||||
else()
|
||||
message(WARNING "macdeployqt not found, Qt frameworks may not be properly deployed")
|
||||
endif()
|
||||
|
||||
# Remove unused Qt frameworks from Windscribe.app
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Removing unused Qt frameworks..."
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:Windscribe>/Contents/Frameworks/QtQml.framework" || (exit 0)
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:Windscribe>/Contents/Frameworks/QtQuick.framework" || (exit 0)
|
||||
)
|
||||
# Remove unused Qt frameworks from main application bundle
|
||||
foreach(_fw ${WS_MAC_UNUSED_FRAMEWORKS})
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>/Contents/Frameworks/${_fw}.framework" || (exit 0)
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Sign Windscribe.app
|
||||
# Sign main application bundle
|
||||
# First sign with --deep to sign all nested components
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Signing Windscribe.app..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Signing ${WS_MAC_APP_BUNDLE_NAME}..."
|
||||
COMMAND ${CODESIGN_EXECUTABLE}
|
||||
--deep
|
||||
--force
|
||||
--options runtime
|
||||
--timestamp
|
||||
--sign "Developer ID Application"
|
||||
"$<TARGET_BUNDLE_DIR:Windscribe>"
|
||||
"$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>"
|
||||
)
|
||||
# Then sign the main executable with entitlements (only if provisioning profile exists)
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/data/provisioning_profile/embedded.provisionprofile")
|
||||
if(WS_MAC_ENTITLEMENTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/data/provisioning_profile/embedded.provisionprofile")
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Signing main executable with entitlements..."
|
||||
COMMAND ${CODESIGN_EXECUTABLE}
|
||||
--force
|
||||
--options runtime
|
||||
--timestamp
|
||||
--entitlements "${CMAKE_CURRENT_BINARY_DIR}/src/client/windscribe_engine.entitlements.configured"
|
||||
--entitlements "${WS_MAC_ENTITLEMENTS}"
|
||||
--sign "Developer ID Application"
|
||||
"$<TARGET_BUNDLE_DIR:Windscribe>/Contents/MacOS/Windscribe"
|
||||
"$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>/Contents/MacOS/${WS_APP_TARGET}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Notarize Windscribe.app
|
||||
# Notarize main application bundle
|
||||
if(ENABLE_NOTARIZE)
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Notarizing Windscribe.app..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Notarizing ${WS_MAC_APP_BUNDLE_NAME}..."
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/notarize.sh
|
||||
"${DEVELOPMENT_TEAM}"
|
||||
"$<TARGET_BUNDLE_DIR:Windscribe>/.."
|
||||
"Windscribe"
|
||||
"$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>/.."
|
||||
"${WS_APP_TARGET}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create windscribe.tar.lzma directly in installer's Resources directory
|
||||
# Create compressed app archive in installer's Resources directory
|
||||
set(_INSTALLER_RESOURCES "$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>/Contents/Resources")
|
||||
add_custom_command(TARGET prep-installer-macos POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating windscribe.tar.lzma archive..."
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
"${CMAKE_BINARY_DIR}/src/installer/mac/installer/installer.app/Contents/Resources"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove -f
|
||||
"${CMAKE_BINARY_DIR}/src/installer/mac/installer/installer.app/Contents/Resources/windscribe.tar.lzma"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating ${WS_PRODUCT_NAME_LOWER}.tar.lzma..."
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${_INSTALLER_RESOURCES}"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove -f "${_INSTALLER_RESOURCES}/${WS_PRODUCT_NAME_LOWER}.tar.lzma"
|
||||
COMMAND tar --lzma -cf
|
||||
"${CMAKE_BINARY_DIR}/src/installer/mac/installer/installer.app/Contents/Resources/windscribe.tar.lzma"
|
||||
-C "$<TARGET_BUNDLE_DIR:Windscribe>"
|
||||
"${_INSTALLER_RESOURCES}/${WS_PRODUCT_NAME_LOWER}.tar.lzma"
|
||||
-C "$<TARGET_BUNDLE_DIR:${WS_APP_TARGET}>"
|
||||
.
|
||||
)
|
||||
|
||||
# Installer packaging - creates DMG
|
||||
if(BUILD_INSTALLER)
|
||||
add_custom_target(build-dmg ALL
|
||||
DEPENDS prep-installer-macos installer
|
||||
DEPENDS prep-installer-macos ${WS_MAC_INSTALLER_TARGET}
|
||||
)
|
||||
|
||||
# Run macdeployqt on installer.app
|
||||
if(MACDEPLOYQT_EXECUTABLE)
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running macdeployqt on installer.app..."
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} "$<TARGET_BUNDLE_DIR:installer>" -always-overwrite
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} "$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>" -always-overwrite
|
||||
)
|
||||
endif()
|
||||
|
||||
# Remove unused Qt frameworks from installer.app
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:installer>/Contents/Frameworks/QtQml.framework" || (exit 0)
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:installer>/Contents/Frameworks/QtQuick.framework" || (exit 0)
|
||||
)
|
||||
foreach(_fw ${WS_MAC_UNUSED_FRAMEWORKS})
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>/Contents/Frameworks/${_fw}.framework" || (exit 0)
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Sign installer.app
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
@@ -107,53 +108,42 @@ if(BUILD_INSTALLER)
|
||||
--options runtime
|
||||
--timestamp
|
||||
--sign "Developer ID Application"
|
||||
"$<TARGET_BUNDLE_DIR:installer>"
|
||||
COMMAND ${CODESIGN_EXECUTABLE} -v "$<TARGET_BUNDLE_DIR:installer>"
|
||||
"$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>"
|
||||
COMMAND ${CODESIGN_EXECUTABLE} -v "$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>"
|
||||
)
|
||||
|
||||
# Rename installer.app to WindscribeInstaller.app
|
||||
# Rename installer.app to ${WS_MAC_INSTALLER_BUNDLE_NAME}
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Renaming installer.app to WindscribeInstaller.app..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Renaming installer.app to ${WS_MAC_INSTALLER_BUNDLE_NAME}..."
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_INSTALLER_FILES}"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory "${BUILD_INSTALLER_FILES}/WindscribeInstaller.app"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory "${BUILD_INSTALLER_FILES}/${WS_MAC_INSTALLER_BUNDLE_NAME}"
|
||||
COMMAND ${CMAKE_COMMAND} -E rename
|
||||
"$<TARGET_BUNDLE_DIR:installer>"
|
||||
"${BUILD_INSTALLER_FILES}/WindscribeInstaller.app"
|
||||
"$<TARGET_BUNDLE_DIR:${WS_MAC_INSTALLER_TARGET}>"
|
||||
"${BUILD_INSTALLER_FILES}/${WS_MAC_INSTALLER_BUNDLE_NAME}"
|
||||
)
|
||||
|
||||
# Notarize WindscribeInstaller.app (before creating DMG)
|
||||
# Notarize ${WS_MAC_INSTALLER_BUNDLE_NAME} (before creating DMG)
|
||||
if(ENABLE_NOTARIZE)
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Notarizing WindscribeInstaller.app..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Notarizing ${WS_MAC_INSTALLER_BUNDLE_NAME}..."
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/notarize.sh
|
||||
"${DEVELOPMENT_TEAM}"
|
||||
"${BUILD_INSTALLER_FILES}"
|
||||
"WindscribeInstaller"
|
||||
"${WS_MAC_INSTALLER_APP_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Create DMG with create-dmg
|
||||
find_program(CREATE_DMG_EXECUTABLE create-dmg)
|
||||
if(NOT CREATE_DMG_EXECUTABLE)
|
||||
message(FATAL_ERROR "create-dmg not found - cannot build DMG")
|
||||
endif()
|
||||
|
||||
# Create DMG with dmgbuild
|
||||
add_custom_command(TARGET build-dmg POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating DMG with create-dmg..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating DMG with dmgbuild..."
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory "${BUILD_EXE_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_EXE_DIR}"
|
||||
COMMAND ${CREATE_DMG_EXECUTABLE}
|
||||
--volname "WindscribeInstaller"
|
||||
--volicon "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/mac/installer/resources/windscribe.icns"
|
||||
--background "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/mac/dmg/installer_background.png"
|
||||
--window-pos 100 425
|
||||
--window-size 350 350
|
||||
--icon-size 64
|
||||
--icon "WindscribeInstaller.app" 175 192
|
||||
--hide-extension "WindscribeInstaller.app"
|
||||
--format ULMO
|
||||
"${BUILD_EXE_DIR}/Windscribe_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}.dmg"
|
||||
"${BUILD_INSTALLER_FILES}/WindscribeInstaller.app"
|
||||
COMMAND python3 -m dmgbuild
|
||||
-s "${WS_MAC_DMGBUILD_SETTINGS}"
|
||||
-D "app=${BUILD_INSTALLER_FILES}/${WS_MAC_INSTALLER_BUNDLE_NAME}"
|
||||
-D "background=${WS_MAC_DMGBUILD_BACKGROUND}"
|
||||
"${WS_MAC_INSTALLER_APP_NAME}"
|
||||
"${BUILD_EXE_DIR}/${WS_MAC_RESOLVED_NAME}.dmg"
|
||||
WORKING_DIRECTORY "${BUILD_INSTALLER_FILES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
+58
-116
@@ -2,13 +2,9 @@
|
||||
# Windows Packaging Configuration
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Define architecture-specific suffix
|
||||
set(ARCH_SUFFIX "amd64")
|
||||
set(WINDSCRIBE_ARCH_SUFFIX "_amd64")
|
||||
if(BUILD_ARM64)
|
||||
set(ARCH_SUFFIX "arm64")
|
||||
set(WINDSCRIBE_ARCH_SUFFIX "_arm64")
|
||||
endif()
|
||||
# Resolve output name templates
|
||||
ws_resolve_output_name("${WS_WIN_OUTPUT_NAME}" WS_WIN_RESOLVED_NAME)
|
||||
ws_resolve_output_name("${WS_WIN_SYMBOLS_NAME}" WS_WIN_RESOLVED_SYMBOLS_NAME)
|
||||
|
||||
# Copy app artifacts target - runs after build-app on Windows
|
||||
if(BUILD_APP)
|
||||
@@ -17,95 +13,6 @@ if(BUILD_APP)
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_SYMBOLS_DIR}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying Windows files to installer directory..."
|
||||
|
||||
# Copy main executables
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/client/Windscribe.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/windscribe-cli/windscribe-cli.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/helper/windows/WindscribeService.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/utils/windows/windscribe_install_helper/WindscribeInstallHelper.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/utils/windows/wireguard_service/WireguardService.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/installer/windows/uninstaller/uninstall.exe" "${BUILD_INSTALLER_FILES}/"
|
||||
|
||||
# Copy Qt config file
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying Qt configuration..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/qt"
|
||||
"${BUILD_INSTALLER_FILES}/qt"
|
||||
|
||||
# Copy custom dependencies (WireGuard, WSTunnel, Wintun, OpenVPN, ctrld, OpenVPN DCO)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying custom dependencies..."
|
||||
|
||||
# OpenVPN
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/tools/openvpn/openvpn.exe"
|
||||
"${BUILD_INSTALLER_FILES}/windscribeopenvpn.exe"
|
||||
|
||||
# ctrld
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/tools/ctrld/ctrld.exe"
|
||||
"${BUILD_INSTALLER_FILES}/windscribectrld.exe"
|
||||
|
||||
# WireGuard
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/tunnel.dll"
|
||||
"${BUILD_INSTALLER_FILES}/tunnel.dll"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/wireguard.dll"
|
||||
"${BUILD_INSTALLER_FILES}/wireguard.dll"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/amneziawgtunnel.dll"
|
||||
"${BUILD_INSTALLER_FILES}/amneziawgtunnel.dll"
|
||||
|
||||
# WSTunnel
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wstunnel/windscribewstunnel.exe"
|
||||
"${BUILD_INSTALLER_FILES}/windscribewstunnel.exe"
|
||||
|
||||
# Wintun
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/wintun/bin/wintun.dll"
|
||||
"${BUILD_INSTALLER_FILES}/wintun.dll"
|
||||
|
||||
# OpenVPN DCO drivers
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_INSTALLER_FILES}/openvpndco/win10"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_INSTALLER_FILES}/openvpndco/win11"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.cat"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win10/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.inf"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win10/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win10/ovpn-dco.sys"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win10/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.cat"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win11/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.inf"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win11/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${WINDSCRIBE_BUILD_LIBS_PATH}/ovpn-dco-win/win11/ovpn-dco.sys"
|
||||
"${BUILD_INSTALLER_FILES}/openvpndco/win11/"
|
||||
|
||||
# Copy architecture-specific files (devcon, tapctl, split tunnel driver)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying architecture-specific files..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/driver_utils/${ARCH_SUFFIX}/devcon.exe"
|
||||
"${BUILD_INSTALLER_FILES}/devcon.exe"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/driver_utils/${ARCH_SUFFIX}/tapctl.exe"
|
||||
"${BUILD_INSTALLER_FILES}/tapctl.exe"
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${BUILD_INSTALLER_FILES}/splittunnel"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/splittunnel/${ARCH_SUFFIX}/windscribesplittunnel.cat"
|
||||
"${BUILD_INSTALLER_FILES}/splittunnel/windscribesplittunnel.cat"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/splittunnel/${ARCH_SUFFIX}/windscribesplittunnel.inf"
|
||||
"${BUILD_INSTALLER_FILES}/splittunnel/windscribesplittunnel.inf"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/additional_files/splittunnel/${ARCH_SUFFIX}/windscribesplittunnel.sys"
|
||||
"${BUILD_INSTALLER_FILES}/splittunnel/windscribesplittunnel.sys"
|
||||
|
||||
# Copy common files (licenses, etc.)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying common files..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
@@ -113,16 +20,51 @@ if(BUILD_APP)
|
||||
"${BUILD_INSTALLER_FILES}/open_source_licenses.txt"
|
||||
)
|
||||
|
||||
if(CI_MODE)
|
||||
# Copy additional files (drivers, configs, etc.)
|
||||
foreach(_entry ${WS_WIN_ADDITIONAL_FILES})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
if(_src MATCHES "^DIR:")
|
||||
string(SUBSTRING "${_src}" 4 -1 _src_dir)
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${_src_dir}" "${BUILD_INSTALLER_FILES}/${_dest}"
|
||||
)
|
||||
else()
|
||||
get_filename_component(_dest_dir "${BUILD_INSTALLER_FILES}/${_dest}" DIRECTORY)
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${_dest_dir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}" "${BUILD_INSTALLER_FILES}/${_dest}"
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Copy app target executables
|
||||
foreach(_target ${WS_WIN_APP_TARGETS})
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
# Collect symbol files (PDB)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Collecting symbol files..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/client/Windscribe.pdb" "${BUILD_SYMBOLS_DIR}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/windscribe-cli/windscribe-cli.pdb" "${BUILD_SYMBOLS_DIR}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/helper/windows/WindscribeService.pdb" "${BUILD_SYMBOLS_DIR}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/utils/windows/windscribe_install_helper/WindscribeInstallHelper.pdb" "${BUILD_SYMBOLS_DIR}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_BINARY_DIR}/src/utils/windows/wireguard_service/WireguardService.pdb" "${BUILD_SYMBOLS_DIR}/"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_FILE:${_target}>" "${BUILD_INSTALLER_FILES}/"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Copy bundled helper binaries
|
||||
foreach(_entry ${WS_BUNDLED_HELPERS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}" "${BUILD_INSTALLER_FILES}/${_dest}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(BUILD_SYMBOLS)
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Collecting symbol files..."
|
||||
)
|
||||
foreach(_target ${WS_WIN_PDB_TARGETS})
|
||||
list(APPEND COPY_ARTIFACTS_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PDB_FILE:${_target}>" "${BUILD_SYMBOLS_DIR}/"
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
add_custom_target(copy-app-artifacts ALL
|
||||
@@ -144,7 +86,7 @@ if(BUILD_INSTALLER)
|
||||
file(MAKE_DIRECTORY "${BUILD_SYMBOLS_DIR}")
|
||||
file(MAKE_DIRECTORY "${BUILD_BOOTSTRAP_FILES}")
|
||||
|
||||
set(WINDSCRIBE_7Z_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/installer/resources/windscribe.7z")
|
||||
set(WINDSCRIBE_7Z_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}/windows/installer/resources/${WS_PRODUCT_NAME_LOWER}.7z")
|
||||
|
||||
if(BUILD_APP)
|
||||
file(REMOVE "${WINDSCRIBE_7Z_FILE}")
|
||||
@@ -157,7 +99,7 @@ if(BUILD_INSTALLER)
|
||||
OUTPUT ${WINDSCRIBE_7Z_FILE}
|
||||
DEPENDS ${PACKAGE_APP_DEPENDS}
|
||||
# Create 7z archive (needed by installer build)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating windscribe.7z archive..."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating ${WS_PRODUCT_NAME_LOWER}.7z archive..."
|
||||
COMMAND ${CMAKE_COMMAND} -E remove -f "${WINDSCRIBE_7Z_FILE}"
|
||||
COMMAND ${7ZIP_EXECUTABLE} a "${WINDSCRIBE_7Z_FILE}" "${BUILD_INSTALLER_FILES}/*" -y -bso0 -bsp0
|
||||
)
|
||||
@@ -171,11 +113,11 @@ endif()
|
||||
|
||||
# Bootstrap packaging - packages installer.exe and builds bootstrap
|
||||
if(BUILD_BOOTSTRAP)
|
||||
set(WINDSCRIBE_INSTALLER_7Z "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/bootstrap/resources/windscribeinstaller.7z")
|
||||
set(WINDSCRIBE_INSTALLER_7Z "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/${INSTALLER_TYPE}/windows/bootstrap/resources/${WS_PRODUCT_NAME_LOWER}installer.7z")
|
||||
|
||||
if(BUILD_INSTALLER)
|
||||
file(REMOVE "${WINDSCRIBE_INSTALLER_7Z}")
|
||||
set(PREP_BOOTSTRAP_DEPENDS installer)
|
||||
set(PREP_BOOTSTRAP_DEPENDS ${WS_WIN_INSTALLER_TARGET})
|
||||
if(TARGET sign-installer)
|
||||
list(APPEND PREP_BOOTSTRAP_DEPENDS sign-installer)
|
||||
endif()
|
||||
@@ -190,8 +132,8 @@ if(BUILD_BOOTSTRAP)
|
||||
|
||||
# Copy installer.exe to bootstrap directory with version name
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_BINARY_DIR}/src/installer/windows/installer/installer.exe"
|
||||
"${BUILD_BOOTSTRAP_FILES}/Windscribe_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}${WINDSCRIBE_ARCH_SUFFIX}.exe"
|
||||
"${CMAKE_BINARY_DIR}/src/installer/${INSTALLER_TYPE}/windows/installer/${WS_WIN_INSTALLER_TARGET}.exe"
|
||||
"${BUILD_BOOTSTRAP_FILES}/${WS_WIN_RESOLVED_NAME}.exe"
|
||||
|
||||
# Create bootstrap 7z archive
|
||||
COMMAND ${CMAKE_COMMAND} -E remove -f "${WINDSCRIBE_INSTALLER_7Z}"
|
||||
@@ -201,7 +143,7 @@ if(BUILD_BOOTSTRAP)
|
||||
add_custom_target(prep-bootstrap DEPENDS ${WINDSCRIBE_INSTALLER_7Z})
|
||||
|
||||
# Make bootstrap depend on prep-bootstrap so the 7z file exists before building
|
||||
add_dependencies(bootstrap prep-bootstrap)
|
||||
add_dependencies(${WS_WIN_BOOTSTRAP_TARGET} prep-bootstrap)
|
||||
endif()
|
||||
|
||||
# Deploy target - copy bootstrap and symbols to build-exe (runs for both build and sign)
|
||||
@@ -215,7 +157,7 @@ if(BUILD_BOOTSTRAP OR SIGN_BOOTSTRAP)
|
||||
add_dependencies(deploy sign-bootstrap)
|
||||
elseif(BUILD_BOOTSTRAP)
|
||||
# When building (not signing), deploy runs after bootstrap
|
||||
add_dependencies(deploy bootstrap)
|
||||
add_dependencies(deploy ${WS_WIN_BOOTSTRAP_TARGET})
|
||||
endif()
|
||||
|
||||
set(DEPLOY_COMMANDS
|
||||
@@ -226,14 +168,14 @@ if(BUILD_BOOTSTRAP OR SIGN_BOOTSTRAP)
|
||||
|
||||
# Copy final bootstrap to build-exe
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${CMAKE_BINARY_DIR}/src/installer/windows/bootstrap/windscribe_installer.exe"
|
||||
"${BUILD_EXE_DIR}/Windscribe_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}${WINDSCRIBE_ARCH_SUFFIX}.exe"
|
||||
"${CMAKE_BINARY_DIR}/src/installer/${INSTALLER_TYPE}/windows/bootstrap/${WS_PRODUCT_NAME_LOWER}_installer.exe"
|
||||
"${BUILD_EXE_DIR}/${WS_WIN_RESOLVED_NAME}.exe"
|
||||
)
|
||||
|
||||
if(CI_MODE)
|
||||
if(BUILD_SYMBOLS)
|
||||
list(APPEND DEPLOY_COMMANDS
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Creating symbols archive..."
|
||||
COMMAND ${7ZIP_EXECUTABLE} a "${BUILD_EXE_DIR}/WindscribeSymbols_${PROJECT_VERSION}${WINDSCRIBE_BUILD_SUFFIX}${WINDSCRIBE_ARCH_SUFFIX}.zip" "${BUILD_SYMBOLS_DIR}/*" -y -bso0 -bsp0
|
||||
COMMAND ${7ZIP_EXECUTABLE} a "${BUILD_EXE_DIR}/${WS_WIN_RESOLVED_SYMBOLS_NAME}.zip" "${BUILD_SYMBOLS_DIR}/*" -y -bso0 -bsp0
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Usage: cmake -DINTEGRATION=gui [-DNO_SUFFIX=1] -P cmake/print_version.cmake
|
||||
if(NOT DEFINED INTEGRATION)
|
||||
set(INTEGRATION "gui")
|
||||
endif()
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/integrations/${INTEGRATION}.cmake)
|
||||
|
||||
set(_VERSION "${WS_VERSION_MAJOR}.${WS_VERSION_MINOR}.${WS_VERSION_BUILD}")
|
||||
if(NOT NO_SUFFIX)
|
||||
if(WS_BUILD_TYPE STREQUAL "beta")
|
||||
set(_VERSION "${_VERSION}_beta")
|
||||
elseif(WS_BUILD_TYPE STREQUAL "guinea_pig")
|
||||
set(_VERSION "${_VERSION}_guinea_pig")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message("${_VERSION}")
|
||||
+10
-10
@@ -12,8 +12,8 @@ set(BUILD_INSTALLER_FILES "${BUILD_TEMP_DIR}/InstallerFiles")
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
if(WIN32)
|
||||
set(SIGNTOOL "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/signing/signtool.exe")
|
||||
set(SIGNING_CERT "${CMAKE_CURRENT_SOURCE_DIR}/src/installer/windows/signing/code_signing.der")
|
||||
set(SIGNTOOL "${CMAKE_CURRENT_SOURCE_DIR}/tools/signing/signtool.exe")
|
||||
set(SIGNING_CERT "${CMAKE_CURRENT_SOURCE_DIR}/tools/signing/code_signing.der")
|
||||
set(SIGNING_TIMESTAMP "http://timestamp.digicert.com")
|
||||
set(WINDOWS_CERT_SUBJECT_NAME "Windscribe Limited")
|
||||
|
||||
@@ -47,25 +47,25 @@ if(WIN32)
|
||||
|
||||
if(SIGN_INSTALLER)
|
||||
add_custom_target(sign-installer ALL)
|
||||
if(TARGET installer)
|
||||
add_dependencies(sign-installer installer)
|
||||
if(TARGET ${WS_WIN_INSTALLER_TARGET})
|
||||
add_dependencies(sign-installer ${WS_WIN_INSTALLER_TARGET})
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET sign-installer
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Signing installer.exe..."
|
||||
COMMAND ${SIGNTOOL} sign ${WINDOWS_SIGN_PARAMS} ${CMAKE_BINARY_DIR}/src/installer/windows/installer/installer.exe
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Signing installer..."
|
||||
COMMAND ${SIGNTOOL} sign ${WINDOWS_SIGN_PARAMS} ${CMAKE_BINARY_DIR}/src/installer/${INSTALLER_TYPE}/windows/installer/${WS_WIN_INSTALLER_TARGET}.exe
|
||||
)
|
||||
endif()
|
||||
|
||||
if(SIGN_BOOTSTRAP)
|
||||
add_custom_target(sign-bootstrap ALL)
|
||||
if(TARGET bootstrap)
|
||||
add_dependencies(sign-bootstrap bootstrap)
|
||||
if(TARGET ${WS_WIN_BOOTSTRAP_TARGET})
|
||||
add_dependencies(sign-bootstrap ${WS_WIN_BOOTSTRAP_TARGET})
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET sign-bootstrap
|
||||
COMMAND ${SIGNTOOL} sign ${WINDOWS_SIGN_PARAMS} ${CMAKE_BINARY_DIR}/src/installer/windows/bootstrap/windscribe_installer.exe
|
||||
COMMENT "Signing windscribe_installer.exe..."
|
||||
COMMAND ${SIGNTOOL} sign ${WINDOWS_SIGN_PARAMS} ${CMAKE_BINARY_DIR}/src/installer/${INSTALLER_TYPE}/windows/bootstrap/${WS_PRODUCT_NAME_LOWER}_installer.exe
|
||||
COMMENT "Signing bootstrap..."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Build System Utility Functions
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Resolve an output name template by replacing @VERSION@, @SUFFIX@, @ARCH@ placeholders.
|
||||
# Empty placeholders are replaced with "", and resulting double/trailing underscores are cleaned up.
|
||||
function(ws_resolve_output_name TEMPLATE OUT_VAR)
|
||||
set(_name "${TEMPLATE}")
|
||||
string(REPLACE "@VERSION@" "${PROJECT_VERSION}" _name "${_name}")
|
||||
string(REPLACE "@SUFFIX@" "${WS_BUILD_SUFFIX}" _name "${_name}")
|
||||
if(DEFINED PACKAGE_ARCH)
|
||||
string(REPLACE "@ARCH@" "${PACKAGE_ARCH}" _name "${_name}")
|
||||
else()
|
||||
string(REPLACE "@ARCH@" "" _name "${_name}")
|
||||
endif()
|
||||
# Clean up double underscores and trailing underscores from empty placeholders
|
||||
string(REGEX REPLACE "__+" "_" _name "${_name}")
|
||||
string(REGEX REPLACE "_$" "" _name "${_name}")
|
||||
set(${OUT_VAR} "${_name}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Resolve bundled helper source paths.
|
||||
# Populates WS_BUNDLED_HELPERS as a list of "source_path|dest_name" pairs used by packaging.
|
||||
# Must be called after VCPKG_ROOT and WINDSCRIBE_BUILD_LIBS_PATH are set.
|
||||
function(ws_resolve_bundled_helpers)
|
||||
set(_vcpkg_tools "${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/tools")
|
||||
set(_build_libs "${WINDSCRIBE_BUILD_LIBS_PATH}")
|
||||
set(_p "${WS_PRODUCT_NAME_LOWER}")
|
||||
|
||||
set(_SRC_openvpn_WIN "${_vcpkg_tools}/openvpn/openvpn.exe")
|
||||
set(_SRC_openvpn_POSIX "${_vcpkg_tools}/openvpn/sbin/openvpn")
|
||||
set(_SRC_ctrld_WIN "${_vcpkg_tools}/ctrld/ctrld.exe")
|
||||
set(_SRC_ctrld_POSIX "${_vcpkg_tools}/ctrld/ctrld")
|
||||
set(_SRC_wstunnel_WIN "${_build_libs}/wstunnel/${_p}wstunnel.exe")
|
||||
set(_SRC_wstunnel_POSIX "${_build_libs}/wstunnel/${_p}wstunnel")
|
||||
set(_SRC_amneziawg_POSIX "${_build_libs}/wireguard/${_p}amneziawg")
|
||||
|
||||
# amneziawg on Windows bundles raw DLLs instead of a single prefixed binary.
|
||||
set(_SRC_amneziawg_WIN_DLLS
|
||||
"${_build_libs}/wireguard/tunnel.dll|tunnel.dll"
|
||||
"${_build_libs}/wireguard/wireguard.dll|wireguard.dll"
|
||||
"${_build_libs}/wireguard/amneziawgtunnel.dll|amneziawgtunnel.dll"
|
||||
)
|
||||
|
||||
set(_helpers "")
|
||||
foreach(_helper ${WS_BUNDLED_HELPER_NAMES})
|
||||
if(WIN32 AND DEFINED _SRC_${_helper}_WIN_DLLS)
|
||||
list(APPEND _helpers ${_SRC_${_helper}_WIN_DLLS})
|
||||
continue()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(_src "${_SRC_${_helper}_WIN}")
|
||||
set(_dest "${_p}${_helper}.exe")
|
||||
else()
|
||||
set(_src "${_SRC_${_helper}_POSIX}")
|
||||
set(_dest "${_p}${_helper}")
|
||||
endif()
|
||||
|
||||
list(APPEND _helpers "${_src}|${_dest}")
|
||||
endforeach()
|
||||
set(WS_BUNDLED_HELPERS "${_helpers}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Resolve shared library source paths.
|
||||
# Populates WS_SHARED_LIBS as a list of "source_path|dest_name" pairs.
|
||||
# Must be called after VCPKG_ROOT is set.
|
||||
function(ws_resolve_shared_libs)
|
||||
set(_vcpkg_lib "${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/lib")
|
||||
set(_libs "")
|
||||
|
||||
foreach(_lib ${WS_SHARED_LIB_NAMES})
|
||||
if(_lib STREQUAL "wsnet")
|
||||
list(APPEND _libs "$<TARGET_FILE:wsnet>|$<TARGET_FILE_NAME:wsnet>")
|
||||
elseif(_lib STREQUAL "openssl")
|
||||
if(APPLE)
|
||||
list(APPEND _libs
|
||||
"${_vcpkg_lib}/libssl.3.dylib|libssl.3.dylib"
|
||||
"${_vcpkg_lib}/libcrypto.3.dylib|libcrypto.3.dylib")
|
||||
elseif(UNIX)
|
||||
list(APPEND _libs
|
||||
"${_vcpkg_lib}/libssl.so.3|libssl.so.3"
|
||||
"${_vcpkg_lib}/libcrypto.so.3|libcrypto.so.3")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown shared library: ${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(WS_SHARED_LIBS "${_libs}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
+7
-7
@@ -27,10 +27,10 @@ if(NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
if(WIN32)
|
||||
if(BUILD_ARM64)
|
||||
set(VCPKG_TARGET_TRIPLET "ws-arm64-windows-static-release")
|
||||
elseif(CI_MODE)
|
||||
set(VCPKG_TARGET_TRIPLET "ws-x64-windows-static-release")
|
||||
else()
|
||||
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(VCPKG_TARGET_TRIPLET "x64-windows-static")
|
||||
else()
|
||||
set(VCPKG_TARGET_TRIPLET "ws-x64-windows-static-release")
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
if(CI_MODE)
|
||||
@@ -46,7 +46,7 @@ if(NOT DEFINED VCPKG_TARGET_TRIPLET)
|
||||
if(MACOS_ARCH STREQUAL "arm64")
|
||||
set(VCPKG_TARGET_TRIPLET "ws-arm64-osx")
|
||||
else()
|
||||
set(VCPKG_TARGET_TRIPLET "x64-osx")
|
||||
set(VCPKG_TARGET_TRIPLET "ws-x64-osx")
|
||||
endif()
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
@@ -87,10 +87,10 @@ macro(install_vcpkg_dependencies)
|
||||
|
||||
# Add host triplet for Windows and Linux
|
||||
if(WIN32)
|
||||
if(CI_MODE)
|
||||
list(APPEND VCPKG_INSTALL_CMD "--host-triplet=ws-x64-windows-static-release")
|
||||
else()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
list(APPEND VCPKG_INSTALL_CMD "--host-triplet=x64-windows-static")
|
||||
else()
|
||||
list(APPEND VCPKG_INSTALL_CMD "--host-triplet=ws-x64-windows-static-release")
|
||||
endif()
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
list(APPEND VCPKG_INSTALL_CMD "--host-triplet=${VCPKG_TARGET_TRIPLET}")
|
||||
|
||||
@@ -12,11 +12,17 @@ endif()
|
||||
|
||||
project(wssecure LANGUAGES CXX)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
@ONLY
|
||||
)
|
||||
|
||||
add_library(wssecure SHARED
|
||||
dllmain.cpp
|
||||
wssecure.h
|
||||
wssecure.cpp
|
||||
version.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
)
|
||||
|
||||
target_compile_definitions(wssecure PRIVATE WSSECURE_LIBRARY)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "../../client/client-common/version/windscribe_version.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION WINDSCRIBE_MAJOR_VERSION, WINDSCRIBE_MINOR_VERSION, WINDSCRIBE_BUILD_VERSION, 0
|
||||
PRODUCTVERSION WINDSCRIBE_MAJOR_VERSION, WINDSCRIBE_MINOR_VERSION, WINDSCRIBE_BUILD_VERSION, 0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Windscribe Limited\0"
|
||||
VALUE "FileDescription", "Windscribe process mitigation policy library\0"
|
||||
VALUE "FileVersion", WINDSCRIBE_VERSION_STR
|
||||
VALUE "LegalCopyright", WINDSCRIBE_COPYRIGHT_STR
|
||||
VALUE "OriginalFilename", "wssecure.dll\0"
|
||||
VALUE "ProductName", "WSSecure\0"
|
||||
VALUE "ProductVersion", WINDSCRIBE_VERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <windows.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION WS_VERSION_MAJOR, WS_VERSION_MINOR, WS_VERSION_BUILD, 0
|
||||
PRODUCTVERSION WS_VERSION_MAJOR, WS_VERSION_MINOR, WS_VERSION_BUILD, 0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "@WS_VENDOR@\0"
|
||||
VALUE "FileDescription", "@WS_PRODUCT_NAME@ process mitigation policy library\0"
|
||||
VALUE "FileVersion", WS_VERSION "\0"
|
||||
VALUE "LegalCopyright", WS_COPYRIGHT "\0"
|
||||
VALUE "OriginalFilename", "wssecure.dll\0"
|
||||
VALUE "ProductName", "WSSecure\0"
|
||||
VALUE "ProductVersion", WS_VERSION "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
+115
-136
@@ -3,11 +3,11 @@ cmake_minimum_required(VERSION 3.23)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
set(X_VCPKG_APPLOCAL_DEPS_INSTALL ON)
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "Minimum OS X deployment version")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "13" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
project(Windscribe)
|
||||
project(${WS_APP_TARGET})
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
@@ -41,35 +41,18 @@ if(DEFINE_QT_CREATOR_DEV_BUILD_MACRO)
|
||||
add_definitions(-DQT_CREATOR_DEV_BUILD)
|
||||
endif(DEFINE_QT_CREATOR_DEV_BUILD_MACRO)
|
||||
|
||||
if(UNIX AND (NOT APPLE))
|
||||
option(DEFINE_CLI_ONLY_MACRO "Build GUI-less client" OFF)
|
||||
# if build requested a headless client, set the necessary definitions
|
||||
if(DEFINE_CLI_ONLY_MACRO)
|
||||
add_definitions(-DCLI_ONLY)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Network LinguistTools Test)
|
||||
endif(DEFINE_CLI_ONLY_MACRO)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINE_CLI_ONLY_MACRO)
|
||||
# This is a workaround for https://bugreports.qt.io/browse/QTBUG-89754 / #499
|
||||
# Without this flag, on Linux libOpenGL.so.0 will be linked instead of libGL,
|
||||
# which causes Windscribe to not start on some distributions where libopengl0 is not
|
||||
# installed by default.
|
||||
|
||||
# This is a workaround for https://bugreports.qt.io/browse/QTBUG-89754 / #499
|
||||
# Without this flag, on Linux libOpenGL.so.0 will be linked instead of libGL,
|
||||
# which causes the application to not start on some distributions where libopengl0 is not
|
||||
# installed by default.
|
||||
if("Widgets" IN_LIST WS_QT_COMPONENTS)
|
||||
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Network LinguistTools Test)
|
||||
endif()
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS ${WS_QT_COMPONENTS})
|
||||
|
||||
set(PROJECT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(DEFINE_CLI_ONLY_MACRO)
|
||||
set(PROJECT_SOURCES main_cli.cpp)
|
||||
set(PROJECT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/frontend/cli)
|
||||
else()
|
||||
set(PROJECT_SOURCES main_gui.cpp)
|
||||
set(PROJECT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/frontend/gui)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set (OS_SPECIFIC_LIBRARIES
|
||||
psapi.lib
|
||||
@@ -82,7 +65,12 @@ if (WIN32)
|
||||
# $<$<NOT:$<CONFIG:Debug>>:../libs/wssecure/wssecure>
|
||||
)
|
||||
|
||||
list(APPEND PROJECT_SOURCES client.rc)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/client.rc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/client.rc
|
||||
@ONLY
|
||||
)
|
||||
list(APPEND PROJECT_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/client.rc)
|
||||
if(CI_MODE)
|
||||
add_compile_options("$<$<CONFIG:Release>:/Zi>")
|
||||
add_link_options("$<$<CONFIG:Release>:/DEBUG>" "$<$<CONFIG:Release>:/OPT:REF>" "$<$<CONFIG:Release>:/OPT:ICF>")
|
||||
@@ -105,125 +93,120 @@ elseif (APPLE)
|
||||
)
|
||||
|
||||
# add Mac icon to Resources bundle subfolder
|
||||
set(MAC_APP_ICON ${CMAKE_CURRENT_SOURCE_DIR}/frontend/gui/resources/icons/Mac/windscribe.icns)
|
||||
set(MAC_APP_ICON ${CMAKE_CURRENT_SOURCE_DIR}/${WS_MAC_APP_ICON})
|
||||
get_filename_component(WS_MAC_ICON_FILE "${WS_MAC_APP_ICON}" NAME)
|
||||
set_source_files_properties(${MAC_APP_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
list(APPEND PROJECT_SOURCES ${MAC_APP_ICON})
|
||||
|
||||
# add additional files to Resources bundle subfolder
|
||||
file(GLOB MAC_RESOURCES_FILES ${CMAKE_CURRENT_SOURCE_DIR}/engine/mac/resources/*.*)
|
||||
set_source_files_properties(${MAC_RESOURCES_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
list(APPEND PROJECT_SOURCES ${MAC_RESOURCES_FILES})
|
||||
# configure and add additional files to Resources bundle subfolder
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/engine/mac/resources/dns.sh.in ${CMAKE_CURRENT_BINARY_DIR}/dns.sh @ONLY)
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dns.sh PROPERTIES MACOSX_PACKAGE_LOCATION "Resources" GENERATED TRUE)
|
||||
list(APPEND PROJECT_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dns.sh)
|
||||
endif()
|
||||
|
||||
qt_add_executable(Windscribe
|
||||
qt_add_executable(${WS_APP_TARGET}
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
if (NOT DEFINE_QT_CREATOR_DEV_BUILD_MACRO)
|
||||
#postbuild copy commands for Windows
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/openvpn/openvpn.exe $<TARGET_FILE_DIR:Windscribe>/windscribeopenvpn.exe)
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/ctrld/ctrld.exe $<TARGET_FILE_DIR:Windscribe>/windscribectrld.exe)
|
||||
foreach(_entry ${WS_BUNDLED_HELPERS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${_src}" "$<TARGET_FILE_DIR:${WS_APP_TARGET}>/${_dest}")
|
||||
endforeach()
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
#postbuild copy commands for Mac
|
||||
if (NOT DEFINE_QT_CREATOR_DEV_BUILD_MACRO)
|
||||
set(WINDSCRIBE_BUILD_LIBS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../build-libs)
|
||||
|
||||
# Ensure launcher is built before Windscribe
|
||||
add_dependencies(Windscribe WindscribeLauncher)
|
||||
add_dependencies(Windscribe com.windscribe.client.splittunnelextension)
|
||||
# Ensure launcher is built before client
|
||||
add_dependencies(${WS_APP_TARGET} ${WS_MAC_LAUNCHER_TARGET})
|
||||
add_dependencies(${WS_APP_TARGET} ${WS_MAC_SPLIT_TUNNEL_BUNDLE_ID})
|
||||
|
||||
# Copy launcher bundle
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
$<TARGET_BUNDLE_DIR:WindscribeLauncher> $<TARGET_FILE_DIR:Windscribe>/../Library/LoginItems/WindscribeLauncher.app)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
$<TARGET_BUNDLE_DIR:${WS_MAC_LAUNCHER_TARGET}> $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Library/LoginItems/${WS_MAC_LAUNCHER_TARGET}.app)
|
||||
|
||||
# Copy helper executable
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
$<TARGET_FILE_DIR:Windscribe>/../Library/LaunchServices)
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:com.windscribe.helper.macos> $<TARGET_FILE_DIR:Windscribe>/../Library/LaunchServices/)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
$<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Library/LaunchServices)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:${WS_MAC_HELPER_BUNDLE_ID}> $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Library/LaunchServices/)
|
||||
|
||||
# Copy openssl, wsnet, and post-quantum libs to Frameworks
|
||||
add_custom_command(TARGET Windscribe POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Copying dependency libraries to Frameworks..."
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libcrypto.3.dylib
|
||||
$<TARGET_FILE_DIR:Windscribe>/../Frameworks/libcrypto.3.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libssl.3.dylib
|
||||
$<TARGET_FILE_DIR:Windscribe>/../Frameworks/libssl.3.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:wsnet::wsnet>
|
||||
$<TARGET_FILE_DIR:Windscribe>/../Frameworks/
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Fixing RPATH on wsnet..."
|
||||
COMMAND install_name_tool -add_rpath "@loader_path" $<TARGET_FILE_DIR:Windscribe>/../Frameworks/libwsnet.dylib
|
||||
)
|
||||
# Copy shared libraries to Frameworks
|
||||
foreach(_entry ${WS_SHARED_LIBS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}" "$<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Frameworks/${_dest}"
|
||||
)
|
||||
endforeach()
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:Windscribe>/../Helpers)
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/openvpn/sbin/openvpn $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribeopenvpn)
|
||||
|
||||
# Copy split tunnel extension
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
$<TARGET_BUNDLE_DIR:com.windscribe.client.splittunnelextension> $<TARGET_FILE_DIR:Windscribe>/../Library/SystemExtensions/com.windscribe.client.splittunnelextension.systemextension)
|
||||
|
||||
# apply install_name_tool commands for the windscribeopenvpn binary, fix for the openssl libs
|
||||
add_custom_command(TARGET Windscribe POST_BUILD
|
||||
COMMAND bash -c [[OLD=$(otool -L ${0} | grep ${1} | uniq | sed s/.dylib.*/.dylib/ | awk '{$1=$1;print}'); install_name_tool -change ${OLD} @executable_path/../Frameworks/${1}.3.dylib ${0}]] $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribeopenvpn libssl
|
||||
COMMAND bash -c [[OLD=$(otool -L ${0} | grep ${1} | uniq | sed s/.dylib.*/.dylib/ | awk '{$1=$1;print}'); install_name_tool -change ${OLD} @executable_path/../Frameworks/${1}.3.dylib ${0}]] $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribeopenvpn libcrypto
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${WINDSCRIBE_BUILD_LIBS_PATH}/wireguard/windscribeamneziawg $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribeamneziawg)
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/ctrld/ctrld $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribectrld)
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${WINDSCRIBE_BUILD_LIBS_PATH}/wstunnel/windscribewstunnel $<TARGET_FILE_DIR:Windscribe>/../Helpers/windscribewstunnel)
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../data/provisioning_profile/embedded.provisionprofile")
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../data/provisioning_profile/embedded.provisionprofile" $<TARGET_FILE_DIR:Windscribe>/../embedded.provisionprofile)
|
||||
# Fix RPATH on wsnet so it can find sibling libraries in Frameworks
|
||||
if("wsnet" IN_LIST WS_SHARED_LIB_NAMES)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD
|
||||
COMMAND install_name_tool -add_rpath "@loader_path" $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Frameworks/libwsnet.dylib
|
||||
)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../build/src/windscribe-cli/windscribe-cli $<TARGET_FILE_DIR:Windscribe>/windscribe-cli)
|
||||
add_custom_command(TARGET Windscribe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/client-common/licenses/open_source_licenses.txt $<TARGET_FILE_DIR:Windscribe>/../Resources/open_source_licenses.txt)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Helpers)
|
||||
|
||||
# Copy bundled helpers to Helpers/
|
||||
foreach(_entry ${WS_BUNDLED_HELPERS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${_src}" "$<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Helpers/${_dest}")
|
||||
endforeach()
|
||||
|
||||
# Copy split tunnel extension
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
$<TARGET_BUNDLE_DIR:${WS_MAC_SPLIT_TUNNEL_BUNDLE_ID}> $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Library/SystemExtensions/${WS_MAC_SPLIT_TUNNEL_BUNDLE_ID}.systemextension)
|
||||
|
||||
# Fix openssl dynamic link paths in helpers that link against openssl
|
||||
foreach(_helper ${WS_MAC_RPATH_BINARIES})
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD
|
||||
COMMAND bash -c [[OLD=$(otool -L ${0} | grep ${1} | uniq | sed s/.dylib.*/.dylib/ | awk '{$1=$1;print}'); install_name_tool -change ${OLD} @executable_path/../Frameworks/${1}.3.dylib ${0}]] $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Helpers/${WS_PRODUCT_NAME_LOWER}${_helper} libssl
|
||||
COMMAND bash -c [[OLD=$(otool -L ${0} | grep ${1} | uniq | sed s/.dylib.*/.dylib/ | awk '{$1=$1;print}'); install_name_tool -change ${OLD} @executable_path/../Frameworks/${1}.3.dylib ${0}]] $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Helpers/${WS_PRODUCT_NAME_LOWER}${_helper} libcrypto
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../data/provisioning_profile/embedded.provisionprofile")
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../data/provisioning_profile/embedded.provisionprofile" $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../embedded.provisionprofile)
|
||||
endif()
|
||||
|
||||
if(TARGET ${WS_CLI_TARGET})
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
$<TARGET_FILE:${WS_CLI_TARGET}> $<TARGET_FILE_DIR:${WS_APP_TARGET}>/${WS_CLI_EXECUTABLE_NAME})
|
||||
endif()
|
||||
add_custom_command(TARGET ${WS_APP_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/client-common/licenses/open_source_licenses.txt $<TARGET_FILE_DIR:${WS_APP_TARGET}>/../Resources/open_source_licenses.txt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_options(Windscribe PRIVATE "/IGNORE:4099")
|
||||
target_link_options(${WS_APP_TARGET} PRIVATE "/IGNORE:4099")
|
||||
elseif (APPLE)
|
||||
set_property(TARGET Windscribe APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
|
||||
set_property(TARGET ${WS_APP_TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS "-fobjc-arc")
|
||||
endif()
|
||||
|
||||
if(UNIX AND (NOT APPLE) AND DEFINE_CLI_ONLY_MACRO)
|
||||
set(CLIENT_LIBS cli frontend-common)
|
||||
else()
|
||||
set(CLIENT_LIBS gui frontend-common Qt6::Widgets)
|
||||
endif()
|
||||
|
||||
target_link_libraries(Windscribe PRIVATE ${CLIENT_LIBS} engine client-common wsnet::wsnet spdlog::spdlog Qt6::Network ${OS_SPECIFIC_LIBRARIES})
|
||||
target_link_libraries(${WS_APP_TARGET} PRIVATE ${FRONTEND_TYPE} frontend-common ${WS_CLIENT_EXTRA_LIBS} engine client-common wsnet::wsnet spdlog::spdlog Qt6::Network ${OS_SPECIFIC_LIBRARIES})
|
||||
|
||||
if (UNIX AND (NOT APPLE))
|
||||
qt_import_plugins(Windscribe INCLUDE Qt6::QWaylandIntegrationPlugin Qt6::QXcbIntegrationPlugin)
|
||||
qt_import_plugins(${WS_APP_TARGET} INCLUDE Qt6::QWaylandIntegrationPlugin Qt6::QXcbIntegrationPlugin)
|
||||
endif()
|
||||
|
||||
target_include_directories(Windscribe PRIVATE
|
||||
target_include_directories(${WS_APP_TARGET} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/engine
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/client-common
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/frontend/frontend-common
|
||||
${PROJECT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Configure Info.plist with DEVELOPMENT_TEAM substitution
|
||||
@@ -237,24 +220,25 @@ if(APPLE)
|
||||
|
||||
# Configure entitlements with DEVELOPMENT_TEAM substitution
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/engine/mac/windscribe_engine.entitlements
|
||||
${CMAKE_CURRENT_BINARY_DIR}/windscribe_engine.entitlements.configured
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/engine/mac/engine.entitlements
|
||||
${CMAKE_CURRENT_BINARY_DIR}/engine.entitlements.configured
|
||||
@ONLY
|
||||
)
|
||||
set(WINDSCRIBE_ENTITLEMENTS ${CMAKE_CURRENT_BINARY_DIR}/windscribe_engine.entitlements.configured)
|
||||
set(WINDSCRIBE_ENTITLEMENTS ${CMAKE_CURRENT_BINARY_DIR}/engine.entitlements.configured)
|
||||
else()
|
||||
set(WINDSCRIBE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/info.plist)
|
||||
endif()
|
||||
|
||||
set_target_properties(Windscribe PROPERTIES
|
||||
set_target_properties(${WS_APP_TARGET} PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
COMPILE_WARNING_AS_ERROR TRUE
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(Windscribe PROPERTIES
|
||||
set_target_properties(${WS_APP_TARGET} PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_INFO_PLIST ${WINDSCRIBE_INFO_PLIST}
|
||||
OUTPUT_NAME "${WS_PRODUCT_NAME}"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
INSTALL_RPATH "@executable_path/../Frameworks"
|
||||
)
|
||||
@@ -264,45 +248,40 @@ add_subdirectory(engine)
|
||||
add_subdirectory(client-common)
|
||||
add_subdirectory(frontend)
|
||||
|
||||
qt_finalize_executable(Windscribe)
|
||||
qt_finalize_executable(${WS_APP_TARGET})
|
||||
|
||||
# ----- Install section -----
|
||||
if (APPLE)
|
||||
install(TARGETS Windscribe wsnet
|
||||
install(TARGETS ${WS_APP_TARGET} wsnet
|
||||
RUNTIME DESTINATION .
|
||||
LIBRARY DESTINATION "Windscribe.app/Contents/Frameworks"
|
||||
LIBRARY DESTINATION "${WS_PRODUCT_NAME}.app/Contents/Frameworks"
|
||||
BUNDLE DESTINATION .
|
||||
)
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libcrypto.3.dylib DESTINATION Windscribe.app/Contents/Frameworks)
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libssl.3.dylib DESTINATION Windscribe.app/Contents/Frameworks)
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libcrypto.3.dylib DESTINATION "${WS_PRODUCT_NAME}.app/Contents/Frameworks")
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libssl.3.dylib DESTINATION "${WS_PRODUCT_NAME}.app/Contents/Frameworks")
|
||||
else()
|
||||
install(TARGETS Windscribe
|
||||
install(TARGETS ${WS_APP_TARGET}
|
||||
RUNTIME DESTINATION .
|
||||
LIBRARY DESTINATION "lib"
|
||||
BUNDLE DESTINATION .
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/windscribeopenvpn.exe DESTINATION .)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/windscribectrld.exe DESTINATION .)
|
||||
if(WIN32 OR (UNIX AND NOT APPLE))
|
||||
foreach(_entry ${WS_BUNDLED_HELPERS})
|
||||
string(REPLACE "|" ";" _pair "${_entry}")
|
||||
list(GET _pair 0 _src)
|
||||
list(GET _pair 1 _dest)
|
||||
install(FILES "${_src}"
|
||||
RENAME "${_dest}"
|
||||
DESTINATION .
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(UNIX AND (NOT APPLE))
|
||||
install(IMPORTED_RUNTIME_ARTIFACTS wsnet DESTINATION lib)
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libcrypto.so.3 DESTINATION lib)
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libssl.so.3 DESTINATION lib)
|
||||
|
||||
# copy openvpn
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/openvpn/sbin/openvpn
|
||||
RENAME windscribeopenvpn
|
||||
DESTINATION .
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
# copy ctrld
|
||||
install(FILES ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/ctrld/ctrld
|
||||
RENAME windscribectrld
|
||||
DESTINATION .
|
||||
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -14,15 +14,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Network)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
names.h
|
||||
version/appversion.cpp
|
||||
version/appversion.h
|
||||
version/windscribe_version.h
|
||||
)
|
||||
|
||||
add_library(client-common STATIC ${PROJECT_SOURCES})
|
||||
|
||||
target_link_libraries(client-common PRIVATE Qt6::Core Qt6::Network OpenSSL::Crypto wsnet::wsnet spdlog::spdlog)
|
||||
target_link_libraries(client-common PRIVATE Qt6::Core Qt6::Network OpenSSL::Crypto spdlog::spdlog wsnet::wsnet)
|
||||
target_compile_definitions(client-common PRIVATE CMAKE_LIBRARY_LIBRARY
|
||||
WINVER=0x0601
|
||||
_WIN32_WINNT=0x0601
|
||||
|
||||
@@ -91,10 +91,11 @@ AmneziawgUnblockParams::AmneziawgUnblockParams(const std::string &json)
|
||||
QJsonObject obj = value.toObject();
|
||||
|
||||
// Parse required fields
|
||||
if (!obj.contains("title")) {
|
||||
if (!obj.contains("id") || !obj.contains("title")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
param.id = obj["id"].toString();
|
||||
param.title = obj["title"].toString();
|
||||
|
||||
if (obj.contains("countries")) {
|
||||
@@ -140,6 +141,19 @@ QStringList AmneziawgUnblockParams::presets() const
|
||||
return presets;
|
||||
}
|
||||
|
||||
QString AmneziawgUnblockParams::getTitleById(const QString &id)
|
||||
{
|
||||
if (id.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
for (const auto ¶m : std::as_const(params_)) {
|
||||
if (param.id == id)
|
||||
return param.title;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
AmneziawgUnblockParam AmneziawgUnblockParams::getUnblockParamForPreset(const QString &preset)
|
||||
{
|
||||
AmneziawgUnblockParam param;
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace api_responses {
|
||||
|
||||
struct AmneziawgUnblockParam
|
||||
{
|
||||
QString id;
|
||||
QString title;
|
||||
QStringList countries;
|
||||
int jc = 0;
|
||||
@@ -37,6 +38,7 @@ public:
|
||||
|
||||
bool isValid() const { return !params_.isEmpty(); }
|
||||
QStringList presets() const;
|
||||
QString getTitleById(const QString &id);
|
||||
|
||||
AmneziawgUnblockParam getUnblockParamForPreset(const QString &preset);
|
||||
|
||||
|
||||
@@ -1,78 +1,35 @@
|
||||
#include "group.h"
|
||||
#include <QJsonArray>
|
||||
#include "utils/ws_assert.h"
|
||||
#include <wsnet/WSNetServerLocations.h>
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
bool Group::initFromJson(QJsonObject &obj, QStringList &forceDisconnectNodes)
|
||||
void Group::initFromWsnet(const wsnet::ServerGroup &src)
|
||||
{
|
||||
if (!obj.contains("id") || !obj.contains("city") || !obj.contains("nick") ||
|
||||
!obj.contains("pro") || !obj.contains("ping_ip") || !obj.contains("wg_pubkey"))
|
||||
{
|
||||
d->isValid_ = false;
|
||||
return false;
|
||||
}
|
||||
d->id_ = src.id;
|
||||
d->city_ = QString::fromStdString(src.city);
|
||||
d->nick_ = QString::fromStdString(src.nick);
|
||||
d->status_ = src.status;
|
||||
d->premiumOnly_ = src.premiumOnly;
|
||||
d->pingIp_ = QString::fromStdString(src.pingIp);
|
||||
d->pingHost_ = QString::fromStdString(src.pingHost);
|
||||
d->wg_pubkey_ = QString::fromStdString(src.wgPubKey);
|
||||
d->ovpn_x509_ = QString::fromStdString(src.ovpnX509);
|
||||
d->link_speed_ = src.linkSpeed;
|
||||
d->netLoad_ = src.netLoad;
|
||||
d->p2p_ = src.p2p;
|
||||
d->dnsHostName_ = QString::fromStdString(src.dnsHostName);
|
||||
|
||||
d->id_ = obj["id"].toInt();
|
||||
d->city_ = obj["city"].toString();
|
||||
d->nick_ = obj["nick"].toString();
|
||||
d->pro_ = obj["pro"].toInt();
|
||||
d->pingIp_ = obj["ping_ip"].toString();
|
||||
d->pingHost_ = obj["ping_host"].toString();
|
||||
d->wg_pubkey_ = obj["wg_pubkey"].toString();
|
||||
d->ovpn_x509_ = obj["ovpn_x509"].toString();
|
||||
|
||||
if (obj.contains("link_speed"))
|
||||
{
|
||||
bool bConverted;
|
||||
d->link_speed_ = obj.value("link_speed").toString().toInt(&bConverted);
|
||||
if (!bConverted) {
|
||||
d->link_speed_ = 100;
|
||||
}
|
||||
}
|
||||
|
||||
// Using -1 to indicate to the UI logic that the load (health) value was invalid/missing,
|
||||
// and therefore this location should be excluded when calculating the region's average
|
||||
// load value.
|
||||
// Note: the server json does not include a health value for premium locations when the
|
||||
// user is logged into a free account.
|
||||
if (obj.contains("health"))
|
||||
{
|
||||
d->health_ = obj.value("health").toInt(-1);
|
||||
if ((d->health_ < 0) || (d->health_ > 100)) {
|
||||
d->health_ = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
d->health_ = -1;
|
||||
}
|
||||
|
||||
if (obj.contains("nodes"))
|
||||
{
|
||||
const auto nodesArray = obj["nodes"].toArray();
|
||||
for (const QJsonValue &serverNodeValue : nodesArray)
|
||||
{
|
||||
QJsonObject objServerNode = serverNodeValue.toObject();
|
||||
// wsnet already filtered out force_disconnect nodes; all remaining nodes are regular
|
||||
if (d->status_ == 1) {
|
||||
for (const auto &n : src.nodes) {
|
||||
Node node;
|
||||
if (!node.initFromJson(objServerNode))
|
||||
{
|
||||
d->isValid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// not add node with flag force_diconnect, but add it to another list
|
||||
if (node.isForceDisconnect())
|
||||
{
|
||||
forceDisconnectNodes << node.getHostname();
|
||||
}
|
||||
else
|
||||
{
|
||||
d->nodes_ << node;
|
||||
}
|
||||
node.initFromWsnet(n);
|
||||
d->nodes_ << node;
|
||||
}
|
||||
}
|
||||
|
||||
d->isValid_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Group::operator==(const Group &other) const
|
||||
@@ -80,13 +37,15 @@ bool Group::operator==(const Group &other) const
|
||||
return d->id_ == other.d->id_ &&
|
||||
d->city_ == other.d->city_ &&
|
||||
d->nick_ == other.d->nick_ &&
|
||||
d->pro_ == other.d->pro_ &&
|
||||
d->status_ == other.d->status_ &&
|
||||
d->premiumOnly_ == other.d->premiumOnly_ &&
|
||||
d->pingIp_ == other.d->pingIp_ &&
|
||||
d->pingHost_ == other.d->pingHost_ &&
|
||||
d->wg_pubkey_ == other.d->wg_pubkey_ &&
|
||||
d->ovpn_x509_ == other.d->ovpn_x509_ &&
|
||||
d->link_speed_ == other.d->link_speed_ &&
|
||||
d->health_ == other.d->health_ &&
|
||||
d->netLoad_ == other.d->netLoad_ &&
|
||||
d->p2p_ == other.d->p2p_ &&
|
||||
d->dnsHostName_ == other.d->dnsHostName_ &&
|
||||
d->nodes_ == other.d->nodes_ &&
|
||||
d->isValid_ == other.d->isValid_;
|
||||
@@ -97,38 +56,4 @@ bool Group::operator!=(const Group &other) const
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream& stream, const Group& g)
|
||||
{
|
||||
WS_ASSERT(g.d->isValid_);
|
||||
stream << g.versionForSerialization_;
|
||||
stream << g.d->id_ << g.d->city_ << g.d->nick_ << g.d->pro_ << g.d->pingIp_ << g.d->pingHost_ << g.d->wg_pubkey_ << g.d->ovpn_x509_ << g.d->link_speed_ <<
|
||||
g.d->health_ << g.d->dnsHostName_ << g.d->nodes_;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream& operator >>(QDataStream& stream, Group& g)
|
||||
{
|
||||
quint32 version;
|
||||
stream >> version;
|
||||
if (version > g.versionForSerialization_) {
|
||||
stream.setStatus(QDataStream::ReadCorruptData);
|
||||
g.d->isValid_ = false;
|
||||
return stream;
|
||||
}
|
||||
|
||||
if (version == 1) {
|
||||
stream >> g.d->id_ >> g.d->city_ >> g.d->nick_ >> g.d->pro_ >> g.d->pingIp_ >> g.d->wg_pubkey_ >> g.d->ovpn_x509_ >> g.d->link_speed_ >>
|
||||
g.d->health_ >> g.d->dnsHostName_ >> g.d->nodes_;
|
||||
} else if (version == g.versionForSerialization_) {
|
||||
stream >> g.d->id_ >> g.d->city_ >> g.d->nick_ >> g.d->pro_ >> g.d->pingIp_ >> g.d->pingHost_ >> g.d->wg_pubkey_ >> g.d->ovpn_x509_ >> g.d->link_speed_ >>
|
||||
g.d->health_ >> g.d->dnsHostName_ >> g.d->nodes_;
|
||||
}
|
||||
|
||||
g.d->isValid_ = true;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} // namespace api_responses
|
||||
|
||||
@@ -7,25 +7,29 @@
|
||||
#include "node.h"
|
||||
#include "utils/ws_assert.h"
|
||||
|
||||
namespace wsnet { struct ServerGroup; }
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
class GroupData : public QSharedData
|
||||
{
|
||||
public:
|
||||
GroupData() : id_(0), pro_(0), link_speed_(100), health_(0), isValid_(false) {}
|
||||
GroupData() : id_(0), status_(1), premiumOnly_(false), link_speed_(100), netLoad_(0), p2p_(0), isValid_(false) {}
|
||||
|
||||
GroupData(const GroupData &other)
|
||||
: QSharedData(other),
|
||||
id_(other.id_),
|
||||
city_(other.city_),
|
||||
nick_(other.nick_),
|
||||
pro_(other.pro_),
|
||||
status_(other.status_),
|
||||
premiumOnly_(other.premiumOnly_),
|
||||
pingIp_(other.pingIp_),
|
||||
pingHost_(other.pingHost_),
|
||||
wg_pubkey_(other.wg_pubkey_),
|
||||
ovpn_x509_(other.ovpn_x509_),
|
||||
link_speed_(other.link_speed_),
|
||||
health_(other.health_),
|
||||
netLoad_(other.netLoad_),
|
||||
p2p_(other.p2p_),
|
||||
nodes_(other.nodes_),
|
||||
isValid_(other.isValid_) {}
|
||||
~GroupData() {}
|
||||
@@ -33,13 +37,15 @@ public:
|
||||
int id_;
|
||||
QString city_;
|
||||
QString nick_;
|
||||
int pro_; // 0 - for free account, 1 - for pro account
|
||||
int status_;
|
||||
bool premiumOnly_;
|
||||
QString pingIp_;
|
||||
QString pingHost_;
|
||||
QString wg_pubkey_;
|
||||
QString ovpn_x509_;
|
||||
int link_speed_;
|
||||
int health_;
|
||||
int netLoad_;
|
||||
int p2p_;
|
||||
QString dnsHostName_; // if not empty, then use this dns, overwise from parent Location
|
||||
|
||||
QVector<Node> nodes_;
|
||||
@@ -56,19 +62,21 @@ public:
|
||||
explicit Group() : d(new GroupData) {}
|
||||
Group(const Group &other) : d (other.d) {}
|
||||
|
||||
bool initFromJson(QJsonObject &obj, QStringList &forceDisconnectNodes);
|
||||
void initFromWsnet(const wsnet::ServerGroup &src);
|
||||
|
||||
int getId() const { WS_ASSERT(d->isValid_); return d->id_; }
|
||||
QString getCity() const { WS_ASSERT(d->isValid_); return d->city_; }
|
||||
QString getNick() const { WS_ASSERT(d->isValid_); return d->nick_; }
|
||||
bool isPro() const { WS_ASSERT(d->isValid_); return d->pro_ != 0; }
|
||||
bool isPremiumOnly() const { WS_ASSERT(d->isValid_); return d->premiumOnly_; }
|
||||
bool isDisabled() const { WS_ASSERT(d->isValid_); return d->nodes_.isEmpty(); }
|
||||
int status() const { WS_ASSERT(d->isValid_); return d->status_; }
|
||||
QString getPingIp() const { WS_ASSERT(d->isValid_); return d->pingIp_; }
|
||||
QString getPingHost() const { WS_ASSERT(d->isValid_); return d->pingHost_; }
|
||||
QString getWgPubKey() const { WS_ASSERT(d->isValid_); return d->wg_pubkey_; }
|
||||
QString getOvpnX509() const { WS_ASSERT(d->isValid_); return d->ovpn_x509_; }
|
||||
int getLinkSpeed() const { WS_ASSERT(d->isValid_); return d->link_speed_; }
|
||||
int getHealth() const { WS_ASSERT(d->isValid_); return d->health_; }
|
||||
int getNetLoad() const { WS_ASSERT(d->isValid_); return d->netLoad_; }
|
||||
int getP2P() const { WS_ASSERT(d->isValid_); return d->p2p_; }
|
||||
|
||||
int getNodesCount() const { WS_ASSERT(d->isValid_); return d->nodes_.count(); }
|
||||
const Node &getNode(int ind) const { WS_ASSERT(d->isValid_); return d->nodes_[ind]; }
|
||||
@@ -79,13 +87,8 @@ public:
|
||||
bool operator== (const Group &other) const;
|
||||
bool operator!= (const Group &other) const;
|
||||
|
||||
friend QDataStream& operator <<(QDataStream& stream, const Group& g);
|
||||
friend QDataStream& operator >>(QDataStream& stream, Group& g);
|
||||
|
||||
|
||||
private:
|
||||
QSharedDataPointer<GroupData> d;
|
||||
static constexpr quint32 versionForSerialization_ = 2;
|
||||
};
|
||||
|
||||
} //namespace api_responses
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <wsnet/WSNetServerLocations.h>
|
||||
|
||||
const int typeIdApiLocation = qRegisterMetaType<api_responses::Location>("apiinfo::Location");
|
||||
const int typeIdApiLocationVector = qRegisterMetaType<QVector<api_responses::Location>>("QVector<apiinfo::Location>");
|
||||
@@ -11,42 +12,24 @@ const int typeIdApiLocationVector = qRegisterMetaType<QVector<api_responses::Loc
|
||||
namespace api_responses {
|
||||
|
||||
|
||||
bool Location::initFromJson(const QJsonObject &obj, QStringList &forceDisconnectNodes)
|
||||
void Location::initFromWsnet(const wsnet::ServerLocation &src)
|
||||
{
|
||||
if (!obj.contains("id") || !obj.contains("name") || !obj.contains("country_code") ||
|
||||
!obj.contains("premium_only") || !obj.contains("p2p") || !obj.contains("groups"))
|
||||
{
|
||||
d->isValid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
d->id_ = obj["id"].toInt();
|
||||
d->name_ = obj["name"].toString();
|
||||
d->countryCode_ = obj["country_code"].toString();
|
||||
d->shortName_ = obj["short_name"].toString();
|
||||
d->premiumOnly_ = obj["premium_only"].toInt();
|
||||
d->p2p_ = obj["p2p"].toInt();
|
||||
if (obj.contains("dns_hostname"))
|
||||
{
|
||||
d->dnsHostName_ = obj["dns_hostname"].toString();
|
||||
}
|
||||
|
||||
const auto groupsArray = obj["groups"].toArray();
|
||||
for (const QJsonValue &serverGroupValue : groupsArray)
|
||||
{
|
||||
QJsonObject objServerGroup = serverGroupValue.toObject();
|
||||
d->id_ = src.id;
|
||||
d->name_ = QString::fromStdString(src.name);
|
||||
d->countryCode_ = QString::fromStdString(src.countryCode);
|
||||
d->shortName_ = QString::fromStdString(src.shortName);
|
||||
d->premiumOnly_ = src.premiumOnly;
|
||||
d->dnsHostName_ = QString::fromStdString(src.dnsHostName);
|
||||
|
||||
for (const auto &g : src.groups) {
|
||||
Group group;
|
||||
if (!group.initFromJson(objServerGroup, forceDisconnectNodes))
|
||||
{
|
||||
d->isValid_ = false;
|
||||
return false;
|
||||
group.initFromWsnet(g);
|
||||
if (g.status != 0) {
|
||||
d->groups_ << group;
|
||||
}
|
||||
d->groups_ << group;
|
||||
}
|
||||
|
||||
d->isValid_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList Location::getAllPingIps() const
|
||||
@@ -67,7 +50,6 @@ bool Location::operator ==(const Location &other) const
|
||||
d->countryCode_ == other.d->countryCode_ &&
|
||||
d->shortName_ == other.d->shortName_ &&
|
||||
d->premiumOnly_ == other.d->premiumOnly_ &&
|
||||
d->p2p_ == other.d->p2p_ &&
|
||||
d->dnsHostName_ == other.d->dnsHostName_ &&
|
||||
d->groups_ == other.d->groups_ &&
|
||||
d->isValid_ == other.d->isValid_;
|
||||
@@ -78,31 +60,4 @@ bool Location::operator !=(const Location &other) const
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream& stream, const Location& l)
|
||||
{
|
||||
WS_ASSERT(l.d->isValid_);
|
||||
stream << l.versionForSerialization_;
|
||||
stream << l.d->id_ << l.d->name_ << l.d->countryCode_ << l.d->premiumOnly_ << l.d->p2p_ << l.d->dnsHostName_ << l.d->groups_ << l.d->shortName_;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream& operator >>(QDataStream& stream, Location& l)
|
||||
{
|
||||
quint32 version;
|
||||
stream >> version;
|
||||
if (version > l.versionForSerialization_)
|
||||
{
|
||||
stream.setStatus(QDataStream::ReadCorruptData);
|
||||
l.d->isValid_ = false;
|
||||
return stream;
|
||||
}
|
||||
stream >> l.d->id_ >> l.d->name_ >> l.d->countryCode_ >> l.d->premiumOnly_ >> l.d->p2p_ >> l.d->dnsHostName_ >> l.d->groups_;
|
||||
if (version >= 2) {
|
||||
stream >> l.d->shortName_;
|
||||
}
|
||||
l.d->isValid_ = true;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // namespace api_responses
|
||||
|
||||
@@ -5,12 +5,14 @@
|
||||
#include <QSharedPointer>
|
||||
#include "group.h"
|
||||
|
||||
namespace wsnet { struct ServerLocation; }
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
class LocationData : public QSharedData
|
||||
{
|
||||
public:
|
||||
LocationData() : id_(0), premiumOnly_(0), p2p_(0),
|
||||
LocationData() : id_(0), premiumOnly_(0),
|
||||
isValid_(false) {}
|
||||
|
||||
LocationData(const LocationData &other)
|
||||
@@ -20,7 +22,6 @@ public:
|
||||
countryCode_(other.countryCode_),
|
||||
shortName_(other.shortName_),
|
||||
premiumOnly_(other.premiumOnly_),
|
||||
p2p_(other.p2p_),
|
||||
dnsHostName_(other.dnsHostName_),
|
||||
groups_(other.groups_),
|
||||
isValid_(other.isValid_) {}
|
||||
@@ -30,8 +31,7 @@ public:
|
||||
QString name_;
|
||||
QString countryCode_;
|
||||
QString shortName_;
|
||||
int premiumOnly_;
|
||||
int p2p_;
|
||||
bool premiumOnly_;
|
||||
QString dnsHostName_;
|
||||
|
||||
QVector<Group> groups_;
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
explicit Location() : d(new LocationData) {}
|
||||
Location(const Location &other) : d (other.d) {}
|
||||
|
||||
bool initFromJson(const QJsonObject &obj, QStringList &forceDisconnectNodes);
|
||||
void initFromWsnet(const wsnet::ServerLocation &src);
|
||||
|
||||
int getId() const { WS_ASSERT(d->isValid_); return d->id_; }
|
||||
QString getName() const { WS_ASSERT(d->isValid_); return d->name_; }
|
||||
@@ -55,7 +55,6 @@ public:
|
||||
QString getShortName() const { WS_ASSERT(d->isValid_); return d->shortName_; }
|
||||
QString getDnsHostName() const { WS_ASSERT(d->isValid_); return d->dnsHostName_; }
|
||||
bool isPremiumOnly() const { WS_ASSERT(d->isValid_); return d->premiumOnly_; }
|
||||
int getP2P() const { WS_ASSERT(d->isValid_); return d->p2p_; }
|
||||
|
||||
int groupsCount() const { WS_ASSERT(d->isValid_); return d->groups_.count(); }
|
||||
Group getGroup(int ind) const { WS_ASSERT(d->isValid_); return d->groups_.at(ind); }
|
||||
@@ -66,12 +65,8 @@ public:
|
||||
bool operator == (const Location &other) const;
|
||||
bool operator != (const Location &other) const;
|
||||
|
||||
friend QDataStream& operator <<(QDataStream& stream, const Location& l);
|
||||
friend QDataStream& operator >>(QDataStream& stream, Location& l);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<LocationData> d;
|
||||
static constexpr quint32 versionForSerialization_ = 2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,45 +1,24 @@
|
||||
#include "node.h"
|
||||
#include "utils/ws_assert.h"
|
||||
#include <QString>
|
||||
#include <wsnet/WSNetServerLocations.h>
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
bool Node::initFromJson(QJsonObject &obj)
|
||||
void Node::initFromWsnet(const wsnet::ServerNode &src)
|
||||
{
|
||||
if (!obj.contains("ip") || !obj.contains("ip2") || !obj.contains("ip3") || !obj.contains("hostname") || !obj.contains("weight"))
|
||||
{
|
||||
d->isValid_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
d->ips_ << obj["ip"].toString();
|
||||
d->ips_ << obj["ip2"].toString();
|
||||
d->ips_ << obj["ip3"].toString();
|
||||
d->hostname_ = obj["hostname"].toString();
|
||||
d->weight_ = obj["weight"].toInt();
|
||||
|
||||
if (obj.contains("force_disconnect"))
|
||||
{
|
||||
d->forceDisconnect_ = obj["force_disconnect"].toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
d->forceDisconnect_ = 0;
|
||||
}
|
||||
|
||||
d->isValid_ = true;
|
||||
return true;
|
||||
d->ips_ = { QString::fromStdString(src.ip),
|
||||
QString::fromStdString(src.ip2),
|
||||
QString::fromStdString(src.ip3) };
|
||||
d->host_ = QString::fromStdString(src.host);
|
||||
d->weight_ = src.weight;
|
||||
d->isValid_ = true;
|
||||
}
|
||||
|
||||
QString Node::getHostname() const
|
||||
QString Node::getHost() const
|
||||
{
|
||||
WS_ASSERT(d->isValid_);
|
||||
return d->hostname_;
|
||||
}
|
||||
|
||||
bool Node::isForceDisconnect() const
|
||||
{
|
||||
WS_ASSERT(d->isValid_);
|
||||
return d->forceDisconnect_ == 1;
|
||||
return d->host_;
|
||||
}
|
||||
|
||||
QString Node::getIp(int ind) const
|
||||
@@ -59,9 +38,8 @@ int Node::getWeight() const
|
||||
bool Node::operator==(const Node &other) const
|
||||
{
|
||||
return d->ips_ == other.d->ips_ &&
|
||||
d->hostname_ == other.d->hostname_ &&
|
||||
d->host_ == other.d->host_ &&
|
||||
d->weight_ == other.d->weight_ &&
|
||||
d->forceDisconnect_ == other.d->forceDisconnect_ &&
|
||||
d->isValid_ == other.d->isValid_;
|
||||
}
|
||||
|
||||
@@ -70,30 +48,4 @@ bool Node::operator!=(const Node &other) const
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream &stream, const Node &n)
|
||||
{
|
||||
WS_ASSERT(n.d->isValid_);
|
||||
stream << n.versionForSerialization_;
|
||||
// forceDisconnect_ does not require serialization
|
||||
stream << n.d->ips_ << n.d->hostname_ << n.d->weight_;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream& operator >>(QDataStream &stream, Node &n)
|
||||
{
|
||||
quint32 version;
|
||||
stream >> version;
|
||||
if (version > n.versionForSerialization_)
|
||||
{
|
||||
stream.setStatus(QDataStream::ReadCorruptData);
|
||||
n.d->isValid_ = false;
|
||||
return stream;
|
||||
}
|
||||
|
||||
stream >> n.d->ips_ >> n.d->hostname_ >> n.d->weight_;
|
||||
n.d->isValid_ = true;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} //namespace api_responses
|
||||
|
||||
@@ -4,19 +4,20 @@
|
||||
#include <QSharedDataPointer>
|
||||
#include <QStringList>
|
||||
|
||||
namespace wsnet { struct ServerNode; }
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
class NodeData : public QSharedData
|
||||
{
|
||||
public:
|
||||
NodeData() : weight_(0), forceDisconnect_(0), isValid_(false) {}
|
||||
NodeData() : weight_(0), isValid_(false) {}
|
||||
~NodeData() {}
|
||||
|
||||
// data from API
|
||||
QVector<QString> ips_; // 3 ips
|
||||
QString hostname_;
|
||||
QString host_;
|
||||
int weight_;
|
||||
int forceDisconnect_;
|
||||
|
||||
// internal state
|
||||
bool isValid_;
|
||||
@@ -28,22 +29,17 @@ class Node
|
||||
public:
|
||||
Node() : d(new NodeData) {}
|
||||
|
||||
bool initFromJson(QJsonObject &obj);
|
||||
void initFromWsnet(const wsnet::ServerNode &src);
|
||||
|
||||
QString getHostname() const;
|
||||
bool isForceDisconnect() const;
|
||||
QString getHost() const;
|
||||
QString getIp(int ind) const;
|
||||
int getWeight() const;
|
||||
|
||||
bool operator== (const Node &other) const;
|
||||
bool operator!= (const Node &other) const;
|
||||
|
||||
friend QDataStream& operator <<(QDataStream &stream, const Node &n);
|
||||
friend QDataStream& operator >>(QDataStream &stream, Node &n);
|
||||
|
||||
private:
|
||||
QSharedDataPointer<NodeData> d;
|
||||
static constexpr quint32 versionForSerialization_ = 1;
|
||||
};
|
||||
|
||||
} //namespace api_responses
|
||||
|
||||
@@ -1,40 +1,18 @@
|
||||
#include "serverlist.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <wsnet/WSNetServerLocations.h>
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
ServerList::ServerList(const std::string &json)
|
||||
ServerList::ServerList(std::shared_ptr<wsnet::WSNetServerLocations> serverLocations)
|
||||
{
|
||||
if (json.empty())
|
||||
if (!serverLocations)
|
||||
return;
|
||||
|
||||
QJsonParseError errCode;
|
||||
auto doc = QJsonDocument::fromJson(QByteArray(json.c_str()), &errCode);
|
||||
auto jsonObject = doc.object();
|
||||
|
||||
// get country_override parameter
|
||||
if (jsonObject.contains("info")) {
|
||||
auto jsonInfo = jsonObject["info"].toObject();
|
||||
if (jsonInfo.contains("country_override")) {
|
||||
countryOverride_ = jsonInfo["country_override"].toString();
|
||||
}
|
||||
}
|
||||
|
||||
// parse locations array
|
||||
const QJsonArray jsonData = jsonObject["data"].toArray();
|
||||
for (int i = 0; i < jsonData.size(); ++i) {
|
||||
if (jsonData.at(i).isObject()) {
|
||||
Location sl;
|
||||
QJsonObject dataElement = jsonData.at(i).toObject();
|
||||
if (sl.initFromJson(dataElement, forceDisconnectNodes_)) {
|
||||
locations_ << sl;
|
||||
} else {
|
||||
QJsonDocument invalidData(dataElement);
|
||||
}
|
||||
}
|
||||
for (const auto &loc : serverLocations->locations()) {
|
||||
Location location;
|
||||
location.initFromWsnet(loc);
|
||||
locations_ << location;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace api_responses
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <QString>
|
||||
#include "location.h"
|
||||
|
||||
namespace wsnet { class WSNetServerLocations; }
|
||||
|
||||
namespace api_responses {
|
||||
|
||||
class ServerList
|
||||
{
|
||||
public:
|
||||
ServerList(const std::string &json);
|
||||
explicit ServerList(std::shared_ptr<wsnet::WSNetServerLocations> serverLocations);
|
||||
|
||||
QVector<Location> locations() const { return locations_; }
|
||||
QStringList forceDisconnectNodes() const { return forceDisconnectNodes_; }
|
||||
QString countryOverride() const { return countryOverride_; }
|
||||
|
||||
private:
|
||||
QVector<Location> locations_;
|
||||
QStringList forceDisconnectNodes_;
|
||||
QString countryOverride_;
|
||||
|
||||
};
|
||||
|
||||
} //namespace api_responses
|
||||
|
||||
@@ -134,6 +134,14 @@ SessionStatus::SessionStatus(const std::string &json) : d(new SessionStatusData)
|
||||
d->static_ips_ = 0;
|
||||
}
|
||||
|
||||
d->amneziawgConfigId_.clear();
|
||||
if (jsonData.contains("server_inventory") && jsonData["server_inventory"].isObject()) {
|
||||
auto jsonServerInventoryObj = jsonData["server_inventory"].toObject();
|
||||
if (jsonServerInventoryObj.contains("amneziawg_config_id")) {
|
||||
d->amneziawgConfigId_ = jsonServerInventoryObj["amneziawg_config_id"].toString();
|
||||
}
|
||||
}
|
||||
|
||||
d->isInitialized_ = true;
|
||||
}
|
||||
|
||||
@@ -299,6 +307,12 @@ qint64 SessionStatus::getTrafficMax() const
|
||||
return d->traffic_max_;
|
||||
}
|
||||
|
||||
QString SessionStatus::getAmneziaConfigId() const
|
||||
{
|
||||
WS_ASSERT(d->isInitialized_);
|
||||
return d->amneziawgConfigId_;
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream& stream, const SessionStatus& ss)
|
||||
{
|
||||
WS_ASSERT(ss.d->isInitialized_);
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
QString authHash_;
|
||||
QString revisionHash_;
|
||||
QSet<QString> staticIpsUpdateDevices_;
|
||||
QString amneziawgConfigId_; // if empty do not use
|
||||
};
|
||||
|
||||
// implicitly shared class SessionStatus
|
||||
@@ -70,6 +71,7 @@ public:
|
||||
qint32 getStatus() const;
|
||||
qint64 getTrafficUsed() const;
|
||||
qint64 getTrafficMax() const;
|
||||
QString getAmneziaConfigId() const;
|
||||
|
||||
bool isInitialized() const;
|
||||
void clear();
|
||||
|
||||
@@ -590,5 +590,64 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ShowPorts : public Command
|
||||
{
|
||||
public:
|
||||
ShowPorts() {}
|
||||
explicit ShowPorts(char *buf, int size)
|
||||
{
|
||||
QByteArray arr(buf, size);
|
||||
QDataStream ds(&arr, QIODevice::ReadOnly);
|
||||
ds >> protocol_;
|
||||
}
|
||||
|
||||
std::vector<char> getData() const override
|
||||
{
|
||||
QByteArray arr;
|
||||
QDataStream ds(&arr, QIODevice::WriteOnly);
|
||||
ds << protocol_;
|
||||
return std::vector<char>(arr.begin(), arr.end());
|
||||
}
|
||||
|
||||
std::string getStringId() const override { return getCommandStringId(); }
|
||||
std::string getDebugString() const override
|
||||
{
|
||||
return "CliCommands::ShowPorts debug string";
|
||||
}
|
||||
static std::string getCommandStringId() { return "CliCommands::ShowPorts"; }
|
||||
|
||||
QString protocol_;
|
||||
};
|
||||
|
||||
class PortsList : public Command
|
||||
{
|
||||
public:
|
||||
PortsList() {}
|
||||
explicit PortsList(char *buf, int size)
|
||||
{
|
||||
QByteArray arr(buf, size);
|
||||
QDataStream ds(&arr, QIODevice::ReadOnly);
|
||||
ds >> ports_;
|
||||
}
|
||||
|
||||
std::vector<char> getData() const override
|
||||
{
|
||||
QByteArray arr;
|
||||
QDataStream ds(&arr, QIODevice::WriteOnly);
|
||||
ds << ports_;
|
||||
return std::vector<char>(arr.begin(), arr.end());
|
||||
}
|
||||
|
||||
std::string getStringId() const override { return getCommandStringId(); }
|
||||
std::string getDebugString() const override
|
||||
{
|
||||
return "CliCommands::PortsList debug string";
|
||||
}
|
||||
static std::string getCommandStringId() { return "CliCommands::PortsList"; }
|
||||
|
||||
QVector<uint> ports_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace CliCommands
|
||||
} // namespace IPC
|
||||
|
||||
@@ -54,6 +54,10 @@ Command *CommandFactory::makeCommand(const std::string strId, char *buf, int siz
|
||||
return new IPC::CliCommands::ShowAmneziawg(buf, size);
|
||||
} else if (strId == IPC::CliCommands::AmneziawgPresetsList::getCommandStringId()) {
|
||||
return new IPC::CliCommands::AmneziawgPresetsList(buf, size);
|
||||
} else if (strId == IPC::CliCommands::ShowPorts::getCommandStringId()) {
|
||||
return new IPC::CliCommands::ShowPorts(buf, size);
|
||||
} else if (strId == IPC::CliCommands::PortsList::getCommandStringId()) {
|
||||
return new IPC::CliCommands::PortsList(buf, size);
|
||||
}
|
||||
|
||||
WS_ASSERT(false);
|
||||
|
||||
@@ -33,9 +33,9 @@ void Connection::connect()
|
||||
QObject::connect(localSocket_, &QLocalSocket::readyRead, this, &Connection::onReadyRead);
|
||||
QObject::connect(localSocket_, &QLocalSocket::errorOccurred, this, &Connection::onSocketError);
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
localSocket_->connectToServer("/var/run/windscribe/localipc.sock");
|
||||
localSocket_->connectToServer(WS_POSIX_RUN_DIR "/localipc.sock");
|
||||
#else
|
||||
localSocket_->connectToServer("Windscribe8rM7bza5OR");
|
||||
localSocket_->connectToServer(WS_APP_IDENTIFIER "8rM7bza5OR");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ bool Server::start()
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
// remove socket file, if already exists (for Mac/Linux)
|
||||
QString connectingPathName = QDir::tempPath();
|
||||
QFile::remove("/var/run/windscribe/localipc.sock");
|
||||
QFile::remove(WS_POSIX_RUN_DIR "/localipc.sock");
|
||||
|
||||
bool b = server_.listen("/var/run/windscribe/localipc.sock");
|
||||
bool b = server_.listen(WS_POSIX_RUN_DIR "/localipc.sock");
|
||||
#else
|
||||
bool b = server_.listen("Windscribe8rM7bza5OR");
|
||||
bool b = server_.listen(WS_APP_IDENTIFIER "8rM7bza5OR");
|
||||
#endif
|
||||
|
||||
if (!b)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Windscribe uses the following open source software:
|
||||
This application uses the following open source software:
|
||||
- Boost C++ Libraries (BSLv1)
|
||||
- cURL library (Curl License)
|
||||
- Markus F.X.J. Oberhumer's LZO (GPLv2)
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define INSTALLER_FILENAME_MAC_APP "WindscribeInstaller.app" // engine
|
||||
|
||||
#define INSTALLER_INNER_BINARY_MAC "Contents/MacOS/installer" // engine
|
||||
|
||||
#define LAUNCHER_BUNDLE_ID "com.windscribe.launcher.macos" // gui
|
||||
#define GUI_BUNDLE_ID "com.windscribe.client" // commmon, launcher
|
||||
#define HELPER_BUNDLE_ID "com.windscribe.helper.macos" // engine
|
||||
#define HELPER_BUNDLE_ID_PATH_FROM_ENGINE "Contents/Library/LaunchServices/com.windscribe.helper.macos" // engine
|
||||
@@ -33,7 +33,7 @@ void EngineSettings::saveToSettings()
|
||||
d->firewallSettings << d->connectionSettings << apiResolutionSettingsNotUsed << d->proxySettings << d->packetSize <<
|
||||
d->macAddrSpoofing << d->dnsPolicy << d->tapAdapter << d->customOvpnConfigsPath << d->isKeepAliveEnabled <<
|
||||
d->connectedDnsInfo << d->dnsManager << d->networkPreferredProtocols <<
|
||||
d->isAntiCensorship << d->decoyTrafficSettings << d->amneziawgPreset;
|
||||
d->isAntiCensorship << d->decoyTrafficSettings << d->amneziawgPreset << d->serverRoutingMethod;
|
||||
}
|
||||
|
||||
QSettings settings;
|
||||
@@ -81,6 +81,9 @@ bool EngineSettings::loadFromSettings()
|
||||
if (version >= 8) {
|
||||
ds >> d->amneziawgPreset;
|
||||
}
|
||||
if (version >= 9) {
|
||||
ds >> d->serverRoutingMethod;
|
||||
}
|
||||
|
||||
if (ds.status() == QDataStream::Ok) {
|
||||
bLoaded = true;
|
||||
@@ -105,7 +108,7 @@ bool EngineSettings::loadFromSettings()
|
||||
}
|
||||
|
||||
#ifdef CLI_ONLY
|
||||
QSettings ini("Windscribe", "windscribe_cli");
|
||||
QSettings ini(WS_SETTINGS_ORG, WS_SETTINGS_CLI);
|
||||
fromIni(ini);
|
||||
#endif
|
||||
|
||||
@@ -294,6 +297,16 @@ void EngineSettings::setDecoyTrafficSettings(const DecoyTrafficSettings &decoyTr
|
||||
d->decoyTrafficSettings = decoyTrafficSettings;
|
||||
}
|
||||
|
||||
SERVER_ROUTING_METHOD_TYPE EngineSettings::serverRoutingMethod() const
|
||||
{
|
||||
return d->serverRoutingMethod;
|
||||
}
|
||||
|
||||
void EngineSettings::setServerRoutingMethod(SERVER_ROUTING_METHOD_TYPE method)
|
||||
{
|
||||
d->serverRoutingMethod = method;
|
||||
}
|
||||
|
||||
void EngineSettings::setMacAddrSpoofing(const MacAddrSpoofing &macAddrSpoofing)
|
||||
{
|
||||
d->macAddrSpoofing = macAddrSpoofing;
|
||||
@@ -335,7 +348,8 @@ bool EngineSettings::operator==(const EngineSettings &other) const
|
||||
other.d->dnsManager == d->dnsManager &&
|
||||
other.d->decoyTrafficSettings == d->decoyTrafficSettings &&
|
||||
other.d->networkPreferredProtocols == d->networkPreferredProtocols &&
|
||||
other.d->amneziawgPreset == d->amneziawgPreset;
|
||||
other.d->amneziawgPreset == d->amneziawgPreset &&
|
||||
other.d->serverRoutingMethod == d->serverRoutingMethod;
|
||||
}
|
||||
|
||||
bool EngineSettings::operator!=(const EngineSettings &other) const
|
||||
@@ -430,6 +444,10 @@ void EngineSettingsData::fromJson(const QJsonObject &json)
|
||||
amneziawgPreset = json[kJsonAmneziawgPresetProp].toString();
|
||||
}
|
||||
|
||||
if (json.contains(kJsonServerRoutingMethodProp) && json[kJsonServerRoutingMethodProp].isDouble()) {
|
||||
serverRoutingMethod = SERVER_ROUTING_METHOD_TYPE_fromInt(json[kJsonServerRoutingMethodProp].toInt());
|
||||
}
|
||||
|
||||
if (json.contains(kJsonMacAddrSpoofingProp) && json[kJsonMacAddrSpoofingProp].isObject()) {
|
||||
macAddrSpoofing = types::MacAddrSpoofing(json[kJsonMacAddrSpoofingProp].toObject());
|
||||
}
|
||||
@@ -475,6 +493,7 @@ QJsonObject EngineSettingsData::toJson(bool isForDebugLog) const
|
||||
json[kJsonIsTerminateSocketsProp] = isTerminateSockets;
|
||||
json[kJsonLanguageProp] = language;
|
||||
json[kJsonAmneziawgPresetProp] = amneziawgPreset;
|
||||
json[kJsonServerRoutingMethodProp] = static_cast<int>(serverRoutingMethod);
|
||||
json[kJsonMacAddrSpoofingProp] = macAddrSpoofing.toJson(isForDebugLog);
|
||||
|
||||
QJsonObject networkPreferredProtocolsObj;
|
||||
@@ -493,6 +512,7 @@ QJsonObject EngineSettingsData::toJson(bool isForDebugLog) const
|
||||
// For log readability by humans/AI.
|
||||
json["dnsManagerDesc"] = DNS_MANAGER_TYPE_toString(dnsManager);
|
||||
json["dnsPolicyDesc"] = DNS_POLICY_TYPE_toString(dnsPolicy);
|
||||
json["serverRoutingMethodDesc"] = SERVER_ROUTING_METHOD_TYPE_toString(serverRoutingMethod);
|
||||
json["updateChannelDesc"] = UPDATE_CHANNEL_toString(updateChannel);
|
||||
} else {
|
||||
json[kJsonCustomOvpnConfigsPathProp] = Utils::toBase64(customOvpnConfigsPath);
|
||||
@@ -528,6 +548,7 @@ void EngineSettingsData::fromIni(QSettings &settings)
|
||||
decoyTrafficSettings.fromIni(settings);
|
||||
isAntiCensorship = settings.value(kIniIsAntiCensorshipProp, isAntiCensorship).toBool();
|
||||
amneziawgPreset = settings.value(kIniAmneziawgPresetProp, amneziawgPreset).toString();
|
||||
serverRoutingMethod = SERVER_ROUTING_METHOD_TYPE_fromInt(settings.value(kIniServerRoutingMethodProp, static_cast<int>(serverRoutingMethod)).toInt());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(QString("Advanced"));
|
||||
@@ -561,6 +582,7 @@ void EngineSettingsData::toIni(QSettings &settings) const
|
||||
decoyTrafficSettings.toIni(settings);
|
||||
settings.setValue(kIniIsAntiCensorshipProp, isAntiCensorship);
|
||||
settings.setValue(kIniAmneziawgPresetProp, amneziawgPreset);
|
||||
settings.setValue(kIniServerRoutingMethodProp, static_cast<int>(serverRoutingMethod));
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup(QString("Advanced"));
|
||||
|
||||
@@ -44,6 +44,7 @@ struct EngineSettingsData : public QSharedData
|
||||
QMap<QString, types::ConnectionSettings> networkPreferredProtocols;
|
||||
QString language;
|
||||
QString amneziawgPreset;
|
||||
SERVER_ROUTING_METHOD_TYPE serverRoutingMethod = SERVER_ROUTING_METHOD_AUTO;
|
||||
|
||||
void fromJson(const QJsonObject &json);
|
||||
QJsonObject toJson(bool isForDebugLog) const;
|
||||
@@ -53,6 +54,7 @@ struct EngineSettingsData : public QSharedData
|
||||
private:
|
||||
static const inline QString kIniAmneziawgPresetProp = "AmneziawgPreset";
|
||||
static const inline QString kIniDnsManagerProp = "DNSManager";
|
||||
static const inline QString kIniServerRoutingMethodProp = "ServerRoutingMethod";
|
||||
static const inline QString kIniDnsPolicyProp = "DNSPolicy";
|
||||
static const inline QString kIniIsAllowLanTrafficProp = "AllowLANTraffic";
|
||||
static const inline QString kIniIsAntiCensorshipProp = "CircumventCensorship";
|
||||
@@ -62,6 +64,7 @@ private:
|
||||
static const inline QString kIniUpdateChannelProp = "UpdateChannel";
|
||||
|
||||
static const inline QString kJsonAmneziawgPresetProp = "amneziawgPreset";
|
||||
static const inline QString kJsonServerRoutingMethodProp = "serverRoutingMethod";
|
||||
static const inline QString kJsonConnectedDnsInfoProp = "connectedDnsInfo";
|
||||
static const inline QString kJsonConnectionSettingsProp = "connectionSettings";
|
||||
static const inline QString kJsonCustomOvpnConfigsPathProp = "customOvpnConfigsPath";
|
||||
@@ -143,6 +146,9 @@ public:
|
||||
DecoyTrafficSettings decoyTrafficSettings() const;
|
||||
void setDecoyTrafficSettings(const DecoyTrafficSettings &decoyTrafficSettings);
|
||||
|
||||
SERVER_ROUTING_METHOD_TYPE serverRoutingMethod() const;
|
||||
void setServerRoutingMethod(SERVER_ROUTING_METHOD_TYPE method);
|
||||
|
||||
bool operator==(const EngineSettings &other) const;
|
||||
bool operator!=(const EngineSettings &other) const;
|
||||
QJsonObject toJson(bool isForDebugLog) const;
|
||||
@@ -160,7 +166,7 @@ private:
|
||||
|
||||
// for serialization
|
||||
static constexpr quint32 magic_ = 0x7745C2AE;
|
||||
static constexpr int versionForSerialization_ = 8; // should increment the version if the data format is changed
|
||||
static constexpr int versionForSerialization_ = 9; // should increment the version if the data format is changed
|
||||
};
|
||||
|
||||
} // types namespace
|
||||
|
||||
@@ -748,3 +748,34 @@ QList<QPair<QString, QVariant>> ASPECT_RATIO_MODE_toList()
|
||||
l << qMakePair(ASPECT_RATIO_MODE_toString(ASPECT_RATIO_MODE_TILE), ASPECT_RATIO_MODE_TILE);
|
||||
return l;
|
||||
}
|
||||
|
||||
QList<QPair<QString, QVariant> > SERVER_ROUTING_METHOD_TYPE_toList()
|
||||
{
|
||||
QList<QPair<QString, QVariant>> l;
|
||||
l << qMakePair(SERVER_ROUTING_METHOD_TYPE_toString(SERVER_ROUTING_METHOD_AUTO), SERVER_ROUTING_METHOD_AUTO);
|
||||
l << qMakePair(SERVER_ROUTING_METHOD_TYPE_toString(SERVER_ROUTING_METHOD_REGULAR), SERVER_ROUTING_METHOD_REGULAR);
|
||||
l << qMakePair(SERVER_ROUTING_METHOD_TYPE_toString(SERVER_ROUTING_METHOD_ALTERNATIVE), SERVER_ROUTING_METHOD_ALTERNATIVE);
|
||||
return l;
|
||||
}
|
||||
|
||||
QString SERVER_ROUTING_METHOD_TYPE_toString(SERVER_ROUTING_METHOD_TYPE p)
|
||||
{
|
||||
if (p == SERVER_ROUTING_METHOD_AUTO) return QObject::tr("Auto");
|
||||
else if (p == SERVER_ROUTING_METHOD_REGULAR) return QObject::tr("Regular");
|
||||
else if (p == SERVER_ROUTING_METHOD_ALTERNATIVE) return QObject::tr("Alternate");
|
||||
else {
|
||||
WS_ASSERT(false);
|
||||
return QObject::tr("UNKNOWN");
|
||||
}
|
||||
}
|
||||
|
||||
SERVER_ROUTING_METHOD_TYPE SERVER_ROUTING_METHOD_TYPE_fromInt(int t)
|
||||
{
|
||||
if (t == 0) return SERVER_ROUTING_METHOD_AUTO;
|
||||
else if (t == 1) return SERVER_ROUTING_METHOD_REGULAR;
|
||||
else if (t == 2) return SERVER_ROUTING_METHOD_ALTERNATIVE;
|
||||
else {
|
||||
WS_ASSERT(false);
|
||||
return SERVER_ROUTING_METHOD_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,12 @@ enum ORDER_LOCATION_TYPE {
|
||||
ORDER_LOCATION_BY_LATENCY = 2
|
||||
};
|
||||
|
||||
enum SERVER_ROUTING_METHOD_TYPE {
|
||||
SERVER_ROUTING_METHOD_AUTO = 0,
|
||||
SERVER_ROUTING_METHOD_REGULAR = 1,
|
||||
SERVER_ROUTING_METHOD_ALTERNATIVE = 2
|
||||
};
|
||||
|
||||
enum BACKGROUND_TYPE
|
||||
{
|
||||
BACKGROUND_TYPE_NONE = 0,
|
||||
@@ -323,6 +329,10 @@ ORDER_LOCATION_TYPE ORDER_LOCATION_TYPE_fromInt(int t);
|
||||
QString ORDER_LOCATION_TYPE_toString(ORDER_LOCATION_TYPE p);
|
||||
QList<QPair<QString, QVariant>> ORDER_LOCATION_TYPE_toList();
|
||||
|
||||
SERVER_ROUTING_METHOD_TYPE SERVER_ROUTING_METHOD_TYPE_fromInt(int t);
|
||||
QString SERVER_ROUTING_METHOD_TYPE_toString(SERVER_ROUTING_METHOD_TYPE p);
|
||||
QList<QPair<QString, QVariant>> SERVER_ROUTING_METHOD_TYPE_toList();
|
||||
|
||||
BACKGROUND_TYPE BACKGROUND_TYPE_fromInt(int t);
|
||||
SOUND_NOTIFICATION_TYPE SOUND_NOTIFICATION_TYPE_fromInt(int t);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "ws_branding.h"
|
||||
|
||||
static constexpr unsigned long long SIMPLE_CRYPT_KEY = 0x4572A4ACF31A31BA;
|
||||
|
||||
@@ -15,7 +16,7 @@ static constexpr unsigned int kMinWindowsBuildNumberForOpenVPNDCO = 19041;
|
||||
// The initial production Windows 11 build number.
|
||||
static constexpr unsigned int kWindows11BuildNumber = 22000;
|
||||
|
||||
static const wchar_t* kOpenVPNAdapterIdentifier = L"WindscribeOpenVPN";
|
||||
static const wchar_t* kOpenVPNAdapterIdentifier = WS_APP_IDENTIFIER_W L"OpenVPN";
|
||||
|
||||
static const std::wstring kWireGuardAdapterIdentifier = L"WindscribeWireguard";
|
||||
static const std::wstring kWireGuardAdapterIdentifier = WS_APP_IDENTIFIER_W L"Wireguard";
|
||||
static const std::wstring kWireGuardServiceIdentifier = L"WireGuardTunnel$" + kWireGuardAdapterIdentifier;
|
||||
|
||||
@@ -13,16 +13,19 @@ bool City::operator==(const City &other) const
|
||||
other.city == city &&
|
||||
other.nick == nick &&
|
||||
other.pingTimeMs == pingTimeMs &&
|
||||
other.isPro == isPro &&
|
||||
other.isPremiumOnly == isPremiumOnly &&
|
||||
other.isDisabled == isDisabled &&
|
||||
other.staticIpCountryCode == staticIpCountryCode &&
|
||||
other.staticIpShortName == staticIpShortName &&
|
||||
other.staticIpType == staticIpType &&
|
||||
other.staticIp == staticIp &&
|
||||
other.customConfigType == customConfigType &&
|
||||
other.customConfigProtocol == customConfigProtocol &&
|
||||
other.customConfigPort == customConfigPort &&
|
||||
other.customConfigIsCorrect == customConfigIsCorrect &&
|
||||
other.customConfigErrorMessage == customConfigErrorMessage &&
|
||||
other.is10Gbps == is10Gbps &&
|
||||
other.isNoP2P == isNoP2P &&
|
||||
other.health == health;
|
||||
}
|
||||
|
||||
@@ -38,7 +41,6 @@ bool Location::operator==(const Location &other) const
|
||||
other.countryCode == countryCode &&
|
||||
other.shortName == shortName &&
|
||||
other.isPremiumOnly == isPremiumOnly &&
|
||||
other.isNoP2P == isNoP2P &&
|
||||
other.cities == cities;
|
||||
}
|
||||
|
||||
@@ -79,7 +81,7 @@ Location Location::locationFromJsonObject(const QJsonObject &obj)
|
||||
location.countryCode = obj["country_code"].toString();
|
||||
location.shortName = obj["short_name"].toString();
|
||||
location.isPremiumOnly = obj["is_premium_only"].toBool();
|
||||
location.isNoP2P = !obj["is_p2p_supported"].toBool();
|
||||
bool locationLevelNoP2P = !obj["is_p2p_supported"].toBool();
|
||||
|
||||
for (const auto &c : obj["cities"].toArray())
|
||||
{
|
||||
@@ -91,7 +93,7 @@ Location Location::locationFromJsonObject(const QJsonObject &obj)
|
||||
city.city = objCity["name"].toString();
|
||||
city.nick = objCity["nick"].toString();
|
||||
city.pingTimeMs = objCity["ping_time"].toInt();
|
||||
city.isPro = objCity["is_premium_only"].toBool();
|
||||
city.isPremiumOnly = objCity["is_premium_only"].toBool();
|
||||
city.isDisabled = objCity["is_disabled"].toBool();
|
||||
city.staticIpCountryCode = objCity["static_ip_country_code"].toString();
|
||||
city.staticIpShortName = objCity["static_ip_short_name"].toString();
|
||||
@@ -102,8 +104,13 @@ Location Location::locationFromJsonObject(const QJsonObject &obj)
|
||||
city.customConfigErrorMessage = objCity["custom_config_error_message"].toString();
|
||||
city.is10Gbps = (objCity["link_speed"].toInt() == 10000);
|
||||
city.health = objCity["health"].toInt();
|
||||
if (objCity.contains("is_p2p_supported"))
|
||||
city.isNoP2P = !objCity["is_p2p_supported"].toBool();
|
||||
else
|
||||
city.isNoP2P = locationLevelNoP2P;
|
||||
location.cities << city;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "enums.h"
|
||||
#include "locationid.h"
|
||||
#include "pingtime.h"
|
||||
#include "protocol.h"
|
||||
|
||||
namespace types {
|
||||
|
||||
@@ -13,7 +14,7 @@ struct City
|
||||
QString city;
|
||||
QString nick;
|
||||
PingTime pingTimeMs;
|
||||
bool isPro = false;
|
||||
bool isPremiumOnly = false;
|
||||
bool isDisabled = false;
|
||||
|
||||
// specific for static IP location
|
||||
@@ -24,10 +25,13 @@ struct City
|
||||
|
||||
// specific for custom config location
|
||||
CUSTOM_CONFIG_TYPE customConfigType = CUSTOM_CONFIG_OPENVPN;
|
||||
Protocol customConfigProtocol;
|
||||
uint customConfigPort = 0;
|
||||
bool customConfigIsCorrect = false;
|
||||
QString customConfigErrorMessage;
|
||||
|
||||
bool is10Gbps = false;
|
||||
bool isNoP2P = false;
|
||||
int health = 0; // correct values [0..100]
|
||||
|
||||
bool operator==(const City &other) const;
|
||||
@@ -42,7 +46,6 @@ struct Location
|
||||
QString countryCode;
|
||||
QString shortName;
|
||||
bool isPremiumOnly = false;
|
||||
bool isNoP2P = false;
|
||||
QVector<City> cities;
|
||||
|
||||
bool operator==(const Location &other) const;
|
||||
|
||||
@@ -28,6 +28,8 @@ target_sources(client-common PRIVATE
|
||||
network_utils/dnschecker.h
|
||||
network_utils/network_utils.cpp
|
||||
network_utils/network_utils.h
|
||||
openvpnversioncontroller.cpp
|
||||
openvpnversioncontroller.h
|
||||
simplecrypt.cpp
|
||||
simplecrypt.h
|
||||
utils.cpp
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <QtGlobal>
|
||||
#include "dnsutils.h"
|
||||
#include "ws_branding.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <winsock2.h>
|
||||
@@ -46,8 +47,8 @@ std::vector<std::wstring> getOSDefaultDnsServers()
|
||||
while (pCurrAddresses)
|
||||
{
|
||||
// Warning: we control the FriendlyName of the wireguard-nt adapter, but not the Description.
|
||||
if ((wcsstr(pCurrAddresses->Description, L"Windscribe") == 0) && // ignore Windscribe TAP and Windscribe Ikev2 adapters
|
||||
(wcsstr(pCurrAddresses->FriendlyName, L"Windscribe") == 0)) // ignore Windscribe wireguard-nt tunnel
|
||||
if ((wcsstr(pCurrAddresses->Description, WS_PRODUCT_NAME_W) == 0) &&
|
||||
(wcsstr(pCurrAddresses->FriendlyName, WS_PRODUCT_NAME_W) == 0))
|
||||
{
|
||||
PIP_ADAPTER_DNS_SERVER_ADDRESS dnsServerAddress = pCurrAddresses->FirstDnsServerAddress;
|
||||
while (dnsServerAddress)
|
||||
|
||||
@@ -23,15 +23,6 @@ class ExecutableSignaturePrivate;
|
||||
and is named 'code_signing.pfx'. Also ensure the WINDOWS_CERT_SUBJECT_NAME
|
||||
in executable_signature_defs.h matches this certificate.
|
||||
|
||||
- Linux:
|
||||
- You can use tools/create_new_linux_keypair.sh to create a key pair used to sign
|
||||
the binaries and verify their signature. The key pair will be created in the
|
||||
common/keys/linux folder.
|
||||
- The signature file used to validate an executable should be installed in a
|
||||
'signatures' subfolder relative to the executable.
|
||||
For example: to validate /opt/windscribe/windscribeapp, the signature file
|
||||
must be in /opt/windscribe/signatures/windscribeapp.sig
|
||||
|
||||
- ExecutableSignaturePrivate implemented for each platform in:
|
||||
- ExecutableSignature_win
|
||||
- ExecutableSignature_mac
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "utils/winutils.h"
|
||||
#endif
|
||||
|
||||
// non-filtered windscribe-specific advanced settings will cause error when connecting with openvpn
|
||||
// non-filtered non-OpenVPN advanced settings will cause error when connecting with openvpn
|
||||
// configs prefixed with "ws-" will be ignored by openvpn profile
|
||||
const QString WS_PREFIX = "ws-";
|
||||
const QString WS_MTU_OFFSET_IKEV_STR = WS_PREFIX + "mtu-offset-ikev2";
|
||||
@@ -319,17 +319,6 @@ bool ExtraConfig::isLegalOpenVpnCommand(const QString &command) const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filter out potentially malicious commands.
|
||||
const char *kUnsafeCommands[] = {
|
||||
"up", "down", "ipchange", "route-up", "route-pre-down", "auth-user-pass-verify",
|
||||
"client-connect", "client-disconnect", "learn-address", "tls-verify", "log", "log-append",
|
||||
"tmp-dir", "plugin"
|
||||
};
|
||||
const size_t kNumUnsafeCommands = sizeof(kUnsafeCommands) / sizeof(kUnsafeCommands[0]);
|
||||
for (size_t i = 0; i < kNumUnsafeCommands; ++i) {
|
||||
if (trimmed_command.startsWith(QString("%1 ").arg(kUnsafeCommands[i]), Qt::CaseInsensitive))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -360,7 +349,7 @@ bool ExtraConfig::useOpenVpnDCO()
|
||||
|
||||
ExtraConfig::ExtraConfig() : QObject(),
|
||||
path_(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
|
||||
+ "/windscribe_extra.conf"),
|
||||
+ "/" WS_EXTRA_CONFIG_NAME),
|
||||
fileWatcher_(nullptr),
|
||||
fileExists_(false)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
// for work with windscribe_extra.conf file (additional parameters), thread-safe access
|
||||
// for work with advanced parameters file, thread-safe access
|
||||
// all ikev2 params will be prefixed with --ikev2, so you don't use them when using OpenVPN, and vise versa
|
||||
// ikev2 options:
|
||||
// --ikev2-compression - enable ikev2 compression for Windows (RASEO_IpHeaderCompression and RASEO_SwCompression flags)
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include "version/appversion.h"
|
||||
|
||||
class HardcodedSettings
|
||||
{
|
||||
public:
|
||||
@@ -15,7 +17,11 @@ public:
|
||||
}
|
||||
|
||||
QString windscribeHost() const { return "windscribe.com"; }
|
||||
QString windscribeServerUrl() const { return "www." + windscribeHost(); }
|
||||
QString windscribeServerUrl() const {
|
||||
if (AppVersion::instance().isStaging())
|
||||
return "www-staging." + windscribeHost();
|
||||
return "www." + windscribeHost();
|
||||
}
|
||||
|
||||
const QStringList openDns() const;
|
||||
const QStringList googleDns() const;
|
||||
|
||||
@@ -102,7 +102,7 @@ bool IpValidation::isValidUrlForCtrld(const QString &str)
|
||||
return httpsRegex.match(str).hasMatch() || sdnsRegex.match(str).hasMatch();
|
||||
}
|
||||
|
||||
bool IpValidation::isWindscribeReservedIp(const QString &str)
|
||||
bool IpValidation::isReservedIp(const QString &str)
|
||||
{
|
||||
return str.startsWith("10.255.255.");
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
static bool isValidIpForCidr(const QString &str);
|
||||
static bool isLocalIp(const QString &str);
|
||||
static bool isValidUrlForCtrld(const QString &str);
|
||||
static bool isWindscribeReservedIp(const QString &str);
|
||||
static bool isReservedIp(const QString &str);
|
||||
static QString getRemoteIdFromDomain(const QString &str);
|
||||
|
||||
#if defined(QT_DEBUG)
|
||||
|
||||
@@ -69,8 +69,13 @@ const QString getLastInstallPlatform()
|
||||
|
||||
bool isAppAlreadyRunning()
|
||||
{
|
||||
// Look for process containing "Windscribe" -- exclude grep and Engine
|
||||
QString cmd = "ps axco command | grep Windscribe | grep -v grep | grep -v WindscribeEngine | grep -v windscribe-cli";
|
||||
// Look for process containing the product name -- exclude grep and Engine
|
||||
QString cmd = "ps axco command | grep " WS_APP_EXECUTABLE_NAME " | grep -v grep";
|
||||
#ifdef WS_IS_WINDSCRIBE
|
||||
cmd += " | grep -v " WS_APP_IDENTIFIER "Engine"; // Exclude older 1.x engine process
|
||||
#endif
|
||||
if (strlen(WS_CLI_EXECUTABLE_NAME) > 0)
|
||||
cmd += " | grep -v " WS_CLI_EXECUTABLE_NAME;
|
||||
QString response = Utils::execCmd(cmd);
|
||||
return response.trimmed() != "";
|
||||
}
|
||||
@@ -247,9 +252,9 @@ QString getDistroName()
|
||||
return distro;
|
||||
}
|
||||
|
||||
gid_t getWindscribeGid()
|
||||
gid_t getAppGid()
|
||||
{
|
||||
struct group *grp = getgrnam("windscribe");
|
||||
struct group *grp = getgrnam(WS_PRODUCT_NAME_LOWER);
|
||||
if (grp == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace LinuxUtils
|
||||
{
|
||||
const QString LAST_INSTALL_PLATFORM_FILE = "/etc/windscribe/platform";
|
||||
const QString LAST_INSTALL_PLATFORM_FILE = WS_POSIX_CONFIG_DIR "/platform";
|
||||
const QString DEB_PLATFORM_NAME_X64 = QString("linux_deb_x64");
|
||||
const QString DEB_PLATFORM_NAME_X64_CLI = QString("linux_deb_x64_cli");
|
||||
const QString DEB_PLATFORM_NAME_ARM64 = QString("linux_deb_arm64");
|
||||
@@ -23,7 +23,7 @@ namespace LinuxUtils
|
||||
QString getLinuxKernelVersion();
|
||||
QString getDistroName();
|
||||
const QString getLastInstallPlatform();
|
||||
gid_t getWindscribeGid();
|
||||
gid_t getAppGid();
|
||||
bool isImmutableDistro();
|
||||
|
||||
// CLI
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
|
||||
namespace log_utils {
|
||||
|
||||
// merge logs files log_gui.txt, windscribeservice.log, and WireguardServiceLog.txt (Windows only) to one,
|
||||
// cutting out the middle of the log if the count of lines exceeds MAX_COUNT_OF_LINES
|
||||
// merge client, helper, and installer logs to one, cutting out the middle of the log if the count of lines exceeds MAX_COUNT_OF_LINES
|
||||
class MergeLog
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -42,19 +42,21 @@ void paths::deleteOldUnusedLogs()
|
||||
QFile::remove(appDataPath + "/ping_log_custom_configs.txt");
|
||||
QFile::remove(appDataPath + "/log_singleappinstanceguard.txt");
|
||||
|
||||
#ifdef WS_IS_WINDSCRIBE
|
||||
// remove Windscribe folder which is no longer used since version 2.xx
|
||||
// now we use only Windcribe2 folder
|
||||
// now we use only Windscribe2 folder
|
||||
QDir dir(appDataPath);
|
||||
if (dir.cdUp()) {
|
||||
if (dir.cd("Windscribe"))
|
||||
dir.removeRecursively();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString paths::serviceLogLocation(bool previous)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return serviceLogFolder() + addPreviousSuffix("/windscribe_service.log", previous);
|
||||
return serviceLogFolder() + addPreviousSuffix("/" WS_PRODUCT_NAME_LOWER "_service.log", previous);
|
||||
#else
|
||||
return serviceLogFolder() + addPreviousSuffix("/helper.log", previous);
|
||||
#endif
|
||||
@@ -88,9 +90,9 @@ QString paths::clientLogFolder()
|
||||
QString paths::serviceLogFolder()
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
return "/var/log/windscribe";
|
||||
return WS_LINUX_LOG_DIR;
|
||||
#elif defined(Q_OS_MACOS)
|
||||
return "/Library/Logs/com.windscribe.helper.macos";
|
||||
return "/Library/Logs/" WS_MAC_HELPER_BUNDLE_ID;
|
||||
#else
|
||||
return qApp->applicationDirPath();
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "executable_signature/executable_signature.h"
|
||||
#include "log/categories.h"
|
||||
#include "macutils.h"
|
||||
#include "names.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace {
|
||||
@@ -98,8 +97,13 @@ void MacUtils::setArrowCursor()
|
||||
|
||||
bool MacUtils::isAppAlreadyRunning()
|
||||
{
|
||||
// Look for process containing "Windscribe" -- exclude grep and Engine
|
||||
QString cmd = "ps axco command | grep Windscribe | grep -v grep | grep -v WindscribeEngine | grep -v windscribe-cli";
|
||||
// Look for process containing the product name -- exclude grep and Engine
|
||||
QString cmd = "ps axco command | grep " WS_APP_EXECUTABLE_NAME " | grep -v grep";
|
||||
#ifdef WS_IS_WINDSCRIBE
|
||||
cmd += " | grep -v " WS_APP_IDENTIFIER "Engine"; // Exclude older 1.x engine process
|
||||
#endif
|
||||
if (strlen(WS_CLI_EXECUTABLE_NAME) > 0)
|
||||
cmd += " | grep -v " WS_CLI_EXECUTABLE_NAME;
|
||||
QString response = Utils::execCmd(cmd);
|
||||
return response.trimmed() != "";
|
||||
}
|
||||
@@ -142,7 +146,7 @@ NSRunningApplication *guiApplicationByBundleName()
|
||||
{
|
||||
NSRunningApplication *app = [apps objectAtIndex: i];
|
||||
QString appBundleId = QString::fromNSString([app bundleIdentifier]);
|
||||
if (appBundleId == QString(GUI_BUNDLE_ID))
|
||||
if (appBundleId == QString(WS_MAC_GUI_BUNDLE_ID))
|
||||
{
|
||||
if ([app processIdentifier] != [currentApp processIdentifier])
|
||||
{
|
||||
@@ -181,18 +185,18 @@ void MacUtils::getNSWindowCenter(void *nsView, int &outX, int &outY)
|
||||
|
||||
bool MacUtils::dynamicStoreEntryHasKey(const QString &entry, const QString &key)
|
||||
{
|
||||
SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("WindscribeKeyChecker"), NULL, NULL);
|
||||
SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("" WS_APP_IDENTIFIER "KeyChecker"), NULL, NULL);
|
||||
if (dynRef == NULL) {
|
||||
qCCritical(LOG_BASIC) << "dynamicStoreEntryHasKey - SCDynamicStoreCreate failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
CFStringRef setByWindscribeValue = NULL;
|
||||
CFStringRef setByAppValue = NULL;
|
||||
CFStringRef entryCFString = entry.toCFString();
|
||||
CFStringRef keyCFString = key.toCFString();
|
||||
CFDictionaryRef dnskey = (CFDictionaryRef) SCDynamicStoreCopyValue(dynRef, entryCFString);
|
||||
if (dnskey != NULL) {
|
||||
setByWindscribeValue = (CFStringRef) CFDictionaryGetValue(dnskey, keyCFString);
|
||||
setByAppValue = (CFStringRef) CFDictionaryGetValue(dnskey, keyCFString);
|
||||
CFRelease(dnskey);
|
||||
} else {
|
||||
qCCritical(LOG_BASIC) << "dynamicStoreEntryHasKey - SCDynamicStoreCopyValue failed";
|
||||
@@ -200,7 +204,7 @@ bool MacUtils::dynamicStoreEntryHasKey(const QString &entry, const QString &key)
|
||||
CFRelease(dynRef);
|
||||
CFRelease(entryCFString);
|
||||
CFRelease(keyCFString);
|
||||
return setByWindscribeValue != NULL;
|
||||
return setByAppValue != NULL;
|
||||
}
|
||||
|
||||
bool MacUtils::verifyAppBundleIntegrity()
|
||||
@@ -253,7 +257,7 @@ bool MacUtils::isParentProcessGui()
|
||||
if ((status != 0) && (strlen(pathBuffer) != 0))
|
||||
{
|
||||
QString parentPath = QString::fromStdString(pathBuffer);
|
||||
QString guiPath = QCoreApplication::applicationDirPath() + "/../../../../MacOS/Windscribe";
|
||||
QString guiPath = QCoreApplication::applicationDirPath() + "/../../../../MacOS/" WS_APP_EXECUTABLE_NAME;
|
||||
guiPath = QDir::cleanPath(guiPath);
|
||||
|
||||
if (parentPath.compare(guiPath, Qt::CaseInsensitive) == 0)
|
||||
|
||||
@@ -359,7 +359,7 @@ static bool isNetworkUnidentified(const QString &adapterGUID)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool isRowUsableForWindscribe(const IfTable2Row &row)
|
||||
static bool isRowUsableForAppVpn(const IfTable2Row &row)
|
||||
{
|
||||
switch (row.interfaceType) {
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
@@ -378,7 +378,7 @@ static bool isRowUsableForWindscribe(const IfTable2Row &row)
|
||||
return row.valid && row.interfaceType != IF_TYPE_PPP && !row.endPointInterface && row.connectorPresent;
|
||||
}
|
||||
|
||||
static IfTable2Row lowestMetricNonWindscribeIfTableRow()
|
||||
static IfTable2Row lowestMetricNonVpnIfTableRow()
|
||||
{
|
||||
IfTable2Row lowestMetricIfRow;
|
||||
|
||||
@@ -393,7 +393,7 @@ static IfTable2Row lowestMetricNonWindscribeIfTableRow()
|
||||
if (ipAdapter.index == row.index) {
|
||||
IfTable2Row ifRow = tableRowByIndex(ifTable2, row.index);
|
||||
// We call this function to determine the current interface, so also make sure that the row is media-connected.
|
||||
if (isRowUsableForWindscribe(ifRow) && ifRow.mediaConnected && !ifRow.isWindscribeAdapter()) {
|
||||
if (isRowUsableForAppVpn(ifRow) && ifRow.mediaConnected && !ifRow.isAppVpnAdapter()) {
|
||||
const auto row_metric = static_cast<int>(row.metric);
|
||||
if (row_metric < lowestMetric) {
|
||||
lowestMetric = row_metric;
|
||||
@@ -447,7 +447,7 @@ static QList<AdapterAddress> getAdapterAddressesTable()
|
||||
|
||||
bool NetworkUtils_win::isInterfaceSpoofed(int interfaceIndex)
|
||||
{
|
||||
return interfaceSubkeyHasProperty(interfaceIndex, "WindscribeMACSpoofed");
|
||||
return interfaceSubkeyHasProperty(interfaceIndex, WS_APP_IDENTIFIER "MACSpoofed");
|
||||
}
|
||||
|
||||
bool NetworkUtils_win::pingWithMtu(const QString &url, int mtu)
|
||||
@@ -491,7 +491,7 @@ QString NetworkUtils_win::currentNetworkInterfaceGuid()
|
||||
// (which is not useful to determine if the interface has changed), or it forces an update
|
||||
// (which we want to avoid until we know something actually changed).
|
||||
|
||||
IfTable2Row row = lowestMetricNonWindscribeIfTableRow();
|
||||
IfTable2Row row = lowestMetricNonVpnIfTableRow();
|
||||
if (!row.valid) {
|
||||
return "";
|
||||
}
|
||||
@@ -508,7 +508,7 @@ bool NetworkUtils_win::haveActiveInterface()
|
||||
QList<IfTable2Row> ifTable2 = getIfTable2();
|
||||
for (const IpAdapter &ia : ipAdapters) {
|
||||
IfTable2Row row = tableRowByIndex(ifTable2, ia.index);
|
||||
if (isRowUsableForWindscribe(row) && row.mediaConnected) {
|
||||
if (isRowUsableForAppVpn(row) && row.mediaConnected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -519,7 +519,7 @@ types::NetworkInterface NetworkUtils_win::currentNetworkInterface()
|
||||
{
|
||||
types::NetworkInterface curNetworkInterface = types::NetworkInterface::noNetworkInterface();
|
||||
|
||||
IfTable2Row row = lowestMetricNonWindscribeIfTableRow();
|
||||
IfTable2Row row = lowestMetricNonVpnIfTableRow();
|
||||
if (!row.valid) {
|
||||
return curNetworkInterface;
|
||||
}
|
||||
@@ -607,7 +607,7 @@ QVector<types::NetworkInterface> NetworkUtils_win::currentNetworkInterfaces(bool
|
||||
assert(false);
|
||||
continue;
|
||||
}
|
||||
if (!isRowUsableForWindscribe(it2Row)) {
|
||||
if (!isRowUsableForAppVpn(it2Row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ DWORD WlanUtils_win::getSsidFromHelper(const QString &interfaceGUID, QString &ou
|
||||
if (result == ERROR_ACCESS_DENIED) {
|
||||
if (warnWLanAPIBlocked) {
|
||||
warnWLanAPIBlocked = false;
|
||||
qCWarning(LOG_BASIC) << "*** the WlanQueryInterface API is blocked on this computer. Windscribe will be unable to determine your Wi-Fi SSID until you enable Location services for Windows.";
|
||||
qCWarning(LOG_BASIC) << "*** the WlanQueryInterface API is blocked on this computer. The application will be unable to determine your Wi-Fi SSID until you enable Location services for Windows.";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -81,10 +81,10 @@ struct IfTable2Row
|
||||
index(index), interfaceGuid(guid), description(description), alias(alias), op_status(op_status), connectorPresent(connectorPresent),
|
||||
endPointInterface(endPointInterface), valid(true), interfaceType(interfaceType), mediaConnected(mediaConnected) {}
|
||||
|
||||
bool isWindscribeAdapter() const
|
||||
bool isAppVpnAdapter() const
|
||||
{
|
||||
// Warning: we control the alias of the wireguard-nt adapter, but not the description.
|
||||
return description.contains("windscribe", Qt::CaseInsensitive) || alias.contains("windscribe", Qt::CaseInsensitive);
|
||||
return description.contains(WS_PRODUCT_NAME, Qt::CaseInsensitive) || alias.contains(WS_PRODUCT_NAME, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
void print()
|
||||
|
||||
+4
-4
@@ -4,14 +4,14 @@
|
||||
#include <QDir>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "utils/winutils.h"
|
||||
#include "winutils.h"
|
||||
#else
|
||||
#include "boost/process/v1/io.hpp"
|
||||
#include "boost/process/v1/child.hpp"
|
||||
#include <QRegularExpression>
|
||||
#endif
|
||||
|
||||
#include "utils/ws_assert.h"
|
||||
#include "ws_assert.h"
|
||||
|
||||
QString OpenVpnVersionController::getOpenVpnVersion()
|
||||
{
|
||||
@@ -37,9 +37,9 @@ QString OpenVpnVersionController::getOpenVpnFilePath()
|
||||
QString OpenVpnVersionController::getOpenVpnFileName()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return QString("windscribeopenvpn.exe");
|
||||
return QString(WS_PRODUCT_NAME_LOWER "openvpn.exe");
|
||||
#else
|
||||
return QString("windscribeopenvpn");
|
||||
return QString(WS_PRODUCT_NAME_LOWER "openvpn");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <sddl.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <codecvt>
|
||||
#include <sstream>
|
||||
|
||||
@@ -16,47 +17,26 @@ static std::string wstring_to_string(const std::wstring &wideStr)
|
||||
return converter.to_bytes(wideStr);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// ServiceControlManager class implementation
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: ServiceControlManager constructor
|
||||
*
|
||||
* PURPOSE: Constructs an instance of the ServiceControlManager class and initializes the
|
||||
* member data. The user must then call OpenSCM() to open a connection
|
||||
* to a specific Service Control Manager before calling any other
|
||||
* methods.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Constructs an instance of the ServiceControlManager class and initializes the member data.
|
||||
openSCM must be called to open a connection to a specific Service Control Manager before
|
||||
calling any other methods.
|
||||
*/
|
||||
ServiceControlManager::ServiceControlManager()
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: ServiceControlManager destructor
|
||||
*
|
||||
* PURPOSE: Destructs an instance of the ServiceControlManager class.
|
||||
*
|
||||
* INPUT: None.
|
||||
*******************************************************************************/
|
||||
ServiceControlManager::~ServiceControlManager()
|
||||
{
|
||||
closeSCM();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: openSCM
|
||||
*
|
||||
* PURPOSE: Opens a connection to the specified SCM.
|
||||
*
|
||||
* INPUT: desiredAccess: desired access rights, as defined by the OpenSCManager
|
||||
* Win32 API.
|
||||
*
|
||||
* serverName: Points to a null-terminated string that names the
|
||||
* target computer. If the pointer is NULL or points to an empty
|
||||
* string, the method connects to the SCM on the local computer.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Opens a connection to the specified SCM with the desired access rights, as defined by the
|
||||
OpenSCManager Win32 API. serverName points to a null-terminated string naming the target
|
||||
computer. If the pointer is NULL or points to an empty string, the method connects to the
|
||||
SCM on the local computer.
|
||||
*/
|
||||
void ServiceControlManager::openSCM(DWORD desiredAccess, LPCTSTR serverName)
|
||||
{
|
||||
closeSCM();
|
||||
@@ -90,16 +70,6 @@ void ServiceControlManager::openSCM(DWORD desiredAccess, LPCTSTR serverName)
|
||||
throw std::system_error(lastError, std::system_category(), wstring_to_string(errorMsg.str()));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: closeSCM()
|
||||
*
|
||||
* PURPOSE: Closes the open SCM and service handles.
|
||||
*
|
||||
* THROWS: This method does not throw an exception. The method may be called
|
||||
* for 'clean-up' after another ServiceControlManager method raises an exception.
|
||||
* Thus we don't want this method raising an exception thereby 'cancelling'
|
||||
* the first exception.
|
||||
*******************************************************************************/
|
||||
void ServiceControlManager::closeSCM() noexcept
|
||||
{
|
||||
closeService();
|
||||
@@ -112,21 +82,13 @@ void ServiceControlManager::closeSCM() noexcept
|
||||
serverName_.clear();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: openService
|
||||
*
|
||||
* PURPOSE: Opens a handle to an existing service.
|
||||
* OpenSCM must be called before calling this method.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to open. The maximum string length is 256 characters. The
|
||||
* SCM database preserves the case of the characters, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Opens a handle to an existing service. openSCM must be called before calling this method.
|
||||
serviceName points to a null-terminated string naming the service to open. The maximum
|
||||
string length is 256 characters. The SCM database preserves the case of the characters,
|
||||
but service name comparisons are always case insensitive. A slash (/), backslash (\),
|
||||
comma, and space are invalid service name characters.
|
||||
*/
|
||||
void ServiceControlManager::openService(LPCTSTR serviceName, DWORD desiredAccess)
|
||||
{
|
||||
std::error_code ec;
|
||||
@@ -185,18 +147,6 @@ bool ServiceControlManager::openService(LPCTSTR serviceName, DWORD desiredAccess
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: closeService
|
||||
*
|
||||
* PURPOSE: Closes an open service handle.
|
||||
*
|
||||
* INPUT: None.
|
||||
*
|
||||
* THROWS: This method does not throw an exception. The method may be called
|
||||
* for 'clean-up' after another ServiceControlManager method raises an exception.
|
||||
* Thus we don't want this method raising an exception thereby 'cancelling'
|
||||
* the first exception.
|
||||
*******************************************************************************/
|
||||
void ServiceControlManager::closeService() noexcept
|
||||
{
|
||||
if (service_ != NULL) {
|
||||
@@ -206,24 +156,10 @@ void ServiceControlManager::closeService() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: queryServiceStatus
|
||||
*
|
||||
* PURPOSE: Determines the status (started, stopped, pending, etc.) of the
|
||||
* service. OpenService must be called before calling this method.
|
||||
*
|
||||
* OUTPUT: dwStatus: receives one of the following status codes:
|
||||
*
|
||||
* SERVICE_STOPPED
|
||||
* SERVICE_START_PENDING
|
||||
* SERVICE_STOP_PENDING
|
||||
* SERVICE_RUNNING
|
||||
* SERVICE_CONTINUE_PENDING
|
||||
* SERVICE_PAUSE_PENDING
|
||||
* SERVICE_PAUSED
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Determines the status (started, stopped, pending, etc.) of the service. openService must be
|
||||
called before calling this method.
|
||||
*/
|
||||
DWORD ServiceControlManager::queryServiceStatus() const
|
||||
{
|
||||
std::error_code ec;
|
||||
@@ -265,29 +201,13 @@ DWORD ServiceControlManager::queryServiceStatus(std::error_code& ec) const noexc
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: queryServiceConfig
|
||||
*
|
||||
* PURPOSE: Retrieves the configuration parameters of the service.
|
||||
* OpenService must be called before calling this method.
|
||||
*
|
||||
* OUTPUT: exePath: receives the full path to the service's executable.
|
||||
*
|
||||
* accountName: receives the account name in the form of
|
||||
* DomainName\Username, which the service process will be logged
|
||||
* on as when it runs.
|
||||
*
|
||||
* startType: receives one of the following status codes:
|
||||
*
|
||||
* SERVICE_AUTO_START - NT starts service automatically
|
||||
* SERVICE_DEMAND_START - user must start the service
|
||||
* SERVICE_DISABLED - service cannot be started
|
||||
*
|
||||
* serviceShareProcess: true if the service shares a process with
|
||||
* other services.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Retrieves the configuration parameters of the service. openService must be called before calling this method.
|
||||
exePath: receives the full path to the service's executable.
|
||||
accountName: receives the account name in the form of DomainName\Username, which the service process will be logged on as when it runs.
|
||||
startType: receives a start code of SERVICE_AUTO_START, SERVICE_DEMAND_START, or SERVICE_DISABLED.
|
||||
serviceShareProcess: true if the service shares a process with other services.
|
||||
*/
|
||||
void ServiceControlManager::queryServiceConfig(std::wstring &exePath, std::wstring &accountName,
|
||||
DWORD& startType, bool& serviceShareProcess) const
|
||||
{
|
||||
@@ -342,20 +262,14 @@ void ServiceControlManager::queryServiceConfig(std::wstring &exePath, std::wstri
|
||||
accountName = lpConfig->lpServiceStartName;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: startService
|
||||
*
|
||||
* PURPOSE: Instructs the SCM to start the service. OpenService must be called
|
||||
* before calling this method.
|
||||
*
|
||||
* INPUT: None.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
void ServiceControlManager::startService()
|
||||
/*
|
||||
Instructs the SCM to start the service and waits at most timeoutMs for the service to start.
|
||||
openService must be called before calling this method.
|
||||
*/
|
||||
void ServiceControlManager::startService(int timeoutMs)
|
||||
{
|
||||
std::error_code ec;
|
||||
if (startService(ec)) {
|
||||
if (startService(ec, timeoutMs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -422,7 +336,7 @@ void ServiceControlManager::startService()
|
||||
throw std::system_error(ec, wstring_to_string(errorMsg.str()));
|
||||
}
|
||||
|
||||
bool ServiceControlManager::startService(std::error_code& ec) noexcept
|
||||
bool ServiceControlManager::startService(std::error_code& ec, int timeoutMs) noexcept
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
@@ -434,7 +348,8 @@ bool ServiceControlManager::startService(std::error_code& ec) noexcept
|
||||
DWORD lastError;
|
||||
if (::StartService(service_, 0, NULL)) {
|
||||
// Wait for start service command to complete.
|
||||
for (int i = 0; !blockStartStopRequests_ && i < 200; i++) {
|
||||
const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs);
|
||||
while (!blockStartStopRequests_) {
|
||||
DWORD status = queryServiceStatus(ec);
|
||||
if (ec) {
|
||||
return false;
|
||||
@@ -449,7 +364,11 @@ bool ServiceControlManager::startService(std::error_code& ec) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
::Sleep(100);
|
||||
if (std::chrono::steady_clock::now() >= deadline) {
|
||||
break;
|
||||
}
|
||||
|
||||
::Sleep(50);
|
||||
}
|
||||
|
||||
lastError = (blockStartStopRequests_ ? ERROR_CANCELLED : ERROR_SERVICE_START_HANG);
|
||||
@@ -467,20 +386,14 @@ bool ServiceControlManager::startService(std::error_code& ec) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: stopService
|
||||
*
|
||||
* PURPOSE: Instructs the SCM to stop the service. OpenService must be called
|
||||
* before calling this method.
|
||||
*
|
||||
* INPUT: None.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
void ServiceControlManager::stopService()
|
||||
/*
|
||||
Instructs the SCM to stop the service and waits at most timeoutMs for the service to stop.
|
||||
openService must be called before calling this method.
|
||||
*/
|
||||
void ServiceControlManager::stopService(int timeoutMs)
|
||||
{
|
||||
std::error_code ec;
|
||||
if (stopService(ec)) {
|
||||
if (stopService(ec, timeoutMs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -519,7 +432,7 @@ void ServiceControlManager::stopService()
|
||||
throw std::system_error(ec, wstring_to_string(errorMsg.str()));
|
||||
}
|
||||
|
||||
bool ServiceControlManager::stopService(std::error_code& ec) noexcept
|
||||
bool ServiceControlManager::stopService(std::error_code& ec, int timeoutMs) noexcept
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
@@ -534,13 +447,16 @@ bool ServiceControlManager::stopService(std::error_code& ec) noexcept
|
||||
// Wait for stop service command to complete.
|
||||
DWORD currentState = status.dwCurrentState;
|
||||
|
||||
// Wait at most 20 seconds for the service to stop.
|
||||
for (int i = 0; (!blockStartStopRequests_ && (currentState != SERVICE_STOPPED) && (i < 200)); i++) {
|
||||
::Sleep(100);
|
||||
const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs);
|
||||
while (!blockStartStopRequests_ && currentState != SERVICE_STOPPED) {
|
||||
::Sleep(50);
|
||||
currentState = queryServiceStatus(ec);
|
||||
if (ec) {
|
||||
return false;
|
||||
}
|
||||
if (std::chrono::steady_clock::now() >= deadline) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentState == SERVICE_STOPPED) {
|
||||
@@ -561,52 +477,24 @@ bool ServiceControlManager::stopService(std::error_code& ec) noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: stopService
|
||||
*
|
||||
* PURPOSE: Opens the SCM and instructs it to stop the service if it is installed.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to open. The maximum string length is 256 characters. The
|
||||
* SCM database preserves the case of the characters, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
void ServiceControlManager::stopService(LPCTSTR serviceName)
|
||||
/*
|
||||
Opens the SCM and instructs it to stop the service if it is installed.
|
||||
*/
|
||||
void ServiceControlManager::stopService(LPCTSTR serviceName, int timeoutMs)
|
||||
{
|
||||
openSCM(SC_MANAGER_CONNECT);
|
||||
if (isServiceInstalled(serviceName)) {
|
||||
openService(serviceName, SERVICE_QUERY_STATUS | SERVICE_STOP);
|
||||
stopService();
|
||||
stopService(timeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: deleteService
|
||||
*
|
||||
* PURPOSE: Initiates deletion of the service from the SCM database.
|
||||
*
|
||||
* NOTES: - OpenSCM must be called before calling this method.
|
||||
* - The service must exist.
|
||||
* - This method does not wait for the service to be deleted. If the
|
||||
* system/SCM are busy, it may take some time for the service to be
|
||||
* actually deleted from the SCM database.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to delete. The maximum string length is 256 characters.
|
||||
* The SCM database preserves the character's case, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* stopRunningService: attempt to stop the service, if it's running,
|
||||
* before asking the SCM to delete it.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Initiates deletion of the service from the SCM database. The specified service must exist and openSCM
|
||||
must be called before calling this method. This method does not wait for the service to be deleted.
|
||||
If the system/SCM are busy, it may take some time for the service to be actually deleted from the SCM
|
||||
database.
|
||||
*/
|
||||
void ServiceControlManager::deleteService(LPCTSTR serviceName, bool stopRunningService)
|
||||
{
|
||||
openService(serviceName);
|
||||
@@ -652,25 +540,11 @@ void ServiceControlManager::deleteService(LPCTSTR serviceName, bool stopRunningS
|
||||
throw std::system_error(lastError, std::system_category(), wstring_to_string(errorMsg.str()));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: deleteService
|
||||
*
|
||||
* PURPOSE: Stops the service if it is running and initiates deletion of the
|
||||
* service from the SCM database. Waits at most 20s for the SCM to
|
||||
* report the service as deleted.
|
||||
*
|
||||
* NOTES: OpenSCM must be called before calling this method.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to delete. The maximum string length is 256 characters.
|
||||
* The SCM database preserves the character's case, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* ec: contains the WIN32 error code if a failure occurs.
|
||||
*******************************************************************************/
|
||||
bool ServiceControlManager::deleteService(LPCTSTR serviceName, std::error_code& ec) noexcept
|
||||
/*
|
||||
Stops the service if it is running and initiates deletion of the service from the SCM database. Waits at most
|
||||
timeoutMs for the SCM to report the service as deleted. openSCM must be called before calling this method.
|
||||
*/
|
||||
bool ServiceControlManager::deleteService(LPCTSTR serviceName, std::error_code& ec, int timeoutMs) noexcept
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
@@ -716,8 +590,9 @@ bool ServiceControlManager::deleteService(LPCTSTR serviceName, std::error_code&
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait at most 20 seconds for the service to be deleted.
|
||||
for (int i = 0; i < 200; i++) {
|
||||
// Wait for the service to be deleted.
|
||||
const auto deadline = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs);
|
||||
do {
|
||||
result = openService(serviceName, SERVICE_QUERY_STATUS, ec);
|
||||
if (!result) {
|
||||
if (ec.value() == ERROR_SERVICE_DOES_NOT_EXIST) {
|
||||
@@ -729,28 +604,12 @@ bool ServiceControlManager::deleteService(LPCTSTR serviceName, std::error_code&
|
||||
}
|
||||
|
||||
closeService();
|
||||
::Sleep(100);
|
||||
}
|
||||
::Sleep(50);
|
||||
} while (std::chrono::steady_clock::now() < deadline);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: isServiceInstalled
|
||||
*
|
||||
* PURPOSE: Queries the SCM database to see if the service is installed.
|
||||
* OpenSCM must be called before calling this method.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to query. The maximum string length is 256 characters.
|
||||
* The SCM database preserves the character's case, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
bool ServiceControlManager::isServiceInstalled(LPCTSTR serviceName) const
|
||||
{
|
||||
if (serviceName == NULL) {
|
||||
@@ -768,54 +627,31 @@ bool ServiceControlManager::isServiceInstalled(LPCTSTR serviceName) const
|
||||
return installed;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: installService
|
||||
*
|
||||
* PURPOSE: Installs a service.
|
||||
* OpenSCM must be called before calling this method.
|
||||
*
|
||||
* INPUT: serviceName: Points to a null-terminated string that names the
|
||||
* service to install. The maximum string length is 256 characters.
|
||||
* The SCM database preserves the character's case, but service
|
||||
* name comparisons are always case insensitive. A slash (/),
|
||||
* backslash (\), comma, and space are invalid service name
|
||||
* characters.
|
||||
*
|
||||
* binaryPathName: Points to a null-terminated string that contains
|
||||
* the fully qualified path to the service binary file.
|
||||
*
|
||||
* displayName: Points to a null-terminated string that is to be
|
||||
* used by user interface programs to identify the service. This
|
||||
* string has a maximum length of 256 characters. The name is
|
||||
* case-preserved in the SCM. display name comparisons are always
|
||||
* case-insensitive.
|
||||
*
|
||||
* description: Points to a null-terminated string that specifies
|
||||
* the description of the service.
|
||||
*
|
||||
* serviceType: specify one of the following service types:
|
||||
*
|
||||
* SERVICE_WIN32_OWN_PROCESS
|
||||
* SERVICE_WIN32_SHARE_PROCESS
|
||||
*
|
||||
* startType: specify one of the following start types:
|
||||
*
|
||||
* SERVICE_AUTO_START - started automatically by the SCM during
|
||||
* system startup.
|
||||
*
|
||||
* SERVICE_DEMAND_START - started by the SCM when a process calls
|
||||
* the StartService function.
|
||||
*
|
||||
* dependencies: Points to a double null-terminated array of
|
||||
* null-separated names of services that the system must start
|
||||
* before this service. Specify NULL or an empty string if the
|
||||
* service has no dependencies.
|
||||
*
|
||||
* allowInteractiveUserStartStop: if true logged in non-admin users can
|
||||
* start and stop the service.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Installs a service. oOpenSCM must be called before calling this method.
|
||||
|
||||
serviceName: points to a null-terminated string that names the service to install. The maximum string
|
||||
length is 256 characters. The SCM database preserves the character's case, but service name comparisons
|
||||
are always case insensitive. A slash (/), backslash (\), comma, and space are invalid service name
|
||||
characters.
|
||||
|
||||
binaryPathName: points to a null-terminated string that contains the fully qualified path to the service binary file.
|
||||
|
||||
displayName: points to a null-terminated string that is to be used by user interface programs to identify the
|
||||
service. This string has a maximum length of 256 characters. The name is case-preserved in the SCM. Display
|
||||
name comparisons are always case-insensitive.
|
||||
|
||||
description: points to a null-terminated string that specifies the description of the service.
|
||||
|
||||
serviceType: specify a service type of SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS.
|
||||
|
||||
startType: specify a start type of SERVICE_AUTO_START or SERVICE_DEMAND_START.
|
||||
|
||||
dependencies: points to a double null-terminated array of null-separated names of services that the system must start
|
||||
before this service. Specify NULL or an empty string if the service has no dependencies.
|
||||
|
||||
allowInteractiveUserStartStop: if true, logged in non-admin users can start and stop the service.
|
||||
*/
|
||||
void ServiceControlManager::installService(LPCTSTR serviceName, LPCTSTR binaryPathName,
|
||||
LPCTSTR displayName, LPCTSTR description,
|
||||
DWORD serviceType, DWORD startType,
|
||||
@@ -881,17 +717,10 @@ void ServiceControlManager::installService(LPCTSTR serviceName, LPCTSTR binaryP
|
||||
throw std::system_error(lastError, std::system_category(), wstring_to_string(errorMsg.str()));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: sendControlCode
|
||||
*
|
||||
* PURPOSE: Sends a control code to the service. The service will ignore the
|
||||
* code if it does not recognize it.
|
||||
* OpenService must be called before calling this method.
|
||||
*
|
||||
* INPUT: code: the control code to send.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Sends a control code to the service. The service will ignore the code if it does not recognize it.
|
||||
openService must be called before calling this method.
|
||||
*/
|
||||
void ServiceControlManager::sendControlCode(DWORD code) const
|
||||
{
|
||||
DWORD lastError;
|
||||
@@ -1020,13 +849,9 @@ void ServiceControlManager::grantUserStartStopPermission() const
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* METHOD: exePath
|
||||
*
|
||||
* PURPOSE: Retrieves the full path to the service's executable.
|
||||
*
|
||||
* THROWS: A system_error object.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
Retrieves the full path to the service's executable.
|
||||
*/
|
||||
std::wstring ServiceControlManager::exePath() const
|
||||
{
|
||||
DWORD numBytesNeeded = 0;
|
||||
@@ -1095,4 +920,37 @@ std::wstring ServiceControlManager::exePath() const
|
||||
return exePath;
|
||||
}
|
||||
|
||||
std::wstring ServiceControlManager::serviceStatusToString(DWORD status)
|
||||
{
|
||||
std::wstring desc;
|
||||
switch (status) {
|
||||
case SERVICE_STOPPED:
|
||||
desc = L"stopped";
|
||||
break;
|
||||
case SERVICE_START_PENDING:
|
||||
desc = L"start pending";
|
||||
break;
|
||||
case SERVICE_STOP_PENDING:
|
||||
desc = L"stop pending";
|
||||
break;
|
||||
case SERVICE_RUNNING:
|
||||
desc = L"running";
|
||||
break;
|
||||
case SERVICE_CONTINUE_PENDING:
|
||||
desc = L"continue pending";
|
||||
break;
|
||||
case SERVICE_PAUSE_PENDING:
|
||||
desc = L"pause pending";
|
||||
break;
|
||||
case SERVICE_PAUSED:
|
||||
desc = L"paused";
|
||||
break;
|
||||
default:
|
||||
desc = L"unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
} // end namespace wsl
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
namespace wsl
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// ServiceControlManager class definition
|
||||
|
||||
class ServiceControlManager
|
||||
{
|
||||
public:
|
||||
@@ -18,7 +15,7 @@ public:
|
||||
~ServiceControlManager();
|
||||
|
||||
void deleteService(LPCTSTR serviceName, bool stopRunningService = true);
|
||||
bool deleteService(LPCTSTR serviceName, std::error_code& ec) noexcept;
|
||||
bool deleteService(LPCTSTR serviceName, std::error_code& ec, int timeoutMs = 20000) noexcept;
|
||||
|
||||
void installService(LPCTSTR serviceName, LPCTSTR binaryPathName,
|
||||
LPCTSTR displayName, LPCTSTR description,
|
||||
@@ -43,11 +40,11 @@ public:
|
||||
void sendControlCode(DWORD code) const;
|
||||
void setServiceDescription(LPCTSTR description) const;
|
||||
void setServiceSIDType(DWORD serviceSidType) const;
|
||||
void startService();
|
||||
bool startService(std::error_code& ec) noexcept;
|
||||
void stopService();
|
||||
void stopService(LPCTSTR serviceName);
|
||||
bool stopService(std::error_code& ec) noexcept;
|
||||
void startService(int timeoutMs = 20000);
|
||||
bool startService(std::error_code& ec, int timeoutMs = 20000) noexcept;
|
||||
void stopService(int timeoutMs = 20000);
|
||||
void stopService(LPCTSTR serviceName, int timeoutMs = 20000);
|
||||
bool stopService(std::error_code& ec, int timeoutMs = 20000) noexcept;
|
||||
|
||||
// Prevents the initiation of, and aborts any currently running, start/stop requests.
|
||||
void blockStartStopRequests();
|
||||
@@ -57,6 +54,8 @@ public:
|
||||
|
||||
std::wstring exePath() const;
|
||||
|
||||
static std::wstring serviceStatusToString(DWORD status);
|
||||
|
||||
private:
|
||||
std::wstring serverName_;
|
||||
std::wstring serviceName_;
|
||||
@@ -69,9 +68,6 @@ private:
|
||||
std::wstring serverNameForDebug() const;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// ServiceControlManager inline methods
|
||||
|
||||
inline bool
|
||||
ServiceControlManager::isSCMOpen() const
|
||||
{
|
||||
@@ -96,6 +92,4 @@ ServiceControlManager::unblockStartStopRequests()
|
||||
blockStartStopRequests_ = false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
} // end namespace wsl
|
||||
|
||||
@@ -278,7 +278,7 @@ QString Utils::getPlatformNameSafe()
|
||||
{
|
||||
QString platform = getPlatformName();
|
||||
#ifdef Q_OS_LINUX
|
||||
// Default to debian so most of our API calls don't fail if we cannot find the /etc/windscribe/platform
|
||||
// Default to debian so most of our API calls don't fail if we cannot find the platform file
|
||||
// file (someone would have to manually delete)
|
||||
if (platform.isEmpty())
|
||||
#ifdef __aarch64__
|
||||
@@ -338,9 +338,13 @@ QString Utils::fromBase64(const QString& str)
|
||||
|
||||
bool Utils::isCLIRunning(int minCount)
|
||||
{
|
||||
if (strlen(WS_CLI_EXECUTABLE_NAME) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
return WinUtils::enumerateProcesses("windscribe-cli.exe").size() > minCount;
|
||||
return WinUtils::enumerateProcesses(WS_CLI_EXECUTABLE_NAME ".exe").size() > minCount;
|
||||
#else
|
||||
return Utils::execCmd("ps axco command | grep windscribe-cli | grep -v grep | wc -l").trimmed().toInt() > minCount;
|
||||
return Utils::execCmd("ps axco command | grep " WS_CLI_EXECUTABLE_NAME " | grep -v grep | wc -l").trimmed().toInt() > minCount;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "wincryptutils.h"
|
||||
#include "ws_branding.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <dpapi.h>
|
||||
@@ -26,7 +27,7 @@ string WinCryptUtils::encrypt(const wstring &str, EncodeMode mode)
|
||||
dataIn.cbData = str.size() * sizeof(str.at(0));
|
||||
dataIn.pbData = (BYTE*)str.c_str();
|
||||
|
||||
BOOL result = ::CryptProtectData(&dataIn, L"Windscribe Desktop Client", NULL,
|
||||
BOOL result = ::CryptProtectData(&dataIn, WS_PRODUCT_NAME_W L" Desktop Client", NULL,
|
||||
NULL, NULL, 0, &dataOut);
|
||||
if (result == FALSE) {
|
||||
throw system_error(::GetLastError(), generic_category(), "WinCryptUtils::encrypt CryptProtectData failed");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "winutils.h"
|
||||
#include "ws_branding.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
@@ -646,11 +647,11 @@ FindAppWindowHandleProc(HWND hwnd, LPARAM lParam)
|
||||
std::filesystem::path path(std::wstring(imageName, pathLen));
|
||||
std::wstring exeName(path.filename());
|
||||
|
||||
if (_wcsicmp(exeName.c_str(), L"windscribe.exe") == 0) {
|
||||
if (_wcsicmp(exeName.c_str(), WS_APP_EXECUTABLE_NAME_W L".exe") == 0) {
|
||||
TCHAR buffer[128];
|
||||
int resultLen = ::GetWindowText(hwnd, buffer, sizeof(buffer) / sizeof(buffer[0]));
|
||||
|
||||
if (resultLen > 0 && (_wcsicmp(buffer, L"windscribe") == 0)) {
|
||||
if (resultLen > 0 && (_wcsicmp(buffer, WS_PRODUCT_NAME_LOWER_W) == 0)) {
|
||||
EnumWindowInfo* pWindowInfo = (EnumWindowInfo*)lParam;
|
||||
pWindowInfo->appMainWindow = hwnd;
|
||||
return FALSE;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include "ws_branding.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
@@ -8,7 +9,7 @@
|
||||
|
||||
namespace WinUtils
|
||||
{
|
||||
const std::wstring wmActivateGui = L"WindscribeAppActivate";
|
||||
const std::wstring wmActivateGui = WS_APP_IDENTIFIER_W L"AppActivate";
|
||||
|
||||
bool reboot();
|
||||
bool isWindows10orGreater();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "log/categories.h"
|
||||
#include "../version/windscribe_version.h" // this file must be included, there are defined WINDSCRIBE_IS_BETA or WINDSCRIBE_IS_GUINEA_PIG
|
||||
|
||||
#if defined(WINDSCRIBE_IS_BETA) || defined(WINDSCRIBE_IS_GUINEA_PIG)
|
||||
#define WS_ASSERT(b) { \
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "appversion.h"
|
||||
#include "windscribe_version.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
@@ -10,17 +9,17 @@ QString AppVersion::version() const
|
||||
|
||||
QString AppVersion::major() const
|
||||
{
|
||||
return QString::number(WINDSCRIBE_MAJOR_VERSION);
|
||||
return QString::number(WS_VERSION_MAJOR);
|
||||
}
|
||||
|
||||
QString AppVersion::minor() const
|
||||
{
|
||||
return QString::number(WINDSCRIBE_MINOR_VERSION);
|
||||
return QString::number(WS_VERSION_MINOR);
|
||||
}
|
||||
|
||||
QString AppVersion::build() const
|
||||
{
|
||||
return QString::number(WINDSCRIBE_BUILD_VERSION);
|
||||
return QString::number(WS_VERSION_BUILD);
|
||||
}
|
||||
|
||||
QString AppVersion::fullVersionString() const
|
||||
@@ -71,7 +70,7 @@ QString AppVersion::semanticVersionString() const
|
||||
}
|
||||
|
||||
AppVersion::AppVersion() :
|
||||
version_(QString::asprintf("%d.%d", WINDSCRIBE_MAJOR_VERSION, WINDSCRIBE_MINOR_VERSION)),
|
||||
version_(QString::asprintf("%d.%d", WS_VERSION_MAJOR, WS_VERSION_MINOR)),
|
||||
isStaging_(false),
|
||||
#ifdef WINDSCRIBE_IS_BETA
|
||||
buildChannel_(UPDATE_CHANNEL_BETA)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include "windscribe_version.h"
|
||||
#include "types/enums.h"
|
||||
|
||||
class AppVersion
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WINDSCRIBE_MAJOR_VERSION 2
|
||||
#define WINDSCRIBE_MINOR_VERSION 21
|
||||
#define WINDSCRIBE_BUILD_VERSION 7
|
||||
|
||||
// only one of these should be enabled; neither -> stable
|
||||
//#define WINDSCRIBE_IS_BETA
|
||||
//#define WINDSCRIBE_IS_GUINEA_PIG
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
#define WINDSCRIBE_VERSION_STR STR(WINDSCRIBE_MAJOR_VERSION) "." STR(WINDSCRIBE_MINOR_VERSION) "." STR(WINDSCRIBE_BUILD_VERSION)
|
||||
#define WINDSCRIBE_VERSION_STR_UNICODE STR(WINDSCRIBE_MAJOR_VERSION) L"." STR(WINDSCRIBE_MINOR_VERSION) L"." STR(WINDSCRIBE_BUILD_VERSION)
|
||||
#define WINDSCRIBE_MAJOR_MINOR_VERSION_STR STR(WINDSCRIBE_MAJOR_VERSION) "." STR(WINDSCRIBE_MINOR_VERSION)
|
||||
#define WINDSCRIBE_COPYRIGHT_STR "Copyright (C) 2026 Windscribe Limited"
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
// Wide-string (wchar_t) variants of branding macros defined as compile definitions
|
||||
// by CMake (via add_compile_definitions in CMakeLists.txt). Windows APIs frequently
|
||||
// require wide strings, so this header avoids repeating L"..." conversions everywhere.
|
||||
|
||||
#define _WS_WIDEN2(x) L##x
|
||||
#define _WS_WIDEN(x) _WS_WIDEN2(x)
|
||||
|
||||
#define WS_APP_EXECUTABLE_NAME_W _WS_WIDEN(WS_APP_EXECUTABLE_NAME)
|
||||
#define WS_APP_IDENTIFIER_W _WS_WIDEN(WS_APP_IDENTIFIER)
|
||||
#define WS_PRODUCT_NAME_W _WS_WIDEN(WS_PRODUCT_NAME)
|
||||
#define WS_PRODUCT_NAME_LOWER_W _WS_WIDEN(WS_PRODUCT_NAME_LOWER)
|
||||
#define WS_PRODUCT_NAME_UPPER_W _WS_WIDEN(WS_PRODUCT_NAME_UPPER)
|
||||
#define WS_WIN_CONFIG_SUBDIR_W _WS_WIDEN(WS_WIN_CONFIG_SUBDIR)
|
||||
#define WS_WIN_IKEV2_CONNECTION_NAME_W _WS_WIDEN(WS_WIN_IKEV2_CONNECTION_NAME)
|
||||
#define WS_SETTINGS_ORG_W _WS_WIDEN(WS_SETTINGS_ORG)
|
||||
#define WS_SETTINGS_APP_W _WS_WIDEN(WS_SETTINGS_APP)
|
||||
@@ -1,38 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "../client-common/version/windscribe_version.h"
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "frontend/gui/resources/icons/win/windscribe.ico"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION WINDSCRIBE_MAJOR_VERSION, WINDSCRIBE_MINOR_VERSION, WINDSCRIBE_BUILD_VERSION, 0
|
||||
PRODUCTVERSION WINDSCRIBE_MAJOR_VERSION, WINDSCRIBE_MINOR_VERSION, WINDSCRIBE_BUILD_VERSION, 0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Windscribe Limited\0"
|
||||
VALUE "FileDescription", "Windscribe\0"
|
||||
VALUE "FileVersion", WINDSCRIBE_VERSION_STR
|
||||
VALUE "LegalCopyright", WINDSCRIBE_COPYRIGHT_STR
|
||||
VALUE "OriginalFilename", "Windscribe.exe\0"
|
||||
VALUE "ProductName", "Windscribe\0"
|
||||
VALUE "ProductVersion", WINDSCRIBE_VERSION_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <windows.h>
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "@WS_WIN_APP_ICON@"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION WS_VERSION_MAJOR, WS_VERSION_MINOR, WS_VERSION_BUILD, 0
|
||||
PRODUCTVERSION WS_VERSION_MAJOR, WS_VERSION_MINOR, WS_VERSION_BUILD, 0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "@WS_VENDOR@\0"
|
||||
VALUE "FileDescription", "@WS_PRODUCT_NAME@\0"
|
||||
VALUE "FileVersion", WS_VERSION "\0"
|
||||
VALUE "LegalCopyright", WS_COPYRIGHT "\0"
|
||||
VALUE "OriginalFilename", "@WS_OUTPUT_PREFIX@.exe\0"
|
||||
VALUE "ProductName", "@WS_PRODUCT_NAME@\0"
|
||||
VALUE "ProductVersion", WS_VERSION "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1200
|
||||
END
|
||||
END
|
||||
/* End of Version info */
|
||||
@@ -5,8 +5,6 @@ target_sources(engine PRIVATE
|
||||
engine.h
|
||||
getdeviceid.cpp
|
||||
getdeviceid.h
|
||||
openvpnversioncontroller.cpp
|
||||
openvpnversioncontroller.h
|
||||
packetsizecontroller.cpp
|
||||
packetsizecontroller.h
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QRegularExpression>
|
||||
#include "utils/log/categories.h"
|
||||
#include "names.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/executable_signature/executable_signature.h"
|
||||
#include <boost/process/v1/io.hpp>
|
||||
@@ -29,7 +28,7 @@ const QString AutoUpdaterHelper_mac::copyInternalInstallerToTempFromDmg(const QS
|
||||
}
|
||||
|
||||
// verify dmg contains installer
|
||||
const QString volumeInstallerFilename = volumeMountPoint + "/" + INSTALLER_FILENAME_MAC_APP;
|
||||
const QString volumeInstallerFilename = volumeMountPoint + "/" + WS_MAC_INSTALLER_BUNDLE_NAME;
|
||||
if (!QFileInfo::exists(volumeInstallerFilename))
|
||||
{
|
||||
qCCritical(LOG_AUTO_UPDATER) << "Volume installer does not exist: " + volumeInstallerFilename;
|
||||
@@ -42,7 +41,7 @@ const QString AutoUpdaterHelper_mac::copyInternalInstallerToTempFromDmg(const QS
|
||||
// remove pre-existing temp installer
|
||||
QFileInfo dmgFileInfo(dmgFilename);
|
||||
const QString tempDirName = dmgFileInfo.canonicalPath();
|
||||
QString tempInstallerFilename = tempDirName + "/" + INSTALLER_FILENAME_MAC_APP;
|
||||
QString tempInstallerFilename = tempDirName + "/" + WS_MAC_INSTALLER_BUNDLE_NAME;
|
||||
if (QFileInfo::exists(tempInstallerFilename))
|
||||
{
|
||||
qCDebug(LOG_AUTO_UPDATER) << "Temp installer already exists -- removing: " << tempInstallerFilename;
|
||||
@@ -104,7 +103,7 @@ bool AutoUpdaterHelper_mac::verifyAndRun(const QString &tempInstallerFilename,
|
||||
args.append(additionalArgs.split(" "));
|
||||
|
||||
QProcess process;
|
||||
process.setProgram(tempInstallerFilename + "/" + INSTALLER_INNER_BINARY_MAC);
|
||||
process.setProgram(tempInstallerFilename + "/" + WS_MAC_INSTALLER_INNER_BINARY);
|
||||
process.setArguments(args);
|
||||
process.setWorkingDirectory(appFolder);
|
||||
process.setStandardOutputFile(QProcess::nullDevice());
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "names.h"
|
||||
#include "utils/log/categories.h"
|
||||
#include "utils/ws_assert.h"
|
||||
|
||||
@@ -224,7 +223,7 @@ void DownloadHelper::removeAutoUpdateInstallerFiles()
|
||||
#ifdef Q_OS_MACOS
|
||||
// remove temp installer.app on mac:
|
||||
// | installer.app was unpacked from above .dmg
|
||||
const QString & installerApp = downloadDirectory_ + "/" + INSTALLER_FILENAME_MAC_APP;
|
||||
const QString & installerApp = downloadDirectory_ + "/" + WS_MAC_INSTALLER_BUNDLE_NAME;
|
||||
if (QFile::exists(installerApp)) {
|
||||
qCDebug(LOG_DOWNLOADER) << "Removing auto-update temporary installer app";
|
||||
Utils::removeDirectory(installerApp);
|
||||
|
||||
@@ -12,7 +12,7 @@ public:
|
||||
|
||||
private:
|
||||
// if byIfIndex == true, then find by ifIndex
|
||||
// overwise by "Windscribe" description
|
||||
// overwise by product name in description
|
||||
static AdapterGatewayInfo getAdapterInfo(bool byIfIndex, unsigned long ifIndex, const QString &adapterIdentifier);
|
||||
static void getAdapterIpAndGateway(unsigned long ifIndex, QString &outIp, QString &outGateway);
|
||||
};
|
||||
|
||||
@@ -147,7 +147,6 @@ void ConnectionManager::clickConnect(const QString &ovpnConfig,
|
||||
if (connector_) {
|
||||
currentProtocol_ = types::Protocol::UNINITIALIZED;
|
||||
SAFE_DELETE(connector_);
|
||||
connector_ = NULL;
|
||||
}
|
||||
|
||||
updateConnectionSettingsPolicy(connectionSettings, portMap, proxySettings);
|
||||
@@ -373,6 +372,11 @@ void ConnectionManager::onConnectionDisconnected()
|
||||
|
||||
testVPNTunnel_->stopTests();
|
||||
doMacRestoreProcedures();
|
||||
|
||||
// Delete the connector to ensure we do not receive any additional events from it, even events
|
||||
// already queued to our event queue. We cannot use connector_->disconnect() here since we connect
|
||||
// to the signals with Qt::QueuedConnection and thus any already queued events will still be delivered.
|
||||
SAFE_DELETE_LATER(connector_);
|
||||
stunnelManager_->killProcess();
|
||||
wstunnelManager_->killProcess();
|
||||
ctrldManager_->killProcess();
|
||||
@@ -465,19 +469,23 @@ void ConnectionManager::onConnectionReconnecting()
|
||||
state_ = STATE_RECONNECTING;
|
||||
emit reconnecting();
|
||||
startReconnectionTimer();
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state_ = STATE_AUTO_DISCONNECT;
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_CONNECTED:
|
||||
WS_ASSERT(!timerReconnection_.isActive());
|
||||
|
||||
if (!connector_->isDisconnected())
|
||||
if (connector_ && !connector_->isDisconnected())
|
||||
{
|
||||
if (state_ != STATE_RECONNECTING)
|
||||
{
|
||||
@@ -602,7 +610,9 @@ void ConnectionManager::onConnectionError(CONNECT_ERROR err)
|
||||
// for AUTH_ERROR signal disconnected will be emitted automatically
|
||||
if (err != CONNECT_ERROR::AUTH_ERROR)
|
||||
{
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -624,7 +634,9 @@ void ConnectionManager::onConnectionError(CONNECT_ERROR err)
|
||||
// for AUTH_ERROR signal disconnected will be emitted automatically
|
||||
if (err != CONNECT_ERROR::AUTH_ERROR)
|
||||
{
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -632,7 +644,9 @@ void ConnectionManager::onConnectionError(CONNECT_ERROR err)
|
||||
state_ = STATE_AUTO_DISCONNECT;
|
||||
if (err != CONNECT_ERROR::AUTH_ERROR)
|
||||
{
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -847,7 +861,7 @@ void ConnectionManager::doConnect()
|
||||
// There is no custom config for IKEv2, so if we get here it is manual mode.
|
||||
// We can get here either by:
|
||||
// - User selecting IKEv2 in manual mode and then enabling Lockdown Mode, or
|
||||
// - User selecting IKEv2 in manual mode in a previous version of Windscribe, then updating.
|
||||
// - User selecting IKEv2 in manual mode in a previous version of the app, then updating.
|
||||
if (!connSettingsPolicy_->isCustomConfig() && connSettingsPolicy_->getCurrentConnectionSettings().protocol == types::Protocol::IKEV2 && MacUtils::isLockdownMode()) {
|
||||
emit errorDuringConnection(CONNECT_ERROR::LOCKDOWN_MODE_IKEV2);
|
||||
return;
|
||||
@@ -1223,53 +1237,39 @@ void ConnectionManager::waitForNetworkConnectivity()
|
||||
|
||||
void ConnectionManager::recreateConnector(types::Protocol protocol)
|
||||
{
|
||||
if (currentProtocol_ == types::Protocol::UNINITIALIZED)
|
||||
{
|
||||
if (currentProtocol_ == types::Protocol::UNINITIALIZED) {
|
||||
WS_ASSERT(connector_ == NULL);
|
||||
}
|
||||
|
||||
if (currentProtocol_ != protocol)
|
||||
{
|
||||
SAFE_DELETE_LATER(connector_);
|
||||
SAFE_DELETE_LATER(connector_);
|
||||
|
||||
if (protocol.isOpenVpnProtocol())
|
||||
{
|
||||
connector_ = new OpenVPNConnection(this, helper_);
|
||||
}
|
||||
else if (protocol.isIkev2Protocol())
|
||||
{
|
||||
if (protocol.isWireGuardProtocol()) {
|
||||
connector_ = new WireGuardConnection(this, helper_);
|
||||
} else if (protocol.isOpenVpnProtocol()) {
|
||||
connector_ = new OpenVPNConnection(this, helper_);
|
||||
connect(static_cast<OpenVPNConnection *>(connector_), &OpenVPNConnection::requestPrivKeyPassword, this, &ConnectionManager::onConnectionRequestPrivKeyPassword, Qt::QueuedConnection);
|
||||
} else if (protocol.isIkev2Protocol()) {
|
||||
#ifdef Q_OS_WIN
|
||||
connector_ = new IKEv2Connection_win(this, helper_);
|
||||
connector_ = new IKEv2Connection_win(this, helper_);
|
||||
#elif defined Q_OS_MACOS
|
||||
connector_ = new IKEv2Connection_mac(this, helper_);
|
||||
connector_ = new IKEv2Connection_mac(this, helper_);
|
||||
#elif defined Q_OS_LINUX
|
||||
connector_ = new IKEv2Connection_linux(this, helper_);
|
||||
connector_ = new IKEv2Connection_linux(this, helper_);
|
||||
#endif
|
||||
}
|
||||
else if (protocol.isWireGuardProtocol())
|
||||
{
|
||||
connector_ = new WireGuardConnection(this, helper_);
|
||||
}
|
||||
else
|
||||
{
|
||||
WS_ASSERT(false);
|
||||
}
|
||||
|
||||
connect(connector_, &IConnection::connected, this, &ConnectionManager::onConnectionConnected, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::disconnected, this, &ConnectionManager::onConnectionDisconnected, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::reconnecting, this, &ConnectionManager::onConnectionReconnecting, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::error, this, &ConnectionManager::onConnectionError, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::statisticsUpdated, this, &ConnectionManager::onConnectionStatisticsUpdated, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::interfaceUpdated, this, &ConnectionManager::onConnectionInterfaceUpdated, Qt::QueuedConnection);
|
||||
|
||||
connect(connector_, &IConnection::requestUsername, this, &ConnectionManager::onConnectionRequestUsername, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::requestPassword, this, &ConnectionManager::onConnectionRequestPassword, Qt::QueuedConnection);
|
||||
if (protocol.isOpenVpnProtocol()) {
|
||||
connect(static_cast<OpenVPNConnection *>(connector_), &OpenVPNConnection::requestPrivKeyPassword, this, &ConnectionManager::onConnectionRequestPrivKeyPassword, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
currentProtocol_ = protocol;
|
||||
} else {
|
||||
WS_ASSERT(false);
|
||||
}
|
||||
|
||||
connect(connector_, &IConnection::connected, this, &ConnectionManager::onConnectionConnected, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::disconnected, this, &ConnectionManager::onConnectionDisconnected, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::reconnecting, this, &ConnectionManager::onConnectionReconnecting, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::error, this, &ConnectionManager::onConnectionError, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::statisticsUpdated, this, &ConnectionManager::onConnectionStatisticsUpdated, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::interfaceUpdated, this, &ConnectionManager::onConnectionInterfaceUpdated, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::requestUsername, this, &ConnectionManager::onConnectionRequestUsername, Qt::QueuedConnection);
|
||||
connect(connector_, &IConnection::requestPassword, this, &ConnectionManager::onConnectionRequestPassword, Qt::QueuedConnection);
|
||||
|
||||
currentProtocol_ = protocol;
|
||||
}
|
||||
|
||||
void ConnectionManager::restoreConnectionAfterWakeUp()
|
||||
@@ -1314,10 +1314,14 @@ void ConnectionManager::onTunnelTestsFinished(bool bSuccess, const QString &ipAd
|
||||
state_ = STATE_RECONNECTING;
|
||||
emit reconnecting();
|
||||
startReconnectionTimer();
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
} else {
|
||||
state_= STATE_AUTO_DISCONNECT;
|
||||
connector_->startDisconnect();
|
||||
if (connector_) {
|
||||
connector_->startDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@ CtrldManager_win::CtrldManager_win(QObject *parent, bool isCreateLog) : ICtrldMa
|
||||
connect(process_, &QProcess::errorOccurred, this,&CtrldManager_win::onProcessErrorOccurred);
|
||||
process_->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
ctrldExePath_ = QCoreApplication::applicationDirPath() + "/windscribectrld.exe";
|
||||
ctrldExePath_ = QCoreApplication::applicationDirPath() + "/" WS_PRODUCT_NAME_LOWER "ctrld.exe";
|
||||
logPath_ = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/ctrld.log";
|
||||
listenIp_ = "127.0.0.1"; // default listen ip for ctrld utility
|
||||
}
|
||||
@@ -140,11 +140,11 @@ QString CtrldManager_win::getAvailableIp()
|
||||
return "";
|
||||
}
|
||||
|
||||
void CtrldManager_win::terminateWindscribeCtrldProcesses()
|
||||
void CtrldManager_win::terminateAppCtrldProcesses()
|
||||
{
|
||||
QString taskkillPath = WinUtils::getSystemDir() + "\\taskkill.exe";
|
||||
QProcess process;
|
||||
process.start(taskkillPath, QStringList() << "/f" << "/t" << "/im" << "windscribectrld.exe");
|
||||
process.start(taskkillPath, QStringList() << "/f" << "/t" << "/im" << WS_PRODUCT_NAME_LOWER "ctrld.exe");
|
||||
process.waitForFinished(2000);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
void killProcess();
|
||||
QString listenIp() const;
|
||||
|
||||
static void terminateWindscribeCtrldProcesses();
|
||||
static void terminateAppCtrldProcesses();
|
||||
|
||||
private slots:
|
||||
void onProcessStarted();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "finishactiveconnections.h"
|
||||
#include "../openvpnversioncontroller.h"
|
||||
#include "utils/log/logger.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -34,7 +33,7 @@ void FinishActiveConnections::finishAllActiveConnections_win(Helper *helper)
|
||||
finishOpenVpnActiveConnections_win(helper);
|
||||
finishIkev2ActiveConnections_win(helper);
|
||||
finishWireGuardActiveConnections_win(helper);
|
||||
CtrldManager_win::terminateWindscribeCtrldProcesses();
|
||||
CtrldManager_win::terminateAppCtrldProcesses();
|
||||
}
|
||||
|
||||
void FinishActiveConnections::finishOpenVpnActiveConnections_win(Helper *helper)
|
||||
@@ -44,7 +43,7 @@ void FinishActiveConnections::finishOpenVpnActiveConnections_win(Helper *helper)
|
||||
|
||||
void FinishActiveConnections::finishIkev2ActiveConnections_win(Helper *helper)
|
||||
{
|
||||
const QVector<HRASCONN> v = IKEv2Connection_win::getActiveWindscribeConnections();
|
||||
const QVector<HRASCONN> v = IKEv2Connection_win::getActiveAppConnections();
|
||||
|
||||
if (!v.isEmpty())
|
||||
{
|
||||
@@ -72,7 +71,7 @@ void FinishActiveConnections::finishAllActiveConnections_posix(Helper *helper)
|
||||
finishOpenVpnActiveConnections_posix(helper);
|
||||
finishWireGuardActiveConnections_posix(helper);
|
||||
#if defined(Q_OS_MACOS)
|
||||
IKEv2Connection_mac::closeWindscribeActiveConnection();
|
||||
IKEv2Connection_mac::closeAppActiveConnection();
|
||||
#endif
|
||||
helper->executeTaskKill(kTargetCtrld);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
|
||||
|
||||
static void removeIkev2ConnectionFromOS();
|
||||
static void closeWindscribeActiveConnection();
|
||||
static void closeAppActiveConnection();
|
||||
|
||||
private slots:
|
||||
void handleNotificationImpl(int status);
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
namespace KeyChainUtils
|
||||
{
|
||||
const char szServiceName[] = "aaa.windscribe.com.password.ikev2";
|
||||
const char szLabel[] = "aaa.windscribe.com.password.ikev2";
|
||||
const char szDescr[] = "Windscribe IKEv2 password";
|
||||
const char szServiceName[] = WS_MAC_IKEV2_KEYCHAIN_SERVICE;
|
||||
const char szLabel[] = WS_MAC_IKEV2_KEYCHAIN_SERVICE;
|
||||
const char szDescr[] = WS_PRODUCT_NAME " IKEv2 password";
|
||||
|
||||
static const char * trustedAppPaths[] = {
|
||||
"/usr/libexec/neagent"
|
||||
@@ -175,7 +175,7 @@ void IKEv2Connection_mac::startConnect(const QString &configOrUrl, const QString
|
||||
[manager setEnabled:YES];
|
||||
[manager setProtocolConfiguration:(protocol)];
|
||||
[manager setOnDemandEnabled:NO];
|
||||
[manager setLocalizedDescription:@"Windscribe VPN"];
|
||||
[manager setLocalizedDescription:@WS_MAC_VPN_DESCRIPTION];
|
||||
|
||||
NSString *strProtocol = [NSString stringWithFormat:@"{Protocol: %@", protocol];
|
||||
qCInfo(LOG_IKEV2) << QString::fromNSString(strProtocol);
|
||||
@@ -308,7 +308,7 @@ void IKEv2Connection_mac::removeIkev2ConnectionFromOS()
|
||||
KeyChainUtils::removeKeychainItem();
|
||||
}
|
||||
|
||||
void IKEv2Connection_mac::closeWindscribeActiveConnection()
|
||||
void IKEv2Connection_mac::closeAppActiveConnection()
|
||||
{
|
||||
static QWaitCondition waitCondition;
|
||||
static QMutex mutex;
|
||||
@@ -326,7 +326,7 @@ void IKEv2Connection_mac::closeWindscribeActiveConnection()
|
||||
NEVPNConnection * connection = [manager connection];
|
||||
if (connection.status == NEVPNStatusConnected || connection.status == NEVPNStatusConnecting)
|
||||
{
|
||||
if ([manager.localizedDescription isEqualToString:@"Windscribe VPN"] == YES)
|
||||
if ([manager.localizedDescription isEqualToString:@WS_MAC_VPN_DESCRIPTION] == YES)
|
||||
{
|
||||
qCInfo(LOG_IKEV2) << "Previous IKEv2 connection is active. Stop it.";
|
||||
[connection stopVPNTunnel];
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "ws_branding.h"
|
||||
#include "ikev2connection_win.h"
|
||||
#include "ikev2connection_win.h"
|
||||
|
||||
#include <windns.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "adapterutils_win.h"
|
||||
#include "engine/taputils/checkadapterenable.h"
|
||||
@@ -12,34 +14,30 @@
|
||||
#include "utils/ws_assert.h"
|
||||
|
||||
|
||||
#define IKEV2_CONNECTION_NAME L"Windscribe IKEv2"
|
||||
#define IKEV2_CONNECTION_NAME WS_WIN_IKEV2_CONNECTION_NAME_W
|
||||
|
||||
IKEv2Connection_win *IKEv2Connection_win::this_ = NULL;
|
||||
// static global variable, because we reinstall WAN only once during the lifetime of the process
|
||||
bool IKEv2Connection_win::wanReinstalled_ = false;
|
||||
|
||||
|
||||
IKEv2Connection_win::IKEv2Connection_win(QObject *parent, Helper *helper)
|
||||
: IConnection(parent),
|
||||
state_(STATE_DISCONNECTED),
|
||||
helper_(helper),
|
||||
initialEnableIkev2Compression_(false),
|
||||
connHandle_(NULL),
|
||||
disconnectLogic_(this),
|
||||
cntFailedConnectionAttempts_(0)
|
||||
disconnectLogic_(this)
|
||||
{
|
||||
WS_ASSERT(this_ == NULL);
|
||||
this_ = this;
|
||||
initMapConnStates();
|
||||
timerControlConnection_.setInterval(CONTROL_TIMER_PERIOD);
|
||||
connect(&timerControlConnection_, &QTimer::timeout, this, &IKEv2Connection_win::onTimerControlConnection);
|
||||
connect(&disconnectLogic_, &IKEv2ConnectionDisconnectLogic_win::disconnected, this, &IKEv2Connection_win::onHandleDisconnectLogic);
|
||||
WS_ASSERT(state_ == STATE_DISCONNECTED);
|
||||
}
|
||||
|
||||
IKEv2Connection_win::~IKEv2Connection_win()
|
||||
{
|
||||
this_ = NULL;
|
||||
// Ensure RAS is fully disconnected before destroying the class instance. Otherwise it is possible for RasDial2CallbackFunc
|
||||
// to be called after the class instance is destroyed and it will thus have an invalid class instance pointer.
|
||||
if (!isDisconnected()) {
|
||||
startDisconnect();
|
||||
waitForDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void IKEv2Connection_win::startConnect(const QString &configOrUrl, const QString &ip, const QString &dnsHostName, const QString &username,
|
||||
@@ -105,7 +103,7 @@ void IKEv2Connection_win::removeIkev2ConnectionFromOS()
|
||||
}
|
||||
}
|
||||
|
||||
QVector<HRASCONN> IKEv2Connection_win::getActiveWindscribeConnections()
|
||||
QVector<HRASCONN> IKEv2Connection_win::getActiveAppConnections()
|
||||
{
|
||||
QVector<HRASCONN> v;
|
||||
|
||||
@@ -284,6 +282,32 @@ void IKEv2Connection_win::waitForDisconnect()
|
||||
|
||||
void IKEv2Connection_win::doConnect()
|
||||
{
|
||||
// Clean up any stale connections left over from a previous crash or abnormal termination.
|
||||
// If a stale "Windscribe IKEv2" RAS connection exists, RasSetEntryProperties can crash
|
||||
// with an access violation inside the RAS API due to orphaned internal state.
|
||||
QVector<HRASCONN> staleConns = getActiveAppConnections();
|
||||
for (HRASCONN h : std::as_const(staleConns)) {
|
||||
qCInfo(LOG_IKEV2) << "Hanging up stale IKEv2 connection";
|
||||
DWORD dwRet = RasHangUp(h);
|
||||
if (dwRet != ERROR_INVALID_HANDLE) {
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
while (timer.elapsed() < 3000) {
|
||||
QThread::msleep(10);
|
||||
RASCONNSTATUS status;
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.dwSize = sizeof(status);
|
||||
if (RasGetConnectStatus(h, &status) == ERROR_INVALID_HANDLE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!staleConns.isEmpty()) {
|
||||
removeIkev2ConnectionFromOS();
|
||||
}
|
||||
|
||||
bool ikev2DeviceInitialized = false;
|
||||
RASDEVINFO devInfo;
|
||||
if (!getIKEv2Device(&devInfo))
|
||||
@@ -318,8 +342,7 @@ void IKEv2Connection_win::doConnect()
|
||||
|
||||
RASENTRY rasEntry;
|
||||
memset(&rasEntry, 0, sizeof(rasEntry));
|
||||
rasEntry.dwSize = offsetof(RASENTRY, ipv6addr);
|
||||
//rasEntry.dwSize = sizeof(RASENTRY);
|
||||
rasEntry.dwSize = sizeof(RASENTRY);
|
||||
|
||||
wcscpy_s(rasEntry.szLocalPhoneNumber, initialUrl_.toStdWString().c_str());
|
||||
wcscpy_s(rasEntry.szDeviceName, devInfo.szDeviceName);
|
||||
@@ -368,6 +391,7 @@ void IKEv2Connection_win::doConnect()
|
||||
RASDIALPARAMS dialparams;
|
||||
memset(&dialparams, 0, sizeof(dialparams));
|
||||
dialparams.dwSize = sizeof(dialparams);
|
||||
dialparams.dwCallbackId = (ULONG_PTR)this;
|
||||
|
||||
wcscpy_s(dialparams.szEntryName, IKEV2_CONNECTION_NAME);
|
||||
wcscpy_s(dialparams.szUserName, initialUsername_.toStdWString().c_str());
|
||||
@@ -396,7 +420,7 @@ void IKEv2Connection_win::doConnect()
|
||||
// Connecting
|
||||
state_ = STATE_CONNECTING;
|
||||
|
||||
dwErr = RasDial(NULL, NULL, &dialparams, 1, (void *)staticRasDialFunc, &connHandle_);
|
||||
dwErr = RasDial(NULL, NULL, &dialparams, 2, (LPVOID)RasDial2CallbackFunc, &connHandle_);
|
||||
if (dwErr != ERROR_SUCCESS)
|
||||
{
|
||||
qCCritical(LOG_IKEV2) << "RasDial failed with error:" << dwErr;
|
||||
@@ -594,12 +618,14 @@ QString IKEv2Connection_win::rasConnStateToString(tagRASCONNSTATE state)
|
||||
}
|
||||
}
|
||||
|
||||
void IKEv2Connection_win::staticRasDialFunc(HRASCONN hRasConn, UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError)
|
||||
DWORD CALLBACK IKEv2Connection_win::RasDial2CallbackFunc(ULONG_PTR dwCallbackId, DWORD unused, HRASCONN hrasconn, UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError)
|
||||
{
|
||||
if (this_ == NULL) {
|
||||
qCWarning(LOG_IKEV2) << "RasDialFunc callback called after connection object has been deleted";
|
||||
return;
|
||||
IKEv2Connection_win *pThis = (IKEv2Connection_win*)dwCallbackId;
|
||||
if (pThis == NULL) {
|
||||
qCWarning(LOG_IKEV2) << "Skipping RasDialFunc2 callback due to null instance pointer";
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
this_->rasDialFuncCallback(hRasConn, unMsg, rascs, dwError, dwExtendedError);
|
||||
pThis->rasDialFuncCallback(hrasconn, unMsg, rascs, dwError, dwExtendedError);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
ConnectionType getConnectionType() const override { return ConnectionType::IKEV2; }
|
||||
|
||||
static void removeIkev2ConnectionFromOS();
|
||||
static QVector<HRASCONN> getActiveWindscribeConnections();
|
||||
static QVector<HRASCONN> getActiveAppConnections();
|
||||
|
||||
void continueWithUsernameAndPassword(const QString &username, const QString &password) override;
|
||||
void continueWithPassword(const QString &password) override;
|
||||
@@ -51,16 +51,16 @@ private:
|
||||
STATE_REINSTALL_WAN
|
||||
};
|
||||
|
||||
int state_;
|
||||
Helper *helper_;
|
||||
int state_ = STATE_DISCONNECTED;
|
||||
Helper *helper_ = NULL;
|
||||
|
||||
QString initialUrl_;
|
||||
QString initialIp_;
|
||||
QString initialUsername_;
|
||||
QString initialPassword_;
|
||||
bool initialEnableIkev2Compression_;
|
||||
bool initialEnableIkev2Compression_ = false;
|
||||
|
||||
HRASCONN connHandle_;
|
||||
HRASCONN connHandle_ = NULL;
|
||||
QTimer timerControlConnection_;
|
||||
static constexpr int CONTROL_TIMER_PERIOD = 1000;
|
||||
QMap<RASCONNSTATE, QString> mapConnStates_;
|
||||
@@ -69,7 +69,7 @@ private:
|
||||
|
||||
IKEv2ConnectionDisconnectLogic_win disconnectLogic_;
|
||||
|
||||
int cntFailedConnectionAttempts_;
|
||||
int cntFailedConnectionAttempts_ = 0;
|
||||
static constexpr int MAX_FAILED_CONNECTION_ATTEMPTS = 3;
|
||||
|
||||
void doConnect();
|
||||
@@ -81,7 +81,6 @@ private:
|
||||
void initMapConnStates();
|
||||
QString rasConnStateToString(RASCONNSTATE state);
|
||||
|
||||
static IKEv2Connection_win *this_;
|
||||
static bool wanReinstalled_;
|
||||
static void CALLBACK staticRasDialFunc(HRASCONN hrasconn, UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError);
|
||||
static DWORD CALLBACK RasDial2CallbackFunc(ULONG_PTR dwCallbackId, DWORD unused, HRASCONN hrasconn, UINT unMsg, RASCONNSTATE rascs, DWORD dwError, DWORD dwExtendedError);
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ bool MakeOVPNFile::generate(const QString &ovpnData, const QString &ip, types::P
|
||||
config_ += QString("dhcp-option DNS %1\r\n").arg(customDns);
|
||||
}
|
||||
|
||||
// concatenate with windscribe_extra.conf file, if it exists
|
||||
// concatenate with advanced parameters file, if it exists
|
||||
if (!strExtraConfig.isEmpty()) {
|
||||
qCInfo(LOG_CONNECTION) << "Adding extra options to OVPN config:" << strExtraConfig;
|
||||
config_ += strExtraConfig;
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
#include "engine/customconfigs/parseovpnconfigline.h"
|
||||
|
||||
#if defined (Q_OS_WIN)
|
||||
#include "types/global_consts.h"
|
||||
#endif
|
||||
|
||||
MakeOVPNFileFromCustom::MakeOVPNFileFromCustom() : config_()
|
||||
{
|
||||
}
|
||||
@@ -31,13 +27,6 @@ bool MakeOVPNFileFromCustom::generate(const QString &customConfigPath, const QSt
|
||||
config_ += line + "\r\n";
|
||||
}
|
||||
|
||||
#if defined (Q_OS_WIN)
|
||||
// We use the --dev-node option to ensure OpenVPN will only use the dco/wintun adapter instance we create and not
|
||||
// possibly attempt to use an adapter created by other software (e.g. the vanilla OpenVPN client app).
|
||||
config_ += QString("\r\n--dev-node %1\r\n").arg(kOpenVPNAdapterIdentifier);
|
||||
config_ += "\r\n--windows-driver wintun\r\n";
|
||||
#endif
|
||||
|
||||
if (!customDns.isEmpty()) {
|
||||
config_ += "\r\npull-filter ignore \"dhcp-option DNS\"\r\n";
|
||||
config_ += QString("dhcp-option DNS %1\r\n").arg(customDns);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "utils/utils.h"
|
||||
#include "types/enums.h"
|
||||
#include "availableport.h"
|
||||
#include "engine/openvpnversioncontroller.h"
|
||||
#include "utils/openvpnversioncontroller.h"
|
||||
#include "utils/ipvalidation.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -181,7 +181,7 @@ void OpenVPNConnection::run()
|
||||
helper_->disableDnsLeaksProtection();
|
||||
helper_->removeOpenVpnAdapter();
|
||||
// This prevents the adapter/network number from increasing on each connection.
|
||||
helper_->removeWindscribeNetworkProfiles();
|
||||
helper_->removeAppNetworkProfiles();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -430,22 +430,22 @@ void OpenVPNConnection::handleRead(const boost::system::error_code &err, size_t
|
||||
if (serverReply.contains("CONNECTED,SUCCESS", Qt::CaseInsensitive))
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
AdapterGatewayInfo windscribeAdapter = AdapterUtils_win::getConnectedAdapterInfo(QString::fromWCharArray(kOpenVPNAdapterIdentifier));
|
||||
if (!windscribeAdapter.isEmpty())
|
||||
AdapterGatewayInfo vpnAdapter = AdapterUtils_win::getConnectedAdapterInfo(QString::fromWCharArray(kOpenVPNAdapterIdentifier));
|
||||
if (!vpnAdapter.isEmpty())
|
||||
{
|
||||
if (connectionAdapterInfo_.adapterIp() != windscribeAdapter.adapterIp())
|
||||
if (connectionAdapterInfo_.adapterIp() != vpnAdapter.adapterIp())
|
||||
{
|
||||
qCCritical(LOG_CONNECTION) << "Error: Adapter IP detected from openvpn log not equal to the adapter IP from AdapterUtils_win::getWindscribeConnectedAdapterInfo()";
|
||||
qCCritical(LOG_CONNECTION) << "Error: Adapter IP detected from openvpn log not equal to the adapter IP from AdapterUtils_win::getConnectedAdapterInfo()";
|
||||
WS_ASSERT(false);
|
||||
}
|
||||
connectionAdapterInfo_.setAdapterName(windscribeAdapter.adapterName());
|
||||
connectionAdapterInfo_.setAdapterIp(windscribeAdapter.adapterIp());
|
||||
connectionAdapterInfo_.setDnsServers(windscribeAdapter.dnsServers());
|
||||
connectionAdapterInfo_.setIfIndex(windscribeAdapter.ifIndex());
|
||||
connectionAdapterInfo_.setAdapterName(vpnAdapter.adapterName());
|
||||
connectionAdapterInfo_.setAdapterIp(vpnAdapter.adapterIp());
|
||||
connectionAdapterInfo_.setDnsServers(vpnAdapter.dnsServers());
|
||||
connectionAdapterInfo_.setIfIndex(vpnAdapter.ifIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
qCCritical(LOG_CONNECTION) << "Can't detect connected Windscribe adapter";
|
||||
qCCritical(LOG_CONNECTION) << "Can't detect connected VPN adapter";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "sleepevents_win.h"
|
||||
#include "utils/ws_assert.h"
|
||||
#include "utils/log/categories.h"
|
||||
#include "utils/ws_assert.h"
|
||||
#include "ws_branding.h"
|
||||
|
||||
SleepEvents_win *SleepEvents_win::this_ = NULL;
|
||||
|
||||
@@ -26,7 +27,7 @@ SleepEvents_win::~SleepEvents_win()
|
||||
DWORD SleepEvents_win::hiddenWindowThread(void *param)
|
||||
{
|
||||
Q_UNUSED(param);
|
||||
static const wchar_t* className = L"WINDSCRIBE_HIDDEN_WINDOW";
|
||||
static const wchar_t* className = WS_PRODUCT_NAME_UPPER_W L"_HIDDEN_WINDOW";
|
||||
this_->hwnd_ = NULL;
|
||||
WNDCLASSEX wx = {};
|
||||
wx.cbSize = sizeof(WNDCLASSEX);
|
||||
|
||||
@@ -21,7 +21,7 @@ StunnelManager::StunnelManager(QObject *parent, Helper *helper)
|
||||
connect(process_, &QProcess::errorOccurred, this, &StunnelManager::onProcessErrorOccurred);
|
||||
process_->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
stunnelExePath_ = QCoreApplication::applicationDirPath() + "/windscribewstunnel.exe";
|
||||
stunnelExePath_ = QCoreApplication::applicationDirPath() + "/" WS_PRODUCT_NAME_LOWER "wstunnel.exe";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ void WireGuardConnection::run()
|
||||
// This merely installs the wireguard service. We start it with a call to startService below.
|
||||
bool bSuccess = helper_->startWireGuard(isAmneziaWG());
|
||||
if (!bSuccess) {
|
||||
qCCritical(LOG_CONNECTION) << "Windscribe service could not install the WireGuard service";
|
||||
qCCritical(LOG_CONNECTION) << WS_PRODUCT_NAME " service could not install the WireGuard service";
|
||||
emit error(CONNECT_ERROR::WIREGUARD_CONNECTION_ERROR);
|
||||
emit disconnected();
|
||||
return;
|
||||
@@ -183,7 +183,7 @@ void WireGuardConnection::run()
|
||||
}
|
||||
|
||||
if (!helper_->stopWireGuard()) {
|
||||
qCCritical(LOG_CONNECTION) << "WireGuardConnection::run - windscribe service failed to stop the WireGuard service instance";
|
||||
qCCritical(LOG_CONNECTION) << "WireGuardConnection::run - service failed to stop the WireGuard service instance";
|
||||
}
|
||||
|
||||
stopWireGuard.dismiss();
|
||||
@@ -196,7 +196,7 @@ void WireGuardConnection::run()
|
||||
|
||||
if (isAmneziaWG()) {
|
||||
// This prevents the wintun adapter/network number from increasing on each connection.
|
||||
helper_->removeWindscribeNetworkProfiles();
|
||||
helper_->removeAppNetworkProfiles();
|
||||
}
|
||||
|
||||
// Delay emiting signals until we have cleaned up all our resources.
|
||||
@@ -275,15 +275,14 @@ void WireGuardConnection::onGetWireguardStats()
|
||||
// wireguard service.
|
||||
|
||||
types::WireGuardStatus status;
|
||||
if (helper_->getWireGuardStatus(&status)) {
|
||||
if (status.state == types::WireGuardState::ACTIVE)
|
||||
{
|
||||
if (!connectedSignalEmited_ && status.lastHandshake > 0) {
|
||||
onTunnelConnected();
|
||||
}
|
||||
|
||||
emit statisticsUpdated(status.bytesReceived, status.bytesTransmitted, true);
|
||||
if (helper_->getWireGuardStatus(&status) && (status.state == types::WireGuardState::ACTIVE)) {
|
||||
// Check for the rare condition where we did not see the isKeypairCreated() in onGetWireguardLogUpdates
|
||||
// but the kernel driver reports the tunnel as active and receiving handshakes.
|
||||
if (!connectedSignalEmited_ && status.lastHandshake > 0) {
|
||||
onTunnelConnected();
|
||||
}
|
||||
|
||||
emit statisticsUpdated(status.bytesReceived, status.bytesTransmitted, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +432,7 @@ void WireGuardConnection::resetLogReader()
|
||||
|
||||
::CoTaskMemFree(programFilesPath);
|
||||
|
||||
logFile += "\\Windscribe\\config\\log.bin";
|
||||
logFile += "\\" WS_WIN_CONFIG_SUBDIR "\\config\\log.bin";
|
||||
wireguardLog_.reset(new wsl::WireguardRingLogger(logFile, isAmneziaWG()));
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ void WireguardRingLogger::process(int index)
|
||||
return;
|
||||
}
|
||||
|
||||
QDateTime dt = QDateTime::fromMSecsSinceEpoch(timestamp / 1000000, QTimeZone(Qt::UTC));
|
||||
QDateTime dt = QDateTime::fromMSecsSinceEpoch(timestamp / 1000000, QTimeZone::UTC);
|
||||
qCDebug(LOG_WIREGUARD) << dt.toString("ddMMyy hh:mm:ss:zzz") << message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ WstunnelManager::WstunnelManager(QObject *parent, Helper *helper)
|
||||
connect(process_, &QProcess::errorOccurred, this, &WstunnelManager::onProcessErrorOccurred);
|
||||
|
||||
process_->setProcessChannelMode(QProcess::MergedChannels);
|
||||
wstunnelExePath_ = QCoreApplication::applicationDirPath() + "/windscribewstunnel.exe";
|
||||
wstunnelExePath_ = QCoreApplication::applicationDirPath() + "/" WS_PRODUCT_NAME_LOWER "wstunnel.exe";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void CustomConfigsDirWatcher::checkFiles(bool bWithEmitSignal, bool bFileChanged
|
||||
for (const QString &filename : fileList)
|
||||
{
|
||||
// skip our temp file
|
||||
if (filename == "windscribe_temp_config.ovpn")
|
||||
if (filename == WS_PRODUCT_NAME_LOWER "_temp_config.ovpn")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user