This commit is contained in:
Jonathan Martin
2026-04-14 10:21:39 -07:00
parent 662648bdb1
commit 9168f5d309
659 changed files with 8254 additions and 8470 deletions
+176 -59
View File
@@ -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
View File
@@ -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)
+2 -2
View File
@@ -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
View File
@@ -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()
+4 -10
View File
@@ -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
View File
@@ -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}")
+26
View File
@@ -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)
+2 -2
View File
@@ -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()
+19
View File
@@ -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@")
+125
View File
@@ -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@")
+109
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+17
View File
@@ -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
View File
@@ -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()
+92
View File
@@ -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
View File
@@ -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}")
+7 -1
View File
@@ -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)
-35
View File
@@ -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 */
+34
View File
@@ -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
View File
@@ -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()
+1 -3
View File
@@ -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 &param : 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);
+25 -100
View File
@@ -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
+16 -13
View File
@@ -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;
};
+12 -60
View File
@@ -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
+6 -10
View File
@@ -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);
+2 -2
View File
@@ -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
}
+3 -3
View File
@@ -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)
-10
View File
@@ -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
+31
View File
@@ -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;
}
}
+10
View File
@@ -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;
+11 -4
View File
@@ -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;
}
+5 -2
View File
@@ -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
+2 -13
View File
@@ -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)
{
+1 -1
View File
@@ -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;
}
+2 -2
View File
@@ -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:
+6 -4
View File
@@ -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
+13 -9
View File
@@ -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,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
+7 -3
View File
@@ -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");
+3 -2
View File
@@ -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;
+2 -1
View File
@@ -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"
+18
View File
@@ -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)
-38
View File
@@ -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 */
+36
View File
@@ -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 */
-2
View File
@@ -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