[WIP] Added wireguard, prepare to test and debug

This commit is contained in:
Alex Kh 2021-11-30 16:56:24 +04:00
parent e644575bc5
commit 7c7f77adc6
98 changed files with 4410 additions and 302 deletions

24
.gitignore vendored
View file

@ -24,6 +24,29 @@ ui_*.h
Makefile*
*build-*
# Qt-es
client/.xcode/
client/.qmake.cache
client/.qmake.stash
client/*.pro.user
client/*.pro.user.*
client/*.qbs.user
client/*.qbs.user.*
client/*.moc
client/moc_*.cpp
client/qrc_*.cpp
client/ui_*.h
client/ui_*.cpp
client/Makefile*
client/*build-*
client/AmneziaVPN.xcodeproj
client/Debug-iphonesimulator
client/amneziavpn_plugin_import.cpp
client/amneziavpn_qml_plugin_import.cpp
client/qmlcache_loader.cpp
client/rep_ipc_interface_replica.h
client/resources_qmlcache.qrc
# QtCreator
*.autosave
@ -37,6 +60,7 @@ CMakeLists.txt.user*
# MACOS files
.DS_Store
client/.DS_Store
._.DS_Store
._*
*.dmg

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use

View file

@ -58,9 +58,15 @@ ios: {
}
}
CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
INCLUDEPATH += $$PWD/ios/simulator
HEADERS += $$PWD/ios/simulator/botan_all.h
SOURCES += $$PWD/ios/simulator/botan_all.cpp
}
CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
INCLUDEPATH += $$PWD/ios/iphone
HEADERS += $$PWD/ios/iphone/botan_all.h
SOURCES += $$PWD/ios/iphone/botan_all.cpp
}
# CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
# INCLUDEPATH += $$PWD/ios/simulator
# HEADERS += $$PWD/ios/simulator/botan_all.h
# SOURCES += $$PWD/ios/simulator/botan_all.cpp
# }
}

247
client/AmneziaVPN-Swift.h Normal file
View file

@ -0,0 +1,247 @@
#ifndef AmneziaVPN_Swift_h
#define AmneziaVPN_Swift_h
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif
#if __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif
#pragma clang diagnostic ignored "-Wauto-import"
#include <Foundation/Foundation.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if __has_include(<uchar.h>)
# include <uchar.h>
# elif !defined(__cplusplus)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#endif
#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
# define SWIFT_CLASS_PROPERTY(...)
# endif
#endif
#if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#endif
#if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#endif
#if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#endif
#if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
#else
# define SWIFT_RELEASES_ARGUMENT
#endif
#if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define SWIFT_WARN_UNUSED_RESULT
#endif
#if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
#else
# define SWIFT_NORETURN
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_RESILIENT_CLASS)
# if __has_attribute(objc_class_stub)
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
# else
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif
#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif
#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
# define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# if __has_feature(generalized_swift_name)
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# else
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if !defined(SWIFT_UNAVAILABLE_MSG)
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
#endif
#if !defined(SWIFT_AVAILABILITY)
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
#endif
#if !defined(SWIFT_WEAK_IMPORT)
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#endif
#if !defined(SWIFT_DEPRECATED)
# define SWIFT_DEPRECATED __attribute__((deprecated))
#endif
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
#else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
#endif
#if !defined(IBSegueAction)
# define IBSegueAction
#endif
#if __has_feature(modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
@import Foundation;
@import ObjectiveC;
#endif
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
#if __has_warning("-Wpragma-clang-attribute")
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wnullability"
#if __has_attribute(external_source_symbol)
# pragma push_macro("any")
# undef any
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="AmneziaVPN",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
# pragma pop_macro("any")
#endif
@class NSString;
@class NSData;
enum ConnectionState : NSInteger;
@class NSDate;
@class NSNumber;
@class VPNIPAddressRange;
SWIFT_CLASS("_TtC10AmneziaVPN18IOSVpnProtocolImpl")
@interface IOSVpnProtocolImpl : NSObject
- (nonnull instancetype)initWithBundleID:(NSString * _Nonnull)bundleID privateKey:(NSData * _Nonnull)privateKey deviceIpv4Address:(NSString * _Nonnull)deviceIpv4Address deviceIpv6Address:(NSString * _Nonnull)deviceIpv6Address closure:(void (^ _Nonnull)(enum ConnectionState, NSDate * _Nullable))closure callback:(void (^ _Nonnull)(BOOL))callback OBJC_DESIGNATED_INITIALIZER;
- (void)connectWithDnsServer:(NSString * _Nonnull)dnsServer serverIpv6Gateway:(NSString * _Nonnull)serverIpv6Gateway serverPublicKey:(NSString * _Nonnull)serverPublicKey serverIpv4AddrIn:(NSString * _Nonnull)serverIpv4AddrIn serverPort:(NSInteger)serverPort allowedIPAddressRanges:(NSArray<VPNIPAddressRange *> * _Nonnull)allowedIPAddressRanges ipv6Enabled:(Boolean)enabled reason:(NSInteger)reason failureCallback:(void (^ _Nonnull)(void))failureCallback;
- (void)disconnect;
- (void)checkStatusWithCallback:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull, NSString * _Nonnull))callback;
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end
typedef SWIFT_ENUM(NSInteger, ConnectionState, closed) {
ConnectionStateError = 0,
ConnectionStateConnected = 1,
ConnectionStateDisconnected = 2,
};
SWIFT_CLASS("_TtC10AmneziaVPN17VPNIPAddressRange")
@interface VPNIPAddressRange : NSObject
- (nonnull instancetype)initWithAddress:(NSString * _Nonnull)address networkPrefixLength:(uint8_t)networkPrefixLength isIpv6:(BOOL)isIpv6 OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end
#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop
#endif /* AmneziaVPN_Swift_h */

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.security.application-groups</key>
<array/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

View file

@ -0,0 +1 @@
APPL????

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Info.plist</key>
<data>
Vpf+GoPF6i8Z3silvQ81FJOPi2k=
</data>
<key>embedded.mobileprovision</key>
<data>
XsqCdj+fjmJRIQlbMFY/hQ8MMvA=
</data>
</dict>
<key>files2</key>
<dict>
<key>embedded.mobileprovision</key>
<dict>
<key>hash2</key>
<data>
MIAxFA1iZa5ZIg95xlnuoq1pWj1eqsV143zU3y/fs/w=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Default-568h@2x.png</key>
<data>
poDYGy1JWXBgPH3/wCEBNbVTOks=
</data>
<key>Info.plist</key>
<data>
TCqIXlhIQW7A69Ve4j1KetGfmt4=
</data>
<key>LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>
<data>
QDw1rEcub/rLRhQ/kjizyHomgLM=
</data>
<key>LaunchScreen.storyboardc/Info.plist</key>
<data>
n2t8gsDpfE6XkhG31p7IQJRxTxU=
</data>
<key>LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>
<data>
U0x8EM0781fCPb62BbZIXKeDlZ4=
</data>
<key>PkgInfo</key>
<data>
n57qDP4tZfLD1rCS43W0B4LQjzE=
</data>
<key>PlugIns/WireGuardNetworkExtension.appex/Info.plist</key>
<data>
Vpf+GoPF6i8Z3silvQ81FJOPi2k=
</data>
<key>PlugIns/WireGuardNetworkExtension.appex/WireGuardNetworkExtension</key>
<data>
lXak+Jrx39GLG9y+yV7abfizjj0=
</data>
<key>PlugIns/WireGuardNetworkExtension.appex/_CodeSignature/CodeResources</key>
<data>
ghJ0YXx7j96o3qv/XzbZ1TssY4s=
</data>
<key>PlugIns/WireGuardNetworkExtension.appex/embedded.mobileprovision</key>
<data>
XsqCdj+fjmJRIQlbMFY/hQ8MMvA=
</data>
<key>embedded.mobileprovision</key>
<data>
CN/zNwvfKR8n8CTJE8vTbS8nhJY=
</data>
</dict>
<key>files2</key>
<dict>
<key>Default-568h@2x.png</key>
<dict>
<key>hash2</key>
<data>
UdHegDh1HZlDpSEYtzMl4sjA9q8uvK4K9OL0sRTFD6M=
</data>
</dict>
<key>LaunchScreen.storyboardc/01J-lp-oVM-view-Ze5-6b-2t3.nib</key>
<dict>
<key>hash2</key>
<data>
dHm6NLKlFVMgSTmcNjdaMKOOuFZ5X4PUOOFDTUOOV1I=
</data>
</dict>
<key>LaunchScreen.storyboardc/Info.plist</key>
<dict>
<key>hash2</key>
<data>
HyVdXMU7Ux4/KalAao30mpWOK/lEPT4gvYN09wf31cg=
</data>
</dict>
<key>LaunchScreen.storyboardc/UIViewController-01J-lp-oVM.nib</key>
<dict>
<key>hash2</key>
<data>
cWq7q+iQcmpSoaFGecnyPdKFEPFwRD3slgUmxFADkVs=
</data>
</dict>
<key>PlugIns/WireGuardNetworkExtension.appex/Info.plist</key>
<dict>
<key>hash2</key>
<data>
zGanBzJi5ruG2C96kDY8yR9v246oh2ZT26KMjE3t2Gs=
</data>
</dict>
<key>PlugIns/WireGuardNetworkExtension.appex/WireGuardNetworkExtension</key>
<dict>
<key>hash2</key>
<data>
RrENvr9JToqfolIOWfhiXxXt3JyQZ9A7vr2MxwspB/g=
</data>
</dict>
<key>PlugIns/WireGuardNetworkExtension.appex/_CodeSignature/CodeResources</key>
<dict>
<key>hash2</key>
<data>
0oir90Tb6hylweTKthB0OaNQrpXqvEdSW72QdH0u48w=
</data>
</dict>
<key>PlugIns/WireGuardNetworkExtension.appex/embedded.mobileprovision</key>
<dict>
<key>hash2</key>
<data>
MIAxFA1iZa5ZIg95xlnuoq1pWj1eqsV143zU3y/fs/w=
</data>
</dict>
<key>embedded.mobileprovision</key>
<dict>
<key>hash2</key>
<data>
phvsugRYPb6ozM0Feuw5oIla/PgY84jsyntA+R4HqGU=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Info.plist</key>
<data>
Vpf+GoPF6i8Z3silvQ81FJOPi2k=
</data>
<key>embedded.mobileprovision</key>
<data>
XsqCdj+fjmJRIQlbMFY/hQ8MMvA=
</data>
</dict>
<key>files2</key>
<dict>
<key>embedded.mobileprovision</key>
<dict>
<key>hash2</key>
<data>
MIAxFA1iZa5ZIg95xlnuoq1pWj1eqsV143zU3y/fs/w=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

Binary file not shown.

39
client/Info.plist Normal file
View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${QMAKE_SHORT_VERSION}</string>
<key>CFBundleSignature</key>
<string>${QMAKE_PKGINFO_TYPEINFO}</string>
<key>CFBundleVersion</key>
<string>${QMAKE_FULL_VERSION}</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>${IPHONEOS_DEPLOYMENT_TARGET}</string>
<key>NOTE</key>
<string>This file was generated by Qt/QMake.</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View file

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "wireguard-go-version.h"
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
#include <stdbool.h>
#include <stdint.h>
#define WG_KEY_LEN (32)
#define WG_KEY_LEN_BASE64 (45)
#define WG_KEY_LEN_HEX (65)
void key_to_base64(char base64[WG_KEY_LEN_BASE64],
const uint8_t key[WG_KEY_LEN]);
bool key_from_base64(uint8_t key[WG_KEY_LEN], const char* base64);
void key_to_hex(char hex[WG_KEY_LEN_HEX], const uint8_t key[WG_KEY_LEN]);
bool key_from_hex(uint8_t key[WG_KEY_LEN], const char* hex);
bool key_eq(const uint8_t key1[WG_KEY_LEN], const uint8_t key2[WG_KEY_LEN]);
void write_msg_to_log(const char* tag, const char* msg);
#import "TargetConditionals.h"
#if TARGET_OS_OSX
# include <libproc.h>
#endif

View file

@ -260,29 +260,20 @@ ios {
DEFINES += MVPN_IOS
SOURCES += \
# platforms/macos/macospingsender.cpp
OBJECTIVE_SOURCES += \
# platforms/ios/iosiaphandler.mm \
# platforms/ios/iosauthenticationlistener.mm \
# platforms/ios/ioscontroller.mm \
# platforms/ios/iosdatamigration.mm \
platforms/ios/iosglue.mm \
# platforms/ios/iosnotificationhandler.mm \
# platforms/ios/iosutils.mm \
# platforms/macos/macoscryptosettings.mm
HEADERS += \
# platforms/macos/macospingsender.h
protocols/ios_vpnprotocol.h \
platforms/ios/json.h \
platforms/ios/bigint.h \
platforms/ios/bigintipv6addr.h \
platforms/ios/ipaddress.h \
platforms/ios/ipaddressrange.h
OBJECTIVE_HEADERS += \
# platforms/ios/iosiaphandler.h \
# platforms/ios/iosauthenticationlistener.h \
# platforms/ios/ioscontroller.h \
# platforms/ios/iosdatamigration.h \
# platforms/ios/iosnotificationhandler.h \
# platforms/ios/iosutils.h
SOURCES += \
protocols/ios_vpnprotocol.mm \
platforms/ios/json.cpp \
platforms/ios/iosglue.mm \
platforms/ios/ipaddress.cpp \
platforms/ios/ipaddressrange.cpp
Q_ENABLE_BITCODE.value = NO
Q_ENABLE_BITCODE.name = ENABLE_BITCODE
@ -314,18 +305,28 @@ ios {
}
}
CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
message("Building for iPhone Simulator")
ARCH_TAG = "ios_x86_64"
CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
message("Building for iPhone Simulator")
ARCH_TAG = "ios_x86_64"
DEFINES += iphonesimulator
DEFINES += iphoneos
LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libcrypto.a
LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libssl.a
}
LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libcrypto.a
LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libssl.a
}
# CONFIG(iphonesimulator, iphoneos|iphonesimulator) {
# message("Building for iPhone Simulator")
# ARCH_TAG = "ios_x86_64"
#
# DEFINES += iphonesimulator
#
# LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libcrypto.a
# LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libssl.a
# }
NETWORKEXTENSION=1
! build_pass: system(ruby $$PWD/ios/xcode_patcher.rb "$$PWD" "$$OUT_PWD/AmneziaVPN.xcodeproj" "2.0" "2.0.0" "ios" "$$NETWORKEXTENSION"|| echo "Failed to merge xcode with wireguard")
# ! build_pass: system(ruby $$PWD/scripts/xcode_patcher.rb "$$PWD" "$$OUT_PWD/AmneziaVPN.xcodeproj" "2.0" "2.0.0" "ios" "$$NETWORKEXTENSION"|| echo "Failed to merge xcode with wireguard")

View file

