Compare commits

..

33 Commits

Author SHA1 Message Date
Jason A. Donenfeld e437ac389e Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 03:11:33 +02:00
Jason A. Donenfeld 2db2a0921d MainActivity: attempt to fix commit state exceptions
This is an attempt to fix:

java.lang.IllegalStateException:
at android.support.v4.app.FragmentManagerImpl.checkStateLoss (FragmentManager.java:2053)
at android.support.v4.app.FragmentManagerImpl.enqueueAction (FragmentManager.java:2079)
at android.support.v4.app.BackStackRecord.commitInternal (BackStackRecord.java:678)
at android.support.v4.app.BackStackRecord.commit (BackStackRecord.java:632)
at com.wireguard.android.activity.MainActivity.moveToState (MainActivity.java:58)
at com.wireguard.android.activity.MainActivity.onSelectedTunnelChanged (MainActivity.java:157)
at com.wireguard.android.activity.BaseActivity.setSelectedTunnel (BaseActivity.java:75)
at com.wireguard.android.fragment.BaseFragment.setSelectedTunnel (BaseFragment.java:82)
at com.wireguard.android.fragment.TunnelListFragment.lambda$null$4$TunnelListFragment (TunnelListFragment.java:307)
at com.wireguard.android.fragment.TunnelListFragment$$Lambda$4.onClick (Unknown Source:6)
at android.view.View.performClick (View.java:6274)
at android.view.View$PerformClick.run (View.java:24729)
at android.os.Handler.handleCallback (Handler.java:789)
at android.os.Handler.dispatchMessage (Handler.java:98)
at android.os.Looper.loop (Looper.java:169)
at android.app.ActivityThread.main (ActivityThread.java:6595)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:240)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)

But this is probably the wrong way to fix it and instead moveToState
needs to be reimagined.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 03:07:16 +02:00
Jason A. Donenfeld d7889c4e88 style: coloring the navbar looks a bit strange when rotated
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 02:59:26 +02:00
Jason A. Donenfeld 559add3f71 TunnelEditorFragment: plug memory leak on listeners
Apparently these don't get GC'd unless they're removed explicitly,
because there's a global singleton registry of them. So, introduce a
little registry of our own.

Reported-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 02:59:26 +02:00
Jason A. Donenfeld d615304e83 qrcode: minor adjustments
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 02:59:26 +02:00
Eric Kuck 8e0835e570 Added QR code scanner as tunnel import method
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-25 02:05:11 +02:00
Harsh Shandilya bb20c89cd5 tools: Bump wireguard submodule
This force pushing is going to be the death of me

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-24 18:26:53 +02:00
Jason A. Donenfeld 996cbb5f2b tools: support ancient NDKs
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-24 18:09:18 +02:00
Jason A. Donenfeld 8028d708cb tools: let wg(8) play with userspace implementation
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-24 17:57:56 +02:00
Harsh Shandilya 7689905c78 config: Remove Locale based string format
The configurations are supposed to be in a very specific
format which is not user-facing and hence doesn't have to
be adjusted for locale avoiding both the redundancy as well
as potential breakages in the configuration file format from
different locales.

Fixes: 71c67aa24ae2 ("config: Minor cleanup")
Reported-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-24 17:57:56 +02:00
Jason A. Donenfeld 284e42647c tools: pass in debug package name
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-24 17:57:56 +02:00
Jason A. Donenfeld 3a16c08821 Make placeholder pretty
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-23 00:05:12 +02:00
Harsh Shandilya 76fb6a318e Show help text when no tunnels are imported
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-22 23:21:17 +02:00
Jason A. Donenfeld c633f96374 FloatingActionsMenuRecyclerViewScrollListener: add final modifiers
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-22 23:21:17 +02:00
Harsh Shandilya 3357be9557 RTL layout fixes
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-22 18:21:39 +02:00
Harsh Shandilya 6696e838da treewide: Optimize imports
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-22 18:20:23 +02:00
Jason A. Donenfeld d0d56f3a1b fab: move in direct ratio to scroll
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-20 16:41:53 +02:00
Jason A. Donenfeld fbf32a6c29 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-20 15:54:46 +02:00
Harsh Shandilya 3e37289b68 UI: use background color for navbar in dark mode
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-20 15:53:41 +02:00
Jason A. Donenfeld 2d6a45f824 fab: make icons always white
With the new shade of blue, perhaps this simply looks better.

