Compare commits

..

23 Commits

Author SHA1 Message Date
Yaroslav Gurov c5101bca41 fix: use proper configuration for split-tunneled apps 2026-02-04 13:20:09 +01:00
Yaroslav Gurov 5379d79918 fix: xray heap corruption 2026-02-04 12:48:10 +01:00
Yaroslav Gurov 51b06c5960 chore: xray routing fine-tuning 2026-02-03 21:08:27 +01:00
Yaroslav Gurov 32374ad4cc chore: rework xray routing
* get rid of redundant delays
* check if remote calls are successful
2026-02-03 02:16:12 +01:00
Yaroslav Gurov 2276e55fdf chore: move tun init from tun2socks code to ipcserver 2026-02-02 14:29:06 +01:00
Yaroslav Gurov 2aa9716cc0 chore: remove unnecessary steps during xray TUN setup phase 2026-02-02 12:22:01 +01:00
Yaroslav Gurov e24a75e1d5 fix: add enablePeerTraffic call to xray 2026-02-02 01:41:24 +01:00
ik a983d0504e fix: add checks for script components to find out where it can fall (#2169) 2026-01-30 14:43:30 +08:00
vkamn d0b8535395 fix: update tag deploy (#2168) 2026-01-30 13:15:50 +08:00
dpamnezia f84480cf56 chore: fix artifacts upload (#1961) 2026-01-30 12:43:21 +08:00
MrMirDan de7a026ec1 fix: change drawer parents interactivity (#2004)
* fix: change drawer parents interactivity

* update: better vars names
2026-01-30 12:42:53 +08:00
MrMirDan a128c7d247 fix: keyboard navigation (#2023)
* fix: self-hosted easy install card

* fix: label double click when enter/return pressed
2026-01-30 12:42:29 +08:00
MrMirDan f316f0e25a feat: news notifications switch (#2126)
* feat: news notifications switch

* update: text changes

* fix: notifications enabled by default
2026-01-30 12:19:50 +08:00
NickVs2015 ea5242e29b fix: fixed cipher selection (#2110) 2026-01-30 12:18:54 +08:00
NickVs2015 b31a62c55f feat: add support open files by atv (#2082) 2026-01-30 12:11:26 +08:00
yyy-amnezia 02e3107a23 feat: implement service kickstart and improve macos post install script (#2131) 2026-01-30 12:05:20 +08:00
lunardunno 1862850108 feat: checking linux kernel version when installing amneziawg-go (#2098)
* Checking Linux kernel version when installing amneziawg-go

print the Linux kernel version to stdOut for subsequent checking by the server controller.

* Add error for old linux kernel

Add error 214 ServerLinuxKernelTooOld

* Add case for old linux kernel

Add case for error 214 ServerLinuxKernelTooOld

* Added kernel check for Awg2

Added Linux kernel version check and introduced corresponding ServerLinuxKernelTooOld error for Awg2.
2026-01-30 12:04:27 +08:00
vkamn f73792844c chore: revoke #2148 (#2160) 2026-01-26 19:39:47 +08:00
Yaroslav Gurov a7199ca6f5 fix: add +x permissions to wireguard-go on linux (#2159) 2026-01-26 19:16:39 +08:00
vkamn 5e757cdd3b chore: bump qt version for linux build (#2157) 2026-01-25 21:35:16 +08:00
vkamn 92af1f3268 chore: runners (#2150)
* chore: change runner for linux and android

* chore: add libsecret to linux build

* chore: bump version
2026-01-23 12:05:31 +08:00
Yaroslav Gurov aad9d6dae2 chore: remove redundant gateway (#2148) 2026-01-22 18:21:15 +08:00
Yaroslav Gurov 423fe3fd4f fix: remove redundant gateway from xrayprotocol (#2147) 2026-01-22 18:03:36 +08:00
71 changed files with 610 additions and 698 deletions
+4 -4
View File
@@ -10,10 +10,10 @@ env:
jobs: jobs:
Build-Linux-Ubuntu: Build-Linux-Ubuntu:
runs-on: 4-core runs-on: android-runner
env: env:
QT_VERSION: 6.8.3 QT_VERSION: 6.10.1
QIF_VERSION: 4.7 QIF_VERSION: 4.7
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }} PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }} PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
@@ -58,7 +58,7 @@ jobs:
- name: 'Build project' - name: 'Build project'
run: | run: |
sudo apt-get install libxkbcommon-x11-0 sudo apt-get install libxkbcommon-x11-0 libsecret-1-dev
export QT_BIN_DIR=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64/bin export QT_BIN_DIR=${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/gcc_64/bin
export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin export QIF_BIN_DIR=${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin
bash deploy/build_linux.sh bash deploy/build_linux.sh
@@ -537,7 +537,7 @@ jobs:
# ------------------------------------------------------ # ------------------------------------------------------
Build-Android: Build-Android:
runs-on: 4-core runs-on: android-runner
env: env:
ANDROID_BUILD_PLATFORM: android-36 ANDROID_BUILD_PLATFORM: android-36
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
- name: Verify git tag - name: Verify git tag
run: | run: |
TAG_NAME=${{ inputs.RELEASE_VERSION }} TAG_NAME=${{ inputs.RELEASE_VERSION }}
CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/') CMAKE_TAG=$(grep 'set(AMNEZIAVPN_VERSION' CMakeLists.txt | sed -E 's/.*AMNEZIAVPN_VERSION ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/')
if [[ "$TAG_NAME" == "$CMAKE_TAG" ]]; then if [[ "$TAG_NAME" == "$CMAKE_TAG" ]]; then
echo "Git tag ($TAG_NAME) matches CMakeLists.txt version ($CMAKE_TAG)." echo "Git tag ($TAG_NAME) matches CMakeLists.txt version ($CMAKE_TAG)."
else else
+5 -7
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN) set(PROJECT AmneziaVPN)
set(AMNEZIAVPN_VERSION 4.8.12.8) set(AMNEZIAVPN_VERSION 4.8.12.9)
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION} project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION}
DESCRIPTION "AmneziaVPN" DESCRIPTION "AmneziaVPN"
@@ -12,7 +12,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}") set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 2104) set(APP_ANDROID_VERSION_CODE 2105)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux") set(MZ_PLATFORM_NAME "linux")
@@ -24,8 +24,6 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android")
set(MZ_PLATFORM_NAME "android") set(MZ_PLATFORM_NAME "android")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "iOS") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
set(MZ_PLATFORM_NAME "ios") set(MZ_PLATFORM_NAME "ios")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "tvOS")
set(MZ_PLATFORM_NAME "ios")
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten")
set(MZ_PLATFORM_NAME "wasm") set(MZ_PLATFORM_NAME "wasm")
endif() endif()
@@ -35,7 +33,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE) if(APPLE)
if(IOS OR CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(IOS)
set(CMAKE_OSX_ARCHITECTURES "arm64") set(CMAKE_OSX_ARCHITECTURES "arm64")
elseif(MACOS_NE) elseif(MACOS_NE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
@@ -46,7 +44,7 @@ endif()
add_subdirectory(client) add_subdirectory(client)
if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE)
add_subdirectory(service) add_subdirectory(service)
include(${CMAKE_SOURCE_DIR}/deploy/installer/config.cmake) include(${CMAKE_SOURCE_DIR}/deploy/installer/config.cmake)
@@ -54,7 +52,7 @@ endif()
set(AMNEZIA_STAGE_DIR "${CMAKE_BINARY_DIR}/stage") set(AMNEZIA_STAGE_DIR "${CMAKE_BINARY_DIR}/stage")
if(WIN32 AND NOT IOS AND NOT ANDROID AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(WIN32 AND NOT IOS AND NOT ANDROID AND NOT MACOS_NE)
file(TO_CMAKE_PATH "${AMNEZIA_STAGE_DIR}" AMNEZIA_STAGE_DIR_CMAKE) file(TO_CMAKE_PATH "${AMNEZIA_STAGE_DIR}" AMNEZIA_STAGE_DIR_CMAKE)
set(CPACK_GENERATOR "WIX") set(CPACK_GENERATOR "WIX")
+7 -8
View File
@@ -33,7 +33,7 @@ add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}")
add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}") add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}")
add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}") add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}")
if(WIN32 OR (APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
set(PACKAGES ${PACKAGES} Widgets) set(PACKAGES ${PACKAGES} Widgets)
endif() endif()
@@ -46,7 +46,7 @@ set(LIBS ${LIBS}
Qt6::Core5Compat Qt6::Concurrent Qt6::Core5Compat Qt6::Concurrent
) )
if(WIN32 OR (APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
set(LIBS ${LIBS} Qt6::Widgets) set(LIBS ${LIBS} Qt6::Widgets)
endif() endif()
@@ -56,7 +56,7 @@ target_include_directories(${PROJECT} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
) )
if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID))
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep)
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_tun2socks.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_tun2socks.rep)
@@ -176,7 +176,7 @@ if(LINUX AND NOT ANDROID)
link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux) link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux)
endif() endif()
if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID))
add_compile_definitions(AMNEZIA_DESKTOP) add_compile_definitions(AMNEZIA_DESKTOP)
endif() endif()
@@ -184,8 +184,7 @@ if(ANDROID)
include(cmake/android.cmake) include(cmake/android.cmake)
endif() endif()
if(IOS OR CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(IOS)
option(AMNEZIA_IOS_ENABLE_APPLETV_TARGET "Enable Apple TV target settings for iOS/Xcode projects" OFF)
include(cmake/ios.cmake) include(cmake/ios.cmake)
include(cmake/ios-arch-fixup.cmake) include(cmake/ios-arch-fixup.cmake)
elseif(APPLE AND MACOS_NE) elseif(APPLE AND MACOS_NE)
@@ -207,11 +206,11 @@ if(WIN32)
endif() endif()
elseif(LINUX) elseif(LINUX)
set(DEPLOY_PLATFORM_PATH "linux/client") set(DEPLOY_PLATFORM_PATH "linux/client")
elseif(APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") elseif(APPLE AND NOT IOS)
set(DEPLOY_PLATFORM_PATH "macos") set(DEPLOY_PLATFORM_PATH "macos")
endif() endif()
if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(NOT IOS AND NOT ANDROID AND NOT MACOS_NE)
add_custom_command( add_custom_command(
TARGET ${PROJECT} POST_BUILD TARGET ${PROJECT} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E $<IF:$<CONFIG:Debug>,copy_directory,true> COMMAND ${CMAKE_COMMAND} -E $<IF:$<CONFIG:Debug>,copy_directory,true>
+2 -2
View File
@@ -250,7 +250,7 @@ bool AmneziaApplication::parseCommands()
return true; return true;
} }
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
void AmneziaApplication::startLocalServer() { void AmneziaApplication::startLocalServer() {
const QString serverName("AmneziaVPNInstance"); const QString serverName("AmneziaVPNInstance");
QLocalServer::removeServer(serverName); QLocalServer::removeServer(serverName);
@@ -271,7 +271,7 @@ void AmneziaApplication::startLocalServer() {
bool AmneziaApplication::eventFilter(QObject *watched, QEvent *event) bool AmneziaApplication::eventFilter(QObject *watched, QEvent *event)
{ {
if (event->type() == QEvent::Close) { if (event->type() == QEvent::Close) {
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
quit(); quit();
#else #else
if (m_forceQuit) { if (m_forceQuit) {
+3 -3
View File
@@ -6,7 +6,7 @@
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext> #include <QQmlContext>
#include <QThread> #include <QThread>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication> #include <QGuiApplication>
#else #else
#include <QApplication> #include <QApplication>
@@ -19,7 +19,7 @@
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance())) #define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#define AMNEZIA_BASE_CLASS QGuiApplication #define AMNEZIA_BASE_CLASS QGuiApplication
#else #else
#define AMNEZIA_BASE_CLASS QApplication #define AMNEZIA_BASE_CLASS QApplication
@@ -37,7 +37,7 @@ public:
void loadFonts(); void loadFonts();
bool parseCommands(); bool parseCommands();
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
void startLocalServer(); void startLocalServer();
#endif #endif
@@ -1,7 +1,10 @@
package org.amnezia.vpn package org.amnezia.vpn
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
@@ -11,7 +14,25 @@ private const val TAG = "TvFilePicker"
class TvFilePicker : ComponentActivity() { class TvFilePicker : ComponentActivity() {
private val fileChooseResultLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { private val fileChooseResultLauncher = registerForActivityResult(object : ActivityResultContracts.OpenDocument() {
override fun createIntent(context: Context, input: Array<String>): Intent {
val intent = super.createIntent(context, input)
val activitiesToResolveIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.packageManager.queryIntentActivities(intent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong()))
} else {
@Suppress("DEPRECATION")
context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
}
if (activitiesToResolveIntent.all {
val name = it.activityInfo.packageName
name.startsWith("com.google.android.tv.frameworkpackagestubs") || name.startsWith("com.android.tv.frameworkpackagestubs")
}) {
throw ActivityNotFoundException()
}
return intent
}
}) {
setResult(RESULT_OK, Intent().apply { data = it }) setResult(RESULT_OK, Intent().apply { data = it })
finish() finish()
} }
@@ -31,7 +52,7 @@ class TvFilePicker : ComponentActivity() {
private fun getFile() { private fun getFile() {
try { try {
Log.v(TAG, "getFile") Log.v(TAG, "getFile")
fileChooseResultLauncher.launch("*/*") fileChooseResultLauncher.launch(arrayOf("*/*"))
} catch (_: ActivityNotFoundException) { } catch (_: ActivityNotFoundException) {
Log.w(TAG, "Activity not found") Log.w(TAG, "Activity not found")
setResult(RESULT_CANCELED, Intent().apply { putExtra("activityNotFound", true) }) setResult(RESULT_CANCELED, Intent().apply { putExtra("activityNotFound", true) })
+1 -21
View File
@@ -26,7 +26,7 @@ if(WIN32)
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libssl.lib") set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libssl.lib")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libcrypto.lib") set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/windows/win32/libcrypto.lib")
endif() endif()
elseif(APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") elseif(APPLE AND NOT IOS)
if(MACOS_NE) if(MACOS_NE)
set(LIBSSH_LIB_PATH "${LIBSSH_ROOT_DIR}/macos/universal2/libssh.a") set(LIBSSH_LIB_PATH "${LIBSSH_ROOT_DIR}/macos/universal2/libssh.a")
set(ZLIB_LIB_PATH "${LIBSSH_ROOT_DIR}/macos/universal2/libz.a") set(ZLIB_LIB_PATH "${LIBSSH_ROOT_DIR}/macos/universal2/libz.a")
@@ -39,24 +39,6 @@ elseif(APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/macos/include") set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/macos/include")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/macos/lib/libssl.a") set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/macos/lib/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/macos/lib/libcrypto.a") set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/macos/lib/libcrypto.a")
elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
set(TVOS_3RD_ROOT "$ENV{HOME}/Qt_tv/3rd-tvos")
execute_process(
COMMAND xcrun --sdk appletvos --show-sdk-path
OUTPUT_VARIABLE TVOS_SDK_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(LIBSSH_ROOT_DIR "${TVOS_3RD_ROOT}/libssh/0.10.6/appletvos-arm64")
set(OPENSSL_ROOT_DIR "${TVOS_3RD_ROOT}/openssl/3.0.13/appletvos-arm64")
set(OPENSSL_LIBRARIES_DIR "${OPENSSL_ROOT_DIR}/lib")
set(LIBSSH_INCLUDE_DIR "${LIBSSH_ROOT_DIR}")
set(LIBSSH_LIB_PATH "${LIBSSH_ROOT_DIR}/lib/libssh.a")
set(ZLIB_LIB_PATH "${TVOS_SDK_PATH}/usr/lib/libz.tbd")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
set(OPENSSL_LIB_SSL_PATH "${OPENSSL_ROOT_DIR}/lib/libssl.a")
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/lib/libcrypto.a")
elseif(IOS) elseif(IOS)
set(LIBSSH_INCLUDE_DIR "${LIBSSH_ROOT_DIR}/ios/arm64") set(LIBSSH_INCLUDE_DIR "${LIBSSH_ROOT_DIR}/ios/arm64")
set(LIBSSH_LIB_PATH "${LIBSSH_ROOT_DIR}/ios/arm64/libssh.a") set(LIBSSH_LIB_PATH "${LIBSSH_ROOT_DIR}/ios/arm64/libssh.a")
@@ -81,10 +63,8 @@ elseif(LINUX)
set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/linux/x86_64/libcrypto.a") set(OPENSSL_LIB_CRYPTO_PATH "${OPENSSL_ROOT_DIR}/linux/x86_64/libcrypto.a")
endif() endif()
if(NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS")
file(COPY ${OPENSSL_LIB_SSL_PATH} ${OPENSSL_LIB_CRYPTO_PATH} file(COPY ${OPENSSL_LIB_SSL_PATH} ${OPENSSL_LIB_CRYPTO_PATH}
DESTINATION ${OPENSSL_LIBRARIES_DIR}) DESTINATION ${OPENSSL_LIBRARIES_DIR})
endif()
set(OPENSSL_USE_STATIC_LIBS TRUE) set(OPENSSL_USE_STATIC_LIBS TRUE)
-2
View File
@@ -39,7 +39,5 @@ while(IOS_TARGETS)
set_target_properties(${TARGET_NAME} PROPERTIES set_target_properties(${TARGET_NAME} PROPERTIES
XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64" XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64"
XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64" XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64"
XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64"
XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "arm64"
) )
endwhile() endwhile()
+7 -122
View File
@@ -1,20 +1,6 @@
message("Client iOS build") message("Client iOS build")
set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0) set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0)
set(APPLE_PROJECT_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH}) set(APPLE_PROJECT_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(AMNEZIA_IOS_APPLETV ${AMNEZIA_IOS_ENABLE_APPLETV_TARGET})
if(AMNEZIA_IOS_APPLETV)
message("Apple TV target mode is ON")
set(CMAKE_OSX_DEPLOYMENT_TARGET 17.0)
set(QT_NO_SET_DEFAULT_IOS_LAUNCH_SCREEN TRUE)
set(QT_NO_ADD_IOS_LAUNCH_SCREEN_TO_BUNDLE TRUE)
set(IOS_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info-tvOS.plist.in)
set(IOS_LAUNCHSCREEN_STORYBOARD ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/tvOS/AmneziaVPNLaunchScreen.storyboard)
else()
message("Apple TV target mode is OFF")
set(IOS_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info.plist.in)
set(IOS_LAUNCHSCREEN_STORYBOARD ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard)
endif()
enable_language(OBJC) enable_language(OBJC)
@@ -24,15 +10,6 @@ enable_language(Swift)
find_package(Qt6 REQUIRED COMPONENTS ShaderTools) find_package(Qt6 REQUIRED COMPONENTS ShaderTools)
set(LIBS ${LIBS} Qt6::ShaderTools) set(LIBS ${LIBS} Qt6::ShaderTools)
if(AMNEZIA_IOS_APPLETV)
# Use framework linker flags directly for tvOS to avoid iPhoneOS SDK absolute paths.
set(FW_AUTHENTICATIONSERVICES "-framework AuthenticationServices")
set(FW_UIKIT "-framework UIKit")
set(FW_AVFOUNDATION "-framework AVFoundation")
set(FW_FOUNDATION "-framework Foundation")
set(FW_STOREKIT "-framework StoreKit")
set(FW_USERNOTIFICATIONS "-framework UserNotifications")
else()
find_library(FW_AUTHENTICATIONSERVICES AuthenticationServices) find_library(FW_AUTHENTICATIONSERVICES AuthenticationServices)
find_library(FW_UIKIT UIKit) find_library(FW_UIKIT UIKit)
find_library(FW_AVFOUNDATION AVFoundation) find_library(FW_AVFOUNDATION AVFoundation)
@@ -40,7 +17,6 @@ else()
find_library(FW_STOREKIT StoreKit) find_library(FW_STOREKIT StoreKit)
find_library(FW_USERNOTIFICATIONS UserNotifications) find_library(FW_USERNOTIFICATIONS UserNotifications)
find_library(FW_NETWORKEXTENSION NetworkExtension) find_library(FW_NETWORKEXTENSION NetworkExtension)
endif()
set(LIBS ${LIBS} set(LIBS ${LIBS}
${FW_AUTHENTICATIONSERVICES} ${FW_AUTHENTICATIONSERVICES}
@@ -49,12 +25,9 @@ set(LIBS ${LIBS}
${FW_FOUNDATION} ${FW_FOUNDATION}
${FW_STOREKIT} ${FW_STOREKIT}
${FW_USERNOTIFICATIONS} ${FW_USERNOTIFICATIONS}
${FW_NETWORKEXTENSION}
) )
if(NOT AMNEZIA_IOS_APPLETV)
set(LIBS ${LIBS} ${FW_NETWORKEXTENSION})
endif()
set(HEADERS ${HEADERS} set(HEADERS ${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/ios_controller.h ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/ios_controller.h
@@ -84,7 +57,7 @@ target_include_directories(${PROJECT} PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
set_target_properties(${PROJECT} PROPERTIES set_target_properties(${PROJECT} PROPERTIES
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
MACOSX_BUNDLE_INFO_PLIST ${IOS_INFO_PLIST} MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Info.plist.in
MACOSX_BUNDLE_ICON_FILE "AppIcon" MACOSX_BUNDLE_ICON_FILE "AppIcon"
MACOSX_BUNDLE_INFO_STRING "AmneziaVPN" MACOSX_BUNDLE_INFO_STRING "AmneziaVPN"
MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN" MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPN"
@@ -93,6 +66,7 @@ set_target_properties(${PROJECT} PROPERTIES
MACOSX_BUNDLE_LONG_VERSION_STRING "${APPLE_PROJECT_VERSION}-${CMAKE_PROJECT_VERSION_TWEAK}" MACOSX_BUNDLE_LONG_VERSION_STRING "${APPLE_PROJECT_VERSION}-${CMAKE_PROJECT_VERSION_TWEAK}"
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPLE_PROJECT_VERSION}" MACOSX_BUNDLE_SHORT_VERSION_STRING "${APPLE_PROJECT_VERSION}"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/ios/app/main.entitlements"
XCODE_ATTRIBUTE_MARKETING_VERSION "${APPLE_PROJECT_VERSION}" XCODE_ATTRIBUTE_MARKETING_VERSION "${APPLE_PROJECT_VERSION}"
XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}" XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${CMAKE_PROJECT_VERSION_TWEAK}"
XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPN" XCODE_ATTRIBUTE_PRODUCT_NAME "AmneziaVPN"
@@ -100,36 +74,13 @@ set_target_properties(${PROJECT} PROPERTIES
XCODE_GENERATE_SCHEME TRUE XCODE_GENERATE_SCHEME TRUE
XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" XCODE_ATTRIBUTE_ENABLE_BITCODE "NO"
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON
XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks"
XCODE_EMBED_APP_EXTENSIONS networkextension XCODE_EMBED_APP_EXTENSIONS networkextension
) )
if(AMNEZIA_IOS_APPLETV)
set_target_properties(${PROJECT} PROPERTIES
XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "appletvos appletvsimulator"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "3"
XCODE_ATTRIBUTE_TVOS_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
XCODE_ATTRIBUTE_SDKROOT "appletvos"
XCODE_ATTRIBUTE_SDKROOT[sdk=appletvos*] "appletvos"
XCODE_ATTRIBUTE_SDKROOT[sdk=appletvsimulator*] "appletvsimulator"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvos*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvsimulator*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_EXCLUDED_LIBRARY_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/usr/lib/swift"
XCODE_ATTRIBUTE_EXCLUDED_FRAMEWORK_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/System/Library/Frameworks"
)
set_target_properties(${PROJECT} PROPERTIES
QT_IOS_PERMISSIONS ""
)
else()
set_target_properties(${PROJECT} PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/ios/app/main.entitlements"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
)
endif()
if(DEFINED DEPLOY) if(DEFINED DEPLOY)
set_target_properties(${PROJECT} PROPERTIES set_target_properties(${PROJECT} PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
@@ -160,59 +111,6 @@ target_compile_options(${PROJECT} PRIVATE
-DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\" -DVPN_NE_BUNDLEID=\"${BUILD_IOS_APP_IDENTIFIER}.network-extension\"
) )
if(AMNEZIA_IOS_APPLETV)
# qscnetworkreachability plugin links IOKit, which is unavailable on tvOS.
qt_import_plugins(${PROJECT}
NO_DEFAULT
INCLUDE
QIOSIntegrationPlugin
QJpegPlugin
QSvgPlugin
QGifPlugin
QICOPlugin
QSvgIconPlugin
QSecureTransportBackendPlugin
EXCLUDE
QSCNetworkReachabilityNetworkInformationPlugin
QDarwinCameraPermissionPlugin
)
# Static tvOS Qt build doesn't auto-link these plugin archives into the
# Xcode target, but the app entry point lives in QIOSIntegrationPlugin.
set(_amnezia_tvos_static_plugins
Qt6::QIOSIntegrationPlugin
Qt6::QIOSIntegrationPlugin_init
Qt6::QJpegPlugin
Qt6::QJpegPlugin_init
Qt6::QSvgPlugin
Qt6::QSvgPlugin_init
Qt6::QGifPlugin
Qt6::QGifPlugin_init
Qt6::QICOPlugin
Qt6::QICOPlugin_init
Qt6::QSvgIconPlugin
Qt6::QSvgIconPlugin_init
Qt6::QSecureTransportBackendPlugin
Qt6::QSecureTransportBackendPlugin_init
)
foreach(_amnezia_tvos_static_plugin IN LISTS _amnezia_tvos_static_plugins)
if(TARGET ${_amnezia_tvos_static_plugin})
target_link_libraries(${PROJECT} PRIVATE ${_amnezia_tvos_static_plugin})
endif()
endforeach()
unset(_amnezia_tvos_static_plugin)
unset(_amnezia_tvos_static_plugins)
# Qt 6.9.2 iOS package links IOKit via Qt6::Core interface, but tvOS SDK
# does not provide IOKit. Strip this single framework for Apple TV builds.
get_target_property(_qtcore_iface_libs Qt6::Core INTERFACE_LINK_LIBRARIES)
if(_qtcore_iface_libs)
string(REPLACE "-framework IOKit;" "" _qtcore_iface_libs "${_qtcore_iface_libs}")
string(REPLACE ";-framework IOKit" "" _qtcore_iface_libs "${_qtcore_iface_libs}")
set_property(TARGET Qt6::Core PROPERTY INTERFACE_LINK_LIBRARIES "${_qtcore_iface_libs}")
endif()
endif()
set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/amneziawg-apple/Sources) set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/amneziawg-apple/Sources)
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
@@ -225,38 +123,25 @@ target_sources(${PROJECT} PRIVATE
${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift ${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift
) )
if(IOS_LAUNCHSCREEN_STORYBOARD)
target_sources(${PROJECT} PRIVATE target_sources(${PROJECT} PRIVATE
${IOS_LAUNCHSCREEN_STORYBOARD} ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
) )
set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE
${IOS_LAUNCHSCREEN_STORYBOARD} ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/AmneziaVPNLaunchScreen.storyboard
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy ${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
) )
else()
target_sources(${PROJECT} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
)
set_property(TARGET ${PROJECT} APPEND PROPERTY RESOURCE
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/Media.xcassets
${CMAKE_CURRENT_SOURCE_DIR}/ios/app/PrivacyInfo.xcprivacy
)
endif()
add_subdirectory(ios/networkextension) add_subdirectory(ios/networkextension)
add_dependencies(${PROJECT} networkextension) add_dependencies(${PROJECT} networkextension)
if(NOT AMNEZIA_IOS_APPLETV)
set_property(TARGET ${PROJECT} PROPERTY XCODE_EMBED_FRAMEWORKS set_property(TARGET ${PROJECT} PROPERTY XCODE_EMBED_FRAMEWORKS
"${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/OpenVPNAdapter.framework" "${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/OpenVPNAdapter.framework"
) )
set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/) set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/)
target_link_libraries("networkextension" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/OpenVPNAdapter.framework") target_link_libraries("networkextension" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/openvpn/apple/OpenVPNAdapter-ios/OpenVPNAdapter.framework")
endif()
+4 -4
View File
@@ -39,7 +39,7 @@ set(HEADERS ${HEADERS}
${CLIENT_ROOT_DIR}/mozilla/controllerimpl.h ${CLIENT_ROOT_DIR}/mozilla/controllerimpl.h
) )
if(NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(NOT IOS AND NOT MACOS_NE)
set(HEADERS ${HEADERS} set(HEADERS ${HEADERS}
${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.h ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.h
) )
@@ -89,14 +89,14 @@ set(SOURCES ${SOURCES}
${CLIENT_ROOT_DIR}/mozilla/shared/leakdetector.cpp ${CLIENT_ROOT_DIR}/mozilla/shared/leakdetector.cpp
) )
if(NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(NOT IOS AND NOT MACOS_NE)
set(SOURCES ${SOURCES} set(SOURCES ${SOURCES}
${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.cpp ${CLIENT_ROOT_DIR}/platforms/ios/QRCodeReaderBase.cpp
) )
endif() endif()
# Include native macOS platform helpers (dock/status-item) # Include native macOS platform helpers (dock/status-item)
if(APPLE AND NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") if(APPLE AND NOT IOS)
list(APPEND HEADERS list(APPEND HEADERS
${CLIENT_ROOT_DIR}/platforms/macos/macosutils.h ${CLIENT_ROOT_DIR}/platforms/macos/macosutils.h
${CLIENT_ROOT_DIR}/platforms/macos/macosstatusicon.h ${CLIENT_ROOT_DIR}/platforms/macos/macosstatusicon.h
@@ -175,7 +175,7 @@ if(WIN32)
) )
endif() endif()
if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS") OR (LINUX AND NOT ANDROID)) if(WIN32 OR (APPLE AND NOT IOS AND NOT MACOS_NE) OR (LINUX AND NOT ANDROID))
message("Client desktop build") message("Client desktop build")
add_compile_definitions(AMNEZIA_DESKTOP) add_compile_definitions(AMNEZIA_DESKTOP)
@@ -1,13 +1,17 @@
#include "openvpn_configurator.h" #include "openvpn_configurator.h"
#include <QDebug> #include <QDebug>
#include <QCoreApplication>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QProcess> #include <QProcess>
#include <QString> #include <QString>
#include <QTemporaryDir> #include <QTemporaryDir>
#include <QTemporaryFile> #include <QTemporaryFile>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "core/networkUtilities.h" #include "core/networkUtilities.h"
#include "containers/containers_defs.h" #include "containers/containers_defs.h"
@@ -161,7 +165,7 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString,
QString dnsConf = QString("\nscript-security 2\n" QString dnsConf = QString("\nscript-security 2\n"
"up %1/update-resolv-conf.sh\n" "up %1/update-resolv-conf.sh\n"
"down %1/update-resolv-conf.sh\n") "down %1/update-resolv-conf.sh\n")
.arg(QCoreApplication::applicationDirPath()); .arg(qApp->applicationDirPath());
config.append(dnsConf); config.append(dnsConf);
#endif #endif
+11 -7
View File
@@ -1,7 +1,6 @@
#include "ssh_configurator.h" #include "ssh_configurator.h"
#include <QDebug> #include <QDebug>
#include <QCoreApplication>
#include <QObject> #include <QObject>
#include <QProcess> #include <QProcess>
#include <QString> #include <QString>
@@ -9,6 +8,11 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QThread> #include <QThread>
#include <qtimer.h> #include <qtimer.h>
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "core/server_defs.h" #include "core/server_defs.h"
#include "utilities.h" #include "utilities.h"
@@ -20,7 +24,7 @@ SshConfigurator::SshConfigurator(std::shared_ptr<Settings> settings, const QShar
QString SshConfigurator::convertOpenSShKey(const QString &key) QString SshConfigurator::convertOpenSShKey(const QString &key)
{ {
#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_IOS) && !defined(MACOS_NE)
QProcess p; QProcess p;
p.setProcessChannelMode(QProcess::MergedChannels); p.setProcessChannelMode(QProcess::MergedChannels);
@@ -66,13 +70,13 @@ QString SshConfigurator::convertOpenSShKey(const QString &key)
// DEAD CODE. // DEAD CODE.
void SshConfigurator::openSshTerminal(const ServerCredentials &credentials) void SshConfigurator::openSshTerminal(const ServerCredentials &credentials)
{ {
#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_IOS) && !defined(MACOS_NE)
QProcess *p = new QProcess(); QProcess *p = new QProcess();
p->setProcessChannelMode(QProcess::SeparateChannels); p->setProcessChannelMode(QProcess::SeparateChannels);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
p->setProcessEnvironment(prepareEnv()); p->setProcessEnvironment(prepareEnv());
p->setProgram(QCoreApplication::applicationDirPath() + "\\cygwin\\putty.exe"); p->setProgram(qApp->applicationDirPath() + "\\cygwin\\putty.exe");
if (credentials.secretData.contains("PRIVATE KEY")) { if (credentials.secretData.contains("PRIVATE KEY")) {
// todo: connect by key // todo: connect by key
@@ -96,10 +100,10 @@ QProcessEnvironment SshConfigurator::prepareEnv()
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
pathEnvVar.clear(); pathEnvVar.clear();
pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "\\cygwin;"); pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\cygwin;");
pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "\\openvpn;"); pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "\\openvpn;");
#elif defined(Q_OS_MACX) && !defined(MACOS_NE) #elif defined(Q_OS_MACX) && !defined(MACOS_NE)
pathEnvVar.prepend(QDir::toNativeSeparators(QCoreApplication::applicationDirPath()) + "/Contents/MacOS"); pathEnvVar.prepend(QDir::toNativeSeparators(QApplication::applicationDirPath()) + "/Contents/MacOS");
#endif #endif
env.insert("PATH", pathEnvVar); env.insert("PATH", pathEnvVar);
+3 -3
View File
@@ -8,7 +8,7 @@
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_IOS)
#include "platforms/ios/ios_controller.h" #include "platforms/ios/ios_controller.h"
#include <AmneziaVPN-Swift.h> #include <AmneziaVPN-Swift.h>
#endif #endif
@@ -196,7 +196,7 @@ void CoreController::initAndroidController()
void CoreController::initAppleController() void CoreController::initAppleController()
{ {
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #ifdef Q_OS_IOS
IosController::Instance()->initialize(); IosController::Instance()->initialize();
connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) { connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) {
emit m_pageController->goToPageHome(); emit m_pageController->goToPageHome();
@@ -233,7 +233,7 @@ void CoreController::initSignalHandlers()
void CoreController::initNotificationHandler() void CoreController::initNotificationHandler()
{ {
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
m_notificationHandler.reset(NotificationHandler::create(nullptr)); m_notificationHandler.reset(NotificationHandler::create(nullptr));
connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(), connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
+3 -3
View File
@@ -5,7 +5,7 @@
#include <QQmlContext> #include <QQmlContext>
#include <QThread> #include <QThread>
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
#include "ui/systemtray_notificationhandler.h" #include "ui/systemtray_notificationhandler.h"
#endif #endif
@@ -49,7 +49,7 @@
#include "ui/models/sites_model.h" #include "ui/models/sites_model.h"
#include "ui/models/newsModel.h" #include "ui/models/newsModel.h"
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
#include "ui/notificationhandler.h" #include "ui/notificationhandler.h"
#endif #endif
@@ -99,7 +99,7 @@ private:
QSharedPointer<VpnConnection> m_vpnConnection; QSharedPointer<VpnConnection> m_vpnConnection;
QSharedPointer<QTranslator> m_translator; QSharedPointer<QTranslator> m_translator;
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
QScopedPointer<NotificationHandler> m_notificationHandler; QScopedPointer<NotificationHandler> m_notificationHandler;
#endif #endif
@@ -419,6 +419,18 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent
cbReadStdOut, cbReadStdErr); cbReadStdOut, cbReadStdErr);
qDebug().noquote() << "ServerController::installDockerWorker" << stdOut; qDebug().noquote() << "ServerController::installDockerWorker" << stdOut;
if (container == DockerContainer::Awg2) {
QRegularExpression regex(R"(Linux\s+(\d+)\.(\d+)[^\d]*)");
QRegularExpressionMatch match = regex.match(stdOut);
if (match.hasMatch()) {
int majorVersion = match.captured(1).toInt();
int minorVersion = match.captured(2).toInt();
if (majorVersion < 4 || (majorVersion == 4 && minorVersion < 14)) {
return ErrorCode::ServerLinuxKernelTooOld;
}
}
}
if (stdOut.contains("lock")) if (stdOut.contains("lock"))
return ErrorCode::ServerPacketManagerError; return ErrorCode::ServerPacketManagerError;
if (stdOut.contains("command not found")) if (stdOut.contains("command not found"))
+1
View File
@@ -61,6 +61,7 @@ namespace amnezia
ServerDockerOnCgroupsV2 = 211, ServerDockerOnCgroupsV2 = 211,
ServerCgroupMountpoint = 212, ServerCgroupMountpoint = 212,
DockerPullRateLimit = 213, DockerPullRateLimit = 213,
ServerLinuxKernelTooOld = 214,
// Ssh connection errors // Ssh connection errors
SshRequestDeniedError = 300, SshRequestDeniedError = 300,
+1
View File
@@ -29,6 +29,7 @@ QString errorString(ErrorCode code) {
case(ErrorCode::ServerDockerOnCgroupsV2): errorMessage = QObject::tr("Docker error: runc doesn't work on cgroups v2"); break; case(ErrorCode::ServerDockerOnCgroupsV2): errorMessage = QObject::tr("Docker error: runc doesn't work on cgroups v2"); break;
case(ErrorCode::ServerCgroupMountpoint): errorMessage = QObject::tr("Server error: cgroup mountpoint does not exist"); break; case(ErrorCode::ServerCgroupMountpoint): errorMessage = QObject::tr("Server error: cgroup mountpoint does not exist"); break;
case(ErrorCode::DockerPullRateLimit): errorMessage = QObject::tr("Docker error: The pull rate limit has been reached"); break; case(ErrorCode::DockerPullRateLimit): errorMessage = QObject::tr("Docker error: The pull rate limit has been reached"); break;
case(ErrorCode::ServerLinuxKernelTooOld): errorMessage = QObject::tr("Server error: Linux kernel is too old"); break;
// Libssh errors // Libssh errors
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break; case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
+2 -2
View File
@@ -24,7 +24,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
#include <sys/param.h> #include <sys/param.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/socket.h> #include <sys/socket.h>
@@ -404,7 +404,7 @@ QPair<QString, QNetworkInterface> NetworkUtilities::getGatewayAndIface()
close(sock); close(sock);
return { gateway_address, QNetworkInterface::interfaceFromName(interface) }; return { gateway_address, QNetworkInterface::interfaceFromName(interface) };
#endif #endif
#if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if defined(Q_OS_MAC) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
QString gateway; QString gateway;
int index = -1; int index = -1;
-54
View File
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>UIRequiredDeviceCapabilities</key>
<array/>
<key>UIRequiresFullScreen</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UILaunchStoryboardName</key>
<string>AmneziaVPNLaunchScreen</string>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>com.wireguard.ios.app_group_id</key>
<string>group.org.amnezia.AmneziaVPN</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
</dict>
</plist>
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="13122.16" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="wu6-TO-1qx"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
+18 -116
View File
@@ -1,13 +1,6 @@
enable_language(Swift) enable_language(Swift)
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
set(AMNEZIA_IOS_APPLETV ${AMNEZIA_IOS_ENABLE_APPLETV_TARGET})
if(AMNEZIA_IOS_APPLETV)
message("Network Extension tvOS mode is ON")
else()
message("Network Extension tvOS mode is OFF")
endif()
add_executable(networkextension) add_executable(networkextension)
set_target_properties(networkextension PROPERTIES set_target_properties(networkextension PROPERTIES
@@ -35,23 +28,6 @@ set_target_properties(networkextension PROPERTIES
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../Frameworks" XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../../Frameworks"
) )
if(AMNEZIA_IOS_APPLETV)
set_target_properties(networkextension PROPERTIES
XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "appletvos appletvsimulator"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "3"
XCODE_ATTRIBUTE_TVOS_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
XCODE_ATTRIBUTE_SDKROOT "appletvos"
XCODE_ATTRIBUTE_SDKROOT[sdk=appletvos*] "appletvos"
XCODE_ATTRIBUTE_SDKROOT[sdk=appletvsimulator*] "appletvsimulator"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvos*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS[sdk=appletvsimulator*] "$(inherited) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)"
XCODE_ATTRIBUTE_EXCLUDED_LIBRARY_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/usr/lib/swift"
XCODE_ATTRIBUTE_EXCLUDED_FRAMEWORK_SEARCH_PATHS "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk/System/Library/Frameworks"
LINKER_LANGUAGE Swift
)
endif()
if(DEPLOY) if(DEPLOY)
set_target_properties(networkextension PROPERTIES set_target_properties(networkextension PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution" XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Distribution"
@@ -69,49 +45,38 @@ endif()
set_target_properties(networkextension PROPERTIES set_target_properties(networkextension PROPERTIES
XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" XCODE_ATTRIBUTE_SWIFT_VERSION "5.0"
XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES" XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES"
XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/WireGuardNetworkExtension-Bridging-Header.h"
XCODE_ATTRIBUTE_SWIFT_OPTIMIZATION_LEVEL "-Onone" XCODE_ATTRIBUTE_SWIFT_OPTIMIZATION_LEVEL "-Onone"
XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO" XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO"
) )
set_target_properties(networkextension PROPERTIES
XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/WireGuardNetworkExtension-Bridging-Header.h"
)
set_target_properties("networkextension" PROPERTIES set_target_properties("networkextension" PROPERTIES
XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK" XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK"
) )
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
find_library(FW_MOBILE_CORE MobileCoreServices)
find_library(FW_UI_KIT UIKit) find_library(FW_UI_KIT UIKit)
find_library(FW_LIBRESOLV libresolv.9.tbd) find_library(FW_LIBRESOLV libresolv.9.tbd)
if(NOT AMNEZIA_IOS_APPLETV) target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY})
target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE})
target_link_libraries(networkextension PRIVATE ${FW_UI_KIT}) target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
target_link_libraries(networkextension PRIVATE ${FW_LIBRESOLV}) target_link_libraries(networkextension PRIVATE ${FW_LIBRESOLV})
else()
target_link_libraries(networkextension PRIVATE -lresolv)
endif()
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\") target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1) target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources) set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources)
set(NE_COMMON_SOURCES target_sources(networkextension PRIVATE
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
)
set(NE_WIREGUARD_SOURCES
${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PacketTunnelSettingsGenerator.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PacketTunnelSettingsGenerator.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSResolver.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSResolver.swift
${WG_APPLE_SOURCE_DIR}/WireGuardNetworkExtension/ErrorNotifier.swift ${WG_APPLE_SOURCE_DIR}/WireGuardNetworkExtension/ErrorNotifier.swift
${WG_APPLE_SOURCE_DIR}/Shared/Keychain.swift ${WG_APPLE_SOURCE_DIR}/Shared/Keychain.swift
${WG_APPLE_SOURCE_DIR}/Shared/FileManager+Extension.swift
${WG_APPLE_SOURCE_DIR}/Shared/Model/NETunnelProviderProtocol+Extension.swift
${WG_APPLE_SOURCE_DIR}/Shared/Model/TunnelConfiguration+WgQuickConfig.swift ${WG_APPLE_SOURCE_DIR}/Shared/Model/TunnelConfiguration+WgQuickConfig.swift
${WG_APPLE_SOURCE_DIR}/Shared/Model/NETunnelProviderProtocol+Extension.swift
${WG_APPLE_SOURCE_DIR}/Shared/Model/String+ArrayConversion.swift ${WG_APPLE_SOURCE_DIR}/Shared/Model/String+ArrayConversion.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/TunnelConfiguration.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/TunnelConfiguration.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddressRange.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddressRange.swift
@@ -119,50 +84,24 @@ set(NE_WIREGUARD_SOURCES
${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSServer.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSServer.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/InterfaceConfiguration.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/InterfaceConfiguration.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PeerConfiguration.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PeerConfiguration.swift
${WG_APPLE_SOURCE_DIR}/Shared/FileManager+Extension.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c ${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c
${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
)
set(NE_XRAY_SOURCES
${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift ${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+Xray.swift ${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
${CLIENT_ROOT_DIR}/platforms/ios/XrayConfig.swift ${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
) ${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
set(NE_OPENVPN_SOURCES ${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPN.swift ${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPN.swift
) ${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+Xray.swift
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
set(NE_APPLE_GLUE_SOURCES ${CLIENT_ROOT_DIR}/platforms/ios/XrayConfig.swift
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm ${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
) )
if(AMNEZIA_IOS_APPLETV)
list(APPEND NE_APPLE_GLUE_SOURCES
${CLIENT_ROOT_DIR}/platforms/ios/tvos_cgo_stubs.c
)
endif()
target_sources(networkextension PRIVATE ${NE_COMMON_SOURCES})
if(NOT AMNEZIA_IOS_APPLETV)
target_sources(networkextension PRIVATE
${NE_WIREGUARD_SOURCES}
${NE_OPENVPN_SOURCES}
${NE_XRAY_SOURCES}
${NE_APPLE_GLUE_SOURCES}
)
else()
target_sources(networkextension PRIVATE
${NE_WIREGUARD_SOURCES}
${NE_APPLE_GLUE_SOURCES}
)
endif()
target_sources(networkextension PRIVATE target_sources(networkextension PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy ${CMAKE_CURRENT_SOURCE_DIR}/PrivacyInfo.xcprivacy
) )
@@ -174,7 +113,7 @@ set_property(TARGET networkextension APPEND PROPERTY RESOURCE
## Build wireguard-go-version.h ## Build wireguard-go-version.h
execute_process( execute_process(
COMMAND go list -m golang.zx2c4.com/wireguard COMMAND go list -m golang.zx2c4.com/wireguard
WORKING_DIRECTORY ${WG_APPLE_SOURCE_DIR}/WireGuardKitGo WORKING_DIRECTORY ${CLIENT_ROOT_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo
OUTPUT_VARIABLE WG_VERSION_FULL OUTPUT_VARIABLE WG_VERSION_FULL
) )
string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1) string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1)
@@ -183,46 +122,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wireguard-go-version.h.in
target_sources(networkextension PRIVATE target_sources(networkextension PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h)
if(AMNEZIA_IOS_APPLETV)
set(WG_TVOS_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/WireGuardKitGo-appletvos)
set(WG_TVOS_TMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/WireGuardKitGo-appletvos-tmp)
execute_process(
COMMAND make clean
WORKING_DIRECTORY ${WG_APPLE_SOURCE_DIR}/WireGuardKitGo
OUTPUT_QUIET
ERROR_QUIET
)
execute_process(
COMMAND make build
PLATFORM_NAME=appletvos
GOOS_appletvos=ios
GOFLAGS=-tags=netgo
ARCHS=arm64
DEPLOYMENT_TARGET_CLANG_FLAG_NAME=mtvos-version-min
DEPLOYMENT_TARGET_CLANG_ENV_NAME=TVOS_DEPLOYMENT_TARGET
TVOS_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}
CONFIGURATION_BUILD_DIR=${WG_TVOS_LIB_DIR}
CONFIGURATION_TEMP_DIR=${WG_TVOS_TMP_DIR}
WORKING_DIRECTORY ${WG_APPLE_SOURCE_DIR}/WireGuardKitGo
RESULT_VARIABLE WG_TVOS_BUILD_RESULT
)
if(NOT WG_TVOS_BUILD_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to build tvOS WireGuard Go bridge (libwg-go.a)")
endif()
endif()
target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR}) target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR})
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
if(NOT AMNEZIA_IOS_APPLETV)
target_link_directories(networkextension PRIVATE
${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64
)
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64/libwg-go.a) target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64/libwg-go.a)
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/xray/HevSocks5Tunnel.xcframework) target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/xray/HevSocks5Tunnel.xcframework)
else()
target_link_directories(networkextension PRIVATE
${WG_TVOS_LIB_DIR}
)
target_link_libraries(networkextension PRIVATE ${WG_TVOS_LIB_DIR}/libwg-go.a)
endif()
+3 -3
View File
@@ -12,11 +12,11 @@
#include "Windows.h" #include "Windows.h"
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_IOS)
#include "platforms/ios/QtAppDelegate-C-Interface.h" #include "platforms/ios/QtAppDelegate-C-Interface.h"
#endif #endif
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
bool isAnotherInstanceRunning() bool isAnotherInstanceRunning()
{ {
QLocalSocket socket; QLocalSocket socket;
@@ -47,7 +47,7 @@ int main(int argc, char *argv[])
AmneziaApplication app(argc, argv); AmneziaApplication app(argc, argv);
OsSignalHandler::setup(); OsSignalHandler::setup();
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
if (isAnotherInstanceRunning()) { if (isAnotherInstanceRunning()) {
QTimer::singleShot(1000, &app, [&]() { app.quit(); }); QTimer::singleShot(1000, &app, [&]() { app.quit(); });
return app.exec(); return app.exec();
@@ -3,9 +3,7 @@ import NetworkExtension
import Network import Network
import os import os
import Darwin import Darwin
#if !os(tvOS)
import OpenVPNAdapter import OpenVPNAdapter
#endif
enum TunnelProtoType: String { enum TunnelProtoType: String {
case wireguard, openvpn, xray case wireguard, openvpn, xray
@@ -40,10 +38,8 @@ struct Constants {
class PacketTunnelProvider: NEPacketTunnelProvider { class PacketTunnelProvider: NEPacketTunnelProvider {
var wgAdapter: WireGuardAdapter? var wgAdapter: WireGuardAdapter?
#if !os(tvOS)
var ovpnAdapter: OpenVPNAdapter? var ovpnAdapter: OpenVPNAdapter?
private lazy var openVPNPacketFlowAdapter = PacketTunnelFlowAdapter(flow: packetFlow) private lazy var openVPNPacketFlowAdapter = PacketTunnelFlowAdapter(flow: packetFlow)
#endif
private let pathMonitorQueue = DispatchQueue(label: Constants.processQueueName + ".path-monitor") private let pathMonitorQueue = DispatchQueue(label: Constants.processQueueName + ".path-monitor")
private let pathMonitor = NWPathMonitor() private let pathMonitor = NWPathMonitor()
private var didReceiveInitialPathUpdate = false private var didReceiveInitialPathUpdate = false
@@ -53,9 +49,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
var splitTunnelType: Int? var splitTunnelType: Int?
var splitTunnelSites: [String]? var splitTunnelSites: [String]?
#if !os(tvOS)
let vpnReachability = OpenVPNReachability() let vpnReachability = OpenVPNReachability()
#endif
var startHandler: ((Error?) -> Void)? var startHandler: ((Error?) -> Void)?
var stopHandler: (() -> Void)? var stopHandler: (() -> Void)?
@@ -63,11 +57,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
var activeIfaceIdx: UInt32 = 0 var activeIfaceIdx: UInt32 = 0
#if !os(tvOS)
func openVPNPacketFlow() -> OpenVPNAdapterPacketFlow { func openVPNPacketFlow() -> OpenVPNAdapterPacketFlow {
openVPNPacketFlowAdapter openVPNPacketFlowAdapter
} }
#endif
override init() { override init() {
super.init() super.init()
@@ -214,21 +206,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
errorNotifier: errorNotifier, errorNotifier: errorNotifier,
completionHandler: completionHandler) completionHandler: completionHandler)
case .openvpn: case .openvpn:
#if os(tvOS)
completionHandler(NSError(domain: "org.amnezia.ne",
code: -1002,
userInfo: [NSLocalizedDescriptionKey: "OpenVPN backend is not available for tvOS in this build"]))
#else
startOpenVPN(completionHandler: completionHandler) startOpenVPN(completionHandler: completionHandler)
#endif
case .xray: case .xray:
#if os(tvOS)
completionHandler(NSError(domain: "org.amnezia.ne",
code: -1003,
userInfo: [NSLocalizedDescriptionKey: "Xray backend is not available for tvOS in this build"]))
#else
startXray(completionHandler: completionHandler) startXray(completionHandler: completionHandler)
#endif
} }
} }
@@ -245,18 +225,10 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
stopWireguard(with: reason, stopWireguard(with: reason,
completionHandler: completionHandler) completionHandler: completionHandler)
case .openvpn: case .openvpn:
#if os(tvOS)
completionHandler()
#else
stopOpenVPN(with: reason, stopOpenVPN(with: reason,
completionHandler: completionHandler) completionHandler: completionHandler)
#endif
case .xray: case .xray:
#if os(tvOS)
completionHandler()
#else
stopXray(completionHandler: completionHandler) stopXray(completionHandler: completionHandler)
#endif
} }
} }
@@ -270,11 +242,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
case .wireguard: case .wireguard:
handleWireguardStatusMessage(messageData, completionHandler: completionHandler) handleWireguardStatusMessage(messageData, completionHandler: completionHandler)
case .openvpn: case .openvpn:
#if !os(tvOS)
handleOpenVPNStatusMessage(messageData, completionHandler: completionHandler) handleOpenVPNStatusMessage(messageData, completionHandler: completionHandler)
#else
completionHandler?(nil)
#endif
case .xray: case .xray:
break; break;
} }
@@ -292,7 +260,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
private func handle(networkChange changePath: Network.NWPath, completion: @escaping (Error?) -> Void) { private func handle(networkChange changePath: Network.NWPath, completion: @escaping (Error?) -> Void) {
updateActiveInterfaceIndex(for: changePath) updateActiveInterfaceIndex(for: changePath)
neLog(.info, message: "Tunnel restarted.") wg_log(.info, message: "Tunnel restarted.")
startTunnel(options: nil, completionHandler: completion) startTunnel(options: nil, completionHandler: completion)
} }
} }
@@ -353,7 +321,6 @@ extension WireGuardLogLevel {
} }
} }
#if !os(tvOS)
final class PacketTunnelFlowAdapter: NSObject, OpenVPNAdapterPacketFlow { final class PacketTunnelFlowAdapter: NSObject, OpenVPNAdapterPacketFlow {
private let flow: NEPacketTunnelFlow private let flow: NEPacketTunnelFlow
@@ -372,7 +339,6 @@ final class PacketTunnelFlowAdapter: NSObject, OpenVPNAdapterPacketFlow {
flow.writePackets(packets, withProtocols: protocols) flow.writePackets(packets, withProtocols: protocols)
} }
} }
#endif
extension NEProviderStopReason { extension NEProviderStopReason {
var amneziaDescription: String { var amneziaDescription: String {
+1 -1
View File
@@ -1,4 +1,4 @@
#if !MACOS_NE && !TARGET_OS_TV #if !MACOS_NE
#include "QRCodeReaderBase.h" #include "QRCodeReaderBase.h"
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
+5 -11
View File
@@ -959,10 +959,6 @@ void IosController::sendVpnExtensionMessage(NSDictionary* message, std::function
} }
bool IosController::shareText(const QStringList& filesToSend) { bool IosController::shareText(const QStringList& filesToSend) {
#if defined(Q_OS_TVOS)
Q_UNUSED(filesToSend)
return false;
#else
NSMutableArray *sharingItems = [NSMutableArray new]; NSMutableArray *sharingItems = [NSMutableArray new];
for (int i = 0; i < filesToSend.size(); i++) { for (int i = 0; i < filesToSend.size(); i++) {
@@ -971,7 +967,7 @@ bool IosController::shareText(const QStringList& filesToSend) {
} }
#if !MACOS_NE #if !MACOS_NE
UIViewController *qtController = getViewController(); UIViewController *qtController = getViewController();
if (!qtController) return false; if (!qtController) return;
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil]; UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:sharingItems applicationActivities:nil];
#endif #endif
@@ -995,25 +991,23 @@ bool IosController::shareText(const QStringList& filesToSend) {
wait.exec(); wait.exec();
return isAccepted; return isAccepted;
#endif
} }
QString IosController::openFile() { QString IosController::openFile() {
#if defined(Q_OS_TVOS) #if !MACOS_NE
return QString();
#elif !MACOS_NE
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.item"] inMode:UIDocumentPickerModeOpen]; UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[@"public.item"] inMode:UIDocumentPickerModeOpen];
DocumentPickerDelegate *documentPickerDelegate = [[DocumentPickerDelegate alloc] init]; DocumentPickerDelegate *documentPickerDelegate = [[DocumentPickerDelegate alloc] init];
documentPicker.delegate = documentPickerDelegate; documentPicker.delegate = documentPickerDelegate;
UIViewController *qtController = getViewController(); UIViewController *qtController = getViewController();
if (!qtController) return QString(); if (!qtController) return;
[qtController presentViewController:documentPicker animated:YES completion:nil]; [qtController presentViewController:documentPicker animated:YES completion:nil];
#endif #endif
__block QString filePath; __block QString filePath;
#if !MACOS_NE && !defined(Q_OS_TVOS) #if !MACOS_NE
documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) { documentPickerDelegate.documentPickerClosedCallback = ^(NSString *path) {
if (path) { if (path) {
filePath = QString::fromUtf8(path.UTF8String); filePath = QString::fromUtf8(path.UTF8String);
@@ -1,7 +1,6 @@
#import <NetworkExtension/NetworkExtension.h> #import <NetworkExtension/NetworkExtension.h>
#import <NetworkExtension/NETunnelProviderSession.h> #import <NetworkExtension/NETunnelProviderSession.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include <TargetConditionals.h>
#if !MACOS_NE #if !MACOS_NE
#include <UIKit/UIKit.h> #include <UIKit/UIKit.h>
@@ -22,7 +21,7 @@ class IosController;
@end @end
typedef void (^DocumentPickerClosedCallback)(NSString *path); typedef void (^DocumentPickerClosedCallback)(NSString *path);
#if !MACOS_NE && !TARGET_OS_TV #if !MACOS_NE
@interface DocumentPickerDelegate : NSObject <UIDocumentPickerDelegate> @interface DocumentPickerDelegate : NSObject <UIDocumentPickerDelegate>
@property (nonatomic, copy) DocumentPickerClosedCallback documentPickerClosedCallback; @property (nonatomic, copy) DocumentPickerClosedCallback documentPickerClosedCallback;
@@ -26,7 +26,7 @@
@end @end
#if !MACOS_NE && !TARGET_OS_TV #if !MACOS_NE
@implementation DocumentPickerDelegate @implementation DocumentPickerDelegate
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls { - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
@@ -7,24 +7,6 @@
#import <UserNotifications/UserNotifications.h> #import <UserNotifications/UserNotifications.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#if defined(Q_OS_TVOS)
IOSNotificationHandler::IOSNotificationHandler(QObject* parent) : NotificationHandler(parent) {}
IOSNotificationHandler::~IOSNotificationHandler() {}
void IOSNotificationHandler::notify(NotificationHandler::Message type,
const QString& title,
const QString& message,
int timerMsec) {
Q_UNUSED(type)
Q_UNUSED(title)
Q_UNUSED(message)
Q_UNUSED(timerMsec)
}
#else
#if !MACOS_NE #if !MACOS_NE
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@@ -190,5 +172,3 @@ void IOSNotificationHandler::notify(NotificationHandler::Message type, const QSt
}]; }];
} }
#endif #endif
#endif // Q_OS_TVOS
+2 -2
View File
@@ -190,7 +190,7 @@ namespace amnezia
constexpr char defaultPort[] = "51820"; constexpr char defaultPort[] = "51820";
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
constexpr char defaultMtu[] = "1280"; constexpr char defaultMtu[] = "1280";
#else #else
constexpr char defaultMtu[] = "1376"; constexpr char defaultMtu[] = "1376";
@@ -210,7 +210,7 @@ namespace amnezia
namespace awg namespace awg
{ {
constexpr char defaultPort[] = "55424"; constexpr char defaultPort[] = "55424";
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
constexpr char defaultMtu[] = "1280"; constexpr char defaultMtu[] = "1280";
#else #else
constexpr char defaultMtu[] = "1376"; constexpr char defaultMtu[] = "1376";
+2 -2
View File
@@ -4,7 +4,7 @@
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include "vpnprotocol.h" #include "vpnprotocol.h"
#if defined(Q_OS_WINDOWS) || (defined(Q_OS_MACX) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) and !defined MACOS_NE || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
#include "openvpnovercloakprotocol.h" #include "openvpnovercloakprotocol.h"
#include "openvpnprotocol.h" #include "openvpnprotocol.h"
#include "shadowsocksvpnprotocol.h" #include "shadowsocksvpnprotocol.h"
@@ -114,7 +114,7 @@ VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject &
#if defined(Q_OS_WINDOWS) #if defined(Q_OS_WINDOWS)
case DockerContainer::Ipsec: return new Ikev2Protocol(configuration); case DockerContainer::Ipsec: return new Ikev2Protocol(configuration);
#endif #endif
#if defined(Q_OS_WINDOWS) || (defined(Q_OS_MACX) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) and !defined MACOS_NE || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration); case DockerContainer::OpenVpn: return new OpenVpnProtocol(configuration);
case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration); case DockerContainer::Cloak: return new OpenVpnOverCloakProtocol(configuration);
case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration); case DockerContainer::ShadowSocks: return new ShadowSocksVpnProtocol(configuration);
+89 -48
View File
@@ -30,7 +30,11 @@ ErrorCode XrayProtocol::start()
qDebug() << "XrayProtocol::start()"; qDebug() << "XrayProtocol::start()";
const ErrorCode err = IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) { const ErrorCode err = IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
iface->xrayStart(QJsonDocument(m_xrayConfig).toJson()); auto xrayStart = iface->xrayStart(QJsonDocument(m_xrayConfig).toJson());
if (!xrayStart.waitForFinished(1000) || !xrayStart.returnValue()) {
qCritical() << "Failed to start xray";
return ErrorCode::XrayExecutableCrashed;
}
return ErrorCode::NoError; return ErrorCode::NoError;
}, [] () { }, [] () {
return ErrorCode::AmneziaServiceConnectionFailed; return ErrorCode::AmneziaServiceConnectionFailed;
@@ -42,6 +46,65 @@ ErrorCode XrayProtocol::start()
return startTun2Sock(); return startTun2Sock();
} }
ErrorCode XrayProtocol::setupRouting() {
return IpcClient::withInterface([this](QSharedPointer<IpcInterfaceReplica> iface) -> ErrorCode {
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_primaryDNS));
// We don't use secondary DNS if primary DNS is AmneziaDNS
if (!m_primaryDNS.contains(amnezia::protocols::dns::amneziaDnsIp)) {
dnsAddr.push_back(QHostAddress(m_secondaryDNS));
}
#ifdef AMNEZIA_DESKTOP
#ifdef Q_OS_MACOS
const QString tunName = "utun22";
#else
const QString tunName = "tun2";
#endif
auto createTun = iface->createTun(tunName, amnezia::protocols::xray::defaultLocalAddr);
if (!createTun.waitForFinished(1000) || !createTun.returnValue()) {
qWarning() << "Failed to assign IP address for TUN";
return ErrorCode::InternalError;
}
auto updateResolvers = iface->updateResolvers(tunName, dnsAddr);
if (!updateResolvers.waitForFinished(1000) || !updateResolvers.returnValue()) {
qWarning() << "Failed to set DNS resolvers for TUN";
return ErrorCode::InternalError;
}
#endif
if (m_routeMode == Settings::RouteMode::VpnAllSites) {
static const QStringList subnets = { "1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1" };
auto routeAddList = iface->routeAddList(m_vpnGateway, subnets);
if (!routeAddList.waitForFinished(1000) || routeAddList.returnValue() != subnets.count()) {
qWarning() << "Failed to set routes for TUN";
return ErrorCode::InternalError;
}
}
auto StopRoutingIpv6 = iface->StopRoutingIpv6();
if (!StopRoutingIpv6.waitForFinished(1000) || !StopRoutingIpv6.returnValue()) {
qWarning() << "Failed to disable IPv6 routing";
return ErrorCode::InternalError;
}
#ifdef Q_OS_WIN
auto enablePeerTraffic = iface->enablePeerTraffic(m_rawConfig);
if (!enablePeerTraffic.waitForFinished(5000) || !enablePeerTraffic.returnValue()) {
qWarning() << "Failed to enable peer traffic";
return ErrorCode::InternalError;
}
#endif
return ErrorCode::NoError;
},
[] () {
return ErrorCode::AmneziaServiceConnectionFailed;
});
}
ErrorCode XrayProtocol::startTun2Sock() ErrorCode XrayProtocol::startTun2Sock()
{ {
m_t2sProcess->start(); m_t2sProcess->start();
@@ -50,48 +113,23 @@ ErrorCode XrayProtocol::startTun2Sock()
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; }); [&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this, [&](int vpnState) { connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this, [&](int vpnState) {
qDebug() << "PrivilegedProcess setConnectionState " << vpnState; QMetaObject::invokeMethod(this, [this, vpnState]() {
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) { qDebug() << "tun2socks state changed: " << vpnState;
if (vpnState == Vpn::ConnectionState::Connected) { if (vpnState == Vpn::ConnectionState::Connected) {
setConnectionState(Vpn::ConnectionState::Connecting); setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_primaryDNS)); if (ErrorCode res = setupRouting(); res != ErrorCode::NoError) {
// We don't use secondary DNS if primary DNS is AmneziaDNS stop();
if (!m_primaryDNS.contains(amnezia::protocols::dns::amneziaDnsIp)) { setLastError(res);
dnsAddr.push_back(QHostAddress(m_secondaryDNS)); } else
}
#ifdef Q_OS_WIN
QThread::msleep(8000);
#endif
#ifdef Q_OS_MACOS
QThread::msleep(5000);
iface->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
iface->updateResolvers("utun22", dnsAddr);
#endif
#ifdef Q_OS_LINUX
QThread::msleep(1000);
iface->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
iface->updateResolvers("tun2", dnsAddr);
#endif
if (m_routeMode == Settings::RouteMode::VpnAllSites) {
iface->routeAddList(m_vpnGateway, QStringList() << "1.0.0.0/8" << "2.0.0.0/7" << "4.0.0.0/6" << "8.0.0.0/5" << "16.0.0.0/4" << "32.0.0.0/3" << "64.0.0.0/2" << "128.0.0.0/1");
}
iface->StopRoutingIpv6();
#ifdef Q_OS_WIN
iface->updateResolvers("tun2", dnsAddr);
#endif
setConnectionState(Vpn::ConnectionState::Connected); setConnectionState(Vpn::ConnectionState::Connected);
} }
#if !defined(Q_OS_MACOS)
if (vpnState == Vpn::ConnectionState::Disconnected) { if (vpnState == Vpn::ConnectionState::Disconnected)
setConnectionState(Vpn::ConnectionState::Disconnected); stop();
iface->deleteTun("tun2");
iface->StartRoutingIpv6(); }, Qt::QueuedConnection);
iface->clearSavedRoutes();
}
#endif
});
}); });
return ErrorCode::NoError; return ErrorCode::NoError;
@@ -103,24 +141,27 @@ void XrayProtocol::stop()
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) { IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
#ifdef AMNEZIA_DESKTOP #ifdef AMNEZIA_DESKTOP
QRemoteObjectPendingReply<bool> StartRoutingIpv6Resp = iface->StartRoutingIpv6(); auto StartRoutingIpv6 = iface->StartRoutingIpv6();
if (!StartRoutingIpv6Resp.waitForFinished(1000)) { if (!StartRoutingIpv6.waitForFinished(1000) || !StartRoutingIpv6.returnValue()) {
qWarning() << "XrayProtocol::stop(): Failed to start routing ipv6"; qWarning() << "Failed to start routing ipv6";
} }
QRemoteObjectPendingReply<bool> restoreResolvers = iface->restoreResolvers(); auto restoreResolvers = iface->restoreResolvers();
if (!restoreResolvers.waitForFinished(1000)) { if (!restoreResolvers.waitForFinished(1000) || !restoreResolvers.returnValue()) {
qWarning() << "XrayProtocol::stop(): Failed to restore resolvers"; qWarning() << "Failed to restore resolvers";
} }
#if !defined(Q_OS_MACOS) #if !defined(Q_OS_MACOS)
QRemoteObjectPendingReply<bool> deleteTunResp = iface->deleteTun("tun2"); auto deleteTun = iface->deleteTun("tun2");
if (!deleteTunResp.waitForFinished(1000)) { if (!deleteTun.waitForFinished(1000) || !deleteTun.returnValue()) {
qWarning() << "XrayProtocol::stop(): Failed to delete tun"; qWarning() << "Failed to delete tun";
} }
#endif #endif
#endif #endif
iface->xrayStop(); auto xrayStop = iface->xrayStop();
if (!xrayStop.waitForFinished(1000) || !xrayStop.returnValue()) {
qWarning() << "Failed to stop xray";
}
}); });
if (m_t2sProcess) { if (m_t2sProcess) {
+2 -1
View File
@@ -14,10 +14,11 @@ public:
virtual ~XrayProtocol() override; virtual ~XrayProtocol() override;
ErrorCode start() override; ErrorCode start() override;
ErrorCode startTun2Sock();
void stop() override; void stop() override;
private: private:
ErrorCode setupRouting();
ErrorCode startTun2Sock();
void readXrayConfiguration(const QJsonObject &configuration); void readXrayConfiguration(const QJsonObject &configuration);
QJsonObject m_xrayConfig; QJsonObject m_xrayConfig;
+2 -1
View File
@@ -21,4 +21,5 @@ if [ "$(systemctl is-active docker)" != "active" ]; then \
sleep 5; sudo systemctl start docker; sleep 5;\ sleep 5; sudo systemctl start docker; sleep 5;\
fi;\ fi;\
if ! command -v sudo > /dev/null 2>&1; then echo "Failed to install sudo, command not found"; exit 1; fi;\ if ! command -v sudo > /dev/null 2>&1; then echo "Failed to install sudo, command not found"; exit 1; fi;\
docker --version docker --version;\
uname -sr
+9
View File
@@ -94,6 +94,15 @@ public:
setValue("Conf/startMinimized", enabled); setValue("Conf/startMinimized", enabled);
} }
bool isNewsNotifications() const
{
return value("Conf/newsNotifications", true).toBool();
}
void setNewsNotifications(bool enabled)
{
setValue("Conf/newsNotifications", enabled);
}
bool isSaveLogs() const bool isSaveLogs() const
{ {
return value("Conf/saveLogs", false).toBool(); return value("Conf/saveLogs", false).toBool();
@@ -1,5 +1,11 @@
#include "connectionController.h" #include "connectionController.h"
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "utilities.h" #include "utilities.h"
#include "core/controllers/vpnConfigurationController.h" #include "core/controllers/vpnConfigurationController.h"
#include "version.h" #include "version.h"
@@ -27,7 +33,7 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
void ConnectionController::openConnection() void ConnectionController::openConnection()
{ {
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true)) if (!Utils::processIsRunning(Utils::executable(SERVICE_NAME, false), true))
{ {
emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning); emit connectionErrorOccurred(ErrorCode::AmneziaServiceNotRunning);
+3 -3
View File
@@ -19,7 +19,7 @@
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#endif #endif
@@ -602,14 +602,14 @@ bool ImportController::decodeQrCode(const QString &code)
} }
#endif #endif
#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) #if defined Q_OS_ANDROID || defined Q_OS_IOS
void ImportController::startDecodingQr() void ImportController::startDecodingQr()
{ {
m_qrCodeChunks.clear(); m_qrCodeChunks.clear();
m_totalQrCodeChunksCount = 0; m_totalQrCodeChunksCount = 0;
m_receivedQrCodeChunksCount = 0; m_receivedQrCodeChunksCount = 0;
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
m_isQrCodeProcessed = true; m_isQrCodeProcessed = true;
#endif #endif
#if defined Q_OS_ANDROID #if defined Q_OS_ANDROID
+3 -3
View File
@@ -38,7 +38,7 @@ public slots:
QString getConfigFileName(); QString getConfigFileName();
QString getMaliciousWarningText(); QString getMaliciousWarningText();
#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) #if defined Q_OS_ANDROID || defined Q_OS_IOS
void startDecodingQr(); void startDecodingQr();
bool parseQrCodeChunk(const QString &code); bool parseQrCodeChunk(const QString &code);
@@ -70,7 +70,7 @@ private:
void processAmneziaConfig(QJsonObject &config); void processAmneziaConfig(QJsonObject &config);
#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) #if defined Q_OS_ANDROID || defined Q_OS_IOS
void stopDecodingQr(); void stopDecodingQr();
#endif #endif
@@ -83,7 +83,7 @@ private:
ConfigTypes m_configType; ConfigTypes m_configType;
QString m_maliciousWarningText; QString m_maliciousWarningText;
#if defined Q_OS_ANDROID || defined Q_OS_IOS || defined(Q_OS_TVOS) #if defined Q_OS_ANDROID || defined Q_OS_IOS
QMap<int, QByteArray> m_qrCodeChunks; QMap<int, QByteArray> m_qrCodeChunks;
bool m_isQrCodeProcessed; bool m_isQrCodeProcessed;
int m_totalQrCodeChunksCount; int m_totalQrCodeChunksCount;
+1 -3
View File
@@ -2,9 +2,7 @@
#define INSTALLCONTROLLER_H #define INSTALLCONTROLLER_H
#include <QObject> #include <QObject>
#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS)
#include <QProcess> #include <QProcess>
#endif
#include "containers/containers_defs.h" #include "containers/containers_defs.h"
#include "core/defs.h" #include "core/defs.h"
@@ -113,7 +111,7 @@ private:
QString m_privateKeyPassphrase; QString m_privateKeyPassphrase;
#if !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) #ifndef Q_OS_IOS
QList<QSharedPointer<QProcess>> m_sftpMountProcesses; QList<QSharedPointer<QProcess>> m_sftpMountProcesses;
#endif #endif
}; };
+5 -6
View File
@@ -1,12 +1,11 @@
#include "pageController.h" #include "pageController.h"
#include "utils/converter.h" #include "utils/converter.h"
#include "core/errorstrings.h" #include "core/errorstrings.h"
#include <QCoreApplication>
#if defined(MACOS_NE) #if defined(MACOS_NE)
#include "platforms/ios/ios_controller.h" #include "platforms/ios/ios_controller.h"
#endif #endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(MACOS_NE)
#include <QGuiApplication> #include <QGuiApplication>
#else #else
#include <QApplication> #include <QApplication>
@@ -15,7 +14,7 @@
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
#if defined(Q_OS_MACX) && !defined(Q_OS_TVOS) #if defined Q_OS_MAC
#include "ui/macos_util.h" #include "ui/macos_util.h"
#endif #endif
@@ -28,7 +27,7 @@ PageController::PageController(const QSharedPointer<ServersModel> &serversModel,
AndroidController::instance()->setNavigationBarColor(initialPageNavigationBarColor); AndroidController::instance()->setNavigationBarColor(initialPageNavigationBarColor);
#endif #endif
#if defined(Q_OS_MACX) && !defined(Q_OS_TVOS) #if defined Q_OS_MACX
connect(this, &PageController::raiseMainWindow, []() { connect(this, &PageController::raiseMainWindow, []() {
setDockIconVisible(true); setDockIconVisible(true);
}); });
@@ -65,7 +64,7 @@ QString PageController::getPagePath(PageLoader::PageEnum page)
void PageController::closeWindow() void PageController::closeWindow()
{ {
// On mobile platforms, quit app on close; on desktop, just hide window // On mobile platforms, quit app on close; on desktop, just hide window
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
qApp->quit(); qApp->quit();
#else #else
emit hideMainWindow(); emit hideMainWindow();
@@ -119,7 +118,7 @@ void PageController::showOnStartup()
} else { } else {
#if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
emit hideMainWindow(); emit hideMainWindow();
#elif defined(Q_OS_MACX) && !defined(Q_OS_TVOS) #elif defined(Q_OS_MACX)
setDockIconVisible(false); setDockIconVisible(false);
#endif #endif
} }
+14 -7
View File
@@ -12,7 +12,7 @@
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
#include <AmneziaVPN-Swift.h> #include <AmneziaVPN-Swift.h>
#endif #endif
@@ -57,8 +57,6 @@ QString getPlatformName()
return "Windows"; return "Windows";
#elif defined(Q_OS_ANDROID) #elif defined(Q_OS_ANDROID)
return "Android"; return "Android";
#elif defined(Q_OS_TVOS)
return "tvOS";
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
return "Linux"; return "Linux";
#elif defined(Q_OS_MACX) #elif defined(Q_OS_MACX)
@@ -111,7 +109,7 @@ bool SettingsController::isLoggingEnabled()
void SettingsController::toggleLogging(bool enable) void SettingsController::toggleLogging(bool enable)
{ {
m_settings->setSaveLogs(enable); m_settings->setSaveLogs(enable);
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_IOS)
AmneziaVPN::toggleLogging(enable); AmneziaVPN::toggleLogging(enable);
#endif #endif
if (enable == true) { if (enable == true) {
@@ -195,7 +193,7 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data)
if (ok) { if (ok) {
QJsonObject newConfigData = QJsonDocument::fromJson(data).object(); QJsonObject newConfigData = QJsonDocument::fromJson(data).object();
#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || (defined(Q_OS_MACX) && !defined(Q_OS_TVOS)) #if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) || defined(Q_OS_MACX)
bool autoStart = false; bool autoStart = false;
if (newConfigData.contains("Conf/autoStart")) { if (newConfigData.contains("Conf/autoStart")) {
autoStart = newConfigData["Conf/autoStart"].toBool(); autoStart = newConfigData["Conf/autoStart"].toBool();
@@ -232,7 +230,7 @@ void SettingsController::restoreAppConfigFromData(const QByteArray &data)
m_sitesModel->setRouteMode(siteSplitTunnelingRouteMode); m_sitesModel->setRouteMode(siteSplitTunnelingRouteMode);
m_sitesModel->toggleSplitTunneling(siteSplittunnelingEnabled); m_sitesModel->toggleSplitTunneling(siteSplittunnelingEnabled);
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
m_settings->setAutoConnect(false); m_settings->setAutoConnect(false);
m_settings->setStartMinimized(false); m_settings->setStartMinimized(false);
m_settings->setKillSwitchEnabled(false); m_settings->setKillSwitchEnabled(false);
@@ -271,7 +269,7 @@ void SettingsController::clearSettings()
emit changeSettingsFinished(tr("All settings have been reset to default values")); emit changeSettingsFinished(tr("All settings have been reset to default values"));
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
AmneziaVPN::clearSettings(); AmneziaVPN::clearSettings();
#endif #endif
} }
@@ -310,6 +308,15 @@ void SettingsController::toggleStartMinimized(bool enable)
emit startMinimizedChanged(); emit startMinimizedChanged();
} }
bool SettingsController::isNewsNotificationsEnabled()
{
return m_settings->isNewsNotifications();
}
void SettingsController::toggleNewsNotificationsEnabled(bool enable)
{
m_settings->setNewsNotifications(enable);
}
bool SettingsController::isScreenshotsEnabled() bool SettingsController::isScreenshotsEnabled()
{ {
return m_settings->isScreenshotsEnabled(); return m_settings->isScreenshotsEnabled();
@@ -73,6 +73,9 @@ public slots:
bool isStartMinimizedEnabled(); bool isStartMinimizedEnabled();
void toggleStartMinimized(bool enable); void toggleStartMinimized(bool enable);
bool isNewsNotificationsEnabled();
void toggleNewsNotificationsEnabled(bool enable);
bool isScreenshotsEnabled(); bool isScreenshotsEnabled();
void toggleScreenshotsEnabled(bool enable); void toggleScreenshotsEnabled(bool enable);
+4 -4
View File
@@ -14,7 +14,7 @@
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
#include "platforms/ios/ios_controller.h" #include "platforms/ios/ios_controller.h"
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#endif #endif
@@ -31,7 +31,7 @@ void SystemController::saveFile(const QString &fileName, const QString &data)
return; return;
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #ifdef Q_OS_IOS
QUrl fileUrl = QDir::tempPath() + "/" + fileName; QUrl fileUrl = QDir::tempPath() + "/" + fileName;
QFile file(fileUrl.toString()); QFile file(fileUrl.toString());
#else #else
@@ -43,7 +43,7 @@ void SystemController::saveFile(const QString &fileName, const QString &data)
file.write(data.toUtf8()); file.write(data.toUtf8());
file.close(); file.close();
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #ifdef Q_OS_IOS
QStringList filesToSend; QStringList filesToSend;
filesToSend.append(fileUrl.toString()); filesToSend.append(fileUrl.toString());
// todo check if save successful // todo check if save successful
@@ -98,7 +98,7 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString
return AndroidController::instance()->openFile(nameFilter); return AndroidController::instance()->openFile(nameFilter);
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #ifdef Q_OS_IOS
fileName = IosController::Instance()->openFile(); fileName = IosController::Instance()->openFile();
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
+2 -2
View File
@@ -5,7 +5,7 @@
#include <QDebug> #include <QDebug>
#include "notificationhandler.h" #include "notificationhandler.h"
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_IOS)
# include "platforms/ios/iosnotificationhandler.h" # include "platforms/ios/iosnotificationhandler.h"
#else #else
# include "systemtray_notificationhandler.h" # include "systemtray_notificationhandler.h"
@@ -14,7 +14,7 @@
// static // static
NotificationHandler* NotificationHandler::create(QObject* parent) { NotificationHandler* NotificationHandler::create(QObject* parent) {
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) #if defined(Q_OS_IOS)
return new IOSNotificationHandler(parent); return new IOSNotificationHandler(parent);
#else #else
return new SystemTrayNotificationHandler(parent); return new SystemTrayNotificationHandler(parent);
+1 -1
View File
@@ -58,7 +58,7 @@ QString Autostart::appPath() {
return QCoreApplication::applicationFilePath() + " --autostart"; return QCoreApplication::applicationFilePath() + " --autostart";
} }
#elif defined(Q_OS_MACX) && !defined(Q_OS_TVOS) #elif defined Q_OS_MACX
bool Autostart::isAutostart() { bool Autostart::isAutostart() {
QProcess process; QProcess process;
+34
View File
@@ -49,6 +49,36 @@ Item {
return drawerContent.state === stateName return drawerContent.state === stateName
} }
function findComponent(obj, typeCtor) {
if (!obj)
return null
if (obj instanceof typeCtor)
return obj
if (obj.children && obj.children.length > 0) {
for (var i = 0; i < obj.children.length; i++) {
var matchingChildren = findComponent(obj.children[i], typeCtor)
if (matchingChildren) return matchingChildren
}
}
if (obj.contentItem) {
var matchingContentItem = findComponent(obj.contentItem, typeCtor)
if (matchingContentItem) return matchingContentItem
}
return null
}
function setParentInteractive(value) {
var flickableType = findComponent(root.parent, Flickable)
var listViewType = findComponent(root.parent, ListView)
if (flickableType) flickableType.interactive = value
if (listViewType) listViewType.interactive = value
}
Connections { Connections {
target: Qt.application target: Qt.application
@@ -93,6 +123,8 @@ Item {
aboutToHide() aboutToHide()
setParentInteractive(true)
closed() closed()
} }
@@ -118,6 +150,8 @@ Item {
root.aboutToShow() root.aboutToShow()
setParentInteractive(false)
root.opened() root.opened()
} }
@@ -71,6 +71,8 @@ Item {
implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin
MouseArea { MouseArea {
id: mouseArea
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
hoverEnabled: root.enabled hoverEnabled: root.enabled
@@ -296,13 +298,13 @@ Item {
} }
Keys.onEnterPressed: { Keys.onEnterPressed: {
if (clickedFunction && typeof clickedFunction === "function") { if (!rightImageSource && clickedFunction && typeof clickedFunction === "function") {
clickedFunction() clickedFunction()
} }
} }
Keys.onReturnPressed: { Keys.onReturnPressed: {
if (clickedFunction && typeof clickedFunction === "function") { if (!rightImageSource && clickedFunction && typeof clickedFunction === "function") {
clickedFunction() clickedFunction()
} }
} }
@@ -140,6 +140,16 @@ PageType {
ListElement { name : "aes-128-gcm" } ListElement { name : "aes-128-gcm" }
} }
function updateSelectedIndex() {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipher) {
selectedIndex = i
break
}
}
}
clickedFunction: function() { clickedFunction: function() {
cipherDropDown.text = selectedText cipherDropDown.text = selectedText
cipher = cipherDropDown.text cipher = cipherDropDown.text
@@ -147,13 +157,14 @@ PageType {
} }
Component.onCompleted: { Component.onCompleted: {
cipherDropDown.text = cipher updateSelectedIndex()
}
}
for (var i = 0; i < cipherListView.model.count; i++) { Connections {
if (cipherListView.model.get(i).name === cipherDropDown.text) { target: listView.model
selectedIndex = i function onDataChanged() {
} cipherListView.updateSelectedIndex()
}
} }
} }
} }
@@ -192,6 +192,16 @@ PageType {
ListElement { name : qsTr("SHA1") } ListElement { name : qsTr("SHA1") }
} }
function updateSelectedIndex() {
hashDropDown.text = hash
for (var i = 0; i < hashListView.model.count; i++) {
if (hashListView.model.get(i).name === hash) {
selectedIndex = i
break
}
}
}
clickedFunction: function() { clickedFunction: function() {
hashDropDown.text = selectedText hashDropDown.text = selectedText
hash = hashDropDown.text hash = hashDropDown.text
@@ -199,13 +209,14 @@ PageType {
} }
Component.onCompleted: { Component.onCompleted: {
hashDropDown.text = hash updateSelectedIndex()
}
}
for (var i = 0; i < hashListView.model.count; i++) { Connections {
if (hashListView.model.get(i).name === hashDropDown.text) { target: listView.model
currentIndex = i function onDataChanged() {
} hashListView.updateSelectedIndex()
}
} }
} }
} }
@@ -242,6 +253,16 @@ PageType {
ListElement { name : qsTr("none") } ListElement { name : qsTr("none") }
} }
function updateSelectedIndex() {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipher) {
selectedIndex = i
break
}
}
}
clickedFunction: function() { clickedFunction: function() {
cipherDropDown.text = selectedText cipherDropDown.text = selectedText
cipher = cipherDropDown.text cipher = cipherDropDown.text
@@ -249,13 +270,14 @@ PageType {
} }
Component.onCompleted: { Component.onCompleted: {
cipherDropDown.text = cipher updateSelectedIndex()
}
}
for (var i = 0; i < cipherListView.model.count; i++) { Connections {
if (cipherListView.model.get(i).name === cipherDropDown.text) { target: listView.model
currentIndex = i function onDataChanged() {
} cipherListView.updateSelectedIndex()
}
} }
} }
} }
@@ -109,6 +109,16 @@ PageType {
ListElement { name : "aes-128-gcm" } ListElement { name : "aes-128-gcm" }
} }
function updateSelectedIndex() {
cipherDropDown.text = cipher
for (var i = 0; i < cipherListView.model.count; i++) {
if (cipherListView.model.get(i).name === cipher) {
selectedIndex = i
break
}
}
}
clickedFunction: function() { clickedFunction: function() {
cipherDropDown.text = selectedText cipherDropDown.text = selectedText
cipher = cipherDropDown.text cipher = cipherDropDown.text
@@ -116,13 +126,14 @@ PageType {
} }
Component.onCompleted: { Component.onCompleted: {
cipherDropDown.text = cipher updateSelectedIndex()
}
}
for (var i = 0; i < cipherListView.model.count; i++) { Connections {
if (cipherListView.model.get(i).name === cipherDropDown.text) { target: listView.model
currentIndex = i function onDataChanged() {
} cipherListView.updateSelectedIndex()
}
} }
} }
} }
+1 -1
View File
@@ -148,7 +148,7 @@ PageType {
id: news id: news
property string title: qsTr("News & Notifications") property string title: qsTr("News & Notifications")
readonly property string leftImagePath: NewsModel.hasUnread ? "qrc:/images/controls/news-unread.svg" : "qrc:/images/controls/news.svg" readonly property string leftImagePath: NewsModel.hasUnread && SettingsController.isNewsNotificationsEnabled() ? "qrc:/images/controls/news-unread.svg" : "qrc:/images/controls/news.svg"
property bool isVisible: ServersModel.hasServersFromGatewayApi property bool isVisible: ServersModel.hasServersFromGatewayApi
readonly property var clickedHandler: function() { readonly property var clickedHandler: function() {
if (!ServersModel.hasServersFromGatewayApi) { if (!ServersModel.hasServersFromGatewayApi) {
@@ -168,6 +168,29 @@ PageType {
DividerType { DividerType {
visible: !GC.isMobile() visible: !GC.isMobile()
} }
SwitcherType {
id: switcherNewsNotificationEnabled
visible: ServersModel.hasServersFromGatewayApi
Layout.fillWidth: true
Layout.margins: 16
text: qsTr("News Notification")
descriptionText: qsTr("Show notification icon when has unread news")
checked: SettingsController.isNewsNotificationsEnabled()
onToggled: function() {
if (checked !== SettingsController.isNewsNotificationsEnabled()) {
SettingsController.toggleNewsNotificationsEnabled(checked)
}
}
}
DividerType {
visible: !GC.isMobile()
}
} }
footer: ColumnLayout { footer: ColumnLayout {
@@ -107,6 +107,7 @@ PageType {
onClicked: function() { onClicked: function() {
isEasySetup = true isEasySetup = true
checked = true
var defaultContainerProto = ContainerProps.defaultProtocol(dockerContainer) var defaultContainerProto = ContainerProps.defaultProtocol(dockerContainer)
listView.dockerContainer = dockerContainer listView.dockerContainer = dockerContainer
+1 -1
View File
@@ -383,7 +383,7 @@ PageType {
objectName: "settingsTabButton" objectName: "settingsTabButton"
isSelected: tabBar.currentIndex === 2 isSelected: tabBar.currentIndex === 2
image: (ServersModel.hasServersFromGatewayApi && NewsModel.hasUnread) ? "qrc:/images/controls/settings-news.svg" : "qrc:/images/controls/settings.svg" image: (ServersModel.hasServersFromGatewayApi && NewsModel.hasUnread && SettingsController.isNewsNotificationsEnabled()) ? "qrc:/images/controls/settings-news.svg" : "qrc:/images/controls/settings.svg"
Binding { Binding {
target: settingsTabButton target: settingsTabButton
property: "defaultColor" property: "defaultColor"
+2 -2
View File
@@ -190,7 +190,7 @@ bool Utils::processIsRunning(const QString &fileName, const bool fullFlag)
CloseHandle(hSnapshot); CloseHandle(hSnapshot);
return false; return false;
#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(Q_OS_ANDROID) || defined(MACOS_NE) #elif defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || defined(MACOS_NE)
return false; return false;
#else #else
QProcess process; QProcess process;
@@ -250,7 +250,7 @@ bool Utils::killProcessByName(const QString &name)
CloseHandle(hSnapshot); CloseHandle(hSnapshot);
return success; return success;
#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(Q_OS_ANDROID) #elif defined Q_OS_IOS || defined(Q_OS_ANDROID)
return false; return false;
#else #else
return QProcess::execute("pkill", { name }) == 0; return QProcess::execute("pkill", { name }) == 0;
+7 -7
View File
@@ -27,7 +27,7 @@
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
#include "platforms/ios/ios_controller.h" #include "platforms/ios/ios_controller.h"
#endif #endif
@@ -37,7 +37,7 @@
VpnConnection::VpnConnection(std::shared_ptr<Settings> settings, QObject *parent) VpnConnection::VpnConnection(std::shared_ptr<Settings> settings, QObject *parent)
: QObject(parent), m_settings(settings), m_checkTimer(new QTimer(this)) : QObject(parent), m_settings(settings), m_checkTimer(new QTimer(this))
{ {
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
m_checkTimer.setInterval(1000); m_checkTimer.setInterval(1000);
connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged); connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged);
connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged); connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged);
@@ -131,7 +131,7 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
}); });
#endif #endif
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
if (state == Vpn::ConnectionState::Connected || if (state == Vpn::ConnectionState::Connected ||
state == Vpn::ConnectionState::Connecting || state == Vpn::ConnectionState::Connecting ||
state == Vpn::ConnectionState::Reconnecting) { state == Vpn::ConnectionState::Reconnecting) {
@@ -290,7 +290,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
appendSplitTunnelingConfig(); appendSplitTunnelingConfig();
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(Q_OS_TVOS) && !defined(MACOS_NE) #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration)); m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
if (!m_vpnProtocol) { if (!m_vpnProtocol) {
emit connectionStateChanged(Vpn::ConnectionState::Error); emit connectionStateChanged(Vpn::ConnectionState::Error);
@@ -302,7 +302,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
createAndroidConnections(); createAndroidConnections();
m_vpnProtocol.reset(androidVpnProtocol); m_vpnProtocol.reset(androidVpnProtocol);
#elif defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #elif defined Q_OS_IOS || defined(MACOS_NE)
Proto proto = ContainerProps::defaultProtocol(container); Proto proto = ContainerProps::defaultProtocol(container);
IosController::Instance()->connectVpn(proto, m_vpnConfiguration); IosController::Instance()->connectVpn(proto, m_vpnConfiguration);
connect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus); connect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus);
@@ -499,7 +499,7 @@ bool VpnConnection::startNetworkCheckIfReady()
return IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) { return IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
QRemoteObjectPendingReply<bool> reply = iface->startNetworkCheck(gateway, localAddress); QRemoteObjectPendingReply<bool> reply = iface->startNetworkCheck(gateway, localAddress);
return reply.waitForFinished() && reply.returnValue(); return reply.waitForFinished(1000) && reply.returnValue();
}); });
#else #else
return false; return false;
@@ -539,7 +539,7 @@ QString VpnConnection::bytesPerSecToText(quint64 bytes)
void VpnConnection::disconnectFromVpn() void VpnConnection::disconnectFromVpn()
{ {
#if defined(Q_OS_IOS) || defined(Q_OS_TVOS) || defined(MACOS_NE) #if defined(Q_OS_IOS) || defined(MACOS_NE)
// iOS/macOS NE use IosController directly; m_vpnProtocol is not set there. // iOS/macOS NE use IosController directly; m_vpnProtocol is not set there.
IosController::Instance()->disconnectVpn(); IosController::Instance()->disconnectVpn();
disconnect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus); disconnect(&m_checkTimer, &QTimer::timeout, IosController::Instance(), &IosController::checkStatus);
+2
View File
@@ -10,6 +10,8 @@
</array> </array>
<key>KeepAlive</key> <key>KeepAlive</key>
<true/> <true/>
<key>RunAtLoad</key>
<true/>
<key>Sockets</key> <key>Sockets</key>
<dict> <dict>
<key>Listeners</key> <key>Listeners</key>
+38 -26
View File
@@ -7,42 +7,54 @@ LOG_FOLDER=/var/log/$APP_NAME
LOG_FILE="$LOG_FOLDER/post-install.log" LOG_FILE="$LOG_FOLDER/post-install.log"
APP_PATH=/Applications/$APP_NAME.app APP_PATH=/Applications/$APP_NAME.app
rm -rf "$LOG_FOLDER"
mkdir -p "$LOG_FOLDER"
echo "`date` Script started" > "$LOG_FILE"
log() {
echo "`date` $*" >> "$LOG_FILE"
}
run_cmd() {
log "CMD: $*"
"$@" >> "$LOG_FILE" 2>&1
local ec=$?
log "EXIT: $ec"
return $ec
}
# Handle new installations unpacked into localized folder # Handle new installations unpacked into localized folder
if [ -d "/Applications/${APP_NAME}.localized" ]; then if [ -d "/Applications/${APP_NAME}.localized" ]; then
echo "`date` Detected ${APP_NAME}.localized, migrating to standard path" >> $LOG_FILE log "Detected ${APP_NAME}.localized, migrating to standard path"
sudo rm -rf "$APP_PATH" run_cmd sudo rm -rf "$APP_PATH"
sudo mv "/Applications/${APP_NAME}.localized/${APP_NAME}.app" "$APP_PATH" run_cmd sudo mv "/Applications/${APP_NAME}.localized/${APP_NAME}.app" "$APP_PATH"
sudo rm -rf "/Applications/${APP_NAME}.localized" run_cmd sudo rm -rf "/Applications/${APP_NAME}.localized"
fi fi
if launchctl list "$APP_NAME-service" &> /dev/null; then run_cmd launchctl bootout system "$LAUNCH_DAEMONS_PLIST_NAME" || run_cmd launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME"
launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME" run_cmd rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
fi
sudo chmod -R a-w "$APP_PATH/" run_cmd sudo chmod -R a-w "$APP_PATH/"
sudo chown -R root "$APP_PATH/" run_cmd sudo chown -R root "$APP_PATH/"
sudo chgrp -R wheel "$APP_PATH/" run_cmd sudo chgrp -R wheel "$APP_PATH/"
rm -rf $LOG_FOLDER log "Requesting ${APP_NAME} to quit gracefully"
mkdir -p $LOG_FOLDER run_cmd osascript -e 'tell application "AmneziaVPN" to quit' || true
echo "`date` Script started" > $LOG_FILE
echo "Requesting ${APP_NAME} to quit gracefully" >> "$LOG_FILE"
osascript -e 'tell application "AmneziaVPN" to quit'
PLIST_SOURCE="$APP_PATH/Contents/Resources/$PLIST_NAME" PLIST_SOURCE="$APP_PATH/Contents/Resources/$PLIST_NAME"
if [ -f "$PLIST_SOURCE" ]; then if [ -f "$PLIST_SOURCE" ]; then
mv -f "$PLIST_SOURCE" "$LAUNCH_DAEMONS_PLIST_NAME" 2>> $LOG_FILE run_cmd mv -f "$PLIST_SOURCE" "$LAUNCH_DAEMONS_PLIST_NAME"
else else
echo "`date` ERROR: service plist not found at $PLIST_SOURCE" >> $LOG_FILE log "ERROR: service plist not found at $PLIST_SOURCE"
fi fi
chown root:wheel "$LAUNCH_DAEMONS_PLIST_NAME" run_cmd chown root:wheel "$LAUNCH_DAEMONS_PLIST_NAME"
launchctl load "$LAUNCH_DAEMONS_PLIST_NAME" run_cmd chmod 644 "$LAUNCH_DAEMONS_PLIST_NAME"
echo "`date` Launching ${APP_NAME} application" >> $LOG_FILE run_cmd launchctl bootstrap system "$LAUNCH_DAEMONS_PLIST_NAME" || run_cmd launchctl load "$LAUNCH_DAEMONS_PLIST_NAME"
open -a "$APP_PATH" 2>> $LOG_FILE || true run_cmd launchctl enable "system/$APP_NAME-service" || true
run_cmd launchctl kickstart -k "system/$APP_NAME-service" || true
run_cmd launchctl print "system/$APP_NAME-service" || true
log "Launching ${APP_NAME} application"
run_cmd open -a "$APP_PATH" || true
echo "`date` Service status: $?" >> $LOG_FILE log "Script finished"
echo "`date` Script finished" >> $LOG_FILE
+1 -1
View File
@@ -29,7 +29,7 @@ fi
# Unload the service if loaded and remove its plist file regardless # Unload the service if loaded and remove its plist file regardless
if launchctl list "${APP_NAME}-service" &> /dev/null; then if launchctl list "${APP_NAME}-service" &> /dev/null; then
sudo launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME" sudo launchctl bootout system "$LAUNCH_DAEMONS_PLIST_NAME" || sudo launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME"
fi fi
sudo rm -f "$LAUNCH_DAEMONS_PLIST_NAME" sudo rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
+28 -15
View File
@@ -1,9 +1,9 @@
#!/bin/sh #!/bin/bash
set -e set -e
VERSION=$1 VERSION=$1
if [[ $VERSION = '' ]]; then if [[ -z "$VERSION" ]]; then
echo '::error::VERSION does not set. Exiting with error...' echo '::error::VERSION does not set. Exiting with error...'
exit 1 exit 1
fi fi
@@ -20,19 +20,32 @@ if [[ $(cat CHANGELOG) = null ]]; then
exit 1 exit 1
fi fi
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_arm64-v8a.apk # Download files with error handling
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_armeabi-v7a.apk download_file() {
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_x86.apk local url=$1
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android8+_x86_64.apk local filename=$(basename "$url")
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_arm64-v8a.apk echo "Downloading $filename..."
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_armeabi-v7a.apk if ! wget -q "$url"; then
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_x86.apk echo "::error::Failed to download $filename from $url"
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android_7_x86_64.apk exit 8
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_linux_x64.tar.zip fi
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_macos.dmg echo "Successfully downloaded $filename"
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_macos_old.dmg }
wget -q https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_windows_x64.exe
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android9+_arm64-v8a.apk
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android9+_armeabi-v7a.apk
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android9+_x86.apk
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_android9+_x86_64.apk
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_linux_x64.tar
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_macos.pkg
download_file https://github.com/amnezia-vpn/amnezia-client/releases/download/${VERSION}/AmneziaVPN_${VERSION}_x64.exe
cd ../ cd ../
rclone sync ./dist/ r2:/updates/ echo "Syncing to R2..."
if ! rclone sync ./dist/ r2:/updates/; then
echo "::error::Failed to sync files to R2"
exit 8
fi
echo "Deployment completed successfully!"
+2 -2
View File
@@ -38,8 +38,8 @@ class IpcInterface
SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) ); SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) );
SLOT( bool restoreResolvers() ); SLOT( bool restoreResolvers() );
SLOT(void xrayStart(const QString &config)); SLOT(bool xrayStart(const QString &config));
SLOT(void xrayStop()); SLOT(bool xrayStop());
SLOT( bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) ); SLOT( bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) );
SLOT( bool stopNetworkCheck() ); SLOT( bool stopNetworkCheck() );
+2 -2
View File
@@ -304,7 +304,7 @@ bool IpcServer::refreshKillSwitch(bool enabled)
return KillSwitch::instance()->refresh(enabled); return KillSwitch::instance()->refresh(enabled);
} }
void IpcServer::xrayStart(const QString& cfg) bool IpcServer::xrayStart(const QString& cfg)
{ {
#ifdef MZ_DEBUG #ifdef MZ_DEBUG
qDebug() << "IpcServer::xrayStart"; qDebug() << "IpcServer::xrayStart";
@@ -313,7 +313,7 @@ void IpcServer::xrayStart(const QString& cfg)
return Xray::getInstance().startXray(cfg); return Xray::getInstance().startXray(cfg);
} }
void IpcServer::xrayStop() bool IpcServer::xrayStop()
{ {
#ifdef MZ_DEBUG #ifdef MZ_DEBUG
qDebug() << "IpcServer::xrayStop"; qDebug() << "IpcServer::xrayStop";
+2 -2
View File
@@ -44,8 +44,8 @@ public:
virtual bool refreshKillSwitch( bool enabled ) override; virtual bool refreshKillSwitch( bool enabled ) override;
virtual bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) override; virtual bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) override;
virtual bool restoreResolvers() override; virtual bool restoreResolvers() override;
virtual void xrayStart(const QString& cfg) override; virtual bool xrayStart(const QString& cfg) override;
virtual void xrayStop() override; virtual bool xrayStop() override;
virtual bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) override; virtual bool startNetworkCheck(const QString& serverIpv4Gateway, const QString& deviceIpv4Address) override;
virtual bool stopNetworkCheck() override; virtual bool stopNetworkCheck() override;
+1 -5
View File
@@ -29,9 +29,7 @@ void IpcProcessTun2Socks::start()
QString XrayConStr = "socks5://127.0.0.1:10808"; QString XrayConStr = "socks5://127.0.0.1:10808";
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QStringList arguments({"-device", "tun://tun2?guid={081A8A84-8D12-4DF5-B8C4-396D5B0053E4}", "-proxy", XrayConStr, "-tun-post-up", QStringList arguments({"-device", "tun://tun2?guid={081A8A84-8D12-4DF5-B8C4-396D5B0053E4}", "-proxy", XrayConStr });
QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255")
.arg(amnezia::protocols::xray::defaultLocalAddr)});
#endif #endif
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr}); QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr});
@@ -47,8 +45,6 @@ void IpcProcessTun2Socks::start()
Utils::killProcessByName(Utils::executable("tun2socks", false)); Utils::killProcessByName(Utils::executable("tun2socks", false));
} }
m_t2sProcess->start();
connect(m_t2sProcess.data(), &QProcess::readyReadStandardOutput, this, [this]() { connect(m_t2sProcess.data(), &QProcess::readyReadStandardOutput, this, [this]() {
QString line = m_t2sProcess.data()->readAllStandardOutput(); QString line = m_t2sProcess.data()->readAllStandardOutput();
if (line.contains("[STACK] tun://") && line.contains("<-> socks5://127.0.0.1")) { if (line.contains("[STACK] tun://") && line.contains("<-> socks5://127.0.0.1")) {
+2 -2
View File
@@ -6,7 +6,7 @@ project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION})
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS DBus Core Network Widgets RemoteObjects Core5Compat) find_package(Qt6 REQUIRED COMPONENTS DBus Core Network Widgets RemoteObjects Core5Compat Concurrent)
qt_standard_project_setup() qt_standard_project_setup()
@@ -353,7 +353,7 @@ include_directories(
add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES}) add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES})
target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus ${LIBS}) target_link_libraries(${PROJECT} PRIVATE Qt6::Core Qt6::Widgets Qt6::Network Qt6::RemoteObjects Qt6::Core5Compat Qt6::DBus Qt6::Concurrent ${LIBS})
target_compile_definitions(${PROJECT} PRIVATE "MZ_$<UPPER_CASE:${MZ_PLATFORM_NAME}>") target_compile_definitions(${PROJECT} PRIVATE "MZ_$<UPPER_CASE:${MZ_PLATFORM_NAME}>")
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+3
View File
@@ -66,6 +66,9 @@ void Router::resetIpStack()
bool Router::createTun(const QString &dev, const QString &subnet) bool Router::createTun(const QString &dev, const QString &subnet)
{ {
#ifdef Q_OS_WIN
return RouterWin::Instance().createTun(dev, subnet);
#endif
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
return RouterLinux::Instance().createTun(dev, subnet); return RouterLinux::Instance().createTun(dev, subnet);
#endif #endif
+53 -8
View File
@@ -5,6 +5,7 @@
#include <tchar.h> #include <tchar.h>
#include <QProcess> #include <QProcess>
#include <QtConcurrent>
#include <core/networkUtilities.h> #include <core/networkUtilities.h>
@@ -308,6 +309,37 @@ void RouterWin::resetIpStack()
} }
} }
bool RouterWin::createTun(const QString &dev, const QString &subnet)
{
NET_LUID luid;
DWORD res = ConvertInterfaceAliasToLuid(reinterpret_cast<const wchar_t*>(dev.utf16()), &luid);
if (res != NO_ERROR) {
qCritical() << "Failed to convert luid: " << res;
return false;
}
MIB_UNICASTIPADDRESS_ROW row;
InitializeUnicastIpAddressEntry(&row);
row.InterfaceLuid = luid;
row.Address.si_family = AF_INET;
inet_pton(AF_INET, subnet.toStdString().c_str(), &row.Address.Ipv4.sin_addr);
row.OnLinkPrefixLength = 32;
row.ValidLifetime = 0xffffffff;
row.PreferredLifetime = 0xffffffff;
row.DadState = IpDadStatePreferred;
res = CreateUnicastIpAddressEntry(&row);
if (res != NO_ERROR && res != ERROR_OBJECT_ALREADY_EXISTS) {
qDebug() << "Failed to create IP address:" << res;
return false;
}
return true;
}
void RouterWin::suspendWcmSvc(bool suspend) void RouterWin::suspendWcmSvc(bool suspend)
{ {
if (suspend == m_suspended) return; if (suspend == m_suspended) return;
@@ -465,11 +497,19 @@ bool RouterWin::StopRoutingIpv6()
qDebug() << "RouterWin::StopRoutingIpv6"; qDebug() << "RouterWin::StopRoutingIpv6";
if (auto loopback = findLoopbackIface(); loopback.isValid()) { if (auto loopback = findLoopbackIface(); loopback.isValid()) {
for (auto subnet : kIpv6Subnets) { QFuture<bool> res = QtConcurrent::mappedReduced(kIpv6Subnets, [loopback](const QString &subnet) -> bool {
QProcess{}.execute("netsh", { "interface", "ipv6", "add", "route", subnet, QString("interface=%1").arg(loopback.index()), "metric=0", "store=active" }); int res = QProcess::execute("netsh", { "interface", "ipv6", "add", "route", subnet, QString("interface=%1").arg(loopback.index()), "metric=0", "store=active" });
return res == 0;
},
[](bool &result, bool success) {
result = result && success;
}, true);
res.waitForFinished();
return res.result();
} }
}
return true; return false;
} }
bool RouterWin::StartRoutingIpv6() bool RouterWin::StartRoutingIpv6()
@@ -477,9 +517,14 @@ bool RouterWin::StartRoutingIpv6()
qDebug() << "RouterWin::StartRoutingIpv6"; qDebug() << "RouterWin::StartRoutingIpv6";
if (auto loopback = findLoopbackIface(); loopback.isValid()) { if (auto loopback = findLoopbackIface(); loopback.isValid()) {
for (auto subnet : kIpv6Subnets) { QFuture<bool> res = QtConcurrent::mappedReduced(kIpv6Subnets, [loopback](const QString &subnet) -> bool {
QProcess{}.execute("netsh", { "interface", "ipv6", "delete", "route", subnet, QString("interface=%1").arg(loopback.index()) }); int res = QProcess::execute("netsh", { "interface", "ipv6", "delete", "route", subnet, QString("interface=%1").arg(loopback.index()) });
return res == 0;
},
[](bool &result, bool success) {
result = result && success;
}, true);
} }
}
return true; return false;
} }
+1
View File
@@ -45,6 +45,7 @@ public:
bool StartRoutingIpv6(); bool StartRoutingIpv6();
bool StopRoutingIpv6(); bool StopRoutingIpv6();
bool createTun(const QString &dev, const QString &subnet);
void suspendWcmSvc(bool suspend); void suspendWcmSvc(bool suspend);
bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers); bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers);
bool restoreResolvers(); bool restoreResolvers();
+22 -18
View File
@@ -27,7 +27,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
void Xray::startXray(const QString &cfg) bool Xray::startXray(const QString &cfg)
{ {
qDebug() << "Xray::startXray()"; qDebug() << "Xray::startXray()";
@@ -40,34 +40,38 @@ void Xray::startXray(const QString &cfg)
if (auto err = amnezia_xray_setsockcallback(ctxSockCallback, this); err != nullptr) { if (auto err = amnezia_xray_setsockcallback(ctxSockCallback, this); err != nullptr) {
qDebug() << "[xray] sockopt failed: " << err; qDebug() << "[xray] sockopt failed: " << err;
free(err); amnezia_xray_free(err);
return; return false;
}
QByteArray bytes = cfg.toUtf8();
if (auto err = amnezia_xray_configure(bytes.data()); err != nullptr) {
qDebug() << "[xray] configuration failed: " << err;
free(err);
return;
} }
amnezia_xray_setloghandler(ctxLogHandler, this); amnezia_xray_setloghandler(ctxLogHandler, this);
if (auto err = amnezia_xray_start(); err != nullptr) { QByteArray bytes = cfg.toUtf8();
qDebug() << "[xray] failed to start: " << err; if (auto err = amnezia_xray_configure(bytes.data()); err != nullptr) {
free(err); qDebug() << "[xray] configuration failed: " << err;
return; amnezia_xray_free(err);
} return false;
} }
void Xray::stopXray() if (auto err = amnezia_xray_start(); err != nullptr) {
qDebug() << "[xray] failed to start: " << err;
amnezia_xray_free(err);
return false;
}
return true;
}
bool Xray::stopXray()
{ {
qDebug() << "Xray::stopXray()"; qDebug() << "Xray::stopXray()";
if (auto err = amnezia_xray_stop(); err != nullptr) { if (auto err = amnezia_xray_stop(); err != nullptr) {
qDebug() << "[xray] failed to stop: " << err; qDebug() << "[xray] failed to stop: " << err;
free(err); amnezia_xray_free(err);
return; return false;
} }
return true;
} }
void Xray::logHandler(char* str) void Xray::logHandler(char* str)
+2 -2
View File
@@ -12,8 +12,8 @@ public:
return instance; return instance;
} }
void startXray(const QString& cfg); bool startXray(const QString& cfg);
void stopXray(); bool stopXray();
private: private:
static void ctxSockCallback(uintptr_t fd, void* ctx) { static void ctxSockCallback(uintptr_t fd, void* ctx) {