@ -18,22 +18,22 @@ Settings &VpnConfigurator::m_settings()
}
QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials,
DockerContainer container, const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode)
DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode)
{
switch (proto) {
case Protocol::OpenVpn:
case Proto::OpenVpn:
return OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, errorCode);
case Protocol::ShadowSocks:
case Proto::ShadowSocks:
return ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, errorCode);
case Protocol::Cloak:
case Proto::Cloak:
return CloakConfigurator::genCloakConfig(credentials, container, containerConfig, errorCode);
case Protocol::WireGuard:
case Proto::WireGuard:
return WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode);
case Protocol::Ikev2:
case Proto::Ikev2:
return Ikev2Configurator::genIkev2Config(credentials, container, containerConfig, errorCode);
default:
@ -41,23 +41,23 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia
}
}
QString VpnConfigurator::processConfigWithLocalSettings(DockerContainer container, Protocol proto, QString config)
QString VpnConfigurator::processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config)
{
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
if (proto == Protocol::OpenVpn) {
if (proto == Proto::OpenVpn) {
return OpenVpnConfigurator::processConfigWithLocalSettings(config);
}
return config;
}
QString VpnConfigurator::processConfigWithExportSettings(DockerContainer container, Protocol proto, QString config)
QString VpnConfigurator::processConfigWithExportSettings(DockerContainer container, Proto proto, QString config)
{
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
if (proto == Protocol::OpenVpn) {
if (proto == Proto::OpenVpn) {
return OpenVpnConfigurator::processConfigWithExportSettings(config);
}
return config;
@ -66,7 +66,7 @@ QString VpnConfigurator::processConfigWithExportSettings(DockerContainer contain
void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig,
const QString &stdOut)
{
Protocol mainProto = ContainerProps::defaultProtocol(container);
Proto mainProto = ContainerProps::defaultProtocol(container);
if (container == DockerContainer::TorWebSite) {
QJsonObject protocol = containerConfig.value(ProtocolProps::protoToString(mainProto)).toObject();

View file

@ -13,10 +13,10 @@ class VpnConfigurator
public:
static QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container,
const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode = nullptr);
const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr);
static QString processConfigWithLocalSettings(DockerContainer container, Protocol proto, QString config);
static QString processConfigWithExportSettings(DockerContainer container, Protocol proto, QString config);
static QString processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config);
static QString processConfigWithExportSettings(DockerContainer container, Proto proto, QString config);
// workaround for containers which is not support normal configaration
static void updateContainerConfigAfterInstallation(DockerContainer container,

View file

@ -27,29 +27,29 @@ QString ContainerProps::containerToString(amnezia::DockerContainer c){
return "amnezia-" + containerKey.toLower();
}
QVector<amnezia::Protocol> ContainerProps::protocolsForContainer(amnezia::DockerContainer container)
QVector<amnezia::Proto> ContainerProps::protocolsForContainer(amnezia::DockerContainer container)
{
switch (container) {
case DockerContainer::None:
return { };
case DockerContainer::OpenVpn:
return { Protocol::OpenVpn };
return { Proto::OpenVpn };
case DockerContainer::ShadowSocks:
return { Protocol::OpenVpn, Protocol::ShadowSocks };
return { Proto::OpenVpn, Proto::ShadowSocks };
case DockerContainer::Cloak:
return { Protocol::OpenVpn, Protocol::ShadowSocks, Protocol::Cloak };
return { Proto::OpenVpn, Proto::ShadowSocks, Proto::Cloak };
case DockerContainer::Ipsec:
return { Protocol::Ikev2 /*, Protocol::L2tp */};
return { Proto::Ikev2 /*, Protocol::L2tp */};
case DockerContainer::Dns:
return { };
case DockerContainer::Sftp:
return { Protocol::Sftp};
return { Proto::Sftp};
default:
return { defaultProtocol(container) };
@ -118,21 +118,21 @@ amnezia::ServiceType ContainerProps::containerService(DockerContainer c)
}
}
Protocol ContainerProps::defaultProtocol(DockerContainer c)
Proto ContainerProps::defaultProtocol(DockerContainer c)
{
switch (c) {
case DockerContainer::None : return Protocol::Any;
case DockerContainer::OpenVpn : return Protocol::OpenVpn;
case DockerContainer::Cloak : return Protocol::Cloak;
case DockerContainer::ShadowSocks : return Protocol::ShadowSocks;
case DockerContainer::WireGuard : return Protocol::WireGuard;
case DockerContainer::Ipsec : return Protocol::Ikev2;
case DockerContainer::None : return Proto::Any;
case DockerContainer::OpenVpn : return Proto::OpenVpn;
case DockerContainer::Cloak : return Proto::Cloak;
case DockerContainer::ShadowSocks : return Proto::ShadowSocks;
case DockerContainer::WireGuard : return Proto::WireGuard;
case DockerContainer::Ipsec : return Proto::Ikev2;
case DockerContainer::TorWebSite : return Protocol::TorWebSite;
case DockerContainer::Dns : return Protocol::Dns;
case DockerContainer::TorWebSite : return Proto::TorWebSite;
case DockerContainer::Dns : return Proto::Dns;
//case DockerContainer::FileShare : return Protocol::FileShare;
case DockerContainer::Sftp : return Protocol::Sftp;
default: return Protocol::Any;
case DockerContainer::Sftp : return Proto::Sftp;
default: return Proto::Any;
}
}

View file

@ -46,13 +46,13 @@ public:
Q_INVOKABLE static QMap<DockerContainer, QString> containerDescriptions();
// these protocols will be displayed in container settings
Q_INVOKABLE static QVector<Protocol> protocolsForContainer(DockerContainer container);
Q_INVOKABLE static QVector<Proto> protocolsForContainer(DockerContainer container);
Q_INVOKABLE static ServiceType containerService(DockerContainer c);
// binding between Docker container and main protocol of given container
// it may be changed fot future containers :)
Q_INVOKABLE static Protocol defaultProtocol(DockerContainer c);
Q_INVOKABLE static Proto defaultProtocol(DockerContainer c);
};

View file

@ -449,7 +449,7 @@ ErrorCode ServerController::updateContainer(const ServerCredentials &credentials
QJsonObject ServerController::createContainerInitialConfig(DockerContainer container, int port, TransportProto tp)
{
Protocol mainProto = ContainerProps::defaultProtocol(container);
Proto mainProto = ContainerProps::defaultProtocol(container);
QJsonObject config {
{ config_key::container, ContainerProps::containerToString(container) }
@ -616,11 +616,11 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred
ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config)
{
const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Protocol::OpenVpn)).toObject();
const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Protocol::Cloak)).toObject();
const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Protocol::ShadowSocks)).toObject();
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Protocol::WireGuard)).toObject();
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Protocol::Sftp)).toObject();
const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Proto::OpenVpn)).toObject();
const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject();
const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject();
const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject();
//
Vars vars;
@ -689,7 +689,7 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential
// Sftp vars
vars.append({{"$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Protocol::Sftp))) }});
vars.append({{"$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) }});
vars.append({{"$SFTP_USER", sftpConfig.value(config_key::userName).toString() }});
vars.append({{"$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() }});

View file

@ -2,12 +2,14 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>ADJUST_SDK_TOKEN</key>
<string>$(ADJUST_SDK_TOKEN)</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Mozilla VPN</string>
<string>AmneziaVPN</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIcons</key>
@ -49,7 +51,5 @@
<string>Light</string>
<key>com.wireguard.ios.app_group_id</key>
<string>group.org.mozilla.ios.Guardian</string>
<key>ADJUST_SDK_TOKEN</key>
<string>$(ADJUST_SDK_TOKEN)</string>
</dict>
</plist>

View file

@ -2,13 +2,13 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>$(GROUP_ID_IOS)</string>
</array>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
</dict>
</plist>

0
client/macos/gobridge/api.go Executable file → Normal file
View file

0
client/macos/gobridge/dummy.c Executable file → Normal file
View file

0
client/macos/gobridge/go.mod Executable file → Normal file
View file

0
client/macos/gobridge/go.sum Executable file → Normal file
View file

View file

0
client/macos/gobridge/module.modulemap Executable file → Normal file
View file

0
client/macos/gobridge/wireguard-go-version.h Executable file → Normal file
View file

0
client/macos/gobridge/wireguard.h Executable file → Normal file
View file

View file

@ -116,15 +116,15 @@ int main(int argc, char *argv[])
app.setQuitOnLastWindowClosed(false);
qRegisterMetaType<VpnProtocol::ConnectionState>("VpnProtocol::ConnectionState");
qRegisterMetaType<VpnProtocol::VpnConnectionState>("VpnProtocol::ConnectionState");
qRegisterMetaType<ServerCredentials>("ServerCredentials");
qRegisterMetaType<DockerContainer>("DockerContainer");
qRegisterMetaType<TransportProto>("TransportProto");
qRegisterMetaType<Protocol>("Protocol");
qRegisterMetaType<Proto>("Protocol");
qRegisterMetaType<ServiceType>("ServiceType");
qRegisterMetaType<Page>("Page");
qRegisterMetaType<VpnProtocol::ConnectionState>("ConnectionState");
qRegisterMetaType<VpnProtocol::VpnConnectionState>("ConnectionState");
qRegisterMetaType<PageProtocolLogicBase *>("PageProtocolLogicBase *");
@ -160,7 +160,7 @@ int main(int argc, char *argv[])
engine->rootContext()->setContextProperty("NewServerProtocolsLogic", uiLogic->newServerProtocolsLogic());
engine->rootContext()->setContextProperty("ServerListLogic", uiLogic->serverListLogic());
engine->rootContext()->setContextProperty("ServerSettingsLogic", uiLogic->serverSettingsLogic());
engine->rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverVpnProtocolsLogic());
engine->rootContext()->setContextProperty("ServerContainersLogic", uiLogic->serverprotocolsLogic());
engine->rootContext()->setContextProperty("ShareConnectionLogic", uiLogic->shareConnectionLogic());
engine->rootContext()->setContextProperty("SitesLogic", uiLogic->sitesLogic());
engine->rootContext()->setContextProperty("StartPageLogic", uiLogic->startPageLogic());

View file

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "wireguard-go-version.h"
#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h"
#include <stdbool.h>
#include <stdint.h>
#define WG_KEY_LEN (32)
#define WG_KEY_LEN_BASE64 (45)
#define WG_KEY_LEN_HEX (65)
void key_to_base64(char base64[WG_KEY_LEN_BASE64],
const uint8_t key[WG_KEY_LEN]);
bool key_from_base64(uint8_t key[WG_KEY_LEN], const char* base64);
void key_to_hex(char hex[WG_KEY_LEN_HEX], const uint8_t key[WG_KEY_LEN]);
bool key_from_hex(uint8_t key[WG_KEY_LEN], const char* hex);
bool key_eq(const uint8_t key1[WG_KEY_LEN], const uint8_t key2[WG_KEY_LEN]);
void write_msg_to_log(const char* tag, const char* msg);
#import "TargetConditionals.h"
#if TARGET_OS_OSX
# include <libproc.h>
#endif

View file

@ -0,0 +1,127 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BIGINT_H
#define BIGINT_H
#include <QVector>
// This BigInt implementation is meant to be used for IPv6 addresses. It
// doesn't support dynamic resize: when the max size is reached, the value
// overflows. If you need to change the size, use `resize()`.
class BigInt final {
public:
explicit BigInt(uint8_t bytes) {
m_value.resize(bytes);
memset(m_value.data(), 0, bytes);
}
BigInt(const BigInt& other) { m_value = other.m_value; }
const uint8_t* value() const { return m_value.data(); }
uint8_t size() const { return m_value.size(); }
// Assign operator.
BigInt& operator=(const BigInt& other) {
m_value = other.m_value;
return *this;
}
// Comparison operators.
bool operator==(const BigInt& other) const {
return m_value == other.m_value;
}
bool operator!=(const BigInt& other) const { return !(*this == other); }
bool operator<(const BigInt& other) const { return cmp(other) < 0; }
bool operator>(const BigInt& other) const { return cmp(other) > 0; }
bool operator<=(const BigInt& other) const { return cmp(other) <= 0; }
bool operator>=(const BigInt& other) const { return cmp(other) >= 0; }
// math operators (only some of them are implemented)
BigInt& operator++() {
for (int i = size() - 1; i >= 0; --i) {
if (m_value[i] < UINT8_MAX) {
++m_value[i];
return *this;
}
m_value[i] = 0;
}
// overflow
memset(m_value.data(), 0, size());
return *this;
}
BigInt& operator+=(const BigInt& other) {
Q_ASSERT(other.size() == size());
uint8_t carry = 0;
for (int i = m_value.size() - 1; i >= 0; --i) {
uint16_t total = carry + m_value[i] + other.m_value[i];
m_value[i] = (uint8_t)(total & UINT8_MAX);
carry = (uint8_t)((total & 0xFF00) >> 8);
}
return *this;
}
// Shift operators
BigInt operator>>(int shift) {
BigInt x(size());
x = *this;
for (int i = 0; i < shift; i++) {
BigInt a(size());
a = x;
a.m_value[size() - 1] = x.m_value[size() - 1] >> 1;
for (int j = size() - 2; j >= 0; j--) {
a.m_value[j] = x.m_value[j] >> 1;
if ((x.m_value[j] & 1) != 0) {
a.m_value[j + 1] |= 128; // Set most significant bit or a uint8_t
}
}
x = a;
}
return x;
}
void setValueAt(uint8_t value, uint8_t pos) {
Q_ASSERT(pos < size());
m_value[pos] = value;
}
uint8_t valueAt(uint8_t pos) const {
Q_ASSERT(size() > pos);
return m_value[pos];
}
private:
int cmp(const BigInt& other) const {
Q_ASSERT(size() == other.size());
for (int i = 0; i < size(); i++) {
int diff = (m_value[i] - other.m_value[i]);
if (diff != 0) return diff;
}
return 0;
}
private:
QVector<uint8_t> m_value;
};
#endif // BIGINT_H

View file

@ -0,0 +1,86 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef BIGINTIPV6ADDR_H
#define BIGINTIPV6ADDR_H
#include "bigint.h"
#include <QHostAddress>
class BigIntIPv6Addr final {
public:
BigIntIPv6Addr() : m_value(16) {}
explicit BigIntIPv6Addr(const Q_IPV6ADDR& a) : m_value(16) {
for (int i = 0; i < 16; ++i) m_value.setValueAt(a[i], i);
}
BigIntIPv6Addr(const BigIntIPv6Addr& other) : m_value(16) { *this = other; }
Q_IPV6ADDR value() const {
Q_IPV6ADDR addr;
for (int i = 0; i < 16; ++i) addr[i] = m_value.valueAt(i);
return addr;
}
// Assign operator.
BigIntIPv6Addr& operator=(const BigIntIPv6Addr& other) {
m_value = other.m_value;
return *this;
}
// Comparison operators.
bool operator==(const BigIntIPv6Addr& other) const {
return m_value == other.m_value;
}
bool operator!=(const BigIntIPv6Addr& other) const {
return m_value != other.m_value;
}
bool operator<(const BigIntIPv6Addr& other) const {
return m_value < other.m_value;
}
bool operator>(const BigIntIPv6Addr& other) const {
return m_value > other.m_value;
}
bool operator<=(const BigIntIPv6Addr& other) const {
return m_value <= other.m_value;
}
bool operator>=(const BigIntIPv6Addr& other) const {
return m_value >= other.m_value;
}
// math operators (only some of them are implemented)
BigIntIPv6Addr& operator++() {
++m_value;
return *this;
}
BigIntIPv6Addr& operator+=(const BigIntIPv6Addr& b) {
m_value += b.m_value;
return *this;
}
// Shift operators
BigIntIPv6Addr operator>>(int shift) {
BigIntIPv6Addr x;
x.m_value = m_value >> shift;
return x;
}
private:
BigInt m_value;
};
#endif // BIGINTIPV6ADDR_H

View file

@ -5,12 +5,12 @@
#ifndef IOSCONTROLLER_H
#define IOSCONTROLLER_H
#include "controllerimpl.h"
#include "vpnprotocol.h"
#include <QObject>
class IOSController final : public ControllerImpl {
Q_DISABLE_COPY_MOVE(IOSController)
class IOSVPNProtocol final : public VpnProtocol {
Q_DISABLE_COPY_MOVE(IOSVPNProtocol)
public:
IOSController();

View file

@ -8,7 +8,7 @@
#include <string.h>
#ifndef NETWORK_EXTENSION
# include "logger.h"
//# include "logger.h"
#else
# import <Foundation/Foundation.h>
# import <os/log.h>
@ -183,13 +183,13 @@ EXPORT bool key_eq(const uint8_t key1[WG_KEY_LEN], const uint8_t key2[WG_KEY_LEN
#ifndef NETWORK_EXTENSION
namespace {
Logger logger(LOG_IOS, "IOSSGlue");
//Logger logger(LOG_IOS, "IOSSGlue");
}
#endif
EXPORT void write_msg_to_log(const char* tag, const char* msg) {
#ifndef NETWORK_EXTENSION
logger.debug() << "Swift log - tag:" << tag << "msg: " << msg;
// logger.debug() << "Swift log - tag:" << tag << "msg: " << msg;
#else
os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG, "tag: %s - msg: %s", tag, msg);

View file

@ -7,7 +7,7 @@ import os
class PacketTunnelProvider: NEPacketTunnelProvider {
private lazy var adapter: WireGuardAdapter = {
private lazy var wgAdapter: WireGuardAdapter = {
return WireGuardAdapter(with: self) { logLevel, message in
wg_log(logLevel.osLogLevel, message: message)
}
@ -29,9 +29,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
// Start the tunnel
adapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
guard let adapterError = adapterError else {
let interfaceName = self.adapter.interfaceName ?? "unknown"
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
@ -72,7 +72,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
wg_log(.info, staticMessage: "Stopping tunnel")
adapter.stop { error in
wgAdapter.stop { error in
ErrorNotifier.removeLastErrorFile()
if let error = error {
@ -93,7 +93,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
guard let completionHandler = completionHandler else { return }
if messageData.count == 1 && messageData[0] == 0 {
adapter.getRuntimeConfiguration { settings in
wgAdapter.getRuntimeConfiguration { settings in
var data: Data?
if let settings = settings {
data = settings.data(using: .utf8)!
@ -111,14 +111,14 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
do {
let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: configString)
adapter.update(tunnelConfiguration: tunnelConfiguration) { error in
wgAdapter.update(tunnelConfiguration: tunnelConfiguration) { error in
if let error = error {
wg_log(.error, message: "Failed to switch tunnel configuration: \(error.localizedDescription)")
completionHandler(nil)
return
}
self.adapter.getRuntimeConfiguration { settings in
self.wgAdapter.getRuntimeConfiguration { settings in
var data: Data?
if let settings = settings {
data = settings.data(using: .utf8)!

View file

@ -0,0 +1,292 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import NetworkExtension
let vpnName = "AmneziaVPN"
var vpnBundleID = "";
@objc class VPNIPAddressRange : NSObject {
public var address: NSString = ""
public var networkPrefixLength: UInt8 = 0
public var isIpv6: Bool = false
@objc init(address: NSString, networkPrefixLength: UInt8, isIpv6: Bool) {
super.init()
self.address = address
self.networkPrefixLength = networkPrefixLength
self.isIpv6 = isIpv6
}
}
public class IOSVpnProtocolImpl : NSObject {
private var tunnel: NETunnelProviderManager? = nil
private var stateChangeCallback: ((Bool) -> Void?)? = nil
private var privateKey : PrivateKey? = nil
private var deviceIpv4Address: String? = nil
private var deviceIpv6Address: String? = nil
@objc enum IOSConnectionState: Int { case Error, Connected, Disconnected }
@objc init(bundleID: String, privateKey: Data, deviceIpv4Address: String, deviceIpv6Address: String, closure: @escaping (IOSConnectionState, Date?) -> Void, callback: @escaping (Bool) -> Void) {
super.init()
Logger.configureGlobal(tagged: "APP", withFilePath: "")
vpnBundleID = bundleID;
precondition(!vpnBundleID.isEmpty)
stateChangeCallback = callback
self.privateKey = PrivateKey(rawValue: privateKey)
self.deviceIpv4Address = deviceIpv4Address
self.deviceIpv6Address = deviceIpv6Address
NotificationCenter.default.addObserver(self, selector: #selector(self.vpnStatusDidChange(notification:)), name: Notification.Name.NEVPNStatusDidChange, object: nil)
NETunnelProviderManager.loadAllFromPreferences { [weak self] managers, error in
if let error = error {
Logger.global?.log(message: "Loading from preference failed: \(error)")
closure(IOSConnectionState.Error, nil)
return
}
if self == nil {
Logger.global?.log(message: "We are shutting down.")
return
}
let nsManagers = managers ?? []
Logger.global?.log(message: "We have received \(nsManagers.count) managers.")
let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:))
if tunnel == nil {
Logger.global?.log(message: "Creating the tunnel")
self!.tunnel = NETunnelProviderManager()
closure(IOSConnectionState.Disconnected, nil)
return
}
Logger.global?.log(message: "Tunnel already exists")
self!.tunnel = tunnel
if tunnel?.connection.status == .connected {
closure(IOSConnectionState.Connected, tunnel?.connection.connectedDate)
} else {
closure(IOSConnectionState.Disconnected, nil)
}
}
}
@objc private func vpnStatusDidChange(notification: Notification) {
guard let session = (notification.object as? NETunnelProviderSession), tunnel?.connection == session else { return }
switch session.status {
case .connected:
Logger.global?.log(message: "STATE CHANGED: connected")
case .connecting:
Logger.global?.log(message: "STATE CHANGED: connecting")
case .disconnected:
Logger.global?.log(message: "STATE CHANGED: disconnected")
case .disconnecting:
Logger.global?.log(message: "STATE CHANGED: disconnecting")
case .invalid:
Logger.global?.log(message: "STATE CHANGED: invalid")
case .reasserting:
Logger.global?.log(message: "STATE CHANGED: reasserting")
default:
Logger.global?.log(message: "STATE CHANGED: unknown status")
}
// We care about "unknown" state changes.
if (session.status != .connected && session.status != .disconnected) {
return
}
stateChangeCallback?(session.status == .connected)
}
private static func isOurManager(_ manager: NETunnelProviderManager) -> Bool {
guard
let proto = manager.protocolConfiguration,
let tunnelProto = proto as? NETunnelProviderProtocol
else {
Logger.global?.log(message: "Ignoring manager because the proto is invalid.")
return false
}
if (tunnelProto.providerBundleIdentifier == nil) {
Logger.global?.log(message: "Ignoring manager because the bundle identifier is null.")
return false
}
if (tunnelProto.providerBundleIdentifier != vpnBundleID) {
Logger.global?.log(message: "Ignoring manager because the bundle identifier doesn't match.")
return false;
}
Logger.global?.log(message: "Found the manager with the correct bundle identifier: \(tunnelProto.providerBundleIdentifier!)")
return true
}
@objc func connect(dnsServer: String, serverIpv6Gateway: String, serverPublicKey: String, serverIpv4AddrIn: String, serverPort: Int, allowedIPAddressRanges: Array<VPNIPAddressRange>, ipv6Enabled: Bool, reason: Int, failureCallback: @escaping () -> Void) {
Logger.global?.log(message: "Connecting")
assert(tunnel != nil)
// Let's remove the previous config if it exists.
(tunnel?.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
let keyData = PublicKey(base64Key: serverPublicKey)!
let dnsServerIP = IPv4Address(dnsServer)
let ipv6GatewayIP = IPv6Address(serverIpv6Gateway)
var peerConfiguration = PeerConfiguration(publicKey: keyData)
peerConfiguration.endpoint = Endpoint(from: serverIpv4AddrIn + ":\(serverPort )")
peerConfiguration.allowedIPs = []
allowedIPAddressRanges.forEach {
if (!$0.isIpv6) {
peerConfiguration.allowedIPs.append(IPAddressRange(address: IPv4Address($0.address as String)!, networkPrefixLength: $0.networkPrefixLength))
} else if (ipv6Enabled) {
peerConfiguration.allowedIPs.append(IPAddressRange(address: IPv6Address($0.address as String)!, networkPrefixLength: $0.networkPrefixLength))
}
}
var peerConfigurations: [PeerConfiguration] = []
peerConfigurations.append(peerConfiguration)
var interface = InterfaceConfiguration(privateKey: privateKey!)
if let ipv4Address = IPAddressRange(from: deviceIpv4Address!),
let ipv6Address = IPAddressRange(from: deviceIpv6Address!) {
interface.addresses = [ipv4Address]
if (ipv6Enabled) {
interface.addresses.append(ipv6Address)
}
}
interface.dns = [ DNSServer(address: dnsServerIP!)]
if (ipv6Enabled) {
interface.dns.append(DNSServer(address: ipv6GatewayIP!))
}
let config = TunnelConfiguration(name: vpnName, interface: interface, peers: peerConfigurations)
self.configureTunnel(config: config, reason: reason, failureCallback: failureCallback)
}
func configureTunnel(config: TunnelConfiguration, reason: Int, failureCallback: @escaping () -> Void) {
guard let proto = NETunnelProviderProtocol(tunnelConfiguration: config) else {
failureCallback()
return
}
proto.providerBundleIdentifier = vpnBundleID
tunnel!.protocolConfiguration = proto
tunnel!.localizedDescription = vpnName
tunnel!.isEnabled = true
tunnel!.saveToPreferences { [unowned self] saveError in
if let error = saveError {
Logger.global?.log(message: "Connect Tunnel Save Error: \(error)")
failureCallback()
return
}
Logger.global?.log(message: "Saving the tunnel succeeded")
self.tunnel!.loadFromPreferences { error in
if let error = error {
Logger.global?.log(message: "Connect Tunnel Load Error: \(error)")
failureCallback()
return
}
Logger.global?.log(message: "Loading the tunnel succeeded")
do {
if (reason == 1 /* ReasonSwitching */) {
let settings = config.asWgQuickConfig()
let settingsData = settings.data(using: .utf8)!
try (self.tunnel!.connection as? NETunnelProviderSession)?
.sendProviderMessage(settingsData) { data in
guard let data = data,
let configString = String(data: data, encoding: .utf8)
else {
Logger.global?.log(message: "Failed to convert response to string")
return
}
}
} else {
try (self.tunnel!.connection as? NETunnelProviderSession)?.startTunnel()
}
} catch let error {
Logger.global?.log(message: "Something went wrong: \(error)")
failureCallback()
return
}
}
}
}
@objc func disconnect() {
Logger.global?.log(message: "Disconnecting")
assert(tunnel != nil)
(tunnel!.connection as? NETunnelProviderSession)?.stopTunnel()
}
@objc func checkStatus(callback: @escaping (String, String, String) -> Void) {
Logger.global?.log(message: "Check status")
assert(tunnel != nil)
let proto = tunnel!.protocolConfiguration as? NETunnelProviderProtocol
if proto == nil {
callback("", "", "")
return
}
let tunnelConfiguration = proto?.asTunnelConfiguration()
if tunnelConfiguration == nil {
callback("", "", "")
return
}
let serverIpv4Gateway = tunnelConfiguration?.interface.dns[0].address
if serverIpv4Gateway == nil {
callback("", "", "")
return
}
let deviceIpv4Address = tunnelConfiguration?.interface.addresses[0].address
if deviceIpv4Address == nil {
callback("", "", "")
return
}
guard let session = tunnel?.connection as? NETunnelProviderSession
else {
callback("", "", "")
return
}
do {
try session.sendProviderMessage(Data([UInt8(0)])) { [callback] data in
guard let data = data,
let configString = String(data: data, encoding: .utf8)
else {
Logger.global?.log(message: "Failed to convert data to string")
callback("", "", "")
return
}
callback("\(serverIpv4Gateway!)", "\(deviceIpv4Address!)", configString)
}
} catch {
Logger.global?.log(message: "Failed to retrieve data from session")
callback("", "", "")
}
}
}

View file

@ -0,0 +1,313 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipaddress.h"
#include "bigintipv6addr.h"
#include <QtMath>
namespace {
quint32 s_allIpV4Ones = static_cast<quint32>(qPow(2, 32) - 1);
BigIntIPv6Addr s_allIPv6Ones;
bool s_ipv6Initialized = false;
void maybeInitialize() {
if (s_ipv6Initialized) return;
s_ipv6Initialized = true;
Q_IPV6ADDR allOnes;
memset((void*)&allOnes, static_cast<quint8>(qPow(2, 8) - 1), sizeof(allOnes));
s_allIPv6Ones = BigIntIPv6Addr(allOnes);
}
} // namespace
// static
IPAddress IPAddress::create(const QString& ip) {
if (ip.contains("/")) {
QPair<QHostAddress, int> p = QHostAddress::parseSubnet(ip);
if (p.first.protocol() == QAbstractSocket::IPv4Protocol) {
if (p.second < 32) {
return IPAddress(p.first, p.second);
}
return IPAddress(p.first);
}
if (p.first.protocol() == QAbstractSocket::IPv6Protocol) {
if (p.second < 128) {
return IPAddress(p.first, p.second);
}
return IPAddress(p.first);
}
Q_ASSERT(false);
}
return IPAddress(QHostAddress(ip));
}
IPAddress::IPAddress() {
maybeInitialize();
}
IPAddress::IPAddress(const IPAddress& other) {
maybeInitialize();
*this = other;
}
IPAddress& IPAddress::operator=(const IPAddress& other) {
if (this == &other) return *this;
m_address = other.m_address;
m_prefixLength = other.m_prefixLength;
m_netmask = other.m_netmask;
m_hostmask = other.m_hostmask;
m_broadcastAddress = other.m_broadcastAddress;
return *this;
}
IPAddress::IPAddress(const QHostAddress& address)
: m_address(address), m_broadcastAddress(address) {
maybeInitialize();
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
m_prefixLength = 32;
m_netmask = QHostAddress(s_allIpV4Ones);
m_hostmask = QHostAddress((quint32)(0));
} else {
Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol);
m_prefixLength = 128;
m_netmask = QHostAddress(s_allIPv6Ones.value());
{
Q_IPV6ADDR ipv6;
memset((void*)&ipv6, 0, sizeof(ipv6));
m_hostmask = QHostAddress(ipv6);
}
}
}
IPAddress::IPAddress(const QHostAddress& address, int prefixLength)
: m_address(address), m_prefixLength(prefixLength) {
maybeInitialize();
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
Q_ASSERT(prefixLength >= 0 && prefixLength <= 32);
m_netmask = QHostAddress(s_allIpV4Ones ^ (s_allIpV4Ones >> prefixLength));
m_hostmask = QHostAddress(m_netmask.toIPv4Address() ^ s_allIpV4Ones);
m_broadcastAddress =
QHostAddress(address.toIPv4Address() | m_hostmask.toIPv4Address());
} else {
Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol);
Q_ASSERT(prefixLength >= 0 && prefixLength <= 128);
Q_IPV6ADDR netmask;
{
BigIntIPv6Addr tmp = (s_allIPv6Ones >> prefixLength);
for (int i = 0; i < 16; ++i)
netmask[i] = s_allIPv6Ones.value()[i] ^ tmp.value()[i];
}
m_netmask = QHostAddress(netmask);
{
Q_IPV6ADDR tmp;
for (int i = 0; i < 16; ++i)
tmp[i] = netmask[i] ^ s_allIPv6Ones.value()[i];
m_hostmask = QHostAddress(tmp);
}
{
Q_IPV6ADDR ipv6Address = address.toIPv6Address();
Q_IPV6ADDR ipv6Hostname = m_hostmask.toIPv6Address();
for (int i = 0; i < 16; ++i) ipv6Address[i] |= ipv6Hostname[i];
m_broadcastAddress = QHostAddress(ipv6Address);
}
}
}
IPAddress::~IPAddress() { }
QAbstractSocket::NetworkLayerProtocol IPAddress::type() const {
return m_address.protocol();
}
bool IPAddress::overlaps(const IPAddress& other) const {
return other.contains(m_address) || other.contains(m_broadcastAddress) ||
contains(other.m_address) || contains(other.m_broadcastAddress);
}
bool IPAddress::contains(const QHostAddress& address) const {
if (address.protocol() != m_address.protocol()) {
return false;
}
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
return (m_address.toIPv4Address() <= address.toIPv4Address()) &&
(address.toIPv4Address() <= m_broadcastAddress.toIPv4Address());
}
Q_ASSERT(address.protocol() == QAbstractSocket::IPv6Protocol);
return (BigIntIPv6Addr(m_address.toIPv6Address()) <=
BigIntIPv6Addr(address.toIPv6Address())) &&
(BigIntIPv6Addr(address.toIPv6Address()) <=
BigIntIPv6Addr(m_broadcastAddress.toIPv6Address()));
}
bool IPAddress::operator==(const IPAddress& other) const {
return m_address == other.m_address && m_netmask == other.m_netmask;
}
bool IPAddress::subnetOf(const IPAddress& other) const {
if (other.m_address.protocol() != m_address.protocol()) {
return false;
}
if (m_address.protocol() == QAbstractSocket::IPv4Protocol) {
return other.m_address.toIPv4Address() <= m_address.toIPv4Address() &&
other.m_broadcastAddress.toIPv4Address() >=
m_broadcastAddress.toIPv4Address();
}
Q_ASSERT(m_address.protocol() == QAbstractSocket::IPv6Protocol);
return BigIntIPv6Addr(other.m_address.toIPv6Address()) <=
BigIntIPv6Addr(m_address.toIPv6Address()) &&
BigIntIPv6Addr(other.m_broadcastAddress.toIPv6Address()) >=
BigIntIPv6Addr(m_broadcastAddress.toIPv6Address());
}
QList<IPAddress> IPAddress::subnets() const {
QList<IPAddress> list;
if (m_address.protocol() == QAbstractSocket::IPv4Protocol) {
if (m_prefixLength == 32) {
list.append(*this);
return list;
}
quint64 start = m_address.toIPv4Address();
quint64 end = quint64(m_broadcastAddress.toIPv4Address()) + 1;
quint64 step = ((quint64)m_hostmask.toIPv4Address() + 1) >> 1;
while (start < end) {
int newPrefixLength = m_prefixLength + 1;
if (newPrefixLength == 32) {
list.append(IPAddress(QHostAddress(static_cast<quint32>(start))));
} else {
list.append(IPAddress(QHostAddress(static_cast<quint32>(start)),
m_prefixLength + 1));
}
start += step;
}
return list;
}
Q_ASSERT(m_address.protocol() == QAbstractSocket::IPv6Protocol);
if (m_prefixLength == 128) {
list.append(*this);
return list;
}
BigInt start(17);
{
Q_IPV6ADDR addr = m_address.toIPv6Address();
for (int i = 0; i < 16; ++i) {
start.setValueAt(addr[i], i + 1);
}
}
BigInt end(17);
{
Q_IPV6ADDR addr = m_broadcastAddress.toIPv6Address();
for (int i = 0; i < 16; ++i) {
end.setValueAt(addr[i], i + 1);
}
++end;
}
BigInt step(17);
{
Q_IPV6ADDR addr = m_hostmask.toIPv6Address();
for (int i = 0; i < 16; ++i) {
step.setValueAt(addr[i], i + 1);
}
step = (++step) >> 1;
}
while (start < end) {
int newPrefixLength = m_prefixLength + 1;
Q_IPV6ADDR startIPv6;
for (int i = 0; i < 16; ++i) {
startIPv6[i] = start.valueAt(i + 1);
}
if (newPrefixLength == 128) {
list.append(IPAddress(QHostAddress(startIPv6)));
} else {
list.append(IPAddress(QHostAddress(startIPv6), m_prefixLength + 1));
}
start += step;
}
return list;
}
// static
QList<IPAddress> IPAddress::excludeAddresses(
const QList<IPAddress>& sourceList, const QList<IPAddress>& excludeList) {
QList<IPAddress> results = sourceList;
for (const IPAddress& exclude : excludeList) {
QList<IPAddress> newResults;
for (const IPAddress& ip : results) {
if (ip.overlaps(exclude)) {
QList<IPAddress> range = ip.excludeAddresses(exclude);
newResults.append(range);
} else {
newResults.append(ip);
}
}
results = newResults;
}
return results;
}
QList<IPAddress> IPAddress::excludeAddresses(const IPAddress& ip) const {
QList<IPAddress> sn = subnets();
Q_ASSERT(sn.length() >= 2);
QList<IPAddress> result;
while (sn[0] != ip && sn[1] != ip) {
if (ip.subnetOf(sn[0])) {
result.append(sn[1]);
sn = sn[0].subnets();
} else if (ip.subnetOf(sn[1])) {
result.append(sn[0]);
sn = sn[1].subnets();
} else {
Q_ASSERT(false);
}
}
if (sn[0] == ip) {
result.append(sn[1]);
} else if (sn[1] == ip) {
result.append(sn[0]);
} else {
Q_ASSERT(false);
}
return result;
}

View file

@ -0,0 +1,59 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef IPADDRESS_H
#define IPADDRESS_H
#include <QHostAddress>
class IPAddress final {
public:
static IPAddress create(const QString& ip);
static QList<IPAddress> excludeAddresses(const QList<IPAddress>& sourceList,
const QList<IPAddress>& excludeList);
IPAddress();
IPAddress(const IPAddress& other);
IPAddress& operator=(const IPAddress& other);
~IPAddress();
QString toString() const {
return QString("%1/%2").arg(m_address.toString()).arg(m_prefixLength);
}
const QHostAddress& address() const { return m_address; }
int prefixLength() const { return m_prefixLength; }
const QHostAddress& netmask() const { return m_netmask; }
const QHostAddress& hostmask() const { return m_hostmask; }
const QHostAddress& broadcastAddress() const { return m_broadcastAddress; }
bool overlaps(const IPAddress& other) const;
bool contains(const QHostAddress& address) const;
bool operator==(const IPAddress& other) const;
bool operator!=(const IPAddress& other) const { return !operator==(other); }
bool subnetOf(const IPAddress& other) const;
QList<IPAddress> subnets() const;
QList<IPAddress> excludeAddresses(const IPAddress& ip) const;
QAbstractSocket::NetworkLayerProtocol type() const;
private:
IPAddress(const QHostAddress& address);
IPAddress(const QHostAddress& address, int prefixLength);
private:
QHostAddress m_address;
int m_prefixLength;
QHostAddress m_netmask;
QHostAddress m_hostmask;
QHostAddress m_broadcastAddress;
};
#endif // IPADDRESS_H

View file

@ -0,0 +1,60 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ipaddressrange.h"
#include "ipaddress.h"
IPAddressRange::IPAddressRange(const QString& ipAddress, uint32_t range,
IPAddressType type)
: m_ipAddress(ipAddress), m_range(range), m_type(type) {}
IPAddressRange::IPAddressRange(const QString& prefix) {
QStringList split = prefix.split('/');
m_ipAddress = split[0];
if (m_ipAddress.contains(':')) {
// Probably IPv6
m_type = IPv6;
m_range = 128;
} else {
// Assume IPv4
m_type = IPv4;
m_range = 32;
}
if (split.count() > 1) {
m_range = split[1].toUInt();
}
}
IPAddressRange::IPAddressRange(const IPAddressRange& other) {
*this = other;
}
IPAddressRange& IPAddressRange::operator=(const IPAddressRange& other) {
if (this == &other) return *this;
m_ipAddress = other.m_ipAddress;
m_range = other.m_range;
m_type = other.m_type;
return *this;
}
bool IPAddressRange::operator==(const IPAddressRange& other) const {
if (this == &other) return true;
return m_ipAddress == other.m_ipAddress && m_range == other.m_range &&
m_type == other.m_type;
}
IPAddressRange::~IPAddressRange() { }
// static
QList<IPAddressRange> IPAddressRange::fromIPAddressList(
const QList<IPAddress>& list) {
QList<IPAddressRange> result;
for (const IPAddress& ip : list) {
result.append(IPAddressRange(ip.toString()));
}
return result;
}

View file

@ -0,0 +1,42 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef IPADDRESSRANGE_H
#define IPADDRESSRANGE_H
#include <QObject>
#include <QString>
class IPAddress;
class IPAddressRange final {
public:
enum IPAddressType {
IPv4,
IPv6,
};
static QList<IPAddressRange> fromIPAddressList(const QList<IPAddress>& list);
IPAddressRange(const QString& prefix);
IPAddressRange(const QString& ipAddress, uint32_t range, IPAddressType type);
IPAddressRange(const IPAddressRange& other);
IPAddressRange& operator=(const IPAddressRange& other);
bool operator==(const IPAddressRange& other) const;
~IPAddressRange();
const QString& ipAddress() const { return m_ipAddress; }
uint32_t range() const { return m_range; }
IPAddressType type() const { return m_type; }
const QString toString() const {
return QString("%1/%2").arg(m_ipAddress).arg(m_range);
}
private:
QString m_ipAddress;
uint32_t m_range;
IPAddressType m_type;
};
#endif // IPADDRESSRANGE_H

View file

@ -0,0 +1,732 @@
/**
* QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
* Copyright (C) 2011 Eeli Reilin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file json.cpp
*/
#include <QDateTime>
#include <QStringList>
#include "json.h"
namespace QtJson {
static QString dateFormat, dateTimeFormat;
static bool prettySerialize = false;
static QString sanitizeString(QString str);
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep);
static QVariant parseValue(const QString &json, int &index, bool &success);
static QVariant parseObject(const QString &json, int &index, bool &success);
static QVariant parseArray(const QString &json, int &index, bool &success);
static QVariant parseString(const QString &json, int &index, bool &success);
static QVariant parseNumber(const QString &json, int &index);
static int lastIndexOfNumber(const QString &json, int index);
static void eatWhitespace(const QString &json, int &index);
static int lookAhead(const QString &json, int index);
static int nextToken(const QString &json, int &index);
template<typename T>
QByteArray serializeMap(const T &map, bool &success, int _level = 0) {
QByteArray newline;
QByteArray tabs;
QByteArray tabsFields;
if (prettySerialize && !map.isEmpty()) {
newline = "\n";
for (uint l=1; l<_level; l++) {
tabs += " ";
}
tabsFields = tabs + " ";
}
QByteArray str = "{" + newline;
QList<QByteArray> pairs;
for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) {
bool otherSuccess = true;
QByteArray serializedValue = serialize(it.value(), otherSuccess, _level);
if (serializedValue.isNull()) {
success = false;
break;
}
pairs << tabsFields + sanitizeString(it.key()).toUtf8() + ":" + (prettySerialize ? " " : "") + serializedValue;
}
str += join(pairs, "," + newline) + newline;
str += tabs + "}";
return str;
}
void insert(QVariant &v, const QString &key, const QVariant &value);
void append(QVariant &v, const QVariant &value);
template<typename T>
void cloneMap(QVariant &json, const T &map) {
for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) {
insert(json, it.key(), (*it));
}
}
template<typename T>
void cloneList(QVariant &json, const T &list) {
for (typename T::const_iterator it = list.begin(), itend = list.end(); it != itend; ++it) {
append(json, (*it));
}
}
/**
* parse
*/
QVariant parse(const QString &json) {
bool success = true;
return parse(json, success);
}
/**
* parse
*/
QVariant parse(const QString &json, bool &success) {
success = true;
// Return an empty QVariant if the JSON data is either null or empty
if (!json.isNull() || !json.isEmpty()) {
QString data = json;
// We'll start from index 0
int index = 0;
// Parse the first value
QVariant value = parseValue(data, index, success);
// Return the parsed value
return value;
} else {
// Return the empty QVariant
return QVariant();
}
}
/**
* clone
*/
QVariant clone(const QVariant &data) {
QVariant v;
if (data.type() == QVariant::Map) {
cloneMap(v, data.toMap());
} else if (data.type() == QVariant::Hash) {
cloneMap(v, data.toHash());
} else if (data.type() == QVariant::List) {
cloneList(v, data.toList());
} else if (data.type() == QVariant::StringList) {
cloneList(v, data.toStringList());
} else {
v = QVariant(data);
}
return v;
}
/**
* insert value (map case)
*/
void insert(QVariant &v, const QString &key, const QVariant &value) {
if (!v.canConvert<QVariantMap>()) v = QVariantMap();
QVariantMap *p = (QVariantMap *)v.data();
p->insert(key, clone(value));
}
/**
* append value (list case)
*/
void append(QVariant &v, const QVariant &value) {
if (!v.canConvert<QVariantList>()) v = QVariantList();
QVariantList *p = (QVariantList *)v.data();
p->append(value);
}
QByteArray serialize(const QVariant &data) {
bool success = true;
return serialize(data, success);
}
QByteArray serialize(const QVariant &data, bool &success, int _level /*= 0*/) {
QByteArray newline;
QByteArray tabs;
QByteArray tabsFields;
if (prettySerialize) {
newline = "\n";
for (uint l=0; l<_level; l++) {
tabs += " ";
}
tabsFields = tabs + " ";
}
QByteArray str;
success = true;
if (!data.isValid()) { // invalid or null?
str = "null";
} else if ((data.type() == QVariant::List) ||
(data.type() == QVariant::StringList)) { // variant is a list?
QList<QByteArray> values;
const QVariantList list = data.toList();
Q_FOREACH(const QVariant& v, list) {
bool otherSuccess = true;
QByteArray serializedValue = serialize(v, otherSuccess, _level+1);
if (serializedValue.isNull()) {
success = false;
break;
}
values << tabsFields + serializedValue;
}
if (!values.isEmpty()) {
str = "[" + newline + join( values, "," + newline ) + newline + tabs + "]";
} else {
str = "[]";
}
} else if (data.type() == QVariant::Hash) { // variant is a hash?
str = serializeMap<>(data.toHash(), success, _level+1);
} else if (data.type() == QVariant::Map) { // variant is a map?
str = serializeMap<>(data.toMap(), success, _level+1);
} else if ((data.type() == QVariant::String) ||
(data.type() == QVariant::ByteArray)) {// a string or a byte array?
str = sanitizeString(data.toString()).toUtf8();
} else if (data.type() == QVariant::Double) { // double?
double value = data.toDouble(&success);
if (success) {
str = QByteArray::number(value, 'g');
if (!str.contains(".") && ! str.contains("e")) {
str += ".0";
}
}
} else if (data.type() == QVariant::Bool) { // boolean value?
str = data.toBool() ? "true" : "false";
} else if (data.type() == QVariant::ULongLong) { // large unsigned number?
str = QByteArray::number(data.value<qulonglong>());
} else if (data.canConvert<qlonglong>()) { // any signed number?
str = QByteArray::number(data.value<qlonglong>());
} else if (data.canConvert<long>()) { //TODO: this code is never executed because all smaller types can be converted to qlonglong
str = QString::number(data.value<long>()).toUtf8();
} else if (data.type() == QVariant::DateTime) { // datetime value?
str = sanitizeString(dateTimeFormat.isEmpty()
? data.toDateTime().toString()
: data.toDateTime().toString(dateTimeFormat)).toUtf8();
} else if (data.type() == QVariant::Date) { // date value?
str = sanitizeString(dateTimeFormat.isEmpty()
? data.toDate().toString()
: data.toDate().toString(dateFormat)).toUtf8();
} else if (data.canConvert<QString>()) { // can value be converted to string?
// this will catch QUrl, ... (all other types which can be converted to string)
str = sanitizeString(data.toString()).toUtf8();
} else {
success = false;
}
if (success) {
return str;
}
return QByteArray();
}
QString serializeStr(const QVariant &data) {
return QString::fromUtf8(serialize(data));
}
QString serializeStr(const QVariant &data, bool &success) {
return QString::fromUtf8(serialize(data, success));
}
/**
* \enum JsonToken
*/
enum JsonToken {
JsonTokenNone = 0,
JsonTokenCurlyOpen = 1,
JsonTokenCurlyClose = 2,
JsonTokenSquaredOpen = 3,
JsonTokenSquaredClose = 4,
JsonTokenColon = 5,
JsonTokenComma = 6,
JsonTokenString = 7,
JsonTokenNumber = 8,
JsonTokenTrue = 9,
JsonTokenFalse = 10,
JsonTokenNull = 11
};
static QString sanitizeString(QString str) {
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
str.replace(QLatin1String("\""), QLatin1String("\\\""));
str.replace(QLatin1String("\b"), QLatin1String("\\b"));
str.replace(QLatin1String("\f"), QLatin1String("\\f"));
str.replace(QLatin1String("\n"), QLatin1String("\\n"));
str.replace(QLatin1String("\r"), QLatin1String("\\r"));
str.replace(QLatin1String("\t"), QLatin1String("\\t"));
return QString(QLatin1String("\"%1\"")).arg(str);
}
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep) {
QByteArray res;
Q_FOREACH(const QByteArray &i, list) {
if (!res.isEmpty()) {
res += sep;
}
res += i;
}
return res;
}
/**
* parseValue
*/
static QVariant parseValue(const QString &json, int &index, bool &success) {
// Determine what kind of data we should parse by
// checking out the upcoming token
switch(lookAhead(json, index)) {
case JsonTokenString:
return parseString(json, index, success);
case JsonTokenNumber:
return parseNumber(json, index);
case JsonTokenCurlyOpen:
return parseObject(json, index, success);
case JsonTokenSquaredOpen:
return parseArray(json, index, success);
case JsonTokenTrue:
nextToken(json, index);
return QVariant(true);
case JsonTokenFalse:
nextToken(json, index);
return QVariant(false);
case JsonTokenNull:
nextToken(json, index);
return QVariant();
case JsonTokenNone:
break;
}
// If there were no tokens, flag the failure and return an empty QVariant
success = false;
return QVariant();
}
/**
* parseObject
*/
static QVariant parseObject(const QString &json, int &index, bool &success) {
QVariantMap map;
int token;
// Get rid of the whitespace and increment index
nextToken(json, index);
// Loop through all of the key/value pairs of the object
bool done = false;
while (!done) {
// Get the upcoming token
token = lookAhead(json, index);
if (token == JsonTokenNone) {
success = false;
return QVariantMap();
} else if (token == JsonTokenComma) {
nextToken(json, index);
} else if (token == JsonTokenCurlyClose) {
nextToken(json, index);
return map;
} else {
// Parse the key/value pair's name
QString name = parseString(json, index, success).toString();
if (!success) {
return QVariantMap();
}
// Get the next token
token = nextToken(json, index);
// If the next token is not a colon, flag the failure
// return an empty QVariant
if (token != JsonTokenColon) {
success = false;
return QVariant(QVariantMap());
}
// Parse the key/value pair's value
QVariant value = parseValue(json, index, success);
if (!success) {
return QVariantMap();
}
// Assign the value to the key in the map
map[name] = value;
}
}
// Return the map successfully
return QVariant(map);
}
/**
* parseArray
*/
static QVariant parseArray(const QString &json, int &index, bool &success) {
QVariantList list;
nextToken(json, index);
bool done = false;
while(!done) {
int token = lookAhead(json, index);
if (token == JsonTokenNone) {
success = false;
return QVariantList();
} else if (token == JsonTokenComma) {
nextToken(json, index);
} else if (token == JsonTokenSquaredClose) {
nextToken(json, index);
break;
} else {
QVariant value = parseValue(json, index, success);
if (!success) {
return QVariantList();
}
list.push_back(value);
}
}
return QVariant(list);
}
/**
* parseString
*/
static QVariant parseString(const QString &json, int &index, bool &success) {
QString s;
QChar c;
eatWhitespace(json, index);
c = json[index++];
bool complete = false;
while(!complete) {
if (index == json.size()) {
break;
}
c = json[index++];
if (c == '\"') {
complete = true;
break;
} else if (c == '\\') {
if (index == json.size()) {
break;
}
c = json[index++];
if (c == '\"') {
s.append('\"');
} else if (c == '\\') {
s.append('\\');
} else if (c == '/') {
s.append('/');
} else if (c == 'b') {
s.append('\b');
} else if (c == 'f') {
s.append('\f');
} else if (c == 'n') {
s.append('\n');
} else if (c == 'r') {
s.append('\r');
} else if (c == 't') {
s.append('\t');
} else if (c == 'u') {
int remainingLength = json.size() - index;
if (remainingLength >= 4) {
QString unicodeStr = json.mid(index, 4);
int symbol = unicodeStr.toInt(0, 16);
s.append(QChar(symbol));
index += 4;
} else {
break;
}
}
} else {
s.append(c);
}
}
if (!complete) {
success = false;
return QVariant();
}
return QVariant(s);
}
/**
* parseNumber
*/
static QVariant parseNumber(const QString &json, int &index) {
eatWhitespace(json, index);
int lastIndex = lastIndexOfNumber(json, index);
int charLength = (lastIndex - index) + 1;
QString numberStr;
numberStr = json.mid(index, charLength);
index = lastIndex + 1;
bool ok;
if (numberStr.contains('.')) {
return QVariant(numberStr.toDouble(NULL));
} else if (numberStr.startsWith('-')) {
int i = numberStr.toInt(&ok);
if (!ok) {
qlonglong ll = numberStr.toLongLong(&ok);
return ok ? ll : QVariant(numberStr);
}
return i;
} else {
uint u = numberStr.toUInt(&ok);
if (!ok) {
qulonglong ull = numberStr.toULongLong(&ok);
return ok ? ull : QVariant(numberStr);
}
return u;
}
}
/**
* lastIndexOfNumber
*/
static int lastIndexOfNumber(const QString &json, int index) {
int lastIndex;
for(lastIndex = index; lastIndex < json.size(); lastIndex++) {
if (QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1) {
break;
}
}
return lastIndex -1;
}
/**
* eatWhitespace
*/
static void eatWhitespace(const QString &json, int &index) {
for(; index < json.size(); index++) {
if (QString(" \t\n\r").indexOf(json[index]) == -1) {
break;
}
}
}
/**
* lookAhead
*/
static int lookAhead(const QString &json, int index) {
int saveIndex = index;
return nextToken(json, saveIndex);
}
/**
* nextToken
*/
static int nextToken(const QString &json, int &index) {
eatWhitespace(json, index);
if (index == json.size()) {
return JsonTokenNone;
}
QChar c = json[index];
index++;
switch(c.toLatin1()) {
case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose;
case '[': return JsonTokenSquaredOpen;
case ']': return JsonTokenSquaredClose;
case ',': return JsonTokenComma;
case '"': return JsonTokenString;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-': return JsonTokenNumber;
case ':': return JsonTokenColon;
}
index--; // ^ WTF?
int remainingLength = json.size() - index;
// True
if (remainingLength >= 4) {
if (json[index] == 't' && json[index + 1] == 'r' &&
json[index + 2] == 'u' && json[index + 3] == 'e') {
index += 4;
return JsonTokenTrue;
}
}
// False
if (remainingLength >= 5) {
if (json[index] == 'f' && json[index + 1] == 'a' &&
json[index + 2] == 'l' && json[index + 3] == 's' &&
json[index + 4] == 'e') {
index += 5;
return JsonTokenFalse;
}
}
// Null
if (remainingLength >= 4) {
if (json[index] == 'n' && json[index + 1] == 'u' &&
json[index + 2] == 'l' && json[index + 3] == 'l') {
index += 4;
return JsonTokenNull;
}
}
return JsonTokenNone;
}
void setDateTimeFormat(const QString &format) {
dateTimeFormat = format;
}
void setDateFormat(const QString &format) {
dateFormat = format;
}
QString getDateTimeFormat() {
return dateTimeFormat;
}
QString getDateFormat() {
return dateFormat;
}
void setPrettySerialize(bool enabled) {
prettySerialize = enabled;
}
bool isPrettySerialize() {
return prettySerialize;
}
QQueue<BuilderJsonObject *> BuilderJsonObject::created_list;
BuilderJsonObject::BuilderJsonObject() {
// clean objects previous "created"
while (!BuilderJsonObject::created_list.isEmpty()) {
delete BuilderJsonObject::created_list.dequeue();
}
}
BuilderJsonObject::BuilderJsonObject(JsonObject &json) {
BuilderJsonObject();
obj = json;
}
BuilderJsonObject *BuilderJsonObject::set(const QString &key, const QVariant &value) {
obj[key] = value;
return this;
}
BuilderJsonObject *BuilderJsonObject::set(const QString &key, BuilderJsonObject *builder) {
return set(key, builder->create());
}
BuilderJsonObject *BuilderJsonObject::set(const QString &key, BuilderJsonArray *builder) {
return set(key, builder->create());
}
JsonObject BuilderJsonObject::create() {
BuilderJsonObject::created_list.enqueue(this);
return obj;
}
QQueue<BuilderJsonArray *> BuilderJsonArray::created_list;
BuilderJsonArray::BuilderJsonArray() {
// clean objects previous "created"
while (!BuilderJsonArray::created_list.isEmpty()) {
delete BuilderJsonArray::created_list.dequeue();
}
}
BuilderJsonArray::BuilderJsonArray(JsonArray &json) {
BuilderJsonArray();
array = json;
}
BuilderJsonArray *BuilderJsonArray::add(const QVariant &element) {
array.append(element);
return this;
}
BuilderJsonArray *BuilderJsonArray::add(BuilderJsonObject *builder) {
return add(builder->create());
}
BuilderJsonArray *BuilderJsonArray::add(BuilderJsonArray *builder) {
return add(builder->create());
}
JsonArray BuilderJsonArray::create() {
BuilderJsonArray::created_list.enqueue(this);
return array;
}
BuilderJsonObject *objectBuilder() {
return new BuilderJsonObject();
}
BuilderJsonObject *objectBuilder(JsonObject &json) {
return new BuilderJsonObject(json);
}
BuilderJsonArray *arrayBuilder() {
return new BuilderJsonArray();
}
BuilderJsonArray *arrayBuilder(JsonArray &json) {
return new BuilderJsonArray(json);
}
} //end namespace

265
client/platforms/ios/json.h Normal file
View file

@ -0,0 +1,265 @@
/**
* QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa.
* Copyright (C) 2011 Eeli Reilin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file json.h
*/
#ifndef JSON_H
#define JSON_H
#include <QVariant>
#include <QString>
#include <QQueue>
/**
* \namespace QtJson
* \brief A JSON data parser
*
* Json parses a JSON data into a QVariant hierarchy.
*/
namespace QtJson {
typedef QVariantMap JsonObject;
typedef QVariantList JsonArray;
/**
* Clone a JSON object (makes a deep copy)
*
* \param data The JSON object
*/
QVariant clone(const QVariant &data);
/**
* Insert value to JSON object (QVariantMap)
*
* \param v The JSON object
* \param key The key
* \param value The value
*/
void insert(QVariant &v, const QString &key, const QVariant &value);
/**
* Append value to JSON array (QVariantList)
*
* \param v The JSON array
* \param value The value
*/
void append(QVariant &v, const QVariant &value);
/**
* Parse a JSON string
*
* \param json The JSON data
*/
QVariant parse(const QString &json);
/**
* Parse a JSON string
*
* \param json The JSON data
* \param success The success of the parsing
*/
QVariant parse(const QString &json, bool &success);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
*
* \return QByteArray Textual JSON representation in UTF-8
*/
QByteArray serialize(const QVariant &data);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*
* \return QByteArray Textual JSON representation in UTF-8
*/
QByteArray serialize(const QVariant &data, bool &success, int _level = 0);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
*
* \return QString Textual JSON representation
*/
QString serializeStr(const QVariant &data);
/**
* This method generates a textual JSON representation
*
* \param data The JSON data generated by the parser.
* \param success The success of the serialization
*
* \return QString Textual JSON representation
*/
QString serializeStr(const QVariant &data, bool &success, int _level = 0);
/**
* This method sets date(time) format to be used for QDateTime::toString
* If QString is empty, Qt::TextDate is used.
*
* \param format The JSON data generated by the parser.
*/
void setDateTimeFormat(const QString& format);
void setDateFormat(const QString& format);
/**
* This method gets date(time) format to be used for QDateTime::toString
* If QString is empty, Qt::TextDate is used.
*/
QString getDateTimeFormat();
QString getDateFormat();
/**
* @brief setPrettySerialize enable/disabled pretty-print when serialize() a json
* @param enabled
*/
void setPrettySerialize(bool enabled);
/**
* @brief isPrettySerialize check if is enabled pretty-print when serialize() a json
* @return
*/
bool isPrettySerialize();
/**
* QVariant based Json object
*/
class Object : public QVariant {
template<typename T>
Object& insertKey(Object* ptr, const QString& key) {
T* p = (T*)ptr->data();
if (!p->contains(key)) p->insert(key, QVariant());
return *reinterpret_cast<Object*>(&p->operator[](key));
}
template<typename T>
void removeKey(Object *ptr, const QString& key) {
T* p = (T*)ptr->data();
p->remove(key);
}
public:
Object() : QVariant() {}
Object(const Object& ref) : QVariant(ref) {}
Object& operator=(const QVariant& rhs) {
/** It maybe more robust when running under Qt versions below 4.7 */
QObject * obj = qvariant_cast<QObject *>(rhs);
// setValue(rhs);
setValue(obj);
return *this;
}
Object& operator[](const QString& key) {
if (type() == QVariant::Map)
return insertKey<QVariantMap>(this, key);
else if (type() == QVariant::Hash)
return insertKey<QVariantHash>(this, key);
setValue(QVariantMap());
return insertKey<QVariantMap>(this, key);
}
const Object& operator[](const QString& key) const {
return const_cast<Object*>(this)->operator[](key);
}
void remove(const QString& key) {
if (type() == QVariant::Map)
removeKey<QVariantMap>(this, key);
else if (type() == QVariant::Hash)
removeKey<QVariantHash>(this, key);
}
};
class BuilderJsonArray;
/**
* @brief The BuilderJsonObject class
*/
class BuilderJsonObject {
public:
BuilderJsonObject();
BuilderJsonObject(JsonObject &json);
BuilderJsonObject *set(const QString &key, const QVariant &value);
BuilderJsonObject *set(const QString &key, BuilderJsonObject *builder);
BuilderJsonObject *set(const QString &key, BuilderJsonArray *builder);
JsonObject create();
private:
static QQueue<BuilderJsonObject *> created_list;
JsonObject obj;
};
/**
* @brief The BuilderJsonArray class
*/
class BuilderJsonArray {
public:
BuilderJsonArray();
BuilderJsonArray(JsonArray &json);
BuilderJsonArray *add(const QVariant &element);
BuilderJsonArray *add(BuilderJsonObject *builder);
BuilderJsonArray *add(BuilderJsonArray *builder);
JsonArray create();
private:
static QQueue<BuilderJsonArray *> created_list;
JsonArray array;
};
/**
* @brief Create a BuilderJsonObject
* @return
*/
BuilderJsonObject *objectBuilder();
/**
* @brief Create a BuilderJsonObject starting from copy of another json
* @return
*/
BuilderJsonObject *objectBuilder(JsonObject &json);
/**
* @brief Create a BuilderJsonArray
* @return
*/
BuilderJsonArray *arrayBuilder();
/**
* @brief Create a BuilderJsonArray starting from copy of another json
* @return
*/
BuilderJsonArray *arrayBuilder(JsonArray &json);
}
#endif //JSON_H

View file

@ -46,7 +46,7 @@ constexpr auto PERMISSIONHELPER_CLASS =
} // namespace
AndroidVpnProtocol::AndroidVpnProtocol(Protocol protocol, const QJsonObject &configuration, QObject* parent)
AndroidVpnProtocol::AndroidVpnProtocol(Proto protocol, const QJsonObject &configuration, QObject* parent)
: VpnProtocol(configuration, parent),
m_protocol(protocol),
m_binder(this)

View file

@ -17,7 +17,7 @@ class AndroidVpnProtocol : public VpnProtocol,
Q_OBJECT
public:
explicit AndroidVpnProtocol(Protocol protocol, const QJsonObject& configuration, QObject* parent = nullptr);
explicit AndroidVpnProtocol(Proto protocol, const QJsonObject& configuration, QObject* parent = nullptr);
static AndroidVpnProtocol* instance();
virtual ~AndroidVpnProtocol() override = default;
@ -53,7 +53,7 @@ protected:
private:
Protocol m_protocol;
Proto m_protocol;
bool m_serviceConnected = false;
std::function<void(const QString&)> m_logCallback;

View file

@ -0,0 +1,51 @@
#ifndef IOS_VPNPROTOCOL_H
#define IOS_VPNPROTOCOL_H
#include "vpnprotocol.h"
#include "protocols/protocols_defs.h"
using namespace amnezia;
class IOSVpnProtocol : public VpnProtocol
{
Q_OBJECT
public:
explicit IOSVpnProtocol(amnezia::Proto proto, const QJsonObject& configuration, QObject* parent = nullptr);
static IOSVpnProtocol* instance();
virtual ~IOSVpnProtocol() = default;
bool initialize();
virtual ErrorCode start() override;
virtual void stop() override;
void resume_start();
void checkStatus();
void setNotificationText(const QString& title, const QString& message,
int timerSec);
void setFallbackConnectedNotification();
void getBackendLogs(std::function<void(const QString&)>&& callback);
void cleanupBackendLogs();
signals:
protected slots:
protected:
private:
Proto m_protocol;
bool m_serviceConnected = false;
bool m_checkingStatus = false;
std::function<void(const QString&)> m_logCallback;
};
#endif // IOS_VPNPROTOCOL_H

View file

@ -0,0 +1,298 @@
#include <QDebug>
#include <QHostAddress>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRandomGenerator>
#include <QTextCodec>
#include <QTimer>
#include <QFile>
#include <QByteArray>
#include "json.h"
#include "ipaddressrange.h"
#include "ios_vpnprotocol.h"
#include "core/errorstrings.h"
#include "AmneziaVPN-Swift.h"
namespace
{
IOSVpnProtocol* s_instance = nullptr;
IOSVpnProtocolImpl* m_controller = nullptr;
}
IOSVpnProtocol::IOSVpnProtocol(Proto proto, const QJsonObject &configuration, QObject* parent)
: VpnProtocol(configuration, parent),
m_protocol(proto) {}
IOSVpnProtocol* IOSVpnProtocol::instance() {
return s_instance;
}
bool IOSVpnProtocol::initialize()
{
qDebug() << "Initializing Swift Controller";
static bool creating = false;
// No nested creation!
Q_ASSERT(creating == false);
creating = true;
if (!m_controller) {
bool ok;
QtJson::JsonObject result = QtJson::parse(QJsonDocument(m_rawConfig).toJson(), ok).toMap();
if(!ok) {
qDebug() << QString("An error occurred during parsing");
return false;
}
QString vpnProto = result["protocol"].toString();
qDebug() << "protocol: " << vpnProto;
qDebug() << "config data => ";
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString privateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(privateKey.toLocal8Bit());
qDebug() << " - " << "client_priv_key: " << config["client_priv_key"].toString();
qDebug() << " - " << "client_pub_key: " << config["client_pub_key"].toString();
qDebug() << " - " << "interface config: " << config["config"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QString dns = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast();
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QString allowedips = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast();
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
qDebug() << " - " << "[Interface] address: " << addr;
qDebug() << " - " << "[Interface] dns: " << dns;
qDebug() << " - " << "[Interface] private key: " << privkey;
qDebug() << " - " << "[Peer] public key: " << pubkey;
qDebug() << " - " << "[Peer] preshared key: " << presharedkey;
qDebug() << " - " << "[Peer] allowed ips: " << allowedips;
qDebug() << " - " << "[Peer] endpoint: " << endpoint;
qDebug() << " - " << "[Peer] keepalive: " << keepalive;
qDebug() << " - " << "hostName: " << config["hostName"].toString();
qDebug() << " - " << "psk_key: " << config["psk_key"].toString();
qDebug() << " - " << "server_pub_key: " << config["server_pub_key"].toString();
m_controller = [[IOSVpnProtocolImpl alloc] initWithBundleID:@VPN_NE_BUNDLEID
privateKey:key.toNSData()
deviceIpv4Address:addr.toNSString()
deviceIpv6Address:@"::/0"
closure:^(ConnectionState state, NSDate* date) {
qDebug() << "Creation completed with connection state:" << state;
creating = false;
switch (state) {
case ConnectionStateError: {
[m_controller dealloc];
m_controller = nullptr;
emit initialized(false, false, QDateTime());
return;
}
case ConnectionStateConnected: {
Q_ASSERT(date);
QDateTime qtDate(QDateTime::fromNSDate(date));
emit initialized(true, true, qtDate);
return;
}
case ConnectionStateDisconnected:
// Just in case we are connecting, let's call disconnect.
[m_controller disconnect];
emit initialized(true, false, QDateTime());
return;
}
}
callback:^(BOOL a_connected) {
qDebug() << "State changed: " << a_connected;
if (a_connected) {
emit isConnected();
return;
}
emit isDisconnected();
}];
}
return true;
}
ErrorCode IOSVpnProtocol::start()
{
bool ok;
QtJson::JsonObject result = QtJson::parse(QJsonDocument(m_rawConfig).toJson(), ok).toMap();
if(!ok) {
qDebug() << QString("An error occurred during config parsing");
return InternalError;
}
QString protocol = result["protocol"].toString();
QtJson::JsonObject config = result["wireguard_config_data"].toMap();
QString clientPrivateKey = config["client_priv_key"].toString();
QByteArray key = QByteArray::fromBase64(clientPrivateKey.toLocal8Bit());
QString clientPubKey = config["client_pub_key"].toString();
QString addr = config["config"].toString().split("\n").takeAt(1).split(" = ").takeLast();
QStringList dnsServersList = config["config"].toString().split("\n").takeAt(2).split(" = ").takeLast().split(", ");
QString privkey = config["config"].toString().split("\n").takeAt(3).split(" = ").takeLast();
QString pubkey = config["config"].toString().split("\n").takeAt(6).split(" = ").takeLast();
QString presharedkey = config["config"].toString().split("\n").takeAt(7).split(" = ").takeLast();
QStringList allowedIPList = config["config"].toString().split("\n").takeAt(8).split(" = ").takeLast().split(", ");
QString endpoint = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast();
QString serverAddr = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeFirst();
QString port = config["config"].toString().split("\n").takeAt(9).split(" = ").takeLast().split(":").takeLast();
QString keepalive = config["config"].toString().split("\n").takeAt(10).split(" = ").takeLast();
QString hostname = config["hostName"].toString();
QString pskKey = config["psk_key"].toString();
QString serverPubKey = config["server_pub_key"].toString();
qDebug() << "IOSVPNProtocol starts for" << hostname;
qDebug() << "DNS:" << dnsServersList.takeFirst().toNSString();
qDebug() << "serverPublicKey:" << serverPubKey.toNSString();
qDebug() << "serverIpv4AddrIn:" << serverAddr.toNSString();
qDebug() << "serverPort:" << (uint32_t)port.toInt();
qDebug() << "allowed ip list" << allowedIPList;
NSMutableArray<VPNIPAddressRange*>* allowedIPAddressRangesNS =
[NSMutableArray<VPNIPAddressRange*> arrayWithCapacity:allowedIPList.length()];
for (const IPAddressRange item : allowedIPList) {
VPNIPAddressRange* range =
[[VPNIPAddressRange alloc] initWithAddress:item.ipAddress().toNSString()
networkPrefixLength:item.range()
isIpv6:item.type() == IPAddressRange::IPv6];
[allowedIPAddressRangesNS addObject:[range autorelease]];
}
[m_controller connectWithDnsServer:dnsServersList.takeFirst().toNSString()
serverIpv6Gateway:@"FE80::1"
serverPublicKey:serverPubKey.toNSString()
serverIpv4AddrIn:serverAddr.toNSString()
serverPort:port.toInt()
allowedIPAddressRanges:allowedIPAddressRangesNS
ipv6Enabled:NO
reason:0
failureCallback:^() {
qDebug() << "IOSVPNProtocol - connection failed";
emit isDisconnected();
}];
return NoError;
}
void IOSVpnProtocol::stop()
{
if (!m_controller) {
qDebug() << "Not correctly initialized";
emit isDisconnected();
return;
}
[m_controller disconnect];
}
void IOSVpnProtocol::resume_start()
{
}
void IOSVpnProtocol::checkStatus()
{
qDebug() << "Checking status";
if (m_checkingStatus) {
qDebug() << "We are still waiting for the previous status.";
return;
}
if (!m_controller) {
qDebug() << "Not correctly initialized";
return;
}
m_checkingStatus = true;
[m_controller checkStatusWithCallback:^(NSString* serverIpv4Gateway, NSString* deviceIpv4Address,
NSString* configString) {
QString config = QString::fromNSString(configString);
m_checkingStatus = false;
if (config.isEmpty()) {
return;
}
uint64_t txBytes = 0;
uint64_t rxBytes = 0;
QStringList lines = config.split("\n");
for (const QString& line : lines) {
if (line.startsWith("tx_bytes=")) {
txBytes = line.split("=")[1].toULongLong();
} else if (line.startsWith("rx_bytes=")) {
rxBytes = line.split("=")[1].toULongLong();
}
if (txBytes && rxBytes) {
break;
}
}
qDebug() << "ServerIpv4Gateway:" << QString::fromNSString(serverIpv4Gateway)
<< "DeviceIpv4Address:" << QString::fromNSString(deviceIpv4Address)
<< "RxBytes:" << rxBytes << "TxBytes:" << txBytes;
emit bytesChanged(rxBytes, txBytes);
}];
}
void IOSVpnProtocol::setNotificationText(const QString &title, const QString &message, int timerSec)
{
// TODO: add user notifications?
}
void IOSVpnProtocol::setFallbackConnectedNotification()
{
// TODO: add default user notifications?
}
void IOSVpnProtocol::getBackendLogs(std::function<void (const QString &)> &&callback)
{
std::function<void(const QString&)> a_callback = std::move(callback);
QString groupId(GROUP_ID);
NSURL* groupPath = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:groupId.toNSString()];
NSURL* path = [groupPath URLByAppendingPathComponent:@"networkextension.log"];
QFile file(QString::fromNSString([path path]));
if (!file.open(QIODevice::ReadOnly)) {
a_callback("Network extension log file missing or unreadable.");
return;
}
QByteArray content = file.readAll();
a_callback(content);
}
void IOSVpnProtocol::cleanupBackendLogs()
{
QString groupId(GROUP_ID);
NSURL* groupPath = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:groupId.toNSString()];
NSURL* path = [groupPath URLByAppendingPathComponent:@"networkextension.log"];
QFile file(QString::fromNSString([path path]));
file.remove();
}

View file

@ -2,7 +2,7 @@
using namespace amnezia;
QDebug operator<<(QDebug debug, const amnezia::ProtocolEnumNS::Protocol &p)
QDebug operator<<(QDebug debug, const amnezia::ProtocolEnumNS::Proto &p)
{
QDebugStateSaver saver(debug);
debug.nospace() << ProtocolProps::protoToString(p);
@ -10,29 +10,29 @@ QDebug operator<<(QDebug debug, const amnezia::ProtocolEnumNS::Protocol &p)
return debug;
}
amnezia::Protocol ProtocolProps::protoFromString(QString proto){
QMetaEnum metaEnum = QMetaEnum::fromType<Protocol>();
amnezia::Proto ProtocolProps::protoFromString(QString proto){
QMetaEnum metaEnum = QMetaEnum::fromType<Proto>();
for (int i = 0; i < metaEnum.keyCount(); ++i) {
Protocol p = static_cast<Protocol>(i);
Proto p = static_cast<Proto>(i);
if (proto == protoToString(p)) return p;
}
return Protocol::Any;
return Proto::Any;
}
QString ProtocolProps::protoToString(amnezia::Protocol p){
if (p == Protocol::Any) return "";
QString ProtocolProps::protoToString(amnezia::Proto p){
if (p == Proto::Any) return "";
QMetaEnum metaEnum = QMetaEnum::fromType<Protocol>();
QMetaEnum metaEnum = QMetaEnum::fromType<Proto>();
QString protoKey = metaEnum.valueToKey(static_cast<int>(p));
return protoKey.toLower();
}
QList<amnezia::Protocol> ProtocolProps::allProtocols()
QList<amnezia::Proto> ProtocolProps::allProtocols()
{
QMetaEnum metaEnum = QMetaEnum::fromType<Protocol>();
QList<Protocol> all;
QMetaEnum metaEnum = QMetaEnum::fromType<Proto>();
QList<Proto> all;
for (int i = 0; i < metaEnum.keyCount(); ++i) {
all.append(static_cast<Protocol>(i));
all.append(static_cast<Proto>(i));
}
return all;
@ -48,7 +48,7 @@ TransportProto ProtocolProps::transportProtoFromString(QString p)
return TransportProto::Udp;
}
QString ProtocolProps::transportProtoToString(TransportProto proto, Protocol p)
QString ProtocolProps::transportProtoToString(TransportProto proto, Proto p)
{
QMetaEnum metaEnum = QMetaEnum::fromType<TransportProto>();
QString protoKey = metaEnum.valueToKey(static_cast<int>(proto));
@ -66,124 +66,124 @@ QString ProtocolProps::transportProtoToString(TransportProto proto, Protocol p)
}
QMap<amnezia::Protocol, QString> ProtocolProps::protocolHumanNames()
QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
{
return {
{Protocol::OpenVpn, "OpenVPN"},
{Protocol::ShadowSocks, "ShadowSocks"},
{Protocol::Cloak, "Cloak"},
{Protocol::WireGuard, "WireGuard"},
{Protocol::Ikev2, "IKEv2"},
{Protocol::L2tp, "L2TP"},
{Proto::OpenVpn, "OpenVPN"},
{Proto::ShadowSocks, "ShadowSocks"},
{Proto::Cloak, "Cloak"},
{Proto::WireGuard, "WireGuard"},
{Proto::Ikev2, "IKEv2"},
{Proto::L2tp, "L2TP"},
{Protocol::TorWebSite, "Web site in TOR network"},
{Protocol::Dns, "DNS Service"},
{Protocol::FileShare, "File Sharing Service"},
{Protocol::Sftp, QObject::tr("Sftp service")}
{Proto::TorWebSite, "Web site in TOR network"},
{Proto::Dns, "DNS Service"},
{Proto::FileShare, "File Sharing Service"},
{Proto::Sftp, QObject::tr("Sftp service")}
};
}
QMap<amnezia::Protocol, QString> ProtocolProps::protocolDescriptions()
QMap<amnezia::Proto, QString> ProtocolProps::protocolDescriptions()
{
return {};
}
amnezia::ServiceType ProtocolProps::protocolService(Protocol p)
amnezia::ServiceType ProtocolProps::protocolService(Proto p)
{
switch (p) {
case Protocol::Any : return ServiceType::None;
case Protocol::OpenVpn : return ServiceType::Vpn;
case Protocol::Cloak : return ServiceType::Vpn;
case Protocol::ShadowSocks : return ServiceType::Vpn;
case Protocol::WireGuard : return ServiceType::Vpn;
case Protocol::TorWebSite : return ServiceType::Other;
case Protocol::Dns : return ServiceType::Other;
case Protocol::FileShare : return ServiceType::Other;
case Proto::Any : return ServiceType::None;
case Proto::OpenVpn : return ServiceType::Vpn;
case Proto::Cloak : return ServiceType::Vpn;
case Proto::ShadowSocks : return ServiceType::Vpn;
case Proto::WireGuard : return ServiceType::Vpn;
case Proto::TorWebSite : return ServiceType::Other;
case Proto::Dns : return ServiceType::Other;
case Proto::FileShare : return ServiceType::Other;
default: return ServiceType::Other;
}
}
int ProtocolProps::defaultPort(Protocol p)
int ProtocolProps::defaultPort(Proto p)
{
switch (p) {
case Protocol::Any : return -1;
case Protocol::OpenVpn : return 1194;
case Protocol::Cloak : return 443;
case Protocol::ShadowSocks : return 6789;
case Protocol::WireGuard : return 51820;
case Protocol::Ikev2 : return -1;
case Protocol::L2tp : return -1;
case Proto::Any : return -1;
case Proto::OpenVpn : return 1194;
case Proto::Cloak : return 443;
case Proto::ShadowSocks : return 6789;
case Proto::WireGuard : return 51820;
case Proto::Ikev2 : return -1;
case Proto::L2tp : return -1;
case Protocol::TorWebSite : return -1;
case Protocol::Dns : return 53;
case Protocol::FileShare : return 139;
case Protocol::Sftp : return 222;
case Proto::TorWebSite : return -1;
case Proto::Dns : return 53;
case Proto::FileShare : return 139;
case Proto::Sftp : return 222;
default: return -1;
}
}
bool ProtocolProps::defaultPortChangeable(Protocol p)
bool ProtocolProps::defaultPortChangeable(Proto p)
{
switch (p) {
case Protocol::Any : return false;
case Protocol::OpenVpn : return true;
case Protocol::Cloak : return true;
case Protocol::ShadowSocks : return true;
case Protocol::WireGuard : return true;
case Protocol::Ikev2 : return false;
case Protocol::L2tp : return false;
case Proto::Any : return false;
case Proto::OpenVpn : return true;
case Proto::Cloak : return true;
case Proto::ShadowSocks : return true;
case Proto::WireGuard : return true;
case Proto::Ikev2 : return false;
case Proto::L2tp : return false;
case Protocol::TorWebSite : return true;
case Protocol::Dns : return false;
case Protocol::FileShare : return false;
case Proto::TorWebSite : return true;
case Proto::Dns : return false;
case Proto::FileShare : return false;
default: return -1;
}
}
TransportProto ProtocolProps::defaultTransportProto(Protocol p)
TransportProto ProtocolProps::defaultTransportProto(Proto p)
{
switch (p) {
case Protocol::Any : return TransportProto::Udp;
case Protocol::OpenVpn : return TransportProto::Udp;
case Protocol::Cloak : return TransportProto::Tcp;
case Protocol::ShadowSocks : return TransportProto::Tcp;
case Protocol::WireGuard : return TransportProto::Udp;
case Protocol::Ikev2 : return TransportProto::Udp;
case Protocol::L2tp : return TransportProto::Udp;
case Proto::Any : return TransportProto::Udp;
case Proto::OpenVpn : return TransportProto::Udp;
case Proto::Cloak : return TransportProto::Tcp;
case Proto::ShadowSocks : return TransportProto::Tcp;
case Proto::WireGuard : return TransportProto::Udp;
case Proto::Ikev2 : return TransportProto::Udp;
case Proto::L2tp : return TransportProto::Udp;
// non-vpn
case Protocol::TorWebSite : return TransportProto::Tcp;
case Protocol::Dns : return TransportProto::Udp;
case Protocol::FileShare : return TransportProto::Udp;
case Protocol::Sftp : return TransportProto::Tcp;
case Proto::TorWebSite : return TransportProto::Tcp;
case Proto::Dns : return TransportProto::Udp;
case Proto::FileShare : return TransportProto::Udp;
case Proto::Sftp : return TransportProto::Tcp;
}
}
bool ProtocolProps::defaultTransportProtoChangeable(Protocol p)
bool ProtocolProps::defaultTransportProtoChangeable(Proto p)
{
switch (p) {
case Protocol::Any : return false;
case Protocol::OpenVpn : return true;
case Protocol::Cloak : return false;
case Protocol::ShadowSocks : return false;
case Protocol::WireGuard : return false;
case Protocol::Ikev2 : return false;
case Protocol::L2tp : return false;
case Proto::Any : return false;
case Proto::OpenVpn : return true;
case Proto::Cloak : return false;
case Proto::ShadowSocks : return false;
case Proto::WireGuard : return false;
case Proto::Ikev2 : return false;
case Proto::L2tp : return false;
// non-vpn
case Protocol::TorWebSite : return false;
case Protocol::Dns : return false;
case Protocol::FileShare : return false;
case Protocol::Sftp : return false;
case Proto::TorWebSite : return false;
case Proto::Dns : return false;
case Proto::FileShare : return false;
case Proto::Sftp : return false;
default: return false;
}
}
QString ProtocolProps::key_proto_config_data(Protocol p)
QString ProtocolProps::key_proto_config_data(Proto p)
{
return protoToString(p) + "_config_data";
}
QString ProtocolProps::key_proto_config_path(Protocol p)
QString ProtocolProps::key_proto_config_path(Proto p)
{
return protoToString(p) + "_config_path";
}

View file

@ -24,7 +24,7 @@ constexpr char containers[] = "containers";
constexpr char container[] = "container";
constexpr char defaultContainer[] = "defaultContainer";
constexpr char protocol[] = "protocol";
constexpr char vpnproto[] = "protocol";
constexpr char protocols[] = "protocols";
constexpr char remote[] = "remote";
@ -121,7 +121,7 @@ enum TransportProto {
};
Q_ENUM_NS(TransportProto)
enum Protocol {
enum Proto {
Any = 0,
OpenVpn,
ShadowSocks,
@ -136,7 +136,7 @@ enum Protocol {
FileShare,
Sftp
};
Q_ENUM_NS(Protocol)
Q_ENUM_NS(Proto)
enum ServiceType {
None = 0,
@ -153,29 +153,29 @@ class ProtocolProps : public QObject
Q_OBJECT
public:
Q_INVOKABLE static QList<Protocol> allProtocols();
Q_INVOKABLE static QList<Proto> allProtocols();
// spelling may differ for various protocols - TCP for OpenVPN, tcp for others
Q_INVOKABLE static TransportProto transportProtoFromString(QString p);
Q_INVOKABLE static QString transportProtoToString(TransportProto proto, Protocol p = Protocol::Any);
Q_INVOKABLE static QString transportProtoToString(TransportProto proto, Proto p = Proto::Any);
Q_INVOKABLE static Protocol protoFromString(QString p);
Q_INVOKABLE static QString protoToString(Protocol p);
Q_INVOKABLE static Proto protoFromString(QString p);
Q_INVOKABLE static QString protoToString(Proto p);
Q_INVOKABLE static QMap<Protocol, QString> protocolHumanNames();
Q_INVOKABLE static QMap<Protocol, QString> protocolDescriptions();
Q_INVOKABLE static QMap<Proto, QString> protocolHumanNames();
Q_INVOKABLE static QMap<Proto, QString> protocolDescriptions();
Q_INVOKABLE static ServiceType protocolService(Protocol p);
Q_INVOKABLE static ServiceType protocolService(Proto p);
Q_INVOKABLE static int defaultPort(Protocol p);
Q_INVOKABLE static bool defaultPortChangeable(Protocol p);
Q_INVOKABLE static int defaultPort(Proto p);
Q_INVOKABLE static bool defaultPortChangeable(Proto p);
Q_INVOKABLE static TransportProto defaultTransportProto(Protocol p);
Q_INVOKABLE static bool defaultTransportProtoChangeable(Protocol p);
Q_INVOKABLE static TransportProto defaultTransportProto(Proto p);
Q_INVOKABLE static bool defaultTransportProtoChangeable(Proto p);
Q_INVOKABLE static QString key_proto_config_data(Protocol p);
Q_INVOKABLE static QString key_proto_config_path(Protocol p);
Q_INVOKABLE static QString key_proto_config_data(Proto p);
Q_INVOKABLE static QString key_proto_config_path(Proto p);
};
@ -207,6 +207,6 @@ static void declareQmlProtocolEnum() {
} // namespace amnezia
QDebug operator<<(QDebug debug, const amnezia::Protocol &p);
QDebug operator<<(QDebug debug, const amnezia::Proto &p);
#endif // PROTOCOLS_DEFS_H

View file

@ -15,7 +15,7 @@
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
: QObject(parent),
m_connectionState(ConnectionState::Unknown),
m_connectionState(VpnConnectionState::Unknown),
m_rawConfig(configuration),
m_timeoutTimer(new QTimer(this)),
m_receivedBytes(0),
@ -29,7 +29,7 @@ void VpnProtocol::setLastError(ErrorCode lastError)
{
m_lastError = lastError;
if (lastError){
setConnectionState(ConnectionState::Error);
setConnectionState(VpnConnectionState::Error);
}
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
}
@ -57,7 +57,7 @@ void VpnProtocol::stopTimeoutTimer()
m_timeoutTimer->stop();
}
VpnProtocol::ConnectionState VpnProtocol::connectionState() const
VpnProtocol::VpnConnectionState VpnProtocol::connectionState() const
{
return m_connectionState;
}
@ -70,19 +70,19 @@ void VpnProtocol::setBytesChanged(quint64 receivedBytes, quint64 sentBytes)
m_sentBytes = sentBytes;
}
void VpnProtocol::setConnectionState(VpnProtocol::ConnectionState state)
void VpnProtocol::setConnectionState(VpnProtocol::VpnConnectionState state)
{
qDebug() << "VpnProtocol::setConnectionState" << textConnectionState(state);
if (m_connectionState == state) {
return;
}
if (m_connectionState == ConnectionState::Disconnected && state == ConnectionState::Disconnecting) {
if (m_connectionState == VpnConnectionState::Disconnected && state == VpnConnectionState::Disconnecting) {
return;
}
m_connectionState = state;
if (m_connectionState == ConnectionState::Disconnected) {
if (m_connectionState == VpnConnectionState::Disconnected) {
m_receivedBytes = 0;
m_sentBytes = 0;
}
@ -116,17 +116,17 @@ QString VpnProtocol::routeGateway() const
return m_routeGateway;
}
QString VpnProtocol::textConnectionState(ConnectionState connectionState)
QString VpnProtocol::textConnectionState(VpnConnectionState connectionState)
{
switch (connectionState) {
case ConnectionState::Unknown: return tr("Unknown");
case ConnectionState::Disconnected: return tr("Disconnected");
case ConnectionState::Preparing: return tr("Preparing");
case ConnectionState::Connecting: return tr("Connecting...");
case ConnectionState::Connected: return tr("Connected");
case ConnectionState::Disconnecting: return tr("Disconnecting...");
case ConnectionState::Reconnecting: return tr("Reconnecting...");
case ConnectionState::Error: return tr("Error");
case VpnConnectionState::Unknown: return tr("Unknown");
case VpnConnectionState::Disconnected: return tr("Disconnected");
case VpnConnectionState::Preparing: return tr("Preparing");
case VpnConnectionState::Connecting: return tr("Connecting...");
case VpnConnectionState::Connected: return tr("Connected");
case VpnConnectionState::Disconnecting: return tr("Disconnecting...");
case VpnConnectionState::Reconnecting: return tr("Reconnecting...");
case VpnConnectionState::Error: return tr("Error");
default:
;
}
@ -141,10 +141,10 @@ QString VpnProtocol::textConnectionState() const
bool VpnProtocol::isConnected() const
{
return m_connectionState == ConnectionState::Connected;
return m_connectionState == VpnConnectionState::Connected;
}
bool VpnProtocol::isDisconnected() const
{
return m_connectionState == ConnectionState::Disconnected;
return m_connectionState == VpnConnectionState::Disconnected;
}

View file

@ -20,10 +20,10 @@ public:
explicit VpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
virtual ~VpnProtocol() override = default;
enum ConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, Reconnecting, Error};
Q_ENUM(ConnectionState)
enum VpnConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, Reconnecting, Error};
Q_ENUM(VpnConnectionState)
static QString textConnectionState(ConnectionState connectionState);
static QString textConnectionState(VpnConnectionState connectionState);
virtual ErrorCode prepare() { return ErrorCode::NoError; }
@ -32,7 +32,7 @@ public:
virtual ErrorCode start() = 0;
virtual void stop() = 0;
ConnectionState connectionState() const;
VpnConnectionState connectionState() const;
ErrorCode lastError() const;
QString textConnectionState() const;
void setLastError(ErrorCode lastError);
@ -44,7 +44,7 @@ public:
signals:
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
void connectionStateChanged(VpnProtocol::ConnectionState state);
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
void timeoutTimerEvent();
void protocolError(amnezia::ErrorCode e);
@ -63,9 +63,9 @@ protected:
void stopTimeoutTimer();
virtual void setBytesChanged(quint64 receivedBytes, quint64 sentBytes);
virtual void setConnectionState(VpnProtocol::ConnectionState state);
virtual void setConnectionState(VpnProtocol::VpnConnectionState state);
ConnectionState m_connectionState;
VpnConnectionState m_connectionState;
QString m_routeGateway;
QString m_vpnLocalAddress;
QString m_vpnGateway;

51
client/scripts/commons.sh Normal file
View file

@ -0,0 +1,51 @@
#!/bin/bash
printv() {
if [ -t 1 ]; then
NCOLORS=$(tput colors)
if test -n "$NCOLORS" && test "$NCOLORS" -ge 8; then
NORMAL="$(tput sgr0)"
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
fi
fi
if [[ $2 = 'G' ]]; then
# shellcheck disable=SC2086
echo $1 -e "${GREEN}$3${NORMAL}"
elif [[ $2 = 'Y' ]]; then
# shellcheck disable=SC2086
echo $1 -e "${YELLOW}$3${NORMAL}"
elif [[ $2 = 'N' ]]; then
# shellcheck disable=SC2086
echo $1 -e "$3"
else
# shellcheck disable=SC2086
echo $1 -e "${RED}$3${NORMAL}"
fi
}
print() {
printv '' "$1" "$2"
}
printn() {
printv "-n" "$1" "$2"
}
error() {
printv '' R "$1"
}
die() {
if [[ "$1" ]]; then
error "$1"
else
error Failed
fi
exit 1
}

227
client/scripts/ios_compile.sh Executable file
View file

@ -0,0 +1,227 @@
#!/bin/bash
. $(dirname $0)/commons.sh
if [ -f .env ]; then
. .env
fi
RELEASE=1
OS=
NETWORKEXTENSION=
ADJUST_SDK_TOKEN=
ADJUST="CONFIG-=adjust"
helpFunction() {
print G "Usage:"
print N "\t$0 <ios> [-d|--debug] [-n|--networkextension] [-a|--adjusttoken <adjust_token>]"
print N ""
print N "By default, the project is compiled in release mode. Use -d or --debug for a debug build."
print N "Use -n or --networkextension to force the network-extension component for MacOS too."
print N ""
print N "If MVPN_IOS_ADJUST_TOKEN env is found, this will be used at compilation time."
print N ""
print G "Config variables:"
print N "\tQT_MACOS_BIN=</path/of/the/qt/bin/folder/for/macos>"
print N "\tQT_IOS_BIN=</path/of/the/qt/bin/folder/for/ios>"
print N "\tMVPN_IOS_ADJUST_TOKEN=<token>"
print N ""
exit 0
}
print N "This script compiles AmneziaVPN for MacOS/iOS"
print N ""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-a | --adjusttoken)
ADJUST_SDK_TOKEN="$2"
shift
shift
;;
-d | --debug)
RELEASE=
shift
;;
-n | --networkextension)
NETWORKEXTENSION=1
shift
;;
-h | --help)
helpFunction
;;
*)
if [[ "$OS" ]]; then
helpFunction
fi
OS=$1
shift
;;
esac
done
fetch() {
if command -v "wget" &>/dev/null; then
wget -nc -O "$2" "$1"
return
fi
if command -v "curl" &>/dev/null; then
curl "$1" -o "$2" -s -L
return
fi
die "You must have 'wget' or 'curl' installed."
}
sha256() {
if command -v "sha256sum" &>/dev/null; then
sha256sum "$1"
return 0
fi
if command -v "openssl" &>/dev/null; then
openssl dgst -sha256 "$1"
return 0
fi
die "You must have 'sha256sum' or 'openssl' installed."
}
if [[ "$OS" != "macos" ]] && [[ "$OS" != "ios" ]] && [[ "$OS" != "macostest" ]]; then
helpFunction
fi
if ! [[ "$ADJUST_SDK_TOKEN" ]] && [[ "$MVPN_IOS_ADJUST_TOKEN" ]]; then
print Y "Using the MVPN_IOS_ADJUST_TOKEN value for the adjust token"
ADJUST_SDK_TOKEN=$MVPN_IOS_ADJUST_TOKEN
fi
if [[ "$OS" == "ios" ]]; then
# Network-extension is the default for IOS
NETWORKEXTENSION=1
fi
if ! [ -d "ios" ] || ! [ -d "macos" ]; then
die "This script must be executed at the root of the repository."
fi
QMAKE=qmake
if [ "$OS" = "macos" ] && ! [ "$QT_MACOS_BIN" = "" ]; then
QMAKE=$QT_MACOS_BIN/qmake
elif [ "$OS" = "macostest" ] && ! [ "$QT_MACOS_BIN" = "" ]; then
QMAKE=$QT_MACOS_BIN/qmake
elif [ "$OS" = "ios" ] && ! [ "$QT_IOS_BIN" = "" ]; then
QMAKE=$QT_IOS_BIN/qmake
fi
$QMAKE -v &>/dev/null || die "qmake doesn't exist or it fails"
printn Y "Retrieve the wireguard-go version... "
(cd macos/gobridge && go list -m golang.zx2c4.com/wireguard | sed -n 's/.*v\([0-9.]*\).*/#define WIREGUARD_GO_VERSION "\1"/p') > macos/gobridge/wireguard-go-version.h
print G "done."
printn Y "Cleaning the existing project... "
rm -rf mozillavpn.xcodeproj/ || die "Failed to remove things"
print G "done."
#print Y "Importing translation files..."
#git submodule update --remote --depth 1 i18n || die "Failed to fetch newest translation files"
#python scripts/importLanguages.py $([[ "$OS" = "macos" ]] && echo "-m" || echo "") || die "Failed to import languages"
#
#print Y "Generating glean samples..."
#python scripts/generate_glean.py || die "Failed to generate glean samples"
printn Y "Extract the project version... "
SHORTVERSION=$(cat version.pri | grep VERSION | grep defined | cut -d= -f2 | tr -d \ )
FULLVERSION=$(echo $SHORTVERSION | cut -d. -f1).$(date +"%Y%m%d%H%M")
print G "$SHORTVERSION - $FULLVERSION"
MACOS_FLAGS="
QTPLUGIN+=qsvg
CONFIG-=static
CONFIG+=balrog
MVPN_MACOS=1
"
MACOSTEST_FLAGS="
QTPLUGIN+=qsvg
CONFIG-=static
CONFIG+=DUMMY
"
IOS_FLAGS="
MVPN_IOS=1
Q_OS_IOS=1
"
#printn Y "Mode: "
#if [[ "$RELEASE" ]]; then
# print G "release"
# MODE="CONFIG-=debug CONFIG+=release CONFIG-=debug_and_release"
#else
# print G "debug"
# MODE="CONFIG+=debug CONFIG-=release CONFIG-=debug_and_release"
#fi
MODE="CONFIG-=debug CONFIG+=release CONFIG-=debug_and_release"
OSRUBY=$OS
printn Y "OS: "
print G "$OS"
if [ "$OS" = "macos" ]; then
PLATFORM=$MACOS_FLAGS
elif [ "$OS" = "macostest" ]; then
OSRUBY=macos
PLATFORM=$MACOSTEST_FLAGS
elif [ "$OS" = "ios" ]; then
PLATFORM=$IOS_FLAGS
if [[ "$ADJUST_SDK_TOKEN" ]]; then
printn Y "ADJUST_SDK_TOKEN: "
print G "$ADJUST_SDK_TOKEN"
ADJUST="CONFIG+=adjust"
fi
else
die "Why we are here?"
fi
VPNMODE=
printn Y "VPN mode: "
if [[ "$NETWORKEXTENSION" ]]; then
print G network-extension
VPNMODE="CONFIG+=networkextension"
else
print G daemon
fi
printn Y "Web-Extension: "
WEMODE=
if [ "$OS" = "macos" ]; then
print G web-extension
WEMODE="CONFIG+=webextension"
else
print G none
fi
print Y "Creating the xcode project via qmake..."
$QMAKE \
VERSION=$SHORTVERSION \
BUILD_ID=$FULLVERSION \
-spec macx-xcode \
$MODE \
$VPNMODE \
$WEMODE \
$PLATFORM \
$ADJUST \
./client.pro || die "Compilation failed"
print Y "Patching the xcode project..."
ruby scripts/xcode_patcher.rb "AmneziaVPN.xcodeproj" "$SHORTVERSION" "$FULLVERSION" "$OSRUBY" "$NETWORKEXTENSION" "$ADJUST_SDK_TOKEN" || die "Failed to merge xcode with wireguard"
print G "done."
print Y "Opening in XCode..."
open AmneziaVPN.xcodeproj
print G "All done!"

View file

@ -0,0 +1,664 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
require 'xcodeproj'
class XCodeprojPatcher
attr :project
attr :target_main
attr :target_extension
def run(file, shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token)
open_project file
open_target_main
die 'IOS requires networkExtension mode' if not networkExtension and platform == 'ios'
group = @project.main_group.new_group('Configuration')
@configFile = group.new_file('xcode.xconfig')
setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token
# if platform == 'macos'
# setup_target_loginitem shortVersion, fullVersion, configHash
# setup_target_nativemessaging shortVersion, fullVersion, configHash
# end
if networkExtension
setup_target_extension shortVersion, fullVersion, platform, configHash
setup_target_gobridge
else
setup_target_wireguardgo
setup_target_wireguardtools
end
setup_target_balrog if platform == 'macos'
@project.save
end
def open_project(file)
@project = Xcodeproj::Project.open(file)
die 'Failed to open the project file: ' + file if @project.nil?
end
def open_target_main
@target_main = @project.targets.find { |target| target.to_s == 'AmneziaVPN' }
return @target_main if not @target_main.nil?
die 'Unable to open AmneziaVPN target'
end
def setup_target_main(shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token)
@target_main.build_configurations.each do |config|
config.base_configuration_reference = @configFile
config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"'
config.build_settings['SWIFT_VERSION'] ||= '5.0'
config.build_settings['CLANG_ENABLE_MODULES'] ||= 'YES'
config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= 'macos/app/WireGuard-Bridging-Header.h'
config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= [
"$(inherited)",
"$(PROJECT_DIR)/3rd"
]
# Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion
config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = configHash['APP_ID_MACOS'] if platform == 'macos'
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = configHash['APP_ID_IOS'] if platform == 'ios'
config.build_settings['PRODUCT_NAME'] = 'AmneziaVPN'
# other config
config.build_settings['INFOPLIST_FILE'] ||= platform + '/app/Info.plist'
if platform == 'ios'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'ios/app/main.entitlements'
if adjust_sdk_token != ""
config.build_settings['ADJUST_SDK_TOKEN'] = adjust_sdk_token
end
elsif networkExtension
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/app/app.entitlements'
else
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/app/daemon.entitlements'
end
config.build_settings['CODE_SIGN_IDENTITY'] ||= 'Apple Development'
config.build_settings['ENABLE_BITCODE'] ||= 'NO' if platform == 'ios'
config.build_settings['SDKROOT'] = 'iphoneos' if platform == 'ios'
config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO' if platform == 'ios'
groupId = "";
if (platform == 'macos')
groupId = configHash['DEVELOPMENT_TEAM'] + "." + configHash['GROUP_ID_MACOS']
config.build_settings['APP_ID_MACOS'] ||= configHash['APP_ID_MACOS']
else
groupId = configHash['GROUP_ID_IOS']
config.build_settings['GROUP_ID_IOS'] ||= configHash['GROUP_ID_IOS']
# Force xcode to not set QT_LIBRARY_SUFFIX to "_debug", which causes crash
config.build_settings['QT_LIBRARY_SUFFIX'] = ""
end
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'GROUP_ID=\"' + groupId + '\"',
"VPN_NE_BUNDLEID=\\\"" + (platform == 'macos' ? configHash['NETEXT_ID_MACOS'] : configHash['NETEXT_ID_IOS']) + "\\\"",
]
if config.name == 'Release'
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone'
end
end
if networkExtension
# WireGuard group
group = @project.main_group.new_group('WireGuard')
[
'macos/gobridge/wireguard-go-version.h',
'3rd/wireguard-apple/Sources/Shared/Keychain.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift',
'3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift',
'3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift',
'3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift',
'3rd/wireguard-apple/Sources/WireGuardApp/LocalizationHelper.swift',
'3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift',
'3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c',
'3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift',
].each { |filename|
file = group.new_file(filename)
@target_main.add_file_references([file])
}
# @target_main + swift integration
group = @project.main_group.new_group('SwiftMainIntegration')
[
'platforms/ios/iosvpnprotocol.swift',
'platforms/ios/ioslogger.swift',
].each { |filename|
file = group.new_file(filename)
@target_main.add_file_references([file])
}
end
if (platform == 'ios' && adjust_sdk_token != "")
frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' }
frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' }
framework_ref = frameworks_group.new_file('AdServices.framework')
build_file = frameworks_build_phase.add_file_reference(framework_ref)
build_file.settings = { 'ATTRIBUTES' => ['Weak'] }
framework_ref = frameworks_group.new_file('iAd.framework')
frameworks_build_phase.add_file_reference(framework_ref)
# Adjust SDK
group = @project.main_group.new_group('AdjustSDK')
[
'3rd/adjust-ios-sdk/Adjust/ADJActivityHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityKind.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityPackage.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityState.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdjustFactory.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdRevenue.h',
'3rd/adjust-ios-sdk/Adjust/ADJAttribution.h',
'3rd/adjust-ios-sdk/Adjust/ADJAttributionHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJBackoffStrategy.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSData+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSNumber+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSString+ADJAdditions.h',
'3rd/adjust-ios-sdk/Adjust/ADJConfig.h',
'3rd/adjust-ios-sdk/Adjust/ADJEvent.h',
'3rd/adjust-ios-sdk/Adjust/ADJEventFailure.h',
'3rd/adjust-ios-sdk/Adjust/ADJEventSuccess.h',
'3rd/adjust-ios-sdk/Adjust/ADJLinkResolution.h',
'3rd/adjust-ios-sdk/Adjust/ADJLogger.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageBuilder.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJPackageParams.h',
'3rd/adjust-ios-sdk/Adjust/ADJRequestHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJResponseData.h',
'3rd/adjust-ios-sdk/Adjust/ADJSdkClickHandler.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionFailure.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionParameters.h',
'3rd/adjust-ios-sdk/Adjust/ADJSessionSuccess.h',
'3rd/adjust-ios-sdk/Adjust/ADJSubscription.h',
'3rd/adjust-ios-sdk/Adjust/ADJThirdPartySharing.h',
'3rd/adjust-ios-sdk/Adjust/ADJTimerCycle.h',
'3rd/adjust-ios-sdk/Adjust/ADJTimerOnce.h',
'3rd/adjust-ios-sdk/Adjust/ADJUrlStrategy.h',
'3rd/adjust-ios-sdk/Adjust/ADJUserDefaults.h',
'3rd/adjust-ios-sdk/Adjust/Adjust.h',
'3rd/adjust-ios-sdk/Adjust/ADJUtil.h',
'3rd/adjust-ios-sdk/Adjust/ADJActivityHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityKind.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityPackage.m',
'3rd/adjust-ios-sdk/Adjust/ADJActivityState.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdjustFactory.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdRevenue.m',
'3rd/adjust-ios-sdk/Adjust/ADJAttribution.m',
'3rd/adjust-ios-sdk/Adjust/ADJAttributionHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJBackoffStrategy.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSData+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSNumber+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJAdditions/NSString+ADJAdditions.m',
'3rd/adjust-ios-sdk/Adjust/ADJConfig.m',
'3rd/adjust-ios-sdk/Adjust/ADJEvent.m',
'3rd/adjust-ios-sdk/Adjust/ADJEventFailure.m',
'3rd/adjust-ios-sdk/Adjust/ADJEventSuccess.m',
'3rd/adjust-ios-sdk/Adjust/ADJLinkResolution.m',
'3rd/adjust-ios-sdk/Adjust/ADJLogger.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageBuilder.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJPackageParams.m',
'3rd/adjust-ios-sdk/Adjust/ADJRequestHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJResponseData.m',
'3rd/adjust-ios-sdk/Adjust/ADJSdkClickHandler.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionFailure.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionParameters.m',
'3rd/adjust-ios-sdk/Adjust/ADJSessionSuccess.m',
'3rd/adjust-ios-sdk/Adjust/ADJSubscription.m',
'3rd/adjust-ios-sdk/Adjust/ADJThirdPartySharing.m',
'3rd/adjust-ios-sdk/Adjust/ADJTimerCycle.m',
'3rd/adjust-ios-sdk/Adjust/ADJTimerOnce.m',
'3rd/adjust-ios-sdk/Adjust/ADJUrlStrategy.m',
'3rd/adjust-ios-sdk/Adjust/ADJUserDefaults.m',
'3rd/adjust-ios-sdk/Adjust/Adjust.m',
'3rd/adjust-ios-sdk/Adjust/ADJUtil.m',
].each { |filename|
file = group.new_file(filename)
file_reference = @target_main.add_file_references([file], '-fobjc-arc')
}
end
end
def setup_target_extension(shortVersion, fullVersion, platform, configHash)
@target_extension = @project.new_target(:app_extension, 'WireGuardNetworkExtension', platform == 'macos' ? :osx : :ios)
@target_extension.build_configurations.each do |config|
config.base_configuration_reference = @configFile
config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"'
config.build_settings['SWIFT_VERSION'] ||= '5.0'
config.build_settings['CLANG_ENABLE_MODULES'] ||= 'YES'
config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= 'macos/networkextension/WireGuardNetworkExtension-Bridging-Header.h'
config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO'
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'YES'
# Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion
config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NETEXT_ID_MACOS'] if platform == 'macos'
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NETEXT_ID_IOS'] if platform == 'ios'
config.build_settings['PRODUCT_NAME'] = 'WireGuardNetworkExtension'
# other configs
config.build_settings['INFOPLIST_FILE'] ||= 'macos/networkextension/Info.plist'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= platform + '/networkextension/AmneziaVPNNetworkExtension.entitlements'
config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development'
if platform == 'ios'
config.build_settings['ENABLE_BITCODE'] ||= 'NO'
config.build_settings['SDKROOT'] = 'iphoneos'
config.build_settings['OTHER_LDFLAGS'] ||= [
"-stdlib=libc++",
"-Wl,-rpath,@executable_path/Frameworks",
"-framework",
"AssetsLibrary",
"-framework",
"MobileCoreServices",
"-lm",
"-framework",
"UIKit",
"-lz",
"-framework",
"OpenGLES",
]
end
groupId = "";
if (platform == 'macos')
groupId = configHash['DEVELOPMENT_TEAM'] + "." + configHash['GROUP_ID_MACOS']
else
groupId = configHash['GROUP_ID_IOS']
end
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
# This is needed to compile the iosglue without Qt.
'NETWORK_EXTENSION=1',
'GROUP_ID=\"' + groupId + '\"',
]
if config.name == 'Release'
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone'
end
end
group = @project.main_group.new_group('WireGuardExtension')
[
'3rd/wireguard-apple/Sources/WireGuardKit/WireGuardAdapter.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/DNSResolver.swift',
'3rd/wireguard-apple/Sources/WireGuardNetworkExtension/ErrorNotifier.swift',
'3rd/wireguard-apple/Sources/Shared/Keychain.swift',
'3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift',
'3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift',
'3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift',
'3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift',
'3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c',
'3rd/wireguard-apple/Sources/WireGuardKit/Array+ConcurrentMap.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/IPAddress+AddrInfo.swift',
'3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift',
].each { |filename|
file = group.new_file(filename)
@target_extension.add_file_references([file])
}
# @target_extension + swift integration
group = @project.main_group.new_group('SwiftExtensionIntegration')
[
'platforms/ios/iostunnel.swift',
'platforms/ios/iosglue.mm',
'platforms/ios/ioslogger.swift',
].each { |filename|
file = group.new_file(filename)
@target_extension.add_file_references([file])
}
frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' }
frameworks_build_phase = @target_extension.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' }
frameworks_build_phase.clear
framework_ref = frameworks_group.new_file('libwg-go.a')
frameworks_build_phase.add_file_reference(framework_ref)
framework_ref = frameworks_group.new_file('NetworkExtension.framework')
frameworks_build_phase.add_file_reference(framework_ref)
# This fails: @target_main.add_dependency @target_extension
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = @target_extension.uuid
container_proxy.remote_info = @target_extension.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = @target_extension.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
copy_appex = @target_main.new_copy_files_build_phase
copy_appex.name = 'Copy Network-Extension plugin'
copy_appex.symbol_dst_subfolder_spec = :plug_ins
appex_file = copy_appex.add_file_reference @target_extension.product_reference
appex_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
end
def setup_target_gobridge
target_gobridge = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget)
target_gobridge.build_working_directory = 'macos/gobridge'
target_gobridge.build_tool_path = 'make'
target_gobridge.pass_build_settings_in_environment = '1'
target_gobridge.build_arguments_string = '$(ACTION)'
target_gobridge.name = 'WireGuardGoBridge'
target_gobridge.product_name = 'WireGuardGoBridge'
@project.targets << target_gobridge
@target_extension.add_dependency target_gobridge
end
def setup_target_balrog
target_balrog = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget)
target_balrog.build_working_directory = 'balrog'
target_balrog.build_tool_path = 'make'
target_balrog.pass_build_settings_in_environment = '1'
target_balrog.build_arguments_string = '$(ACTION)'
target_balrog.name = 'WireGuardBalrog'
target_balrog.product_name = 'WireGuardBalrog'
@project.targets << target_balrog
frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' }
frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' }
framework_ref = frameworks_group.new_file('balrog/balrog.a')
frameworks_build_phase.add_file_reference(framework_ref)
# This fails: @target_main.add_dependency target_balrog
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = target_balrog.uuid
container_proxy.remote_info = target_balrog.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = target_balrog.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
end
def setup_target_wireguardtools
target_wireguardtools = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget)
target_wireguardtools.build_working_directory = '3rd/wireguard-tools/src'
target_wireguardtools.build_tool_path = 'make'
target_wireguardtools.pass_build_settings_in_environment = '1'
target_wireguardtools.build_arguments_string = '$(ACTION)'
target_wireguardtools.name = 'WireGuardTools'
target_wireguardtools.product_name = 'WireGuardTools'
@project.targets << target_wireguardtools
# This fails: @target_main.add_dependency target_wireguardtools
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = target_wireguardtools.uuid
container_proxy.remote_info = target_wireguardtools.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = target_wireguardtools.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
copy_wireguardTools = @target_main.new_copy_files_build_phase
copy_wireguardTools.name = 'Copy wireguard-tools'
copy_wireguardTools.symbol_dst_subfolder_spec = :wrapper
copy_wireguardTools.dst_path = 'Contents/Resources/utils'
group = @project.main_group.new_group('WireGuardTools')
file = group.new_file '3rd/wireguard-tools/src/wg'
wireguardTools_file = copy_wireguardTools.add_file_reference file
wireguardTools_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
end
def setup_target_wireguardgo
target_wireguardgo = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget)
target_wireguardgo.build_working_directory = '3rd/wireguard-go'
target_wireguardgo.build_tool_path = 'make'
target_wireguardgo.pass_build_settings_in_environment = '1'
target_wireguardgo.build_arguments_string = '$(ACTION)'
target_wireguardgo.name = 'WireGuardGo'
target_wireguardgo.product_name = 'WireGuardGo'
@project.targets << target_wireguardgo
# This fails: @target_main.add_dependency target_wireguardgo
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = target_wireguardgo.uuid
container_proxy.remote_info = target_wireguardgo.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = target_wireguardgo.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
copy_wireguardGo = @target_main.new_copy_files_build_phase
copy_wireguardGo.name = 'Copy wireguard-go'
copy_wireguardGo.symbol_dst_subfolder_spec = :wrapper
copy_wireguardGo.dst_path = 'Contents/Resources/utils'
group = @project.main_group.new_group('WireGuardGo')
file = group.new_file '3rd/wireguard-go/wireguard-go'
wireguardGo_file = copy_wireguardGo.add_file_reference file
wireguardGo_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
end
def setup_target_loginitem(shortVersion, fullVersion, configHash)
@target_loginitem = @project.new_target(:application, 'AmneziaVPNLoginItem', :osx)
@target_loginitem.build_configurations.each do |config|
config.base_configuration_reference = @configFile
config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"'
# Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion
config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['LOGIN_ID_MACOS']
config.build_settings['PRODUCT_NAME'] = 'AmneziaVPNLoginItem'
# other configs
config.build_settings['INFOPLIST_FILE'] ||= 'macos/loginitem/Info.plist'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/loginitem/MozillaVPNLoginItem.entitlements'
config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development'
config.build_settings['SKIP_INSTALL'] = 'YES'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'APP_ID=\"' + configHash['APP_ID_MACOS'] + '\"',
]
if config.name == 'Release'
config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone'
end
end
group = @project.main_group.new_group('LoginItem')
[
'macos/loginitem/main.m',
].each { |filename|
file = group.new_file(filename)
@target_loginitem.add_file_references([file])
}
# This fails: @target_main.add_dependency @target_loginitem
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = @target_loginitem.uuid
container_proxy.remote_info = @target_loginitem.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = @target_loginitem.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
copy_app = @target_main.new_copy_files_build_phase
copy_app.name = 'Copy LoginItem'
copy_app.symbol_dst_subfolder_spec = :wrapper
copy_app.dst_path = 'Contents/Library/LoginItems'
app_file = copy_app.add_file_reference @target_loginitem.product_reference
app_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
end
def setup_target_nativemessaging(shortVersion, fullVersion, configHash)
@target_nativemessaging = @project.new_target(:application, 'AmneziaVPNNativeMessaging', :osx)
@target_nativemessaging.build_configurations.each do |config|
config.base_configuration_reference = @configFile
config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"'
# Versions and names
config.build_settings['MARKETING_VERSION'] ||= shortVersion
config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NATIVEMESSAGING_ID_MACOS']
config.build_settings['PRODUCT_NAME'] = 'AmneziaVPNNativeMessaging'
# other configs
config.build_settings['INFOPLIST_FILE'] ||= 'macos/nativeMessaging/Info.plist'
config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= 'macos/nativeMessaging/MozillaVPNNativeMessaging.entitlements'
config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development'
config.build_settings['SKIP_INSTALL'] = 'YES'
end
group = @project.main_group.new_group('NativeMessaging')
[
'extension/app/constants.h',
'extension/app/handler.cpp',
'extension/app/handler.h',
'extension/app/json.hpp',
'extension/app/logger.cpp',
'extension/app/logger.h',
'extension/app/main.cpp',
'extension/app/vpnconnection.cpp',
'extension/app/vpnconnection.h',
].each { |filename|
file = group.new_file(filename)
@target_nativemessaging.add_file_references([file])
}
# This fails: @target_main.add_dependency @target_nativemessaging
container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy)
container_proxy.container_portal = @project.root_object.uuid
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
container_proxy.remote_global_id_string = @target_nativemessaging.uuid
container_proxy.remote_info = @target_nativemessaging.name
dependency = @project.new(Xcodeproj::Project::PBXTargetDependency)
dependency.name = @target_nativemessaging.name
dependency.target = @target_main
dependency.target_proxy = container_proxy
@target_main.dependencies << dependency
copy_app = @target_main.new_copy_files_build_phase
copy_app.name = 'Copy LoginItem'
copy_app.symbol_dst_subfolder_spec = :wrapper
copy_app.dst_path = 'Contents/Library/NativeMessaging'
app_file = copy_app.add_file_reference @target_nativemessaging.product_reference
app_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
copy_nativeMessagingManifest = @target_main.new_copy_files_build_phase
copy_nativeMessagingManifest.name = 'Copy native messaging manifest'
copy_nativeMessagingManifest.symbol_dst_subfolder_spec = :wrapper
copy_nativeMessagingManifest.dst_path = 'Contents/Resources/utils'
group = @project.main_group.new_group('WireGuardHelper')
file = group.new_file 'extension/app/manifests/macos/mozillavpn.json'
nativeMessagingManifest_file = copy_nativeMessagingManifest.add_file_reference file
nativeMessagingManifest_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] }
end
def die(msg)
print $msg
exit 1
end
end
if ARGV.length < 4 || (ARGV[3] != "ios" && ARGV[3] != "macos")
puts "Usage: <script> project_file shortVersion fullVersion ios/macos"
exit 1
end
if !File.exist?("xcode.xconfig")
puts "xcode.xconfig file is required! See the template file."
exit 1
end
config = Hash.new
configFile = File.read("xcode.xconfig").split("\n")
configFile.each { |line|
next if line[0] == "#"
if line.include? "="
keys = line.split("=")
config[keys[0].strip] = keys[1].strip
end
}
platform = "macos"
platform = "ios" if ARGV[3] == "ios"
networkExtension = true if ARGV[4] == "1"
adjust_sdk_token = ARGV[5]
r = XCodeprojPatcher.new
r.run ARGV[0], ARGV[1], ARGV[2], platform, networkExtension, config, adjust_sdk_token
exit 0

View file

@ -151,13 +151,13 @@ void Settings::removeContainerConfig(int serverIndex, DockerContainer container)
setContainers(serverIndex, c);
}
QJsonObject Settings::protocolConfig(int serverIndex, DockerContainer container, Protocol proto)
QJsonObject Settings::protocolConfig(int serverIndex, DockerContainer container, Proto proto)
{
const QJsonObject &c = containerConfig(serverIndex, container);
return c.value(ProtocolProps::protoToString(proto)).toObject();
}
void Settings::setProtocolConfig(int serverIndex, DockerContainer container, Protocol proto, const QJsonObject &config)
void Settings::setProtocolConfig(int serverIndex, DockerContainer container, Proto proto, const QJsonObject &config)
{
QJsonObject c = containerConfig(serverIndex, container);
c.insert(ProtocolProps::protoToString(proto), config);
@ -165,11 +165,11 @@ void Settings::setProtocolConfig(int serverIndex, DockerContainer container, Pro
setContainerConfig(serverIndex, container, c);
}
void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer container, Protocol proto)
void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer container, Proto proto)
{
// recursively remove
if (proto == Protocol::Any) {
for (Protocol p: ContainerProps::protocolsForContainer(container)) {
if (proto == Proto::Any) {
for (Proto p: ContainerProps::protocolsForContainer(container)) {
clearLastConnectionConfig(serverIndex, container, p);
}
return;

View file

@ -52,10 +52,10 @@ public:
void setContainerConfig(int serverIndex, DockerContainer container, const QJsonObject &config);
void removeContainerConfig(int serverIndex, DockerContainer container);
QJsonObject protocolConfig(int serverIndex, DockerContainer container, Protocol proto);
void setProtocolConfig(int serverIndex, DockerContainer container, Protocol proto, const QJsonObject &config);
QJsonObject protocolConfig(int serverIndex, DockerContainer container, Proto proto);
void setProtocolConfig(int serverIndex, DockerContainer container, Proto proto, const QJsonObject &config);
void clearLastConnectionConfig(int serverIndex, DockerContainer container, Protocol proto = Protocol::Any);
void clearLastConnectionConfig(int serverIndex, DockerContainer container, Proto proto = Proto::Any);
bool haveAuthData(int serverIndex) const;
QString nextAvailableServerName() const;

View file

@ -28,7 +28,7 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
return QVariant();
}
Protocol p = ProtocolProps::allProtocols().at(index.row());
Proto p = ProtocolProps::allProtocols().at(index.row());
if (role == NameRole) {
return ProtocolProps::protocolHumanNames().value(p);
}

View file

@ -18,7 +18,7 @@ void NewServerProtocolsLogic::onUpdatePage()
void NewServerProtocolsLogic::onPushButtonConfigureClicked(DockerContainer c, int port, TransportProto tp)
{
QMap<DockerContainer, QJsonObject> containers;
Protocol mainProto = ContainerProps::defaultProtocol(c);
Proto mainProto = ContainerProps::defaultProtocol(c);
QJsonObject config {
{ config_key::container, ContainerProps::containerToString(c) },

View file

@ -29,7 +29,7 @@ void ServerContainersLogic::onUpdatePage()
emit updatePage();
}
void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, Protocol p)
void ServerContainersLogic::onPushButtonProtoSettingsClicked(DockerContainer c, Proto p)
{
qDebug()<< "ServerContainersLogic::onPushButtonProtoSettingsClicked" << c << p;
uiLogic()->selectedDockerContainer = c;

View file

@ -12,7 +12,7 @@ class ServerContainersLogic : public PageLogicBase
public:
Q_INVOKABLE void onUpdatePage() override;
Q_INVOKABLE void onPushButtonProtoSettingsClicked(DockerContainer c, Protocol p);
Q_INVOKABLE void onPushButtonProtoSettingsClicked(DockerContainer c, Proto p);
Q_INVOKABLE void onPushButtonDefaultClicked(DockerContainer c);
Q_INVOKABLE void onPushButtonShareClicked(DockerContainer c);
Q_INVOKABLE void onPushButtonRemoveClicked(DockerContainer c);

View file

@ -128,5 +128,5 @@ void ServerSettingsLogic::onLineEditDescriptionEditingFinished()
void ServerSettingsLogic::onPushButtonShareFullClicked()
{
uiLogic()->shareConnectionLogic()->updateSharingPage(uiLogic()->selectedServerIndex, DockerContainer::None);
emit uiLogic()->goToShareProtocolPage(Protocol::Any);
emit uiLogic()->goToShareProtocolPage(Proto::Any);
}

View file

@ -70,7 +70,7 @@ void ShareConnectionLogic::onPushButtonShareAmneziaGenerateClicked()
containerConfig.insert(config_key::container, ContainerProps::containerToString(uiLogic()->selectedDockerContainer));
ErrorCode e = ErrorCode::NoError;
for (Protocol p: ContainerProps::protocolsForContainer(uiLogic()->selectedDockerContainer)) {
for (Proto p: ContainerProps::protocolsForContainer(uiLogic()->selectedDockerContainer)) {
QJsonObject protoConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, p);
QString cfg = VpnConfigurator::genVpnProtocolConfig(credentials, uiLogic()->selectedDockerContainer, containerConfig, p, &e);
@ -115,7 +115,7 @@ void ShareConnectionLogic::onPushButtonShareOpenVpnGenerateClicked()
ErrorCode e = ErrorCode::NoError;
QString cfg = OpenVpnConfigurator::genOpenVpnConfig(credentials, uiLogic()->selectedDockerContainer, containerConfig, &e);
cfg = VpnConfigurator::processConfigWithExportSettings(uiLogic()->selectedDockerContainer, Protocol::OpenVpn, cfg);
cfg = VpnConfigurator::processConfigWithExportSettings(uiLogic()->selectedDockerContainer, Proto::OpenVpn, cfg);
set_textEditShareOpenVpnCodeText(QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString());
}
@ -126,7 +126,7 @@ void ShareConnectionLogic::onPushButtonShareShadowSocksGenerateClicked()
DockerContainer container = uiLogic()->selectedDockerContainer;
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::ShadowSocks);
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Proto::ShadowSocks);
QString cfg = protoConfig.value(config_key::last_config).toString();
if (cfg.isEmpty()) {
@ -168,7 +168,7 @@ void ShareConnectionLogic::onPushButtonShareCloakGenerateClicked()
DockerContainer container = uiLogic()->selectedDockerContainer;
ServerCredentials credentials = m_settings.serverCredentials(serverIndex);
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Protocol::Cloak);
QJsonObject protoConfig = m_settings.protocolConfig(serverIndex, container, Proto::Cloak);
QString cfg = protoConfig.value(config_key::last_config).toString();
if (cfg.isEmpty()) {
@ -195,7 +195,7 @@ void ShareConnectionLogic::onPushButtonShareWireGuardGenerateClicked()
ErrorCode e = ErrorCode::NoError;
QString cfg = WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, &e);
cfg = VpnConfigurator::processConfigWithExportSettings(container, Protocol::WireGuard, cfg);
cfg = VpnConfigurator::processConfigWithExportSettings(container, Proto::WireGuard, cfg);
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::config].toString();
set_textEditShareWireGuardCodeText(cfg);
@ -215,7 +215,7 @@ void ShareConnectionLogic::onPushButtonShareIkev2GenerateClicked()
Ikev2Configurator::ConnectionData connData = Ikev2Configurator::prepareIkev2Config(credentials, container);
QString cfg = Ikev2Configurator::genIkev2Config(connData);
cfg = VpnConfigurator::processConfigWithExportSettings(container, Protocol::Ikev2, cfg);
cfg = VpnConfigurator::processConfigWithExportSettings(container, Proto::Ikev2, cfg);
cfg = QJsonDocument::fromJson(cfg.toUtf8()).object()[config_key::cert].toString();
set_textEditShareIkev2CertText(cfg);

View file

@ -77,7 +77,7 @@ void VpnLogic::onBytesChanged(quint64 receivedData, quint64 sentData)
set_labelSpeedSentText(VpnConnection::bytesPerSecToText(sentData));
}
void VpnLogic::onConnectionStateChanged(VpnProtocol::ConnectionState state)
void VpnLogic::onConnectionStateChanged(VpnProtocol::VpnConnectionState state)
{
qDebug() << "VpnLogic::onConnectionStateChanged" << VpnProtocol::textConnectionState(state);

View file

@ -48,7 +48,7 @@ public slots:
void onDisconnect();
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
void onConnectionStateChanged(VpnProtocol::VpnConnectionState state);
void onVpnProtocolError(amnezia::ErrorCode errorCode);
signals:

View file

@ -22,7 +22,7 @@ QMap<DockerContainer, QJsonObject> WizardLogic::getInstallConfigsFromWizardPage(
{
QJsonObject cloakConfig {
{ config_key::container, ContainerProps::containerToString(DockerContainer::Cloak) },
{ ProtocolProps::protoToString(Protocol::Cloak), QJsonObject {
{ ProtocolProps::protoToString(Proto::Cloak), QJsonObject {
{ config_key::site, lineEditHighWebsiteMaskingText() }}
}
};

View file

@ -52,12 +52,12 @@ QJsonObject CloakLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
void CloakLogic::onPushButtonSaveClicked()
{
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Protocol::Cloak);
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::Cloak);
protocolConfig = getProtocolConfigFromPage(protocolConfig);
QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
QJsonObject newContainerConfig = containerConfig;
newContainerConfig.insert(ProtocolProps::protoToString(Protocol::Cloak), protocolConfig);
newContainerConfig.insert(ProtocolProps::protoToString(Proto::Cloak), protocolConfig);
UiLogic::PageFunc page_func;
page_func.setEnabledFunc = [this] (bool enabled) -> void {

View file

@ -81,12 +81,12 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo
void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked()
{
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Protocol::OpenVpn);
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::OpenVpn);
protocolConfig = getProtocolConfigFromPage(protocolConfig);
QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
QJsonObject newContainerConfig = containerConfig;
newContainerConfig.insert(ProtocolProps::protoToString(Protocol::OpenVpn), protocolConfig);
newContainerConfig.insert(ProtocolProps::protoToString(Proto::OpenVpn), protocolConfig);
UiLogic::PageFunc page_proto_openvpn;
page_proto_openvpn.setEnabledFunc = [this] (bool enabled) -> void {

View file

@ -46,12 +46,12 @@ QJsonObject ShadowSocksLogic::getProtocolConfigFromPage(QJsonObject oldConfig)
void ShadowSocksLogic::onPushButtonSaveClicked()
{
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Protocol::ShadowSocks);
QJsonObject protocolConfig = m_settings.protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::ShadowSocks);
//protocolConfig = getShadowSocksConfigFromPage(protocolConfig);
QJsonObject containerConfig = m_settings.containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer);
QJsonObject newContainerConfig = containerConfig;
newContainerConfig.insert(ProtocolProps::protoToString(Protocol::ShadowSocks), protocolConfig);
newContainerConfig.insert(ProtocolProps::protoToString(Proto::ShadowSocks), protocolConfig);
UiLogic::PageFunc page_proto_shadowsocks;
page_proto_shadowsocks.setEnabledFunc = [this] (bool enabled) -> void {
set_pageEnabled(enabled);

View file

@ -84,21 +84,21 @@ UiLogic::UiLogic(QObject *parent) :
m_newServerProtocolsLogic = new NewServerProtocolsLogic(this);
m_serverListLogic = new ServerListLogic(this);
m_serverSettingsLogic = new ServerSettingsLogic(this);
m_serverVpnProtocolsLogic = new ServerContainersLogic(this);
m_serverprotocolsLogic = new ServerContainersLogic(this);
m_shareConnectionLogic = new ShareConnectionLogic(this);
m_sitesLogic = new SitesLogic(this);
m_startPageLogic = new StartPageLogic(this);
m_vpnLogic = new VpnLogic(this);
m_wizardLogic = new WizardLogic(this);
m_protocolLogicMap.insert(Protocol::OpenVpn, new OpenVpnLogic(this));
m_protocolLogicMap.insert(Protocol::ShadowSocks, new ShadowSocksLogic(this));
m_protocolLogicMap.insert(Protocol::Cloak, new CloakLogic(this));
m_protocolLogicMap.insert(Proto::OpenVpn, new OpenVpnLogic(this));
m_protocolLogicMap.insert(Proto::ShadowSocks, new ShadowSocksLogic(this));
m_protocolLogicMap.insert(Proto::Cloak, new CloakLogic(this));
//m_protocolLogicMap->insert(Protocol::WireGuard, new WireguardLogic(this));
m_protocolLogicMap.insert(Protocol::Dns, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Protocol::Sftp, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Protocol::TorWebSite, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::Dns, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::Sftp, new OtherProtocolsLogic(this));
m_protocolLogicMap.insert(Proto::TorWebSite, new OtherProtocolsLogic(this));
}
@ -108,7 +108,7 @@ UiLogic::~UiLogic()
emit hide();
if (m_vpnConnection->connectionState() != VpnProtocol::ConnectionState::Disconnected) {
if (m_vpnConnection->connectionState() != VpnProtocol::VpnConnectionState::Disconnected) {
m_vpnConnection->disconnectFromVpn();
for (int i = 0; i < 50; i++) {
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
@ -226,7 +226,7 @@ void UiLogic::onUpdateAllPages()
(PageLogicBase *) m_newServerProtocolsLogic,
(PageLogicBase *) m_serverListLogic,
(PageLogicBase *) m_serverSettingsLogic,
(PageLogicBase *) m_serverVpnProtocolsLogic,
(PageLogicBase *) m_serverprotocolsLogic,
(PageLogicBase *) m_shareConnectionLogic,
(PageLogicBase *) m_sitesLogic,
(PageLogicBase *) m_startPageLogic,
@ -620,7 +620,7 @@ void UiLogic::onTrayActivated(QSystemTrayIcon::ActivationReason reason)
emit raise();
}
PageProtocolLogicBase *UiLogic::protocolLogic(Protocol p) {
PageProtocolLogicBase *UiLogic::protocolLogic(Proto p) {
PageProtocolLogicBase *logic = m_protocolLogicMap.value(p);
if (logic) return logic;
else {
@ -644,7 +644,7 @@ PageEnumNS::Page UiLogic::currentPage()
return static_cast<PageEnumNS::Page>(currentPageValue());
}
void UiLogic::setTrayState(VpnProtocol::ConnectionState state)
void UiLogic::setTrayState(VpnProtocol::VpnConnectionState state)
{
QString resourcesPath = ":/images/tray/%1";

View file

@ -92,8 +92,8 @@ public:
Q_INVOKABLE QString containerDesc(int container);
Q_INVOKABLE void onGotoPage(PageEnumNS::Page p, bool reset = true, bool slide = true) { emit goToPage(p, reset, slide); }
Q_INVOKABLE void onGotoProtocolPage(Protocol p, bool reset = true, bool slide = true) { emit goToProtocolPage(p, reset, slide); }
Q_INVOKABLE void onGotoShareProtocolPage(Protocol p, bool reset = true, bool slide = true) { emit goToShareProtocolPage(p, reset, slide); }
Q_INVOKABLE void onGotoProtocolPage(Proto p, bool reset = true, bool slide = true) { emit goToProtocolPage(p, reset, slide); }
Q_INVOKABLE void onGotoShareProtocolPage(Proto p, bool reset = true, bool slide = true) { emit goToShareProtocolPage(p, reset, slide); }
Q_INVOKABLE void onGotoCurrentProtocolsPage();
@ -114,8 +114,8 @@ signals:
void goToPage(PageEnumNS::Page page, bool reset = true, bool slide = true);
void goToProtocolPage(Protocol protocol, bool reset = true, bool slide = true);
void goToShareProtocolPage(Protocol protocol, bool reset = true, bool slide = true);
void goToProtocolPage(Proto protocol, bool reset = true, bool slide = true);
void goToShareProtocolPage(Proto protocol, bool reset = true, bool slide = true);
void closePage();
void setStartPage(PageEnumNS::Page page, bool slide = true);
@ -134,7 +134,7 @@ private slots:
// containers - INOUT arg
void installServer(QMap<DockerContainer, QJsonObject> &containers);
void setTrayState(VpnProtocol::ConnectionState state);
void setTrayState(VpnProtocol::VpnConnectionState state);
void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
private:
@ -183,14 +183,14 @@ public:
NewServerProtocolsLogic *newServerProtocolsLogic() { return m_newServerProtocolsLogic; }
ServerListLogic *serverListLogic() { return m_serverListLogic; }
ServerSettingsLogic *serverSettingsLogic() { return m_serverSettingsLogic; }
ServerContainersLogic *serverVpnProtocolsLogic() { return m_serverVpnProtocolsLogic; }
ServerContainersLogic *serverprotocolsLogic() { return m_serverprotocolsLogic; }
ShareConnectionLogic *shareConnectionLogic() { return m_shareConnectionLogic; }
SitesLogic *sitesLogic() { return m_sitesLogic; }
StartPageLogic *startPageLogic() { return m_startPageLogic; }
VpnLogic *vpnLogic() { return m_vpnLogic; }
WizardLogic *wizardLogic() { return m_wizardLogic; }
Q_INVOKABLE PageProtocolLogicBase *protocolLogic(Protocol p);
Q_INVOKABLE PageProtocolLogicBase *protocolLogic(Proto p);
QObject *qmlRoot() const;
void setQmlRoot(QObject *newQmlRoot);
@ -205,14 +205,14 @@ private:
NewServerProtocolsLogic *m_newServerProtocolsLogic;
ServerListLogic *m_serverListLogic;
ServerSettingsLogic *m_serverSettingsLogic;
ServerContainersLogic *m_serverVpnProtocolsLogic;
ServerContainersLogic *m_serverprotocolsLogic;
ShareConnectionLogic *m_shareConnectionLogic;
SitesLogic *m_sitesLogic;
StartPageLogic *m_startPageLogic;
VpnLogic *m_vpnLogic;
WizardLogic *m_wizardLogic;
QMap<Protocol, PageProtocolLogicBase *> m_protocolLogicMap;
QMap<Proto, PageProtocolLogicBase *> m_protocolLogicMap;
VpnConnection* m_vpnConnection;
QThread m_vpnConnectionThread;

5
client/version.pri Normal file
View file

@ -0,0 +1,5 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
!defined(VERSION, var):VERSION = 1

View file

@ -15,6 +15,10 @@
#include <protocols/android_vpnprotocol.h>
#endif
#ifdef Q_OS_IOS
#include <protocols/ios_vpnprotocol.h>
#endif
#include "ipc.h"
#include "core/ipcclient.h"
@ -38,7 +42,7 @@ void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
emit bytesChanged(receivedBytes, sentBytes);
}
void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
void VpnConnection::onConnectionStateChanged(VpnProtocol::VpnConnectionState state)
{
if (IpcClient::Interface()) {
if (state == VpnProtocol::Connected){
@ -124,10 +128,10 @@ ErrorCode VpnConnection::lastError() const
return m_vpnProtocol.data()->lastError();
}
QMap<Protocol, QString> VpnConnection::getLastVpnConfig(const QJsonObject &containerConfig)
QMap<Proto, QString> VpnConnection::getLastVpnConfig(const QJsonObject &containerConfig)
{
QMap<Protocol, QString> configs;
for (Protocol proto: ProtocolProps::allProtocols()) {
QMap<Proto, QString> configs;
for (Proto proto: ProtocolProps::allProtocols()) {
QString cfg = containerConfig.value(ProtocolProps::protoToString(proto)).toObject().value(config_key::last_config).toString();
@ -137,7 +141,7 @@ QMap<Protocol, QString> VpnConnection::getLastVpnConfig(const QJsonObject &conta
}
QString VpnConnection::createVpnConfigurationForProto(int serverIndex,
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Protocol proto,
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Proto proto,
ErrorCode *errorCode)
{
ErrorCode e = ErrorCode::NoError;
@ -186,7 +190,7 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex,
QJsonObject vpnConfiguration;
for (ProtocolEnumNS::Protocol proto : ContainerProps::protocolsForContainer(container)) {
for (ProtocolEnumNS::Proto proto : ContainerProps::protocolsForContainer(container)) {
QJsonObject vpnConfigData = QJsonDocument::fromJson(
createVpnConfigurationForProto(
serverIndex, credentials, container, containerConfig, proto, &e).toUtf8()).
@ -200,8 +204,8 @@ QJsonObject VpnConnection::createVpnConfiguration(int serverIndex,
vpnConfiguration.insert(ProtocolProps::key_proto_config_data(proto), vpnConfigData);
}
Protocol proto = ContainerProps::defaultProtocol(container);
vpnConfiguration[config_key::protocol] = ProtocolProps::protoToString(proto);
Proto proto = ContainerProps::defaultProtocol(container);
vpnConfiguration[config_key::vpnproto] = ProtocolProps::protoToString(proto);
return vpnConfiguration;
}
@ -212,7 +216,7 @@ void VpnConnection::connectToVpn(int serverIndex,
qDebug() << QString("СonnectToVpn, Server index is %1, container is %2, route mode is")
.arg(serverIndex).arg(ContainerProps::containerToString(container)) << m_settings.routeMode();
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS)
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS)
if (!m_IpcClient) {
m_IpcClient = new IpcClient;
}
@ -228,7 +232,6 @@ void VpnConnection::connectToVpn(int serverIndex,
#endif
m_remoteAddress = credentials.hostName;
emit connectionStateChanged(VpnProtocol::Connecting);
if (m_vpnProtocol) {
@ -241,24 +244,22 @@ void VpnConnection::connectToVpn(int serverIndex,
}
ErrorCode e = ErrorCode::NoError;
m_vpnConfiguration = createVpnConfiguration(serverIndex, credentials, container, containerConfig);
if (e) {
emit connectionStateChanged(VpnProtocol::Error);
return;
}
#ifndef Q_OS_ANDROID
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_IOS)
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
if (!m_vpnProtocol) {
emit VpnProtocol::Error;
return;
}
m_vpnProtocol->prepare();
#else
Protocol proto = ContainerProps::defaultProtocol(container);
#elif defined Q_OS_ANDROID
Proto proto = ContainerProps::defaultProtocol(container);
AndroidVpnProtocol *androidVpnProtocol = new AndroidVpnProtocol(proto, m_vpnConfiguration);
if (!androidVpnProtocol->initialize()) {
qDebug() << QString("Init failed") ;
@ -266,6 +267,15 @@ void VpnConnection::connectToVpn(int serverIndex,
return;
}
m_vpnProtocol.reset(androidVpnProtocol);
#elif defined Q_OS_IOS
Proto proto = ContainerProps::defaultProtocol(container);
IOSVpnProtocol *iosVpnProtocol = new IOSVpnProtocol(proto, m_vpnConfiguration);
if (!iosVpnProtocol->initialize()) {
qDebug() << QString("Init failed") ;
emit VpnProtocol::Error;
return;
}
m_vpnProtocol.reset(iosVpnProtocol);
#endif
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
@ -303,7 +313,7 @@ void VpnConnection::disconnectFromVpn()
// qDebug() << "Disconnect from VPN 2";
}
VpnProtocol::ConnectionState VpnConnection::connectionState()
VpnProtocol::VpnConnectionState VpnConnection::connectionState()
{
if (!m_vpnProtocol) return VpnProtocol::Disconnected;
return m_vpnProtocol->connectionState();

View file

@ -25,9 +25,9 @@ public:
ErrorCode lastError() const;
static QMap<Protocol, QString> getLastVpnConfig(const QJsonObject &containerConfig);
static QMap<Proto, QString> getLastVpnConfig(const QJsonObject &containerConfig);
QString createVpnConfigurationForProto(int serverIndex,
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Protocol proto,
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig, Proto proto,
ErrorCode *errorCode = nullptr);
QJsonObject createVpnConfiguration(int serverIndex,
@ -39,7 +39,7 @@ public:
bool isConnected() const;
bool isDisconnected() const;
VpnProtocol::ConnectionState connectionState();
VpnProtocol::VpnConnectionState connectionState();
QSharedPointer<VpnProtocol> vpnProtocol() const;
void addRoutes(const QStringList &ips);
@ -56,14 +56,14 @@ public slots:
signals:
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
void connectionStateChanged(VpnProtocol::ConnectionState state);
void connectionStateChanged(VpnProtocol::VpnConnectionState state);
void vpnProtocolError(amnezia::ErrorCode error);
void serviceIsNotReady();
protected slots:
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
void onConnectionStateChanged(VpnProtocol::VpnConnectionState state);
protected:
QSharedPointer<VpnProtocol> m_vpnProtocol;

5
client/xcode.xconfig Normal file
View file

@ -0,0 +1,5 @@
DEVELOPMENT_TEAM = X7UJ388FXK
GROUP_ID_IOS = group.ru.kotit.AmneziaVPN.udev
APP_ID_IOS = ru.kotit.AmneziaVPN
NETEXT_ID_IOS = ru.kotit.AmneziaVPN.network-extension