mirror of
https://github.com/amnezia-vpn/amneziawg-android.git
synced 2026-07-03 14:05:13 +02:00
Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62986b5cad | |||
| 296295ab8a | |||
| d1237e2718 | |||
| a26b7c594a | |||
| 853e86e6d0 | |||
| a386e3a3d2 | |||
| 560d9cf967 | |||
| 713947e432 | |||
| f8690ca215 | |||
| 4f26156030 | |||
| b353ed8ae9 | |||
| f269fb175d | |||
| 98fe4438d5 | |||
| 0459d6d9f4 | |||
| 4ff564521f | |||
| 9f139134c2 | |||
| 284ad03ebf | |||
| c3693b3e66 | |||
| 960bc99f5e | |||
| 8d33b648cc | |||
| 38cb184cf8 | |||
| 5d14caf3b2 | |||
| 81c571f0c7 | |||
| 50b21e95c3 | |||
| 059bf88141 | |||
| b3112ab0bd | |||
| 1bb8a10633 | |||
| f3230fc8f9 | |||
| c762bc3120 | |||
| aeb8903ba2 | |||
| 2f244771a2 | |||
| 5ffb1d0c36 | |||
| 62910caae1 | |||
| 866fd35df5 | |||
| 32a2ebb66f | |||
| 70d9a87d0d | |||
| 0bd39309c8 | |||
| 751ce54fa5 | |||
| 72dc677819 | |||
| 7002367e4f | |||
| 5339e48251 | |||
| d626e23210 | |||
| 342ed5e259 | |||
| 2bf09f8e2d | |||
| 36d93a8e1b | |||
| 1d7d306950 | |||
| 06306c669d | |||
| d19e126e2e | |||
| bf84e26a86 | |||
| a03ad51622 | |||
| 447b06ec2c | |||
| 6da1d5ed01 | |||
| 836c367499 | |||
| 15cb99a41f | |||
| fae74dd3ca | |||
| e462ae270d | |||
| 24d5a28a4a | |||
| 3df42898ae | |||
| 1701e4fde4 | |||
| f6d175b774 | |||
| 878c450563 | |||
| b444ea064e | |||
| 4eb90266a2 | |||
| 3935a369b8 | |||
| 32fc760053 | |||
| 5459c6d531 | |||
| a1889b801c | |||
| a86dff9433 | |||
| 02f59b6b27 | |||
| 29bb93cdf7 | |||
| eae06aade7 | |||
| a8b2fc15de | |||
| f699d9cf9a | |||
| ae00e8ce6e | |||
| 2730e75474 | |||
| 00e0224fd1 | |||
| 82c9b75ea1 | |||
| a23c57bab0 | |||
| 02b92c178a | |||
| 8dd6c3e35e | |||
| 78f2fda6ca | |||
| 2f822aa1f6 | |||
| 40f2f073cd | |||
| 37fabf0229 | |||
| fe61522f2a | |||
| 24ded8070f | |||
| 24569a4c49 | |||
| b448d605f0 | |||
| 0dcfde35f4 | |||
| 6acc1125b8 | |||
| 94ecb13d2f | |||
| 6008efcd95 | |||
| d6a8e9d4dc | |||
| bcd8c33005 | |||
| e71c84a785 | |||
| 3474849b1d | |||
| f32c5cc222 | |||
| cf6e1490f4 | |||
| 86951f509c | |||
| 8e9b2c6f05 | |||
| 9ace8dd928 | |||
| 8f727903f3 | |||
| b6aa09bc19 | |||
| 782550318a | |||
| d02543639b | |||
| e1e16cdf3b | |||
| 1bbcf83f43 | |||
| 169bd408f2 | |||
| 777e3b71ba | |||
| 511e54764e | |||
| d0b5fb5107 | |||
| 7c3137e2c8 | |||
| 12a3ec28bc | |||
| 892295c42a | |||
| ea9ef4af24 | |||
| b8870f3599 | |||
| 11301617d2 | |||
| 617be576f8 | |||
| 8523979c9c | |||
| 8768acee68 | |||
| a73d2121e1 | |||
| dd58fad69e | |||
| ba9d689ef9 | |||
| 97d82740d0 | |||
| 0750c29c7f | |||
| 639ee6b5b2 | |||
| f764f2aaa9 | |||
| d2a9c56d9c | |||
| 4c3289aa52 | |||
| 79376bca64 | |||
| b709d36c01 | |||
| 0301c85e2c | |||
| 7e979817e2 | |||
| 13cc4436ca | |||
| bcfbf37ed1 | |||
| 74ff870cf5 | |||
| b4f54e8958 | |||
| d179a3af15 | |||
| 2bac2feeb5 | |||
| 261236c8ce | |||
| 4a7969ef24 |
Generated
+4
-12
@@ -62,21 +62,10 @@
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="10" />
|
||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="10" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<XML>
|
||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="METHOD_ANNOTATION_WRAP" value="0" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
@@ -477,5 +466,8 @@
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright © &#36;today.year WireGuard LLC. All Rights Reserved. SPDX-License-Identifier: Apache-2.0" />
|
||||
<option name="notice" value="Copyright © 2017-&#36;today.year WireGuard LLC. All Rights Reserved. SPDX-License-Identifier: Apache-2.0" />
|
||||
<option name="myName" value="Default" />
|
||||
</copyright>
|
||||
</component>
|
||||
|
||||
@@ -16,13 +16,13 @@ macOS users may need [flock(1)](https://github.com/discoteq/flock).
|
||||
|
||||
## Embedding
|
||||
|
||||
The tunnel library is [on JCenter](https://bintray.com/wireguard/wireguard-android/wireguard-android/_latestVersion), alongside [extensive class library documentation](https://javadoc.io/doc/com.wireguard.android/tunnel).
|
||||
The tunnel library is [on Maven Central](https://search.maven.org/artifact/com.wireguard.android/tunnel), alongside [extensive class library documentation](https://javadoc.io/doc/com.wireguard.android/tunnel).
|
||||
|
||||
```
|
||||
implementation 'com.wireguard.android:tunnel:$wireguardTunnelVersion'
|
||||
```
|
||||
|
||||
The library makes use of Java 8 features, so be sure to support those in your gradle configuration with desugaring:
|
||||
The library makes use of Java 8 features, so be sure to support those in your gradle configuration with [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring):
|
||||
|
||||
```
|
||||
compileOptions {
|
||||
@@ -31,7 +31,7 @@ compileOptions {
|
||||
coreLibraryDesugaringEnabled = true
|
||||
}
|
||||
dependencies {
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.0.10"
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+19
-70
@@ -1,76 +1,26 @@
|
||||
buildscript {
|
||||
ext {
|
||||
activityVersion = '1.2.0-beta02'
|
||||
agpVersion = '4.1.1'
|
||||
annotationsVersion = '1.1.0'
|
||||
appcompatVersion = '1.2.0'
|
||||
biometricVersion = '1.1.0-rc01'
|
||||
collectionVersion = '1.1.0'
|
||||
constraintLayoutVersion = '2.0.4'
|
||||
coordinatorLayoutVersion = '1.1.0'
|
||||
coreKtxVersion = '1.3.2'
|
||||
coroutinesVersion = '1.4.2'
|
||||
datastoreVersion = '1.0.0-alpha02'
|
||||
desugarVersion = '1.0.10'
|
||||
fragmentVersion = '1.3.0-beta02'
|
||||
activityVersion = '1.6.1'
|
||||
annotationsVersion = '1.5.0'
|
||||
appcompatVersion = '1.5.1'
|
||||
biometricVersion = '1.1.0'
|
||||
collectionVersion = '1.2.0'
|
||||
constraintLayoutVersion = '2.1.4'
|
||||
coordinatorLayoutVersion = '1.2.0'
|
||||
coreKtxVersion = '1.9.0'
|
||||
coroutinesVersion = '1.6.4'
|
||||
datastoreVersion = '1.0.0'
|
||||
desugarVersion = '1.1.5'
|
||||
fragmentVersion = '1.5.4'
|
||||
jsr305Version = '3.0.2'
|
||||
junitVersion = '4.13.1'
|
||||
kotlinVersion = '1.4.21'
|
||||
lifecycleRuntimeKtxVersion = '2.3.0-beta01'
|
||||
materialComponentsVersion = '1.3.0-beta01'
|
||||
preferenceVersion = '1.1.1'
|
||||
zxingEmbeddedVersion = '3.6.0'
|
||||
junitVersion = '4.13.2'
|
||||
lifecycleRuntimeKtxVersion = '2.5.1'
|
||||
materialComponentsVersion = '1.7.0'
|
||||
preferenceVersion = '1.2.0'
|
||||
zxingEmbeddedVersion = '4.3.0'
|
||||
|
||||
groupName = 'com.wireguard.android'
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$agpVersion"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "de.undercouch.download" version "4.1.1"
|
||||
}
|
||||
|
||||
task downloadCrowdin(type: Download) {
|
||||
src 'https://crowdin.com/backend/download/project/wireguard.zip'
|
||||
dest file('build/translations.zip')
|
||||
overwrite true
|
||||
}
|
||||
|
||||
task cleanCrowdin(type: Delete) {
|
||||
delete 'ui/src/main/res/values-*/strings.xml'
|
||||
}
|
||||
|
||||
task extractCrowdin(type: Copy, dependsOn: ['downloadCrowdin', 'cleanCrowdin']) {
|
||||
mustRunAfter 'downloadCrowdin'
|
||||
from zipTree(file('build/translations.zip'))
|
||||
into file('build/translations')
|
||||
doFirst {
|
||||
delete 'build/translations'
|
||||
}
|
||||
}
|
||||
|
||||
task crowdin(type: Copy, dependsOn: ['extractCrowdin']) {
|
||||
mustRunAfter 'extractCrowdin'
|
||||
from 'build/translations/wireguard-android/ui/src/main/res'
|
||||
into 'ui/src/main/res/'
|
||||
doLast {
|
||||
delete 'build/translations'
|
||||
delete 'build/translations.zip'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
@@ -79,9 +29,8 @@ task clean(type: Delete) {
|
||||
|
||||
tasks {
|
||||
wrapper {
|
||||
gradleVersion = "6.7.1"
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
distributionSha256Sum = "22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb"
|
||||
gradleVersion = "7.6"
|
||||
distributionSha256Sum = "7ba68c54029790ab444b39d7e293d3236b2632631fb5f2e012bb28b4ff669e4b"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+60
-21
@@ -1,30 +1,69 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.configureondemand=true
|
||||
org.gradle.caching=true
|
||||
|
||||
# https://jakewharton.com/increased-accuracy-of-aapt2-keep-rules/
|
||||
android.useMinimalKeepRules=true
|
||||
# Enable Kotlin incremental compilation
|
||||
kotlin.incremental=true
|
||||
|
||||
# Enable rudimentary R class namespacing where each library only contains
|
||||
# Enable AndroidX support
|
||||
android.useAndroidX=true
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
# Turn off AP discovery in compile path to enable compile avoidance
|
||||
kapt.include.compile.classpath=false
|
||||
|
||||
# Enable non-transitive R class namespacing where each library only contains
|
||||
# references to the resources it declares instead of declarations plus all
|
||||
# transitive dependency references.
|
||||
android.namespacedRClass=true
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Experimental AGP flags
|
||||
# Generate compile-time only R class for app modules.
|
||||
android.enableAppCompileTimeRClass=true
|
||||
# Keep AAPT2 daemons alive between incremental builds.
|
||||
android.keepWorkerActionServicesBetweenBuilds=true
|
||||
# Make R fields non-final to improve build speeds.
|
||||
# http://tools.android.com/tips/non-constant-fields
|
||||
android.nonFinalResIds=true
|
||||
# Enable the newly refactored resource shrinker.
|
||||
android.experimental.enableNewResourceShrinker=true
|
||||
# Enable precise shrinking in the new resource shrinker.
|
||||
android.experimental.enableNewResourceShrinker.preciseShrinking=true
|
||||
# Generate manifest class as a .class directly rather than a Java source file.
|
||||
android.generateManifestClass=true
|
||||
# Generate the text map of source sets and absolute paths to allow
|
||||
# generating relative paths from absolute paths later in the build.
|
||||
android.experimental.enableSourceSetPathsMap=true
|
||||
# Use relative paths for better Gradle caching of library build tasks
|
||||
android.experimental.cacheCompileLibResources=true
|
||||
|
||||
# Default Android build features
|
||||
# Disable BuildConfig generation by default
|
||||
android.defaults.buildfeatures.buildconfig=false
|
||||
# Disable AIDL stub generation by default
|
||||
android.defaults.buildfeatures.aidl=false
|
||||
# Disable RenderScript compilation by default
|
||||
android.defaults.buildfeatures.renderscript=false
|
||||
# Disable resource values generation by default in libraries
|
||||
android.defaults.buildfeatures.resvalues=false
|
||||
# Disable shader compilation by default
|
||||
android.defaults.buildfeatures.shaders=false
|
||||
# Disable Android resource processing by default
|
||||
android.library.defaults.buildfeatures.androidresources=false
|
||||
|
||||
# Suppress warnings for some features that aren't yet stabilized
|
||||
android.suppressUnsupportedOptionWarnings=android.enableR8.fullMode,android.useMinimalKeepRules,android.namespacedRClass,android.suppressUnsupportedOptionWarnings
|
||||
android.suppressUnsupportedOptionWarnings=android.keepWorkerActionServicesBetweenBuilds,\
|
||||
android.experimental.enableNewResourceShrinker,android.experimental.enableNewResourceShrinker.preciseShrinking,\
|
||||
android.enableAppCompileTimeRClass,android.experimental.enableSourceSetPathsMap,android.experimental.cacheCompileLibResources,\
|
||||
android.suppressUnsupportedOptionWarnings
|
||||
|
||||
# OSSRH sometimes struggles with slow deployments, so this makes Gradle
|
||||
# more tolerant to those delays.
|
||||
systemProp.org.gradle.internal.http.connectionTimeout=500000
|
||||
systemProp.org.gradle.internal.http.socketTimeout=500000
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+3
-2
@@ -1,6 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
distributionSha256Sum=7ba68c54029790ab444b39d7e293d3236b2632631fb5f2e012bb28b4ff669e4b
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -17,67 +17,101 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
@@ -106,80 +140,105 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
@@ -1,2 +1,28 @@
|
||||
pluginManagement {
|
||||
def agpVersion = '7.4.2'
|
||||
def kotlinVersion = "1.8.0"
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
plugins {
|
||||
id("com.android.application") version "$agpVersion"
|
||||
id("com.android.library") version "$agpVersion"
|
||||
id("org.jetbrains.kotlin.android") version "$kotlinVersion"
|
||||
id("org.jetbrains.kotlin.kapt") version "$kotlinVersion"
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "wireguard-android"
|
||||
|
||||
include ':tunnel'
|
||||
include ':ui'
|
||||
|
||||
+10
-10
@@ -1,17 +1,21 @@
|
||||
apply plugin: 'com.android.library'
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
version wireguardVersionName
|
||||
group groupName
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
compileSdk 33
|
||||
ndkVersion '21.4.7075529'
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
namespace 'com.wireguard.android.tunnel'
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode wireguardVersionCode
|
||||
versionName wireguardVersionName
|
||||
}
|
||||
@@ -20,9 +24,6 @@ android {
|
||||
path 'tools/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
libraryVariants.all {
|
||||
it.generateBuildConfigProvider.configure { enabled = false }
|
||||
}
|
||||
testOptions.unitTests.all {
|
||||
testLogging {
|
||||
events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
|
||||
@@ -44,16 +45,15 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
disable('LongLogTag')
|
||||
disable('NewApi') // Desugaring!
|
||||
lint {
|
||||
disable 'LongLogTag', 'NewApi'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.annotation:annotation:$annotationsVersion"
|
||||
implementation "androidx.collection:collection:$collectionVersion"
|
||||
implementation "com.google.code.findbugs:jsr305:$jsr305Version"
|
||||
compileOnly "com.google.code.findbugs:jsr305:$jsr305Version"
|
||||
testImplementation "junit:junit:$junitVersion"
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -1,4 +1,5 @@
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'signing'
|
||||
|
||||
afterEvaluate {
|
||||
publishing {
|
||||
@@ -35,17 +36,21 @@ afterEvaluate {
|
||||
name = 'WireGuard'
|
||||
url = 'https://www.wireguard.com/'
|
||||
}
|
||||
developer {
|
||||
name = 'WireGuard'
|
||||
email = 'team@wireguard.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
name = "bintray"
|
||||
url = uri("https://api.bintray.com/maven/wireguard/wireguard-android/wireguard-android/;publish=1;override=0")
|
||||
name = "sonatype"
|
||||
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
|
||||
credentials {
|
||||
username = hasProperty('BINTRAY_USER') ? getProperty('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||
password = hasProperty('BINTRAY_KEY') ? getProperty('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||
username = hasProperty('SONATYPE_USER') ? getProperty('SONATYPE_USER') : System.getenv('SONATYPE_USER')
|
||||
password = hasProperty('SONATYPE_PASSWORD') ? getProperty('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,3 +75,8 @@ android.libraryVariants.all { variant ->
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
useGpgCmd()
|
||||
sign publishing.publications
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<!--
|
||||
~ Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
~ Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
~ SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wireguard.android.tunnel">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name="com.wireguard.android.backend.GoBackend$VpnService"
|
||||
android:permission="android.permission.BIND_VPN_SERVICE">
|
||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.VpnService" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -55,6 +55,7 @@ public final class BackendException extends Exception {
|
||||
VPN_NOT_AUTHORIZED,
|
||||
UNABLE_TO_START_VPN,
|
||||
TUN_CREATION_ERROR,
|
||||
GO_ACTIVATION_ERROR_CODE
|
||||
GO_ACTIVATION_ERROR_CODE,
|
||||
DNS_RESOLUTION_FAILURE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.wireguard.android.backend.BackendException.Reason;
|
||||
import com.wireguard.android.backend.Tunnel.State;
|
||||
import com.wireguard.android.util.SharedLibraryLoader;
|
||||
import com.wireguard.config.Config;
|
||||
import com.wireguard.config.InetEndpoint;
|
||||
import com.wireguard.config.InetNetwork;
|
||||
import com.wireguard.config.Peer;
|
||||
import com.wireguard.crypto.Key;
|
||||
@@ -40,6 +41,7 @@ import androidx.collection.ArraySet;
|
||||
*/
|
||||
@NonNullForAll
|
||||
public final class GoBackend implements Backend {
|
||||
private static final int DNS_RESOLUTION_RETRIES = 10;
|
||||
private static final String TAG = "WireGuard/GoBackend";
|
||||
@Nullable private static AlwaysOnCallback alwaysOnCallback;
|
||||
private static GhettoCompletableFuture<VpnService> vpnService = new GhettoCompletableFuture<>();
|
||||
@@ -68,7 +70,7 @@ public final class GoBackend implements Backend {
|
||||
alwaysOnCallback = cb;
|
||||
}
|
||||
|
||||
private static native String wgGetConfig(int handle);
|
||||
@Nullable private static native String wgGetConfig(int handle);
|
||||
|
||||
private static native int wgGetSocketV4(int handle);
|
||||
|
||||
@@ -115,10 +117,11 @@ public final class GoBackend implements Backend {
|
||||
@Override
|
||||
public Statistics getStatistics(final Tunnel tunnel) {
|
||||
final Statistics stats = new Statistics();
|
||||
if (tunnel != currentTunnel) {
|
||||
if (tunnel != currentTunnel || currentTunnelHandle == -1)
|
||||
return stats;
|
||||
}
|
||||
final String config = wgGetConfig(currentTunnelHandle);
|
||||
if (config == null)
|
||||
return stats;
|
||||
Key key = null;
|
||||
long rx = 0;
|
||||
long tx = 0;
|
||||
@@ -233,6 +236,25 @@ public final class GoBackend implements Backend {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dnsRetry: for (int i = 0; i < DNS_RESOLUTION_RETRIES; ++i) {
|
||||
// Pre-resolve IPs so they're cached when building the userspace string
|
||||
for (final Peer peer : config.getPeers()) {
|
||||
final InetEndpoint ep = peer.getEndpoint().orElse(null);
|
||||
if (ep == null)
|
||||
continue;
|
||||
if (ep.getResolved().orElse(null) == null) {
|
||||
if (i < DNS_RESOLUTION_RETRIES - 1) {
|
||||
Log.w(TAG, "DNS host \"" + ep.getHost() + "\" failed to resolve; trying again");
|
||||
Thread.sleep(1000);
|
||||
continue dnsRetry;
|
||||
} else
|
||||
throw new BackendException(Reason.DNS_RESOLUTION_FAILURE, ep.getHost());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Build config
|
||||
final String goConfig = config.toWgUserspaceString();
|
||||
|
||||
@@ -252,6 +274,9 @@ public final class GoBackend implements Backend {
|
||||
for (final InetAddress addr : config.getInterface().getDnsServers())
|
||||
builder.addDnsServer(addr.getHostAddress());
|
||||
|
||||
for (final String dnsSearchDomain : config.getInterface().getDnsSearchDomains())
|
||||
builder.addSearchDomain(dnsSearchDomain);
|
||||
|
||||
boolean sawDefaultRoute = false;
|
||||
for (final Peer peer : config.getPeers()) {
|
||||
for (final InetNetwork addr : peer.getAllowedIps()) {
|
||||
@@ -278,7 +303,7 @@ public final class GoBackend implements Backend {
|
||||
try (final ParcelFileDescriptor tun = builder.establish()) {
|
||||
if (tun == null)
|
||||
throw new BackendException(Reason.TUN_CREATION_ERROR);
|
||||
Log.d(TAG, "Go backend v" + wgVersion());
|
||||
Log.d(TAG, "Go backend " + wgVersion());
|
||||
currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig);
|
||||
}
|
||||
if (currentTunnelHandle < 0)
|
||||
@@ -294,11 +319,11 @@ public final class GoBackend implements Backend {
|
||||
Log.w(TAG, "Tunnel already down");
|
||||
return;
|
||||
}
|
||||
|
||||
wgTurnOff(currentTunnelHandle);
|
||||
int handleToClose = currentTunnelHandle;
|
||||
currentTunnel = null;
|
||||
currentTunnelHandle = -1;
|
||||
currentConfig = null;
|
||||
wgTurnOff(handleToClose);
|
||||
}
|
||||
|
||||
tunnel.onStateChange(state);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -53,6 +53,10 @@ public final class WgQuickBackend implements Backend {
|
||||
this.toolsInstaller = toolsInstaller;
|
||||
}
|
||||
|
||||
public static boolean hasKernelSupport() {
|
||||
return new File("/sys/module/wireguard").exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRunningTunnelNames() {
|
||||
final List<String> output = new ArrayList<>();
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2019-2020 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.wireguard.android.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.system.OsConstants;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.wireguard.android.util.RootShell.RootShellException;
|
||||
import com.wireguard.crypto.Ed25519;
|
||||
import com.wireguard.util.NonNullForAll;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Class that implements the logic for downloading and loading signed, prebuilt modules for
|
||||
* WireGuard into the running kernel.
|
||||
*/
|
||||
@NonNullForAll
|
||||
@SuppressWarnings("MagicNumber")
|
||||
public class ModuleLoader {
|
||||
private static final String MODULE_LIST_URL = "https://download.wireguard.com/android-module/modules.txt.sig";
|
||||
private static final String MODULE_NAME = "wireguard-%s.ko";
|
||||
private static final String MODULE_PUBLIC_KEY_BASE64 = "RWRmHuT9PSqtwfsLtEx+QS06BJtLgFYteL9WCNjH7yuyu5Y1DieSN7If";
|
||||
private static final String MODULE_URL = "https://download.wireguard.com/android-module/%s";
|
||||
private final File moduleDir;
|
||||
private final RootShell rootShell;
|
||||
private final File tmpDir;
|
||||
private final String userAgent;
|
||||
|
||||
/**
|
||||
* Public constructor for ModuleLoader
|
||||
*
|
||||
* @param context A {@link Context} instance.
|
||||
* @param rootShell A {@link RootShell} instance used to run elevated commands required for module
|
||||
* loading.
|
||||
* @param userAgent A {@link String} that represents the User-Agent string used for connections
|
||||
* to the upstream server.
|
||||
*/
|
||||
public ModuleLoader(final Context context, final RootShell rootShell, final String userAgent) {
|
||||
moduleDir = new File(context.getCacheDir(), "kmod");
|
||||
tmpDir = new File(context.getCacheDir(), "tmp");
|
||||
this.rootShell = rootShell;
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a WireGuard module is already loaded into the kernel.
|
||||
*
|
||||
* @return boolean indicating if WireGuard is already enabled in the kernel.
|
||||
*/
|
||||
public static boolean isModuleLoaded() {
|
||||
return new File("/sys/module/wireguard").exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the correct WireGuard module for the device
|
||||
*
|
||||
* @return {@link OsConstants}.EXIT_SUCCESS if everything succeeds, ENOENT otherwise.
|
||||
* @throws IOException if the remote hash list was not found or empty.
|
||||
* @throws RootShellException if {@link RootShell} has a failure executing elevated commands.
|
||||
* @throws NoSuchAlgorithmException if SHA256 algorithm is not available in device JDK.
|
||||
*/
|
||||
public Integer download() throws IOException, RootShellException, NoSuchAlgorithmException {
|
||||
final List<String> output = new ArrayList<>();
|
||||
rootShell.run(output, "sha256sum /proc/version|cut -d ' ' -f 1");
|
||||
if (output.size() != 1 || output.get(0).length() != 64)
|
||||
throw new InvalidParameterException("Invalid sha256 of /proc/version");
|
||||
final String moduleName = String.format(MODULE_NAME, output.get(0));
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(MODULE_LIST_URL).openConnection();
|
||||
connection.setRequestProperty("User-Agent", userAgent);
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
|
||||
throw new IOException("Hash list could not be found");
|
||||
final byte[] input = new byte[1024 * 1024 * 3 /* 3MiB */];
|
||||
int len;
|
||||
try (final InputStream inputStream = connection.getInputStream()) {
|
||||
len = inputStream.read(input);
|
||||
}
|
||||
if (len <= 0)
|
||||
throw new IOException("Hash list was empty");
|
||||
final Map<String, Sha256Digest> modules = verifySignedHashes(new String(input, 0, len, StandardCharsets.UTF_8));
|
||||
if (modules == null)
|
||||
throw new InvalidParameterException("The signature did not verify or invalid hash list format");
|
||||
if (!modules.containsKey(moduleName))
|
||||
return OsConstants.ENOENT;
|
||||
connection = (HttpURLConnection) new URL(String.format(MODULE_URL, moduleName)).openConnection();
|
||||
connection.setRequestProperty("User-Agent", userAgent);
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
|
||||
throw new IOException("Module file could not be found, despite being on hash list");
|
||||
|
||||
tmpDir.mkdirs();
|
||||
moduleDir.mkdir();
|
||||
File tempFile = null;
|
||||
try {
|
||||
tempFile = File.createTempFile("UNVERIFIED-", null, tmpDir);
|
||||
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
try (final InputStream inputStream = connection.getInputStream();
|
||||
final FileOutputStream outputStream = new FileOutputStream(tempFile)) {
|
||||
int total = 0;
|
||||
while ((len = inputStream.read(input)) > 0) {
|
||||
total += len;
|
||||
if (total > 1024 * 1024 * 15 /* 15 MiB */)
|
||||
throw new IOException("File too big");
|
||||
outputStream.write(input, 0, len);
|
||||
digest.update(input, 0, len);
|
||||
}
|
||||
outputStream.getFD().sync();
|
||||
}
|
||||
if (!Arrays.equals(digest.digest(), modules.get(moduleName).bytes))
|
||||
throw new IOException("Incorrect file hash");
|
||||
|
||||
if (!tempFile.renameTo(new File(moduleDir, moduleName)))
|
||||
throw new IOException("Unable to rename to final destination");
|
||||
} finally {
|
||||
if (tempFile != null)
|
||||
tempFile.delete();
|
||||
}
|
||||
return OsConstants.EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the downloaded module. ModuleLoader#download must be called before this.
|
||||
*
|
||||
* @throws IOException if {@link RootShell} has a failure executing elevated commands.
|
||||
* @throws RootShellException if {@link RootShell} has a failure executing elevated commands.
|
||||
*/
|
||||
public void loadModule() throws IOException, RootShellException {
|
||||
rootShell.run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module might already exist in the app's data.
|
||||
*
|
||||
* @return boolean indicating whether downloadable module might exist already.
|
||||
*/
|
||||
public boolean moduleMightExist() {
|
||||
return moduleDir.exists() && moduleDir.isDirectory();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Map<String, Sha256Digest> verifySignedHashes(final String signifyDigest) {
|
||||
byte[] publicKeyBytes = Base64.decode(MODULE_PUBLIC_KEY_BASE64, Base64.DEFAULT);
|
||||
|
||||
if (publicKeyBytes == null || publicKeyBytes.length != 32 + 10 || publicKeyBytes[0] != 'E' || publicKeyBytes[1] != 'd')
|
||||
return null;
|
||||
|
||||
final String[] lines = signifyDigest.split("\n", 3);
|
||||
if (lines.length != 3)
|
||||
return null;
|
||||
if (!lines[0].startsWith("untrusted comment: "))
|
||||
return null;
|
||||
|
||||
byte[] signatureBytes = Base64.decode(lines[1], Base64.DEFAULT);
|
||||
if (signatureBytes == null || signatureBytes.length != 64 + 10)
|
||||
return null;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (signatureBytes[i] != publicKeyBytes[i])
|
||||
return null;
|
||||
}
|
||||
publicKeyBytes = Arrays.copyOfRange(publicKeyBytes, 10, 10 + 32);
|
||||
signatureBytes = Arrays.copyOfRange(signatureBytes, 10, 10 + 64);
|
||||
if (!Ed25519.verify(lines[2].getBytes(StandardCharsets.UTF_8), signatureBytes, publicKeyBytes))
|
||||
return null;
|
||||
|
||||
final Map<String, Sha256Digest> hashes = new HashMap<>();
|
||||
for (final String line : lines[2].split("\n")) {
|
||||
final String[] components = line.split(" {2}", 2);
|
||||
if (components.length != 2)
|
||||
return null;
|
||||
try {
|
||||
hashes.put(components[1], new Sha256Digest(components[0]));
|
||||
} catch (final Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
private static final class Sha256Digest {
|
||||
private final byte[] bytes;
|
||||
|
||||
private Sha256Digest(final String hex) {
|
||||
if (hex.length() != 64)
|
||||
throw new InvalidParameterException("SHA256 hashes must be 32 bytes long");
|
||||
bytes = new byte[32];
|
||||
for (int i = 0; i < 32; ++i)
|
||||
bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -145,7 +145,7 @@ public final class ToolsInstaller {
|
||||
|
||||
script.append("trap 'rm -rf /data/adb/modules/wireguard' INT TERM EXIT; ");
|
||||
script.append(String.format("rm -rf /data/adb/modules/wireguard/; mkdir -p /data/adb/modules/wireguard%s; ", INSTALL_DIR));
|
||||
script.append("printf 'name=WireGuard Command Line Tools\nversion=1.0\nversionCode=1\nauthor=zx2c4\ndescription=Command line tools for WireGuard\nminMagisk=1500\n' > /data/adb/modules/wireguard/module.prop; ");
|
||||
script.append("printf 'id=wireguard\nname=WireGuard Command Line Tools\nversion=1.0\nversionCode=1\nauthor=zx2c4\ndescription=Command line tools for WireGuard\nminMagisk=1500\n' > /data/adb/modules/wireguard/module.prop; ");
|
||||
script.append("touch /data/adb/modules/wireguard/auto_mount; ");
|
||||
for (final String name : EXECUTABLES) {
|
||||
final File destination = new File("/data/adb/modules/wireguard" + INSTALL_DIR, name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
public final class InetAddresses {
|
||||
@Nullable private static final Method PARSER_METHOD;
|
||||
private static final Pattern WONT_TOUCH_RESOLVER = Pattern.compile("^(((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?)|((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$");
|
||||
private static final Pattern VALID_HOSTNAME = Pattern.compile("^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\\.?$");
|
||||
|
||||
static {
|
||||
Method m = null;
|
||||
@@ -38,6 +39,16 @@ public final class InetAddresses {
|
||||
private InetAddresses() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether input is a valid DNS hostname.
|
||||
*
|
||||
* @param maybeHostname a string that is possibly a DNS hostname
|
||||
* @return whether or not maybeHostname is a valid DNS hostname
|
||||
*/
|
||||
public static boolean isHostname(final CharSequence maybeHostname) {
|
||||
return VALID_HOSTNAME.matcher(maybeHostname).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a numeric IPv4 or IPv6 address without performing any DNS lookups.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,7 @@ public final class Interface {
|
||||
|
||||
private final Set<InetNetwork> addresses;
|
||||
private final Set<InetAddress> dnsServers;
|
||||
private final Set<String> dnsSearchDomains;
|
||||
private final Set<String> excludedApplications;
|
||||
private final Set<String> includedApplications;
|
||||
private final KeyPair keyPair;
|
||||
@@ -50,6 +51,7 @@ public final class Interface {
|
||||
// Defensively copy to ensure immutability even if the Builder is reused.
|
||||
addresses = Collections.unmodifiableSet(new LinkedHashSet<>(builder.addresses));
|
||||
dnsServers = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsServers));
|
||||
dnsSearchDomains = Collections.unmodifiableSet(new LinkedHashSet<>(builder.dnsSearchDomains));
|
||||
excludedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.excludedApplications));
|
||||
includedApplications = Collections.unmodifiableSet(new LinkedHashSet<>(builder.includedApplications));
|
||||
keyPair = Objects.requireNonNull(builder.keyPair, "Interfaces must have a private key");
|
||||
@@ -108,6 +110,7 @@ public final class Interface {
|
||||
final Interface other = (Interface) obj;
|
||||
return addresses.equals(other.addresses)
|
||||
&& dnsServers.equals(other.dnsServers)
|
||||
&& dnsSearchDomains.equals(other.dnsSearchDomains)
|
||||
&& excludedApplications.equals(other.excludedApplications)
|
||||
&& includedApplications.equals(other.includedApplications)
|
||||
&& keyPair.equals(other.keyPair)
|
||||
@@ -135,6 +138,16 @@ public final class Interface {
|
||||
return dnsServers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of DNS search domains associated with the interface.
|
||||
*
|
||||
* @return a set of strings
|
||||
*/
|
||||
public Set<String> getDnsSearchDomains() {
|
||||
// The collection is already immutable.
|
||||
return dnsSearchDomains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of applications excluded from using the interface.
|
||||
*
|
||||
@@ -222,6 +235,7 @@ public final class Interface {
|
||||
sb.append("Address = ").append(Attribute.join(addresses)).append('\n');
|
||||
if (!dnsServers.isEmpty()) {
|
||||
final List<String> dnsServerStrings = dnsServers.stream().map(InetAddress::getHostAddress).collect(Collectors.toList());
|
||||
dnsServerStrings.addAll(dnsSearchDomains);
|
||||
sb.append("DNS = ").append(Attribute.join(dnsServerStrings)).append('\n');
|
||||
}
|
||||
if (!excludedApplications.isEmpty())
|
||||
@@ -254,6 +268,8 @@ public final class Interface {
|
||||
// Defaults to an empty set.
|
||||
private final Set<InetAddress> dnsServers = new LinkedHashSet<>();
|
||||
// Defaults to an empty set.
|
||||
private final Set<String> dnsSearchDomains = new LinkedHashSet<>();
|
||||
// Defaults to an empty set.
|
||||
private final Set<String> excludedApplications = new LinkedHashSet<>();
|
||||
// Defaults to an empty set.
|
||||
private final Set<String> includedApplications = new LinkedHashSet<>();
|
||||
@@ -284,6 +300,16 @@ public final class Interface {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addDnsSearchDomain(final String dnsSearchDomain) {
|
||||
dnsSearchDomains.add(dnsSearchDomain);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addDnsSearchDomains(final Collection<String> dnsSearchDomains) {
|
||||
this.dnsSearchDomains.addAll(dnsSearchDomains);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Interface build() throws BadConfigException {
|
||||
if (keyPair == null)
|
||||
throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY,
|
||||
@@ -326,8 +352,15 @@ public final class Interface {
|
||||
|
||||
public Builder parseDnsServers(final CharSequence dnsServers) throws BadConfigException {
|
||||
try {
|
||||
for (final String dnsServer : Attribute.split(dnsServers))
|
||||
addDnsServer(InetAddresses.parse(dnsServer));
|
||||
for (final String dnsServer : Attribute.split(dnsServers)) {
|
||||
try {
|
||||
addDnsServer(InetAddresses.parse(dnsServer));
|
||||
} catch (final ParseException e) {
|
||||
if (e.getParsingClass() != InetAddress.class || !InetAddresses.isHostname(dnsServer))
|
||||
throw e;
|
||||
addDnsSearchDomain(dnsServer);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
} catch (final ParseException e) {
|
||||
throw new BadConfigException(Section.INTERFACE, Location.DNS, e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2016 Southern Storm Software, Pty Ltd.
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Interface]
|
||||
Address = 192.0.2.2/32,2001:db8:ffff:ffff:ffff:ffff:ffff:ffff/128
|
||||
DNS = 192.0.2.0,yes
|
||||
DNS = 192.0.2.0,invalid_value
|
||||
PrivateKey = TFlmmEUC7V7VtiDYLKsbP5rySTKLIZq1yn8lMqK83wo=
|
||||
[Peer]
|
||||
AllowedIPs = 0.0.0.0/0, ::0/0
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
# Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project("WireGuard")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
|
||||
|
||||
# Work around https://github.com/android-ndk/ndk/issues/602
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
# Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
|
||||
BUILDDIR ?= $(CURDIR)/build
|
||||
DESTDIR ?= $(CURDIR)/out
|
||||
@@ -20,11 +20,12 @@ export GOARCH := $(NDK_GO_ARCH_MAP_$(ANDROID_ARCH_NAME))
|
||||
export GOOS := android
|
||||
export CGO_ENABLED := 1
|
||||
|
||||
GO_VERSION := 1.15.2
|
||||
GO_VERSION := 1.20.2
|
||||
GO_PLATFORM := $(shell uname -s | tr '[:upper:]' '[:lower:]')-$(NDK_GO_ARCH_MAP_$(shell uname -m))
|
||||
GO_TARBALL := go$(GO_VERSION).$(GO_PLATFORM).tar.gz
|
||||
GO_HASH_darwin-amd64 := 9bd39600d9fa1fa4a5ccce8761d249f7421cffe671376f791293c4138f3d7c62
|
||||
GO_HASH_linux-amd64 := b49fda1ca29a1946d6bb2a5a6982cf07ccd2aba849289508ee0f9918f6bb4552
|
||||
GO_HASH_darwin-amd64 := c93b8ced9517d07e1cd4c362c6e2d5242cb139e29b417a328fbf19aded08764c
|
||||
GO_HASH_darwin-arm64 := 7343c87f19e79c0063532e82e1c4d6f42175a32d99f7a4d15e658e88bf97f885
|
||||
GO_HASH_linux-amd64 := 4eaea32f59cde4dc635fbc42161031d13e1c780b87097f4b4234cfce671f1768
|
||||
|
||||
default: $(DESTDIR)/libwg-go.so
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright © 2017-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -10,14 +10,13 @@ package main
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"log"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
@@ -29,13 +28,21 @@ import (
|
||||
)
|
||||
|
||||
type AndroidLogger struct {
|
||||
level C.int
|
||||
interfaceName string
|
||||
level C.int
|
||||
tag *C.char
|
||||
}
|
||||
|
||||
func (l AndroidLogger) Write(p []byte) (int, error) {
|
||||
C.__android_log_write(l.level, C.CString("WireGuard/GoBackend/"+l.interfaceName), C.CString(string(p)))
|
||||
return len(p), nil
|
||||
func cstring(s string) *C.char {
|
||||
b, err := unix.BytePtrFromString(s)
|
||||
if err != nil {
|
||||
b := [1]C.char{}
|
||||
return &b[0]
|
||||
}
|
||||
return (*C.char)(unsafe.Pointer(b))
|
||||
}
|
||||
|
||||
func (l AndroidLogger) Printf(format string, args ...interface{}) {
|
||||
C.__android_log_write(l.level, l.tag, cstring(fmt.Sprintf(format, args...)))
|
||||
}
|
||||
|
||||
type TunnelHandle struct {
|
||||
@@ -55,39 +62,38 @@ func init() {
|
||||
select {
|
||||
case <-signals:
|
||||
n := runtime.Stack(buf, true)
|
||||
if n == len(buf) {
|
||||
n--
|
||||
}
|
||||
buf[n] = 0
|
||||
C.__android_log_write(C.ANDROID_LOG_ERROR, C.CString("WireGuard/GoBackend/Stacktrace"), (*C.char)(unsafe.Pointer(&buf[0])))
|
||||
C.__android_log_write(C.ANDROID_LOG_ERROR, cstring("WireGuard/GoBackend/Stacktrace"), (*C.char)(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
//export wgTurnOn
|
||||
func wgTurnOn(ifnameRef string, tunFd int32, settings string) int32 {
|
||||
interfaceName := string([]byte(ifnameRef))
|
||||
|
||||
func wgTurnOn(interfaceName string, tunFd int32, settings string) int32 {
|
||||
tag := cstring("WireGuard/GoBackend/" + interfaceName)
|
||||
logger := &device.Logger{
|
||||
Debug: log.New(&AndroidLogger{level: C.ANDROID_LOG_DEBUG, interfaceName: interfaceName}, "", 0),
|
||||
Info: log.New(&AndroidLogger{level: C.ANDROID_LOG_INFO, interfaceName: interfaceName}, "", 0),
|
||||
Error: log.New(&AndroidLogger{level: C.ANDROID_LOG_ERROR, interfaceName: interfaceName}, "", 0),
|
||||
Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf,
|
||||
Errorf: AndroidLogger{level: C.ANDROID_LOG_ERROR, tag: tag}.Printf,
|
||||
}
|
||||
|
||||
logger.Debug.Println("Debug log enabled")
|
||||
|
||||
tun, name, err := tun.CreateUnmonitoredTUNFromFD(int(tunFd))
|
||||
if err != nil {
|
||||
unix.Close(int(tunFd))
|
||||
logger.Error.Println(err)
|
||||
logger.Errorf("CreateUnmonitoredTUNFromFD: %v", err)
|
||||
return -1
|
||||
}
|
||||
|
||||
logger.Info.Println("Attaching to interface", name)
|
||||
device := device.NewDevice(tun, logger)
|
||||
logger.Verbosef("Attaching to interface %v", name)
|
||||
device := device.NewDevice(tun, conn.NewStdNetBind(), logger)
|
||||
|
||||
setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(settings)))
|
||||
if setError != nil {
|
||||
err = device.IpcSet(settings)
|
||||
if err != nil {
|
||||
unix.Close(int(tunFd))
|
||||
logger.Error.Println(setError)
|
||||
logger.Errorf("IpcSet: %v", err)
|
||||
return -1
|
||||
}
|
||||
device.DisableSomeRoamingForBrokenMobileSemantics()
|
||||
@@ -96,12 +102,12 @@ func wgTurnOn(ifnameRef string, tunFd int32, settings string) int32 {
|
||||
|
||||
uapiFile, err := ipc.UAPIOpen(name)
|
||||
if err != nil {
|
||||
logger.Error.Println(err)
|
||||
logger.Errorf("UAPIOpen: %v", err)
|
||||
} else {
|
||||
uapi, err = ipc.UAPIListen(name, uapiFile)
|
||||
if err != nil {
|
||||
uapiFile.Close()
|
||||
logger.Error.Println(err)
|
||||
logger.Errorf("UAPIListen: %v", err)
|
||||
} else {
|
||||
go func() {
|
||||
for {
|
||||
@@ -115,8 +121,14 @@ func wgTurnOn(ifnameRef string, tunFd int32, settings string) int32 {
|
||||
}
|
||||
}
|
||||
|
||||
device.Up()
|
||||
logger.Info.Println("Device started")
|
||||
err = device.Up()
|
||||
if err != nil {
|
||||
logger.Errorf("Unable to bring up device: %v", err)
|
||||
uapiFile.Close()
|
||||
device.Close()
|
||||
return -1
|
||||
}
|
||||
logger.Verbosef("Device started")
|
||||
|
||||
var i int32
|
||||
for i = 0; i < math.MaxInt32; i++ {
|
||||
@@ -125,7 +137,9 @@ func wgTurnOn(ifnameRef string, tunFd int32, settings string) int32 {
|
||||
}
|
||||
}
|
||||
if i == math.MaxInt32 {
|
||||
unix.Close(int(tunFd))
|
||||
logger.Errorf("Unable to find empty handle")
|
||||
uapiFile.Close()
|
||||
device.Close()
|
||||
return -1
|
||||
}
|
||||
tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi}
|
||||
@@ -185,19 +199,29 @@ func wgGetConfig(tunnelHandle int32) *C.char {
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
settings := new(bytes.Buffer)
|
||||
writer := bufio.NewWriter(settings)
|
||||
err := handle.device.IpcGetOperation(writer)
|
||||
settings, err := handle.device.IpcGet()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
writer.Flush()
|
||||
return C.CString(settings.String())
|
||||
return C.CString(settings)
|
||||
}
|
||||
|
||||
//export wgVersion
|
||||
func wgVersion() *C.char {
|
||||
return C.CString(device.WireGuardGoVersion)
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return C.CString("unknown")
|
||||
}
|
||||
for _, dep := range info.Deps {
|
||||
if dep.Path == "golang.zx2c4.com/wireguard" {
|
||||
parts := strings.Split(dep.Version, "-")
|
||||
if len(parts) == 3 && len(parts[2]) == 12 {
|
||||
return C.CString(parts[2][:7])
|
||||
}
|
||||
return C.CString(dep.Version)
|
||||
}
|
||||
}
|
||||
return C.CString("unknown")
|
||||
}
|
||||
|
||||
func main() {}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
module golang.zx2c4.com/wireguard/android
|
||||
|
||||
go 1.15
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924 // indirect
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930
|
||||
golang.zx2c4.com/wireguard v0.0.20201119-0.20201223215156-09728dc6b340
|
||||
golang.org/x/sys v0.6.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.7.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
)
|
||||
|
||||
@@ -1,24 +1,10 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
|
||||
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
|
||||
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.zx2c4.com/wireguard v0.0.20201119-0.20201223215156-09728dc6b340 h1:X6jrf2sUEj3n+q2oB/I3C088vQFKREz2UzgVJ8wENtI=
|
||||
golang.zx2c4.com/wireguard v0.0.20201119-0.20201223215156-09728dc6b340/go.mod h1:ITsWNpkFv78VPB7f8MiyuxeEMcHR4jfxHGCJLPP3GHs=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
From 1d1ba1da11afd73008c0e942db7621697055a6b6 Mon Sep 17 00:00:00 2001
|
||||
From 729c58cb1c0496497dac6de3d0bf540f6149618f Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Tue, 15 Sep 2020 13:39:22 +0200
|
||||
Subject: [PATCH] runtime: use CLOCK_BOOTTIME in nanotime on Linux
|
||||
Date: Tue, 21 Mar 2023 15:33:56 +0100
|
||||
Subject: [PATCH] [release-branch.go1.20] runtime: use CLOCK_BOOTTIME in
|
||||
nanotime on Linux
|
||||
|
||||
This makes timers account for having expired while a computer was
|
||||
asleep, which is quite common on mobile devices. Note that BOOTTIME is
|
||||
@@ -28,10 +29,10 @@ Change-Id: I7b2a6ca0c5bc5fce57ec0eeafe7b68270b429321
|
||||
8 files changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
|
||||
index 5b9b638ad7..448ad8b2e6 100644
|
||||
index 12a294153d..17e3524b40 100644
|
||||
--- a/src/runtime/sys_linux_386.s
|
||||
+++ b/src/runtime/sys_linux_386.s
|
||||
@@ -339,13 +339,13 @@ noswitch:
|
||||
@@ -352,13 +352,13 @@ noswitch:
|
||||
|
||||
LEAL 8(SP), BX // &ts (struct timespec)
|
||||
MOVL BX, 4(SP)
|
||||
@@ -48,20 +49,20 @@ index 5b9b638ad7..448ad8b2e6 100644
|
||||
INVOKE_SYSCALL
|
||||
|
||||
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
|
||||
index fe9c6bce85..4836a7c774 100644
|
||||
index c7a89ba536..01f0a6a26e 100644
|
||||
--- a/src/runtime/sys_linux_amd64.s
|
||||
+++ b/src/runtime/sys_linux_amd64.s
|
||||
@@ -311,7 +311,7 @@ noswitch:
|
||||
MOVQ runtime·vdsoClockgettimeSym(SB), AX
|
||||
CMPQ AX, $0
|
||||
JEQ fallback
|
||||
@@ -255,7 +255,7 @@ noswitch:
|
||||
SUBQ $16, SP // Space for results
|
||||
ANDQ $~15, SP // Align for C code
|
||||
|
||||
- MOVL $1, DI // CLOCK_MONOTONIC
|
||||
+ MOVL $7, DI // CLOCK_BOOTTIME
|
||||
LEAQ 0(SP), SI
|
||||
CALL AX
|
||||
MOVQ 0(SP), AX // sec
|
||||
MOVQ runtime·vdsoClockgettimeSym(SB), AX
|
||||
CMPQ AX, $0
|
||||
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
|
||||
index 475f52344c..bb567abcf4 100644
|
||||
index 7b8c4f0e04..9798a1334e 100644
|
||||
--- a/src/runtime/sys_linux_arm.s
|
||||
+++ b/src/runtime/sys_linux_arm.s
|
||||
@@ -11,7 +11,7 @@
|
||||
@@ -73,20 +74,20 @@ index 475f52344c..bb567abcf4 100644
|
||||
|
||||
// for EABI, as we don't support OABI
|
||||
#define SYS_BASE 0x0
|
||||
@@ -366,7 +366,7 @@ noswitch:
|
||||
SUB $24, R13 // Space for results
|
||||
BIC $0x7, R13 // Align for C code
|
||||
@@ -374,7 +374,7 @@ finish:
|
||||
|
||||
// func nanotime1() int64
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$12-8
|
||||
- MOVW $CLOCK_MONOTONIC, R0
|
||||
+ MOVW $CLOCK_BOOTTIME, R0
|
||||
MOVW $8(R13), R1 // timespec
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R2
|
||||
CMP $0, R2
|
||||
MOVW $spec-12(SP), R1 // timespec
|
||||
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R4
|
||||
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
|
||||
index 198a5bacef..9715387f36 100644
|
||||
index 38ff6ac330..6b819c5441 100644
|
||||
--- a/src/runtime/sys_linux_arm64.s
|
||||
+++ b/src/runtime/sys_linux_arm64.s
|
||||
@@ -13,7 +13,7 @@
|
||||
@@ -14,7 +14,7 @@
|
||||
#define AT_FDCWD -100
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
@@ -95,7 +96,7 @@ index 198a5bacef..9715387f36 100644
|
||||
|
||||
#define SYS_exit 93
|
||||
#define SYS_read 63
|
||||
@@ -319,7 +319,7 @@ noswitch:
|
||||
@@ -338,7 +338,7 @@ noswitch:
|
||||
BIC $15, R1
|
||||
MOVD R1, RSP
|
||||
|
||||
@@ -105,10 +106,10 @@ index 198a5bacef..9715387f36 100644
|
||||
CBZ R2, fallback
|
||||
|
||||
diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
|
||||
index afad056d06..2c9162b903 100644
|
||||
index 47f2da524d..6c1a9a2801 100644
|
||||
--- a/src/runtime/sys_linux_mips64x.s
|
||||
+++ b/src/runtime/sys_linux_mips64x.s
|
||||
@@ -304,7 +304,7 @@ noswitch:
|
||||
@@ -326,7 +326,7 @@ noswitch:
|
||||
AND $~15, R1 // Align for C code
|
||||
MOVV R1, R29
|
||||
|
||||
@@ -118,10 +119,10 @@ index afad056d06..2c9162b903 100644
|
||||
|
||||
MOVV runtime·vdsoClockgettimeSym(SB), R25
|
||||
diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s
|
||||
index fab2ab3892..f9af103594 100644
|
||||
index 5e6b6c1504..7f5fd2a80e 100644
|
||||
--- a/src/runtime/sys_linux_mipsx.s
|
||||
+++ b/src/runtime/sys_linux_mipsx.s
|
||||
@@ -238,7 +238,7 @@ TEXT runtime·walltime1(SB),NOSPLIT,$8-12
|
||||
@@ -243,7 +243,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
||||
RET
|
||||
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$8-8
|
||||
@@ -131,11 +132,11 @@ index fab2ab3892..f9af103594 100644
|
||||
MOVW $SYS_clock_gettime, R2
|
||||
SYSCALL
|
||||
diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
|
||||
index fd69ee70a5..ff6bc8355b 100644
|
||||
index d0427a4807..05ee9fede9 100644
|
||||
--- a/src/runtime/sys_linux_ppc64x.s
|
||||
+++ b/src/runtime/sys_linux_ppc64x.s
|
||||
@@ -249,7 +249,7 @@ fallback:
|
||||
JMP finish
|
||||
@@ -298,7 +298,7 @@ fallback:
|
||||
JMP return
|
||||
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
|
||||
- MOVD $1, R3 // CLOCK_MONOTONIC
|
||||
@@ -144,18 +145,18 @@ index fd69ee70a5..ff6bc8355b 100644
|
||||
MOVD R1, R15 // R15 is unchanged by C code
|
||||
MOVD g_m(g), R21 // R21 = m
|
||||
diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s
|
||||
index c15a1d5364..f52c4d5098 100644
|
||||
index 1448670b91..7d2ee3231c 100644
|
||||
--- a/src/runtime/sys_linux_s390x.s
|
||||
+++ b/src/runtime/sys_linux_s390x.s
|
||||
@@ -207,7 +207,7 @@ TEXT runtime·walltime1(SB),NOSPLIT,$16
|
||||
@@ -296,7 +296,7 @@ fallback:
|
||||
RET
|
||||
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$16
|
||||
- MOVW $1, R2 // CLOCK_MONOTONIC
|
||||
+ MOVW $7, R2 // CLOCK_BOOTTIME
|
||||
MOVD $tp-16(SP), R3
|
||||
MOVW $SYS_clock_gettime, R1
|
||||
SYSCALL
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$32-8
|
||||
- MOVW $1, R2 // CLOCK_MONOTONIC
|
||||
+ MOVW $7, R2 // CLOCK_BOOTTIME
|
||||
|
||||
MOVD R15, R7 // Backup stack pointer
|
||||
|
||||
--
|
||||
2.28.0
|
||||
2.40.0
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright © 2017-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright © 2017-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: BSD
|
||||
*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: BSD
|
||||
*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Submodule tunnel/tools/wireguard-tools updated: 265e81a344...b4f6b4f229
+17
-10
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'org.jetbrains.kotlin.kapt'
|
||||
}
|
||||
|
||||
version wireguardVersionName
|
||||
group groupName
|
||||
@@ -10,13 +12,18 @@ group groupName
|
||||
final def keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildFeatures.dataBinding = true
|
||||
buildFeatures.viewBinding = true
|
||||
compileSdk 33
|
||||
ndkVersion "21.4.7075529"
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
dataBinding = true
|
||||
viewBinding = true
|
||||
}
|
||||
namespace = 'com.wireguard.android'
|
||||
defaultConfig {
|
||||
applicationId 'com.wireguard.android'
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode wireguardVersionCode
|
||||
versionName wireguardVersionName
|
||||
buildConfigField 'int', 'MIN_SDK_VERSION', "$minSdkVersion.apiLevel"
|
||||
@@ -50,8 +57,9 @@ android {
|
||||
versionNameSuffix "-debug"
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
disable('LongLogTag')
|
||||
lint {
|
||||
disable 'LongLogTag'
|
||||
warning 'MissingTranslation', 'ImpliedQuantity'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +72,6 @@ dependencies {
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:$coordinatorLayoutVersion"
|
||||
implementation "androidx.biometric:biometric:$biometricVersion"
|
||||
implementation "androidx.core:core-ktx:$coreKtxVersion"
|
||||
implementation "androidx.databinding:databinding-runtime:$agpVersion"
|
||||
implementation "androidx.fragment:fragment-ktx:$fragmentVersion"
|
||||
implementation "androidx.preference:preference-ktx:$preferenceVersion"
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleRuntimeKtxVersion"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">WireGuard β</string>
|
||||
<string name="app_name" translatable="false">WireGuard β</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.wireguard.android"
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
@@ -18,6 +17,9 @@
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera.any"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
@@ -41,9 +43,10 @@
|
||||
|
||||
<activity
|
||||
android:name=".activity.TunnelToggleActivity"
|
||||
android:theme="@style/NoBackgroundTheme" />
|
||||
android:theme="@style/NoBackgroundTheme"
|
||||
android:excludeFromRecents="true"/>
|
||||
|
||||
<activity android:name=".activity.MainActivity">
|
||||
<activity android:name=".activity.MainActivity" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -57,7 +60,8 @@
|
||||
|
||||
<activity
|
||||
android:name=".activity.TvMainActivity"
|
||||
android:theme="@style/TvTheme">
|
||||
android:theme="@style/TvTheme"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
@@ -81,7 +85,8 @@
|
||||
|
||||
<activity
|
||||
android:name=".activity.LogViewerActivity"
|
||||
android:label="@string/log_viewer_title">
|
||||
android:label="@string/log_viewer_title"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
@@ -93,7 +98,7 @@
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true" />
|
||||
|
||||
<receiver android:name=".BootShutdownReceiver">
|
||||
<receiver android:name=".BootShutdownReceiver" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
@@ -102,7 +107,8 @@
|
||||
|
||||
<receiver
|
||||
android:name=".model.TunnelManager$IntentReceiver"
|
||||
android:permission="${applicationId}.permission.CONTROL_TUNNELS">
|
||||
android:permission="${applicationId}.permission.CONTROL_TUNNELS"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.wireguard.android.action.REFRESH_TUNNEL_STATES" />
|
||||
<action android:name="com.wireguard.android.action.SET_TUNNEL_UP" />
|
||||
@@ -113,7 +119,8 @@
|
||||
<service
|
||||
android:name=".QuickTileService"
|
||||
android:icon="@drawable/ic_tile"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android
|
||||
@@ -12,15 +12,16 @@ import android.os.StrictMode.ThreadPolicy
|
||||
import android.os.StrictMode.VmPolicy
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.datastore.DataStore
|
||||
import androidx.datastore.preferences.Preferences
|
||||
import androidx.datastore.preferences.createDataStore
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.preferencesDataStoreFile
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.wireguard.android.backend.Backend
|
||||
import com.wireguard.android.backend.GoBackend
|
||||
import com.wireguard.android.backend.WgQuickBackend
|
||||
import com.wireguard.android.configStore.FileConfigStore
|
||||
import com.wireguard.android.model.TunnelManager
|
||||
import com.wireguard.android.util.ModuleLoader
|
||||
import com.wireguard.android.util.RootShell
|
||||
import com.wireguard.android.util.ToolsInstaller
|
||||
import com.wireguard.android.util.UserKnobs
|
||||
@@ -41,7 +42,6 @@ class Application : android.app.Application() {
|
||||
private val futureBackend = CompletableDeferred<Backend>()
|
||||
private val coroutineScope = CoroutineScope(Job() + Dispatchers.Main.immediate)
|
||||
private var backend: Backend? = null
|
||||
private lateinit var moduleLoader: ModuleLoader
|
||||
private lateinit var rootShell: RootShell
|
||||
private lateinit var preferencesDataStore: DataStore<Preferences>
|
||||
private lateinit var toolsInstaller: ToolsInstaller
|
||||
@@ -65,19 +65,9 @@ class Application : android.app.Application() {
|
||||
|
||||
private suspend fun determineBackend(): Backend {
|
||||
var backend: Backend? = null
|
||||
var didStartRootShell = false
|
||||
if (!ModuleLoader.isModuleLoaded() && moduleLoader.moduleMightExist()) {
|
||||
if (UserKnobs.enableKernelModule.first() && WgQuickBackend.hasKernelSupport()) {
|
||||
try {
|
||||
rootShell.start()
|
||||
didStartRootShell = true
|
||||
moduleLoader.loadModule()
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
if (!UserKnobs.disableKernelModule.first() && ModuleLoader.isModuleLoaded()) {
|
||||
try {
|
||||
if (!didStartRootShell)
|
||||
rootShell.start()
|
||||
val wgQuickBackend = WgQuickBackend(applicationContext, rootShell, toolsInstaller)
|
||||
wgQuickBackend.setMultipleTunnels(UserKnobs.multipleTunnels.first())
|
||||
backend = wgQuickBackend
|
||||
@@ -97,10 +87,10 @@ class Application : android.app.Application() {
|
||||
override fun onCreate() {
|
||||
Log.i(TAG, USER_AGENT)
|
||||
super.onCreate()
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
rootShell = RootShell(applicationContext)
|
||||
toolsInstaller = ToolsInstaller(applicationContext, rootShell)
|
||||
moduleLoader = ModuleLoader(applicationContext, rootShell, USER_AGENT)
|
||||
preferencesDataStore = applicationContext.createDataStore(name = "settings")
|
||||
preferencesDataStore = PreferenceDataStoreFactory.create { applicationContext.preferencesDataStoreFile("settings") }
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
coroutineScope.launch {
|
||||
AppCompatDelegate.setDefaultNightMode(
|
||||
@@ -139,9 +129,6 @@ class Application : android.app.Application() {
|
||||
@JvmStatic
|
||||
suspend fun getBackend() = get().futureBackend.await()
|
||||
|
||||
@JvmStatic
|
||||
fun getModuleLoader() = get().moduleLoader
|
||||
|
||||
@JvmStatic
|
||||
fun getRootShell() = get().rootShell
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -114,7 +114,7 @@ class LogViewerActivity : AppCompatActivity() {
|
||||
val key = KeyPair().privateKey.toHex()
|
||||
LOGS[key] = rawLogLines.toString().toByteArray(Charsets.UTF_8)
|
||||
lastUri = Uri.parse("content://${BuildConfig.APPLICATION_ID}.exported-log/$key")
|
||||
val shareIntent = ShareCompat.IntentBuilder.from(this)
|
||||
val shareIntent = ShareCompat.IntentBuilder(this)
|
||||
.setType("text/plain")
|
||||
.setSubject(getString(R.string.log_export_subject))
|
||||
.setStream(lastUri)
|
||||
@@ -126,9 +126,9 @@ class LogViewerActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.log_viewer, menu)
|
||||
saveButton = menu?.findItem(R.id.save_log)
|
||||
saveButton = menu.findItem(R.id.save_log)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -202,11 +202,7 @@ class LogViewerActivity : AppCompatActivity() {
|
||||
it.scrollToPosition(logLines.size - 1)
|
||||
}
|
||||
} else {
|
||||
/* TODO: I'd prefer for the next line to be:
|
||||
* logLines.lastOrNull()?.msg += "\n$line"
|
||||
* However, as of writing, that causes the kotlin compiler to freak out and crash, spewing bytecode.
|
||||
*/
|
||||
logLines.lastOrNull()?.apply { msg += "\n$line" }
|
||||
logLines.lastOrNull()?.msg += "\n$line"
|
||||
if (haveScrolled) logAdapter.notifyDataSetChanged()
|
||||
}
|
||||
if (!haveScrolled) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
@@ -17,7 +17,6 @@ import com.wireguard.android.R
|
||||
import com.wireguard.android.backend.WgQuickBackend
|
||||
import com.wireguard.android.preference.PreferencesPreferenceDataStore
|
||||
import com.wireguard.android.util.AdminKnobs
|
||||
import com.wireguard.android.util.ModuleLoader
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -79,30 +78,19 @@ class SettingsActivity : ThemeChangeAwareActivity() {
|
||||
startActivity(Intent(requireContext(), LogViewerActivity::class.java))
|
||||
true
|
||||
}
|
||||
val moduleInstaller = preferenceManager.findPreference<Preference>("module_downloader")
|
||||
val kernelModuleDisabler = preferenceManager.findPreference<Preference>("kernel_module_disabler")
|
||||
moduleInstaller?.isVisible = false
|
||||
if (ModuleLoader.isModuleLoaded()) {
|
||||
moduleInstaller?.parent?.removePreference(moduleInstaller)
|
||||
val kernelModuleEnabler = preferenceManager.findPreference<Preference>("kernel_module_enabler")
|
||||
if (WgQuickBackend.hasKernelSupport()) {
|
||||
lifecycleScope.launch {
|
||||
if (Application.getBackend() !is WgQuickBackend) {
|
||||
try {
|
||||
withContext(Dispatchers.IO) { Application.getRootShell().start() }
|
||||
} catch (_: Throwable) {
|
||||
kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler)
|
||||
kernelModuleEnabler?.parent?.removePreference(kernelModuleEnabler)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kernelModuleDisabler?.parent?.removePreference(kernelModuleDisabler)
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
withContext(Dispatchers.IO) { Application.getRootShell().start() }
|
||||
moduleInstaller?.isVisible = true
|
||||
} catch (_: Throwable) {
|
||||
moduleInstaller?.parent?.removePreference(moduleInstaller)
|
||||
}
|
||||
}
|
||||
kernelModuleEnabler?.parent?.removePreference(kernelModuleEnabler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.activity
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.configStore
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.configStore
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
@@ -152,6 +152,12 @@ object BindingAdapters {
|
||||
view.text = if (addresses != null) Attribute.join(addresses.map { it?.hostAddress }) else ""
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@BindingAdapter("android:text")
|
||||
fun setStringSetText(view: TextView, strings: Iterable<String?>?) {
|
||||
view.text = if (strings != null) Attribute.join(strings) else ""
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun tryParseInt(s: String?): Int {
|
||||
if (s == null)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.databinding
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
@@ -15,6 +15,7 @@ import androidx.databinding.Observable
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.wireguard.android.BR
|
||||
import com.wireguard.android.R
|
||||
@@ -88,7 +89,7 @@ class AppListDialogFragment : DialogFragment() {
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val alertDialogBuilder = AlertDialog.Builder(requireActivity())
|
||||
val alertDialogBuilder = MaterialAlertDialogBuilder(requireActivity())
|
||||
val binding = AppListDialogFragmentBinding.inflate(requireActivity().layoutInflater, null, false)
|
||||
binding.executePendingBindings()
|
||||
alertDialogBuilder.setView(binding.root)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
@@ -12,6 +12,7 @@ import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.wireguard.android.Application
|
||||
import com.wireguard.android.R
|
||||
@@ -64,7 +65,7 @@ class ConfigNamingDialogFragment : DialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val activity = requireActivity()
|
||||
imm = activity.getSystemService()
|
||||
val alertDialogBuilder = AlertDialog.Builder(activity)
|
||||
val alertDialogBuilder = MaterialAlertDialogBuilder(activity)
|
||||
alertDialogBuilder.setTitle(R.string.import_from_qr_code)
|
||||
binding = ConfigNamingDialogFragmentBinding.inflate(activity.layoutInflater, null, false)
|
||||
binding?.apply {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
@@ -43,7 +43,7 @@ class TunnelDetailFragment : BaseFragment() {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
binding = TunnelDetailFragmentBinding.inflate(inflater, container, false)
|
||||
binding?.executePendingBindings()
|
||||
return binding!!.root
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
@@ -297,6 +297,7 @@ class TunnelEditorFragment : BaseFragment() {
|
||||
Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
is BiometricAuthenticator.Result.Cancelled -> {}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.fragment
|
||||
@@ -21,7 +21,9 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
import com.google.zxing.qrcode.QRCodeReader
|
||||
import com.journeyapps.barcodescanner.ScanContract
|
||||
import com.journeyapps.barcodescanner.ScanOptions
|
||||
import com.wireguard.android.Application
|
||||
import com.wireguard.android.R
|
||||
import com.wireguard.android.activity.TunnelCreatorActivity
|
||||
@@ -30,6 +32,7 @@ import com.wireguard.android.databinding.TunnelListFragmentBinding
|
||||
import com.wireguard.android.databinding.TunnelListItemBinding
|
||||
import com.wireguard.android.model.ObservableTunnel
|
||||
import com.wireguard.android.util.ErrorMessages
|
||||
import com.wireguard.android.util.QrCodeFromFileScanner
|
||||
import com.wireguard.android.util.TunnelImporter
|
||||
import com.wireguard.android.widget.MultiselectableRelativeLayout
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -51,16 +54,29 @@ class TunnelListFragment : BaseFragment() {
|
||||
val activity = activity ?: return@registerForActivityResult
|
||||
val contentResolver = activity.contentResolver ?: return@registerForActivityResult
|
||||
activity.lifecycleScope.launch {
|
||||
TunnelImporter.importTunnel(contentResolver, data) { showSnackbar(it) }
|
||||
if (QrCodeFromFileScanner.validContentType(contentResolver, data)) {
|
||||
try {
|
||||
val qrCodeFromFileScanner = QrCodeFromFileScanner(contentResolver, QRCodeReader())
|
||||
val result = qrCodeFromFileScanner.scan(data)
|
||||
TunnelImporter.importTunnel(parentFragmentManager, result.text) { showSnackbar(it) }
|
||||
} catch (e: Exception) {
|
||||
val error = ErrorMessages[e]
|
||||
val message = requireContext().getString(R.string.import_error, error)
|
||||
Log.e(TAG, message, e)
|
||||
showSnackbar(message)
|
||||
}
|
||||
} else {
|
||||
TunnelImporter.importTunnel(contentResolver, data) { showSnackbar(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val qrImportResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||
val qrCode = IntentIntegrator.parseActivityResult(result.resultCode, result.data)?.contents
|
||||
?: return@registerForActivityResult
|
||||
val activity = activity ?: return@registerForActivityResult
|
||||
val fragManager = parentFragmentManager
|
||||
activity.lifecycleScope.launch { TunnelImporter.importTunnel(fragManager, qrCode) { showSnackbar(it) } }
|
||||
private val qrImportResultLauncher = registerForActivityResult(ScanContract()) { result ->
|
||||
val qrCode = result.contents
|
||||
val activity = activity
|
||||
if (qrCode != null && activity != null) {
|
||||
activity.lifecycleScope.launch { TunnelImporter.importTunnel(parentFragmentManager, qrCode) { showSnackbar(it) } }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -89,11 +105,10 @@ class TunnelListFragment : BaseFragment() {
|
||||
tunnelFileImportResultLauncher.launch("*/*")
|
||||
}
|
||||
AddTunnelsSheet.REQUEST_SCAN -> {
|
||||
qrImportResultLauncher.launch(IntentIntegrator(requireActivity())
|
||||
qrImportResultLauncher.launch(ScanOptions()
|
||||
.setOrientationLocked(false)
|
||||
.setBeepEnabled(false)
|
||||
.setPrompt(getString(R.string.qr_code_hint))
|
||||
.createScanIntent())
|
||||
.setPrompt(getString(R.string.qr_code_hint)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,7 +116,7 @@ class TunnelListFragment : BaseFragment() {
|
||||
}
|
||||
executePendingBindings()
|
||||
}
|
||||
return binding!!.root
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
@@ -239,7 +254,7 @@ class TunnelListFragment : BaseFragment() {
|
||||
resources = null
|
||||
animateFab(binding?.createFab, true)
|
||||
checkedItems.clear()
|
||||
binding!!.tunnelList.adapter!!.notifyDataSetChanged()
|
||||
binding?.tunnelList?.adapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.model
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.model
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.wireguard.android.model
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
object TunnelComparator : Comparator<String> {
|
||||
private class NaturalSortString(originalString: String) {
|
||||
class NaturalSortToken(val maybeString: String?, val maybeNumber: Int?) : Comparable<NaturalSortToken> {
|
||||
@@ -29,7 +27,7 @@ object TunnelComparator : Comparator<String> {
|
||||
val tokens: MutableList<NaturalSortToken> = ArrayList()
|
||||
|
||||
init {
|
||||
for (s in NATURAL_SORT_DIGIT_FINDER.findAll(originalString.split(WHITESPACE_FINDER).joinToString(" ").toLowerCase(Locale.ENGLISH))) {
|
||||
for (s in NATURAL_SORT_DIGIT_FINDER.findAll(originalString.split(WHITESPACE_FINDER).joinToString(" ").lowercase())) {
|
||||
try {
|
||||
val n = s.value.toInt()
|
||||
tokens.add(NaturalSortToken(null, n))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.model
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.preference
|
||||
@@ -26,7 +26,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
|
||||
class KernelModuleEnablerPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
|
||||
private var state = State.UNKNOWN
|
||||
|
||||
init {
|
||||
@@ -44,10 +44,10 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P
|
||||
activity.lifecycleScope.launch {
|
||||
if (state == State.DISABLED) {
|
||||
setState(State.ENABLING)
|
||||
UserKnobs.setDisableKernelModule(false)
|
||||
UserKnobs.setEnableKernelModule(true)
|
||||
} else if (state == State.ENABLED) {
|
||||
setState(State.DISABLING)
|
||||
UserKnobs.setDisableKernelModule(true)
|
||||
UserKnobs.setEnableKernelModule(false)
|
||||
}
|
||||
val observableTunnels = Application.getTunnelManager().getTunnels()
|
||||
val downings = observableTunnels.map { async(SupervisorJob()) { it.setStateAsync(Tunnel.State.DOWN) } }
|
||||
@@ -76,13 +76,13 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P
|
||||
|
||||
private enum class State(val titleResourceId: Int, val summaryResourceId: Int, val shouldEnableView: Boolean, val visible: Boolean) {
|
||||
UNKNOWN(0, 0, false, false),
|
||||
ENABLED(R.string.module_disabler_enabled_title, R.string.module_disabler_enabled_summary, true, true),
|
||||
DISABLED(R.string.module_disabler_disabled_title, R.string.module_disabler_disabled_summary, true, true),
|
||||
ENABLING(R.string.module_disabler_disabled_title, R.string.success_application_will_restart, false, true),
|
||||
DISABLING(R.string.module_disabler_enabled_title, R.string.success_application_will_restart, false, true);
|
||||
ENABLED(R.string.module_enabler_enabled_title, R.string.module_enabler_enabled_summary, true, true),
|
||||
DISABLED(R.string.module_enabler_disabled_title, R.string.module_enabler_disabled_summary, true, true),
|
||||
ENABLING(R.string.module_enabler_disabled_title, R.string.success_application_will_restart, false, true),
|
||||
DISABLING(R.string.module_enabler_enabled_title, R.string.success_application_will_restart, false, true);
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "WireGuard/KernelModuleDisablerPreference"
|
||||
private const val TAG = "WireGuard/KernelModuleEnablerPreference"
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2019 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.system.OsConstants
|
||||
import android.util.AttributeSet
|
||||
import android.widget.Toast
|
||||
import androidx.preference.Preference
|
||||
import com.wireguard.android.Application
|
||||
import com.wireguard.android.R
|
||||
import com.wireguard.android.activity.SettingsActivity
|
||||
import com.wireguard.android.util.ErrorMessages
|
||||
import com.wireguard.android.util.UserKnobs
|
||||
import com.wireguard.android.util.lifecycleScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class ModuleDownloaderPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
|
||||
private var state = State.INITIAL
|
||||
override fun getSummary() = context.getString(state.messageResourceId)
|
||||
|
||||
override fun getTitle() = context.getString(R.string.module_installer_title)
|
||||
|
||||
override fun onClick() {
|
||||
setState(State.WORKING)
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
when (withContext(Dispatchers.IO) { Application.getModuleLoader().download() }) {
|
||||
OsConstants.ENOENT -> setState(State.NOTFOUND)
|
||||
OsConstants.EXIT_SUCCESS -> {
|
||||
setState(State.SUCCESS)
|
||||
UserKnobs.setDisableKernelModule(null)
|
||||
withContext(Dispatchers.IO) {
|
||||
val restartIntent = Intent(context, SettingsActivity::class.java)
|
||||
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
Application.get().startActivity(restartIntent)
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
else -> setState(State.FAILURE)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
setState(State.FAILURE)
|
||||
Toast.makeText(context, ErrorMessages[e], Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setState(state: State) {
|
||||
if (this.state == state) return
|
||||
this.state = state
|
||||
if (isEnabled != state.shouldEnableView) isEnabled = state.shouldEnableView
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
private enum class State(val messageResourceId: Int, val shouldEnableView: Boolean) {
|
||||
INITIAL(R.string.module_installer_initial, true),
|
||||
FAILURE(R.string.module_installer_error, true),
|
||||
WORKING(R.string.module_installer_working, false),
|
||||
SUCCESS(R.string.success_application_will_restart, false),
|
||||
NOTFOUND(R.string.module_installer_not_found, false);
|
||||
}
|
||||
}
|
||||
+22
-19
@@ -1,16 +1,19 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.wireguard.android.preference
|
||||
|
||||
import androidx.datastore.DataStore
|
||||
import androidx.datastore.preferences.Preferences
|
||||
import androidx.datastore.preferences.edit
|
||||
import androidx.datastore.preferences.preferencesKey
|
||||
import androidx.datastore.preferences.preferencesSetKey
|
||||
import androidx.datastore.preferences.remove
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.floatPreferencesKey
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.core.longPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -21,7 +24,7 @@ import kotlinx.coroutines.runBlocking
|
||||
class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope, private val dataStore: DataStore<Preferences>) : PreferenceDataStore() {
|
||||
override fun putString(key: String?, value: String?) {
|
||||
if (key == null) return
|
||||
val pk = preferencesKey<String>(key)
|
||||
val pk = stringPreferencesKey(key)
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
if (value == null) it.remove(pk)
|
||||
@@ -32,7 +35,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun putStringSet(key: String?, values: Set<String?>?) {
|
||||
if (key == null) return
|
||||
val pk = preferencesSetKey<String>(key)
|
||||
val pk = stringSetPreferencesKey(key)
|
||||
val filteredValues = values?.filterNotNull()?.toSet()
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
@@ -44,7 +47,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun putInt(key: String?, value: Int) {
|
||||
if (key == null) return
|
||||
val pk = preferencesKey<Int>(key)
|
||||
val pk = intPreferencesKey(key)
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
it[pk] = value
|
||||
@@ -54,7 +57,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun putLong(key: String?, value: Long) {
|
||||
if (key == null) return
|
||||
val pk = preferencesKey<Long>(key)
|
||||
val pk = longPreferencesKey(key)
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
it[pk] = value
|
||||
@@ -64,7 +67,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun putFloat(key: String?, value: Float) {
|
||||
if (key == null) return
|
||||
val pk = preferencesKey<Float>(key)
|
||||
val pk = floatPreferencesKey(key)
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
it[pk] = value
|
||||
@@ -74,7 +77,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun putBoolean(key: String?, value: Boolean) {
|
||||
if (key == null) return
|
||||
val pk = preferencesKey<Boolean>(key)
|
||||
val pk = booleanPreferencesKey(key)
|
||||
coroutineScope.launch {
|
||||
dataStore.edit {
|
||||
it[pk] = value
|
||||
@@ -84,7 +87,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getString(key: String?, defValue: String?): String? {
|
||||
if (key == null) return defValue
|
||||
val pk = preferencesKey<String>(key)
|
||||
val pk = stringPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValue }.first()
|
||||
}
|
||||
@@ -92,7 +95,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getStringSet(key: String?, defValues: Set<String?>?): Set<String?>? {
|
||||
if (key == null) return defValues
|
||||
val pk = preferencesSetKey<String>(key)
|
||||
val pk = stringSetPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValues }.first()
|
||||
}
|
||||
@@ -100,7 +103,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getInt(key: String?, defValue: Int): Int {
|
||||
if (key == null) return defValue
|
||||
val pk = preferencesKey<Int>(key)
|
||||
val pk = intPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValue }.first()
|
||||
}
|
||||
@@ -108,7 +111,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getLong(key: String?, defValue: Long): Long {
|
||||
if (key == null) return defValue
|
||||
val pk = preferencesKey<Long>(key)
|
||||
val pk = longPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValue }.first()
|
||||
}
|
||||
@@ -116,7 +119,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getFloat(key: String?, defValue: Float): Float {
|
||||
if (key == null) return defValue
|
||||
val pk = preferencesKey<Float>(key)
|
||||
val pk = floatPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValue }.first()
|
||||
}
|
||||
@@ -124,7 +127,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
|
||||
|
||||
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
|
||||
if (key == null) return defValue
|
||||
val pk = preferencesKey<Boolean>(key)
|
||||
val pk = booleanPreferencesKey(key)
|
||||
return runBlocking {
|
||||
dataStore.data.map { it[pk] ?: defValue }.first()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.preference
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.preference
|
||||
@@ -20,7 +20,6 @@ import com.wireguard.android.util.lifecycleScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.Locale
|
||||
|
||||
class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) {
|
||||
private var versionSummary: String? = null
|
||||
@@ -49,12 +48,12 @@ class VersionPreference(context: Context, attrs: AttributeSet?) : Preference(con
|
||||
init {
|
||||
lifecycleScope.launch {
|
||||
val backend = Application.getBackend()
|
||||
versionSummary = getContext().getString(R.string.version_summary_checking, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH))
|
||||
versionSummary = getContext().getString(R.string.version_summary_checking, getBackendPrettyName(context, backend).lowercase())
|
||||
notifyChanged()
|
||||
versionSummary = try {
|
||||
getContext().getString(R.string.version_summary, getBackendPrettyName(context, backend), withContext(Dispatchers.IO) { backend.version })
|
||||
} catch (_: Throwable) {
|
||||
getContext().getString(R.string.version_summary_unknown, getBackendPrettyName(context, backend).toLowerCase(Locale.ENGLISH))
|
||||
getContext().getString(R.string.version_summary_unknown, getBackendPrettyName(context, backend).lowercase())
|
||||
}
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.preference
|
||||
@@ -98,6 +98,7 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference
|
||||
Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
is BiometricAuthenticator.Result.Cancelled -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.util
|
||||
@@ -11,6 +11,7 @@ import android.widget.TextView
|
||||
import androidx.core.content.getSystemService
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.wireguard.android.R
|
||||
|
||||
/**
|
||||
* Standalone utilities for interacting with the system clipboard.
|
||||
@@ -28,6 +29,6 @@ object ClipboardUtils {
|
||||
}
|
||||
val service = view.context.getSystemService<ClipboardManager>() ?: return
|
||||
service.setPrimaryClip(ClipData.newPlainText(data.second, data.first))
|
||||
Snackbar.make(view, "${data.second} copied to clipboard", Snackbar.LENGTH_LONG).show()
|
||||
Snackbar.make(view, view.context.getString(R.string.copied_to_clipboard, data.second), Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.util
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.util
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.os.RemoteException
|
||||
import com.google.zxing.ChecksumException
|
||||
import com.google.zxing.NotFoundException
|
||||
import com.wireguard.android.Application
|
||||
import com.wireguard.android.R
|
||||
import com.wireguard.android.backend.BackendException
|
||||
@@ -36,7 +38,8 @@ object ErrorMessages {
|
||||
BackendException.Reason.VPN_NOT_AUTHORIZED to R.string.vpn_not_authorized_error,
|
||||
BackendException.Reason.UNABLE_TO_START_VPN to R.string.vpn_start_error,
|
||||
BackendException.Reason.TUN_CREATION_ERROR to R.string.tun_create_error,
|
||||
BackendException.Reason.GO_ACTIVATION_ERROR_CODE to R.string.tunnel_on_error
|
||||
BackendException.Reason.GO_ACTIVATION_ERROR_CODE to R.string.tunnel_on_error,
|
||||
BackendException.Reason.DNS_RESOLUTION_FAILURE to R.string.tunnel_dns_failure
|
||||
)
|
||||
private val KFE_FORMAT_MAP = mapOf(
|
||||
Key.Format.BASE64 to R.string.key_length_explanation_base64,
|
||||
@@ -83,6 +86,12 @@ object ErrorMessages {
|
||||
rootCause is RootShellException -> {
|
||||
resources.getString(RSE_REASON_MAP.getValue(rootCause.reason), *rootCause.format)
|
||||
}
|
||||
rootCause is NotFoundException -> {
|
||||
resources.getString(R.string.error_no_qr_found)
|
||||
}
|
||||
rootCause is ChecksumException -> {
|
||||
resources.getString(R.string.error_qr_checksum)
|
||||
}
|
||||
rootCause.message != null -> {
|
||||
rootCause.message!!
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.wireguard.android.util
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import com.google.zxing.BinaryBitmap
|
||||
import com.google.zxing.DecodeHintType
|
||||
import com.google.zxing.NotFoundException
|
||||
import com.google.zxing.RGBLuminanceSource
|
||||
import com.google.zxing.Reader
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.common.HybridBinarizer
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Encapsulates the logic of scanning a barcode from a file,
|
||||
* @property contentResolver - Resolver to read the incoming data
|
||||
* @property reader - An instance of zxing's [Reader] class to parse the image
|
||||
*/
|
||||
class QrCodeFromFileScanner(
|
||||
private val contentResolver: ContentResolver,
|
||||
private val reader: Reader,
|
||||
) {
|
||||
|
||||
private fun scanBitmapForResult(source: Bitmap): Result {
|
||||
val width = source.width
|
||||
val height = source.height
|
||||
val pixels = IntArray(width * height)
|
||||
source.getPixels(pixels, 0, width, 0, 0, width, height)
|
||||
|
||||
val bBitmap = BinaryBitmap(HybridBinarizer(RGBLuminanceSource(width, height, pixels)))
|
||||
return reader.decode(bBitmap, mapOf(DecodeHintType.TRY_HARDER to true))
|
||||
}
|
||||
|
||||
private fun downscaleBitmap(source: Bitmap, scaledSize: Int): Bitmap {
|
||||
|
||||
val originalWidth = source.width
|
||||
val originalHeight = source.height
|
||||
|
||||
var newWidth = -1
|
||||
var newHeight = -1
|
||||
val multFactor: Float
|
||||
|
||||
when {
|
||||
originalHeight > originalWidth -> {
|
||||
newHeight = scaledSize
|
||||
multFactor = originalWidth.toFloat() / originalHeight.toFloat()
|
||||
newWidth = (newHeight * multFactor).toInt()
|
||||
}
|
||||
originalWidth > originalHeight -> {
|
||||
newWidth = scaledSize
|
||||
multFactor = originalHeight.toFloat() / originalWidth.toFloat()
|
||||
newHeight = (newWidth * multFactor).toInt()
|
||||
}
|
||||
originalHeight == originalWidth -> {
|
||||
newHeight = scaledSize
|
||||
newWidth = scaledSize
|
||||
}
|
||||
}
|
||||
return Bitmap.createScaledBitmap(source, newWidth, newHeight, false)
|
||||
}
|
||||
|
||||
private fun doScan(data: Uri): Result {
|
||||
Log.d(TAG, "Starting to scan an image: $data")
|
||||
contentResolver.openInputStream(data).use { inputStream ->
|
||||
val originalBitmap = BitmapFactory.decodeStream(inputStream)
|
||||
?: throw IllegalArgumentException("Can't decode stream to Bitmap")
|
||||
|
||||
return try {
|
||||
scanBitmapForResult(originalBitmap).also {
|
||||
Log.d(TAG, "Found result in original image")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Original image scan finished with error: $e, will try downscaled image")
|
||||
val scaleBitmap = downscaleBitmap(originalBitmap, 500)
|
||||
scanBitmapForResult(originalBitmap).also { scaleBitmap.recycle() }
|
||||
} finally {
|
||||
originalBitmap.recycle()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to parse incoming data
|
||||
* @return result of the decoding operation
|
||||
* @throws NotFoundException when parser didn't find QR code in the image
|
||||
*/
|
||||
suspend fun scan(data: Uri) = withContext(Dispatchers.Default) { doScan(data) }
|
||||
|
||||
companion object {
|
||||
private const val TAG = "QrCodeFromFileScanner"
|
||||
|
||||
/**
|
||||
* Given a reference to a file, check if this file could be parsed by this class
|
||||
* @return true if the file can be parsed, false if not
|
||||
*/
|
||||
fun validContentType(contentResolver: ContentResolver, data: Uri): Boolean {
|
||||
return contentResolver.getType(data)?.startsWith("image/") == true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.io.ByteArrayInputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.ArrayList
|
||||
import java.util.Locale
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
@@ -50,8 +49,8 @@ object TunnelImporter {
|
||||
require(idx < name.length - 1) { context.getString(R.string.illegal_filename_error, name) }
|
||||
name = name.substring(idx + 1)
|
||||
}
|
||||
val isZip = name.toLowerCase(Locale.ROOT).endsWith(".zip")
|
||||
if (name.toLowerCase(Locale.ROOT).endsWith(".conf")) {
|
||||
val isZip = name.lowercase().endsWith(".zip")
|
||||
if (name.lowercase().endsWith(".conf")) {
|
||||
name = name.substring(0, name.length - ".conf".length)
|
||||
} else {
|
||||
require(isZip) { context.getString(R.string.bad_extension_error) }
|
||||
@@ -71,7 +70,7 @@ object TunnelImporter {
|
||||
}
|
||||
name = name.substring(name.lastIndexOf('/') + 1)
|
||||
}
|
||||
if (name.toLowerCase(Locale.ROOT).endsWith(".conf")) {
|
||||
if (name.lowercase().endsWith(".conf")) {
|
||||
name = name.substring(0, name.length - ".conf".length)
|
||||
} else {
|
||||
continue
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
/*
|
||||
* Copyright © 2020 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.wireguard.android.util
|
||||
|
||||
import androidx.datastore.preferences.edit
|
||||
import androidx.datastore.preferences.preferencesKey
|
||||
import androidx.datastore.preferences.preferencesSetKey
|
||||
import androidx.datastore.preferences.remove
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
||||
import com.wireguard.android.Application
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
object UserKnobs {
|
||||
private val DISABLE_KERNEL_MODULE = preferencesKey<Boolean>("disable_kernel_module")
|
||||
val disableKernelModule: Flow<Boolean>
|
||||
private val ENABLE_KERNEL_MODULE = booleanPreferencesKey("enable_kernel_module")
|
||||
val enableKernelModule: Flow<Boolean>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[DISABLE_KERNEL_MODULE] ?: false
|
||||
it[ENABLE_KERNEL_MODULE] ?: false
|
||||
}
|
||||
|
||||
suspend fun setDisableKernelModule(disable: Boolean?) {
|
||||
suspend fun setEnableKernelModule(enable: Boolean?) {
|
||||
Application.getPreferencesDataStore().edit {
|
||||
if (disable == null)
|
||||
it.remove(DISABLE_KERNEL_MODULE)
|
||||
if (enable == null)
|
||||
it.remove(ENABLE_KERNEL_MODULE)
|
||||
else
|
||||
it[DISABLE_KERNEL_MODULE] = disable
|
||||
it[ENABLE_KERNEL_MODULE] = enable
|
||||
}
|
||||
}
|
||||
|
||||
private val MULTIPLE_TUNNELS = preferencesKey<Boolean>("multiple_tunnels")
|
||||
private val MULTIPLE_TUNNELS = booleanPreferencesKey("multiple_tunnels")
|
||||
val multipleTunnels: Flow<Boolean>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[MULTIPLE_TUNNELS] ?: false
|
||||
}
|
||||
|
||||
private val DARK_THEME = preferencesKey<Boolean>("dark_theme")
|
||||
private val DARK_THEME = booleanPreferencesKey("dark_theme")
|
||||
val darkTheme: Flow<Boolean>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[DARK_THEME] ?: false
|
||||
}
|
||||
|
||||
private val ALLOW_REMOTE_CONTROL_INTENTS = preferencesKey<Boolean>("allow_remote_control_intents")
|
||||
private val ALLOW_REMOTE_CONTROL_INTENTS = booleanPreferencesKey("allow_remote_control_intents")
|
||||
val allowRemoteControlIntents: Flow<Boolean>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[ALLOW_REMOTE_CONTROL_INTENTS] ?: false
|
||||
}
|
||||
|
||||
private val RESTORE_ON_BOOT = preferencesKey<Boolean>("restore_on_boot")
|
||||
private val RESTORE_ON_BOOT = booleanPreferencesKey("restore_on_boot")
|
||||
val restoreOnBoot: Flow<Boolean>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[RESTORE_ON_BOOT] ?: false
|
||||
}
|
||||
|
||||
private val LAST_USED_TUNNEL = preferencesKey<String>("last_used_tunnel")
|
||||
private val LAST_USED_TUNNEL = stringPreferencesKey("last_used_tunnel")
|
||||
val lastUsedTunnel: Flow<String?>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[LAST_USED_TUNNEL]
|
||||
@@ -68,7 +68,7 @@ object UserKnobs {
|
||||
}
|
||||
}
|
||||
|
||||
private val RUNNING_TUNNELS = preferencesSetKey<String>("enabled_configs")
|
||||
private val RUNNING_TUNNELS = stringSetPreferencesKey("enabled_configs")
|
||||
val runningTunnels: Flow<Set<String>>
|
||||
get() = Application.getPreferencesDataStore().data.map {
|
||||
it[RUNNING_TUNNELS] ?: emptySet()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
||||
* Copyright © 2017-2023 WireGuard LLC. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package com.wireguard.android.viewmodel
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user