I don't like hard coding the color away from the theme, however.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-20 15:45:21 +02:00
Jason A. Donenfeld ed802336e6 theme: use less disgusting color
Harsh's "users" were offended by the dark theme. So, we change the
accent to that used by gboard's dark theme, which should be pretty
uncontroversial.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-20 03:23:17 +02:00
Harsh Shandilya b1d1e3b436 TunnelListFragment: Allocate interpolators outside scroll listener
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-20 03:17:49 +02:00
Jason A. Donenfeld d33e322b67 TunnelEditorFragment: fix null pointer dereference
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-19 20:57:00 +02:00
Jason A. Donenfeld 60a6e29350 QuickTileService: fix null pointer dereference
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-19 20:57:00 +02:00
Jason A. Donenfeld 3b0e0c2f16 tools: bump version
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 21:54:14 +02:00
Jason A. Donenfeld ffb8bccbc5 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 18:40:16 +02:00
Jason A. Donenfeld 08170f7e55 TunnelListFragment: setOnScrollListener is old, but we support API 21, so we have to use it
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 18:32:42 +02:00
Jason A. Donenfeld 28d47b3470 AppListDialogFragment: getArguments is null before onCreate
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 18:08:08 +02:00
Jason A. Donenfeld 8e3586328c fab: use auto calculated fling threshold
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 02:32:05 +02:00
Jason A. Donenfeld f315654d40 fab: add fab sized padding at bottom of recycler view
This way we can keep scrolling when there are exactly the right number
of items, so that the toggle switch becomes visible.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2018-07-18 02:15:14 +02:00
Harsh Shandilya fdfab18d45 fab: make fab respond to recyclerview scroll events
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-18 02:15:06 +02:00
Harsh Shandilya d43e77867c fab: slide fab up when a snackbar shows
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-18 02:15:06 +02:00
Harsh Shandilya df03bdd7f9 android: QuickTileService: Do not use slashed icon on Android P
Android P features circle masked QS tiles which make use of colors
to denote STATE_ACTIVE/STATE_INACTIVE rather than a slash across
the drawable as seen on Android Oreo.

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
2018-07-16 17:31:14 +02:00
37 changed files with 555 additions and 100 deletions
+14 -2
View File
@@ -17,8 +17,8 @@ android {
applicationId 'com.wireguard.android'
minSdkVersion 21
targetSdkVersion 27
versionCode 433
versionName '0.0.20180716'
versionCode 436
versionName '0.0.20180724'
}
// If the keystore file exists
if (keystorePropertiesFile.exists()) {
@@ -40,10 +40,20 @@ android {
buildTypes {
release {
if (keystorePropertiesFile.exists()) signingConfig signingConfigs.release
externalNativeBuild {
cmake {
arguments "-DANDROID_PACKAGE_NAME=${android.defaultConfig.applicationId}"
}
}
}
debug {
applicationIdSuffix ".debug"
versionNameSuffix "-debug"
externalNativeBuild {
cmake {
arguments "-DANDROID_PACKAGE_NAME=${android.defaultConfig.applicationId}${applicationIdSuffix}"
}
}
}
}
externalNativeBuild {
@@ -58,6 +68,7 @@ ext {
supportLibsVersion = '27.1.1'
streamsupportVersion = '1.6.0'
jsr305Version = '3.0.2'
zxingEmbeddedVersion = '3.6.0'
}
dependencies {
@@ -70,6 +81,7 @@ dependencies {
implementation "net.sourceforge.streamsupport:android-retrofuture:$streamsupportVersion"
implementation "net.sourceforge.streamsupport:android-retrostreams:$streamsupportVersion"
implementation "com.google.code.findbugs:jsr305:$jsr305Version"
implementation "com.journeyapps:zxing-android-embedded:$zxingEmbeddedVersion"
}
tasks.withType(JavaCompile) {
+6
View File
@@ -4,6 +4,7 @@
package="com.wireguard.android"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -50,6 +51,11 @@
android:label="@string/create_activity_title"
android:parentActivityName=".activity.MainActivity" />
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="screenOrientation" />
<receiver android:name=".BootShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
@@ -55,20 +55,27 @@ public class QuickTileService extends TileService {
icon.setBounds(0, 0, c.getWidth(), c.getHeight());
icon.draw(c);
iconOn = Icon.createWithBitmap(b);
icon.setSlashed(true);
b = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
c = new Canvas(b);
icon.setBounds(0, 0, c.getWidth(), c.getHeight());
icon.draw(c);
iconOff = Icon.createWithBitmap(b);
/* TODO(msf): Change this to an explicit test for P when we start targetting SDK 28 */
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
iconOff = iconOn;
} else {
icon.setSlashed(true);
b = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
c = new Canvas(b);
icon.setBounds(0, 0, c.getWidth(), c.getHeight());
icon.draw(c);
iconOff = Icon.createWithBitmap(b);
}
}
@Override
public void onClick() {
if (tunnel != null) {
final Tile tile = getQsTile();
tile.setIcon(tile.getIcon() == iconOn ? iconOff : iconOn);
tile.updateTile();
if (tile != null) {
tile.setIcon(tile.getIcon() == iconOn ? iconOff : iconOn);
tile.updateTile();
}
tunnel.setState(State.TOGGLE).whenComplete(this::onToggleFinished);
} else {
final Intent intent = new Intent(this, MainActivity.class);
@@ -55,7 +55,7 @@ public class MainActivity extends BaseActivity {
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
if (state.layer > 0)
transaction.addToBackStack(null);
transaction.commit();
transaction.commitAllowingStateLoss(); /* TODO: switch back to .commit() when this function is rewritten. */
} else if (nextState.layer == state.layer - 1) {
if (fragmentManager.getBackStackEntryCount() == 0)
return false;
@@ -6,49 +6,14 @@
package com.wireguard.android.activity;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.util.Log;
import com.wireguard.android.Application;
import java.lang.reflect.Field;
public abstract class ThemeChangeAwareActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "WireGuard/" + ThemeChangeAwareActivity.class.getSimpleName();
@Nullable private static Resources lastResources;
private static boolean lastDarkMode;
private static synchronized void invalidateDrawableCache(final Resources resources, final boolean darkMode) {
if (resources == lastResources && darkMode == lastDarkMode)
return;
try {
Field f;
Object o = resources;
try {
f = o.getClass().getDeclaredField("mResourcesImpl");
f.setAccessible(true);
o = f.get(o);
} catch (final Exception ignored) { }
f = o.getClass().getDeclaredField("mDrawableCache");
f.setAccessible(true);
o = f.get(o);
try {
o.getClass().getMethod("onConfigurationChange", int.class).invoke(o, -1);
} catch (final Exception ignored) {
o.getClass().getMethod("clear").invoke(o);
}
} catch (final Exception e) {
Log.e(TAG, "Failed to flush drawable cache", e);
}
lastResources = resources;
lastDarkMode = darkMode;
}
@Override
@@ -66,12 +31,10 @@ public abstract class ThemeChangeAwareActivity extends AppCompatActivity impleme
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if ("dark_theme".equals(key)) {
final boolean darkMode = sharedPreferences.getBoolean(key, false);
AppCompatDelegate.setDefaultNightMode(
sharedPreferences.getBoolean(key, false) ?
AppCompatDelegate.MODE_NIGHT_YES :
AppCompatDelegate.MODE_NIGHT_NO);
invalidateDrawableCache(getResources(), darkMode);
recreate();
}
}
@@ -8,7 +8,6 @@ package com.wireguard.android.fragment;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -22,10 +21,8 @@ import android.widget.Toast;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.android.activity.BaseActivity;
import com.wireguard.android.databinding.AppListDialogFragmentBinding;
import com.wireguard.android.model.ApplicationData;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.util.ExceptionLoggers;
import com.wireguard.android.util.ObservableKeyedArrayList;
import com.wireguard.android.util.ObservableKeyedList;
@@ -39,7 +36,7 @@ public class AppListDialogFragment extends DialogFragment {
private static final String KEY_EXCLUDED_APPS = "excludedApps";
private final List<String> currentlyExcludedApps = Arrays.asList(getArguments().getStringArray(KEY_EXCLUDED_APPS));
private List<String> currentlyExcludedApps;
private final ObservableKeyedList<String, ApplicationData> appData = new ObservableKeyedArrayList<>();
public static <T extends Fragment & AppExclusionListener> AppListDialogFragment newInstance(final String[] excludedApps, final T target) {
@@ -51,6 +48,13 @@ public class AppListDialogFragment extends DialogFragment {
return fragment;
}
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
currentlyExcludedApps = Arrays.asList(getArguments().getStringArray(KEY_EXCLUDED_APPS));
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
@@ -0,0 +1,115 @@
/*
* Copyright © 2018 Eric Kuck <eric@bluelinelabs.com>.
* Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.fragment;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.android.databinding.ConfigNamingDialogFragmentBinding;
import com.wireguard.config.Config;
import java.io.IOException;
import java.util.Objects;
public class ConfigNamingDialogFragment extends DialogFragment {
private static final String KEY_CONFIG_TEXT = "config_text";
@Nullable private Config config;
@Nullable private ConfigNamingDialogFragmentBinding binding;
@Nullable private InputMethodManager imm;
public static ConfigNamingDialogFragment newInstance(final String configText) {
final Bundle extras = new Bundle();
extras.putString(KEY_CONFIG_TEXT, configText);
final ConfigNamingDialogFragment fragment = new ConfigNamingDialogFragment();
fragment.setArguments(extras);
return fragment;
}
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
config = Config.from(getArguments().getString(KEY_CONFIG_TEXT));
} catch (final IOException exception) {
throw new RuntimeException("Invalid config passed to " + getClass().getSimpleName(), exception);
}
}
@Override public void onResume() {
super.onResume();
final AlertDialog dialog = (AlertDialog) getDialog();
if (dialog != null) {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(v -> createTunnelAndDismiss());
setKeyboardVisible(true);
}
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Activity activity = getActivity();
imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
alertDialogBuilder.setTitle(R.string.import_from_qrcode);
binding = ConfigNamingDialogFragmentBinding.inflate(getActivity().getLayoutInflater(), null, false);
binding.executePendingBindings();
alertDialogBuilder.setView(binding.getRoot());
alertDialogBuilder.setPositiveButton(R.string.create_tunnel, null);
alertDialogBuilder.setNegativeButton(R.string.cancel, (dialog, which) -> dismiss());
return alertDialogBuilder.create();
}
@Override
public void dismiss() {
setKeyboardVisible(false);
super.dismiss();
}
private void createTunnelAndDismiss() {
if (binding != null) {
final String name = binding.tunnelNameText.getText().toString();
Application.getTunnelManager().create(name, config).whenComplete((tunnel, throwable) -> {
if (tunnel != null) {
dismiss();
} else {
binding.tunnelNameTextLayout.setError(throwable.getMessage());
}
});
}
}
private void setKeyboardVisible(final boolean visible) {
Objects.requireNonNull(imm);
if (visible) {
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
} else if (binding != null) {
imm.hideSoftInputFromWindow(binding.tunnelNameText.getWindowToken(), 0);
}
}
}
@@ -36,6 +36,8 @@ import com.wireguard.config.Attribute;
import com.wireguard.config.Config;
import com.wireguard.config.Peer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -96,14 +98,17 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
@Override
public void onItemRangeInserted(final ObservableList<Peer.Observable> sender, final int positionStart, final int itemCount) {
breakObjectOrientedLayeringHandler.onPropertyChanged(binding.getConfig(), BR.peers);
if (binding != null)
breakObjectOrientedLayeringHandler.onPropertyChanged(binding.getConfig(), BR.peers);
}
@Override
public void onItemRangeRemoved(final ObservableList<Peer.Observable> sender, final int positionStart, final int itemCount) {
breakObjectOrientedLayeringHandler.onPropertyChanged(binding.getConfig(), BR.peers);
if (binding != null)
breakObjectOrientedLayeringHandler.onPropertyChanged(binding.getConfig(), BR.peers);
}
};
private final Collection<Object> breakObjectOrientedLayeringHandlerReceivers = new ArrayList<>();
private final Observable.OnPropertyChangedCallback breakObjectOrientedLayeringHandler = new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(final Observable sender, final int propertyId) {
@@ -114,8 +119,11 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
return;
if (propertyId == BR.config) {
config.addOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
breakObjectOrientedLayeringHandlerReceivers.add(config);
config.getInterfaceSection().addOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
breakObjectOrientedLayeringHandlerReceivers.add(config.getInterfaceSection());
config.getPeers().addOnListChangedCallback(breakObjectListOrientedLayeringHandler);
breakObjectOrientedLayeringHandlerReceivers.add(config.getPeers());
} else if (propertyId == BR.dnses || propertyId == BR.peers)
;
else
@@ -134,13 +142,21 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
super.onCreateView(inflater, container, savedInstanceState);
binding = TunnelEditorFragmentBinding.inflate(inflater, container, false);
binding.addOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
breakObjectOrientedLayeringHandlerReceivers.add(binding);
binding.executePendingBindings();
return binding.getRoot();
}
@SuppressWarnings("unchecked")
@Override
public void onDestroyView() {
binding = null;
for (final Object o : breakObjectOrientedLayeringHandlerReceivers) {
if (o instanceof Observable)
((Observable)o).removeOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
else if (o instanceof ObservableList)
((ObservableList)o).removeOnListChangedCallback(breakObjectListOrientedLayeringHandler);
}
super.onDestroyView();
}
@@ -18,6 +18,7 @@ import android.provider.OpenableColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.util.Log;
@@ -27,6 +28,8 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.android.activity.TunnelCreatorActivity;
@@ -35,9 +38,11 @@ import com.wireguard.android.databinding.TunnelListFragmentBinding;
import com.wireguard.android.databinding.TunnelListItemBinding;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.util.ExceptionLoggers;
import com.wireguard.android.widget.fab.FloatingActionsMenuRecyclerViewScrollListener;
import com.wireguard.config.Config;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -71,6 +76,20 @@ public class TunnelListFragment extends BaseFragment {
return false;
}
private void importTunnel(@NonNull final String configText) {
try {
// Ensure the config text is parseable before proceeding…
Config.from(configText);
// Config text is valid, now create the tunnel…
final FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null)
ConfigNamingDialogFragment.newInstance(configText).show(fragmentManager, null);
} catch (final IllegalArgumentException|IOException exception) {
onTunnelImportFinished(Collections.emptyList(), Collections.singletonList(exception));
}
}
private void importTunnel(@Nullable final Uri uri) {
final Activity activity = getActivity();
if (activity == null || uri == null)
@@ -171,11 +190,18 @@ public class TunnelListFragment extends BaseFragment {
if (resultCode == Activity.RESULT_OK && data != null)
importTunnel(data.getData());
return;
case IntentIntegrator.REQUEST_CODE:
final IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null && result.getContents() != null) {
importTunnel(result.getContents());
}
return;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
@SuppressWarnings("deprecation")
@SuppressLint("ClickableViewAccessibility")
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container,
@@ -189,6 +215,7 @@ public class TunnelListFragment extends BaseFragment {
}
return false;
});
binding.tunnelList.setOnScrollListener(new FloatingActionsMenuRecyclerViewScrollListener(binding.createMenu));
binding.executePendingBindings();
return binding.getRoot();
}
@@ -214,6 +241,17 @@ public class TunnelListFragment extends BaseFragment {
binding.createMenu.collapse();
}
public void onRequestScanQRCode(@SuppressWarnings("unused") final View view) {
final IntentIntegrator intentIntegrator = IntentIntegrator.forSupportFragment(this);
intentIntegrator.setOrientationLocked(false);
intentIntegrator.setBeepEnabled(false);
intentIntegrator.setPrompt(getString(R.string.qrcode_hint));
intentIntegrator.initiateScan(Collections.singletonList(IntentIntegrator.QR_CODE));
if (binding != null)
binding.createMenu.collapse();
}
@Override
public void onPause() {
if (binding != null) {
@@ -10,6 +10,7 @@ import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;
import com.wireguard.android.BuildConfig;
import com.wireguard.android.R;
import java.io.BufferedReader;
@@ -45,8 +46,8 @@ public class RootShell {
final File cacheDir = context.getCacheDir();
localBinaryDir = new File(cacheDir, "bin");
localTemporaryDir = new File(cacheDir, "tmp");
preamble = String.format("export CALLING_PACKAGE=com.wireguard.android PATH=\"%s:$PATH\" TMPDIR='%s'; id -u\n",
localBinaryDir, localTemporaryDir);
preamble = String.format("export CALLING_PACKAGE=%s PATH=\"%s:$PATH\" TMPDIR='%s'; id -u\n",
BuildConfig.APPLICATION_ID, localBinaryDir, localTemporaryDir);
}
private static boolean isExecutableInPath(final String name) {
@@ -0,0 +1,31 @@
/*
* Copyright © 2018 Harsh Shandilya <msfjarvis@gmail.com>
* Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.widget.fab;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.util.AttributeSet;
import android.view.View;
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionsMenu> {
public FloatingActionButtonBehavior(final Context context, final AttributeSet attrs) { }
@Override
public boolean layoutDependsOn(final CoordinatorLayout parent, final FloatingActionsMenu child,
final View dependency) {
return dependency instanceof Snackbar.SnackbarLayout;
}
@Override
public boolean onDependentViewChanged(final CoordinatorLayout parent, final FloatingActionsMenu child,
final View dependency) {
child.setBehaviorYTranslation(Math.min(0, dependency.getTranslationY() - dependency.getMeasuredHeight()));
return true;
}
}
@@ -67,6 +67,8 @@ public class FloatingActionsMenu extends ViewGroup {
@Nullable private TouchDelegateGroup mTouchDelegateGroup;
@Nullable private OnFloatingActionsMenuUpdateListener mListener;
private final Rect touchArea = new Rect(0, 0, 0, 0);
private float scrollYTranslation;
private float behaviorYTranslation;
public FloatingActionsMenu(final Context context) {
this(context, null);
@@ -103,6 +105,24 @@ public class FloatingActionsMenu extends ViewGroup {
createAddButton(context);
}
public float getScrollYTranslation() {
return scrollYTranslation;
}
public void setScrollYTranslation(final float scrollYTranslation) {
this.scrollYTranslation = scrollYTranslation;
setTranslationY(behaviorYTranslation + scrollYTranslation);
}
public float getBehaviorYTranslation() {
return behaviorYTranslation;
}
public void setBehaviorYTranslation(final float behaviorYTranslation) {
this.behaviorYTranslation = behaviorYTranslation;
setTranslationY(behaviorYTranslation + scrollYTranslation);
}
public void setOnFloatingActionsMenuUpdateListener(final OnFloatingActionsMenuUpdateListener listener) {
mListener = listener;
}
@@ -112,7 +132,7 @@ public class FloatingActionsMenu extends ViewGroup {
}
private void createAddButton(final Context context) {
final RotatingDrawable rotatingDrawable = new RotatingDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_action_add_inverse, context.getTheme()));
final RotatingDrawable rotatingDrawable = new RotatingDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_action_add_white, context.getTheme()));
mRotatingDrawable = rotatingDrawable;
final TimeInterpolator interpolator = new OvershootInterpolator();
@@ -0,0 +1,27 @@
/*
* Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.widget.fab;
import android.support.v7.widget.RecyclerView;
public class FloatingActionsMenuRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
private static final float SCALE_FACTOR = 1.5f;
private final FloatingActionsMenu menu;
public FloatingActionsMenuRecyclerViewScrollListener(final FloatingActionsMenu menu) {
this.menu = menu;
}
private static float bound(final float min, final float proposal, final float max) {
return Math.min(max, Math.max(min, proposal));
}
@Override
public void onScrolled(final RecyclerView recyclerView, final int dx, final int dy) {
super.onScrolled(recyclerView, dx, dy);
menu.setScrollYTranslation(bound(0, menu.getScrollYTranslation() + dy * SCALE_FACTOR, menu.getMeasuredHeight() - menu.getTranslationY()));
}
}
@@ -10,7 +10,6 @@ import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -71,7 +70,7 @@ public enum Attribute {
}
public String composeWith(final int value) {
return String.format(Locale.getDefault(), "%s = %d%n", token, value);
return String.format("%s = %d%n", token, value);
}
public <T> String composeWith(final Iterable<T> value) {
@@ -20,6 +20,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -32,6 +33,10 @@ public class Config {
private final Interface interfaceSection = new Interface();
private List<Peer> peers = new ArrayList<>();
public static Config from(final String string) throws IOException {
return from(new BufferedReader(new StringReader(string)));
}
public static Config from(final InputStream stream) throws IOException {
return from(new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)));
}
@@ -25,7 +25,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java9.lang.Iterables;
@@ -72,7 +71,7 @@ public class Peer {
private String getEndpointString() {
if (endpoint == null)
return null;
return String.format(Locale.getDefault(), "%s:%d", endpoint.getHostString(), endpoint.getPort());
return String.format("%s:%d", endpoint.getHostString(), endpoint.getPort());
}
public int getPersistentKeepalive() {
@@ -104,12 +103,10 @@ public class Peer {
if (endpoint.isUnresolved())
throw new UnknownHostException(endpoint.getHostString());
if (endpoint.getAddress() instanceof Inet6Address)
return String.format(Locale.getDefault(),
"[%s]:%d",
return String.format("[%s]:%d",
endpoint.getAddress().getHostAddress(),
endpoint.getPort());
return String.format(Locale.getDefault(),
"%s:%d",
return String.format("%s:%d",
endpoint.getAddress().getHostAddress(),
endpoint.getPort());
}
@@ -4,6 +4,6 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="?android:attr/colorBackground"
android:fillColor="#ffffff"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>
@@ -4,6 +4,6 @@
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="?android:attr/colorBackground"
android:fillColor="#ffffff"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
</vector>
@@ -4,6 +4,6 @@
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="?android:attr/colorBackground"
android:fillColor="#ffffff"
android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z" />
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ffffff"
android:pathData="M4,4H10V10H4V4M20,4V10H14V4H20M14,15H16V13H14V11H16V13H18V11H20V13H18V15H20V18H18V20H16V18H13V20H11V16H14V15M16,15V18H18V15H16M4,20V14H10V20H4M6,6V8H8V6H6M16,6V8H18V6H16M6,16V18H8V16H6M4,11H6V13H4V11M9,11H13V15H11V13H9V11M11,6H13V10H11V6M2,2V6H0V2A2,2 0 0,1 2,0H6V2H2M22,0A2,2 0 0,1 24,2V6H22V2H18V0H22M2,18V22H6V24H2A2,2 0 0,1 0,22V18H2M22,22V18H24V22A2,2 0 0,1 22,24H18V22H22Z" />
</vector>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<android.support.design.widget.TextInputLayout
android:id="@+id/tunnel_name_text_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/tunnel_name_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/tunnel_name" />
</android.support.design.widget.TextInputLayout>
</FrameLayout>
</layout>
@@ -55,7 +55,6 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_toStartOf="@+id/tunnel_switch"
android:text="@string/interface_title" />
<com.wireguard.android.widget.ToggleSwitch
@@ -30,20 +30,65 @@
android:id="@+id/tunnel_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@{@dimen/design_fab_size_normal * 1.1f}"
android:clipToPadding="false"
android:choiceMode="multipleChoiceModal"
android:visibility="@{tunnels.size() > 0 ? android.view.View.VISIBLE : android.view.View.GONE}"
app:items="@{tunnels}"
app:layout="@{@layout/tunnel_list_item}"
app:configurationHandler="@{rowConfigurationHandler}" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="@{tunnels.size() == 0 ? android.view.View.VISIBLE : android.view.View.GONE}"
android:layout_gravity="center">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/logo_placeholder"
android:layout_width="140dp"
android:layout_height="140dp"
android:layout_gravity="center"
android:tint="@color/transparent_background_placeholder"
android:layout_marginTop="-70dp"
android:layout_marginBottom="20dp"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="20sp"
android:text="@string/tunnel_list_placeholder" />
</LinearLayout>
<com.wireguard.android.widget.fab.FloatingActionsMenu
android:id="@+id/create_menu"
android:clipChildren="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:layout_margin="@dimen/fab_margin"
app:fab_labelStyle="@style/fab_label"
android:clipChildren="false"
app:fab_labelsPosition="left" >
app:fab_labelsPosition="@integer/label_position"
app:layout_behavior="com.wireguard.android.widget.fab.FloatingActionButtonBehavior" >
<com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/create_from_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestImportConfig}"
app:srcCompat="@drawable/ic_action_open_white"
app:fabSize="mini"
app:fab_title="@string/create_from_file" />
<com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/scan_qr_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestScanQRCode}"
app:srcCompat="@drawable/ic_action_scan_qr_code_white"
app:fabSize="mini"
app:fab_title="@string/create_from_qrcode" />
<com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/create_empty"
@@ -51,17 +96,9 @@
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestCreateConfig}"
app:fabSize="mini"
app:srcCompat="@drawable/ic_action_edit_inverse"
app:srcCompat="@drawable/ic_action_edit_white"
app:fab_title="@string/create_empty" />
<com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/create_from_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestImportConfig}"
app:srcCompat="@drawable/ic_action_open_inverse"
app:fabSize="mini"
app:fab_title="@string/create_from_file" />
</com.wireguard.android.widget.fab.FloatingActionsMenu>
</android.support.design.widget.CoordinatorLayout>
</layout>
@@ -39,7 +39,6 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_toStartOf="@+id/tunnel_switch"
android:ellipsize="end"
android:maxLines="1"
android:text="@{key}" />
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="label_position">1</integer>
</resources>
+4 -1
View File
@@ -6,5 +6,8 @@
<color name="fab_label_text_color">#000000</color>
<color name="fab_label_background_color">#bbbbbb</color>
<color name="accent">#BBDEFB</color>
<color name="accent">#5e97f6</color>
<!-- TODO(msf): replace with ?android:attr/colorBackground with some alpha -->
<color name="transparent_background_placeholder">#aa2e2e2e</color>
</resources>
+3
View File
@@ -7,4 +7,7 @@
<color name="fab_label_background_color">#444444</color>
<color name="accent">#2196F3</color>
<!-- TODO(msf): replace with ?android:attr/colorBackground with some alpha -->
<color name="transparent_background_placeholder">#aafafafa</color>
</resources>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>
+1
View File
@@ -27,4 +27,5 @@
<enum name="right" value="3"/>
</attr>
</declare-styleable>
<integer name="label_position">0</integer>
</resources>
+6
View File
@@ -30,6 +30,8 @@
<string name="create_activity_title">Create WireGuard Tunnel</string>
<string name="create_empty">Create from scratch</string>
<string name="create_from_file">Create from file or archive</string>
<string name="create_from_qrcode">Create from QR code</string>
<string name="create_tunnel">Create Tunnel</string>
<string name="dark_theme_title">Use dark theme</string>
<string name="dark_theme_summary_on">Currently using dark night theme</string>
<string name="dark_theme_summary_off">Currently using light day theme</string>
@@ -50,6 +52,7 @@
<string name="hint_generated">(generated)</string>
<string name="hint_optional">(optional)</string>
<string name="hint_random">(random)</string>
<string name="import_from_qrcode">Import Tunnel from QR Code</string>
<string name="import_error">Unable to import tunnel: %s</string>
<string name="import_success">Imported “%s”</string>
<string name="interface_title">Interface</string>
@@ -68,6 +71,7 @@
<string name="private_key">Private key</string>
<string name="public_key">Public key</string>
<string name="public_key_description">Public key</string>
<string name="qrcode_hint">Tip: generate with `qrencode -t ansiutf8 &lt; tunnel.conf`.</string>
<string name="restore_on_boot_summary">Bring up previously-enabled tunnels on boot</string>
<string name="restore_on_boot_title">Restore on boot</string>
<string name="save">Save</string>
@@ -89,6 +93,8 @@
<string name="tools_installer_title">Install command line tools</string>
<string name="tunnel_create_error">Unable to create tunnel: %s</string>
<string name="tunnel_create_success">Successfully created tunnel “%s”</string>
<string name="tunnel_list_placeholder">Add a tunnel using the blue button</string>
<string name="tunnel_name">Tunnel Name</string>
<string name="tunnel_rename_error">Unable to rename tunnel: %s</string>
<string name="tunnel_rename_success">Successfully renamed tunnel to “%s”</string>
<string name="version_title">WireGuard for Android v%s"</string>
+5 -4
View File
@@ -8,12 +8,12 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
# Work around https://github.com/android-ndk/ndk/issues/602
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
add_executable(libwg-quick.so wireguard/src/tools/wg-quick/android.c)
target_compile_options(libwg-quick.so PUBLIC -O3 -std=gnu11 -Wall -pedantic -Wno-missing-field-initializers)
add_executable(libwg-quick.so wireguard/src/tools/wg-quick/android.c ndk-compat/compat.c)
target_compile_options(libwg-quick.so PUBLIC -O3 -std=gnu11 -Wall -pedantic -Wno-missing-field-initializers -include ${CMAKE_CURRENT_SOURCE_DIR}/ndk-compat/compat.h -DWG_PACKAGE_NAME=\"${ANDROID_PACKAGE_NAME}\")
file(GLOB WG_SOURCES wireguard/src/tools/*.c libmnl/src/*.c)
file(GLOB WG_SOURCES wireguard/src/tools/*.c libmnl/src/*.c ndk-compat/compat.c)
add_executable(libwg.so ${WG_SOURCES})
target_compile_options(libwg.so PUBLIC -idirafter "${CMAKE_CURRENT_SOURCE_DIR}/libmnl/include/" -I "${CMAKE_CURRENT_SOURCE_DIR}/wireguard/src/tools/" -O3 -std=gnu11 -D_GNU_SOURCE -DHAVE_VISIBILITY_HIDDEN -DRUNSTATEDIR=\"\\\"/data/data/com.wireguard.android/cache\\\"\" -Wno-pointer-arith -Wno-unused-parameter)
target_compile_options(libwg.so PUBLIC -idirafter "${CMAKE_CURRENT_SOURCE_DIR}/libmnl/include/" -I "${CMAKE_CURRENT_SOURCE_DIR}/wireguard/src/tools/" -O3 -std=gnu11 -D_GNU_SOURCE -include ${CMAKE_CURRENT_SOURCE_DIR}/ndk-compat/compat.h -DHAVE_VISIBILITY_HIDDEN -DRUNSTATEDIR=\"/data/data/${ANDROID_PACKAGE_NAME}/cache\" -Wno-pointer-arith -Wno-unused-parameter)
add_custom_target(libwg-go.so WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libwg-go" COMMENT "Building wireguard-go" VERBATIM COMMAND make
ANDROID_ARCH_NAME=${ANDROID_ARCH_NAME}
@@ -21,6 +21,7 @@ add_custom_target(libwg-go.so WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib
ANDROID_TOOLCHAIN_ROOT=${ANDROID_TOOLCHAIN_ROOT}
ANDROID_LLVM_TRIPLE=${ANDROID_LLVM_TRIPLE}
ANDROID_SYSROOT=${ANDROID_SYSROOT}
ANDROID_PACKAGE_NAME=${ANDROID_PACKAGE_NAME}
CFLAGS=${CMAKE_C_FLAGS}\ -Wno-unused-command-line-argument
LDFLAGS=${CMAKE_SHARED_LINKER_FLAGS}\ -fuse-ld=gold
DESTDIR=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
+1 -1
View File
@@ -54,5 +54,5 @@ $(DESTDIR)/libwg-go.so: $(FILES) src/git.zx2c4.com/wireguard-go/api-android.go s
mkdir -p $(subst ../wireguard-go/,./src/git.zx2c4.com/wireguard-go/,$(dir $(FILES)))
$(foreach FILE,$(FILES),ln -sfrt $(subst ../wireguard-go/,./src/git.zx2c4.com/wireguard-go/,$(dir $(FILE))) $(FILE);)
GOPATH=$(PWD) go get -v -d git.zx2c4.com/wireguard-go
GOPATH=$(PWD) go build -v -o $(DESTDIR)/libwg-go.so -buildmode c-shared git.zx2c4.com/wireguard-go
GOPATH=$(PWD) go build -ldflags="-X main.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -o $(DESTDIR)/libwg-go.so -buildmode c-shared git.zx2c4.com/wireguard-go
go version > .gobuildversion
@@ -16,6 +16,7 @@ import (
"io/ioutil"
"log"
"math"
"net"
"os"
"os/signal"
"runtime"
@@ -33,11 +34,16 @@ func (l AndroidLogger) Write(p []byte) (int, error) {
return len(p), nil
}
var tunnelHandles map[int32]*Device
type TunnelHandle struct {
device *Device
uapi net.Listener
}
var tunnelHandles map[int32]TunnelHandle
func init() {
roamingDisabled = true
tunnelHandles = make(map[int32]*Device)
tunnelHandles = make(map[int32]TunnelHandle)
signals := make(chan os.Signal)
signal.Notify(signals, unix.SIGUSR2)
go func() {
@@ -85,6 +91,29 @@ func wgTurnOn(ifnameRef string, tun_fd int32, settings string) int32 {
return -1
}
uapiFile, err := UAPIOpen(name)
if err != nil {
unix.Close(int(tun_fd))
logger.Error.Println(err)
return -1
}
uapi, err := UAPIListen(name, uapiFile)
if err != nil {
uapiFile.Close()
unix.Close(int(tun_fd))
logger.Error.Println(err)
return -1
}
go func() {
for {
conn, err := uapi.Accept()
if err != nil {
return
}
go ipcHandle(device, conn)
}
}()
device.Up()
logger.Info.Println("Device started")
@@ -98,27 +127,28 @@ func wgTurnOn(ifnameRef string, tun_fd int32, settings string) int32 {
unix.Close(int(tun_fd))
return -1
}
tunnelHandles[i] = device
tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi}
return i
}
//export wgTurnOff
func wgTurnOff(tunnelHandle int32) {
device, ok := tunnelHandles[tunnelHandle]
handle, ok := tunnelHandles[tunnelHandle]
if !ok {
return
}
delete(tunnelHandles, tunnelHandle)
device.Close()
handle.uapi.Close()
handle.device.Close()
}
//export wgGetSocketV4
func wgGetSocketV4(tunnelHandle int32) int32 {
device, ok := tunnelHandles[tunnelHandle]
handle, ok := tunnelHandles[tunnelHandle]
if !ok {
return -1
}
native, ok := device.net.bind.(*NativeBind)
native, ok := handle.device.net.bind.(*NativeBind)
if !ok {
return -1
}
@@ -138,11 +168,11 @@ func wgGetSocketV4(tunnelHandle int32) int32 {
//export wgGetSocketV6
func wgGetSocketV6(tunnelHandle int32) int32 {
device, ok := tunnelHandles[tunnelHandle]
handle, ok := tunnelHandles[tunnelHandle]
if !ok {
return -1
}
native, ok := device.net.bind.(*NativeBind)
native, ok := handle.device.net.bind.(*NativeBind)
if !ok {
return -1
}
+77
View File
@@ -0,0 +1,77 @@
/* SPDX-License-Identifier: BSD
*
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*
*/
#define FILE_IS_EMPTY
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
#undef FILE_IS_EMPTY
#include <stdio.h>
#include <stdlib.h>
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
{
char *ptr, *eptr;
if (*buf == NULL || *bufsiz == 0) {
*bufsiz = BUFSIZ;
if ((*buf = malloc(*bufsiz)) == NULL)
return -1;
}
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
int c = fgetc(fp);
if (c == -1) {
if (feof(fp)) {
ssize_t diff = (ssize_t)(ptr - *buf);
if (diff != 0) {
*ptr = '\0';
return diff;
}
}
return -1;
}
*ptr++ = c;
if (c == delimiter) {
*ptr = '\0';
return ptr - *buf;
}
if (ptr + 2 >= eptr) {
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;
eptr = nbuf + nbufsiz;
ptr = nbuf + d;
}
}
}
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp)
{
return getdelim(buf, bufsiz, '\n', fp);
}
#endif
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
#undef FILE_IS_EMPTY
#include <string.h>
char *strchrnul(const char *s, int c)
{
char *x = strchr(s, c);
if (!x)
return (char *)s + strlen(s);
return x;
}
#endif
#ifdef FILE_IS_EMPTY
#undef FILE_IS_EMPTY
static char ____x __attribute__((unused));
#endif
+16
View File
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: BSD
*
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*
*/
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
#include <stdio.h>
ssize_t getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp);
ssize_t getline(char **buf, size_t *bufsiz, FILE *fp);
#endif
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24
char *strchrnul(const char *s, int c);
#endif