Implement statistics
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
16890a659e
commit
8b0123042f
@ -24,6 +24,8 @@ import com.wireguard.android.util.SharedLibraryLoader;
|
|||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
import com.wireguard.config.InetNetwork;
|
import com.wireguard.config.InetNetwork;
|
||||||
import com.wireguard.config.Peer;
|
import com.wireguard.config.Peer;
|
||||||
|
import com.wireguard.crypto.Key;
|
||||||
|
import com.wireguard.crypto.KeyFormatException;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -47,6 +49,8 @@ public final class GoBackend implements Backend {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native String wgGetConfig(int handle);
|
||||||
|
|
||||||
private static native int wgGetSocketV4(int handle);
|
private static native int wgGetSocketV4(int handle);
|
||||||
|
|
||||||
private static native int wgGetSocketV6(int handle);
|
private static native int wgGetSocketV6(int handle);
|
||||||
@ -90,7 +94,45 @@ public final class GoBackend implements Backend {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statistics getStatistics(final Tunnel tunnel) {
|
public Statistics getStatistics(final Tunnel tunnel) {
|
||||||
return new Statistics();
|
final Statistics stats = new Statistics();
|
||||||
|
if (tunnel != currentTunnel) {
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
final String config = wgGetConfig(currentTunnelHandle);
|
||||||
|
Key key = null;
|
||||||
|
long rx = 0, tx = 0;
|
||||||
|
for (final String line : config.split("\\n")) {
|
||||||
|
if (line.startsWith("public_key=")) {
|
||||||
|
if (key != null)
|
||||||
|
stats.add(key, rx, tx);
|
||||||
|
rx = 0;
|
||||||
|
tx = 0;
|
||||||
|
try {
|
||||||
|
key = Key.fromHex(line.substring(11));
|
||||||
|
} catch (final KeyFormatException ignored) {
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
} else if (line.startsWith("rx_bytes=")) {
|
||||||
|
if (key == null)
|
||||||
|
continue;
|
||||||
|
try {
|
||||||
|
rx = Long.parseLong(line.substring(9));
|
||||||
|
} catch (final NumberFormatException ignored) {
|
||||||
|
rx = 0;
|
||||||
|
}
|
||||||
|
} else if (line.startsWith("tx_bytes=")) {
|
||||||
|
if (key == null)
|
||||||
|
continue;
|
||||||
|
try {
|
||||||
|
tx = Long.parseLong(line.substring(9));
|
||||||
|
} catch (final NumberFormatException ignored) {
|
||||||
|
tx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key != null)
|
||||||
|
stats.add(key, rx, tx);
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,11 +15,13 @@ import com.wireguard.android.model.Tunnel;
|
|||||||
import com.wireguard.android.model.Tunnel.State;
|
import com.wireguard.android.model.Tunnel.State;
|
||||||
import com.wireguard.android.model.Tunnel.Statistics;
|
import com.wireguard.android.model.Tunnel.Statistics;
|
||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
|
import com.wireguard.crypto.Key;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -83,7 +85,24 @@ public final class WgQuickBackend implements Backend {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Statistics getStatistics(final Tunnel tunnel) {
|
public Statistics getStatistics(final Tunnel tunnel) {
|
||||||
return new Statistics();
|
final Statistics stats = new Statistics();
|
||||||
|
final Collection<String> output = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
if (Application.getRootShell().run(output, String.format("wg show '%s' transfer", tunnel.getName())) != 0)
|
||||||
|
return stats;
|
||||||
|
} catch (final Exception ignored) {
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
for (final String line : output) {
|
||||||
|
final String[] parts = line.split("\\t");
|
||||||
|
if (parts.length != 3)
|
||||||
|
continue;
|
||||||
|
try {
|
||||||
|
stats.add(Key.fromBase64(parts[0]), Long.parseLong(parts[1]), Long.parseLong(parts[2]));
|
||||||
|
} catch (final Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -7,6 +7,8 @@ package com.wireguard.android.fragment;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.databinding.DataBindingUtil;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -15,7 +17,13 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import com.wireguard.android.R;
|
import com.wireguard.android.R;
|
||||||
import com.wireguard.android.databinding.TunnelDetailFragmentBinding;
|
import com.wireguard.android.databinding.TunnelDetailFragmentBinding;
|
||||||
|
import com.wireguard.android.databinding.TunnelDetailPeerBinding;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
|
import com.wireguard.android.model.Tunnel.State;
|
||||||
|
import com.wireguard.crypto.Key;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment that shows details about a specific tunnel.
|
* Fragment that shows details about a specific tunnel.
|
||||||
@ -23,6 +31,20 @@ import com.wireguard.android.model.Tunnel;
|
|||||||
|
|
||||||
public class TunnelDetailFragment extends BaseFragment {
|
public class TunnelDetailFragment extends BaseFragment {
|
||||||
@Nullable private TunnelDetailFragmentBinding binding;
|
@Nullable private TunnelDetailFragmentBinding binding;
|
||||||
|
@Nullable private Timer timer;
|
||||||
|
@Nullable private State lastState = State.TOGGLE;
|
||||||
|
|
||||||
|
private static class StatsTimerTask extends TimerTask {
|
||||||
|
final TunnelDetailFragment tdf;
|
||||||
|
private StatsTimerTask(final TunnelDetailFragment tdf) {
|
||||||
|
this.tdf = tdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
tdf.updateStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
@ -35,6 +57,22 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
inflater.inflate(R.menu.tunnel_detail, menu);
|
inflater.inflate(R.menu.tunnel_detail, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if (timer != null) {
|
||||||
|
timer.cancel();
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
timer = new Timer();
|
||||||
|
timer.scheduleAtFixedRate(new StatsTimerTask(this), 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||||
@Nullable final Bundle savedInstanceState) {
|
@Nullable final Bundle savedInstanceState) {
|
||||||
@ -59,6 +97,8 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
binding.setConfig(null);
|
binding.setConfig(null);
|
||||||
else
|
else
|
||||||
newTunnel.getConfigAsync().thenAccept(binding::setConfig);
|
newTunnel.getConfigAsync().thenAccept(binding::setConfig);
|
||||||
|
lastState = State.TOGGLE;
|
||||||
|
updateStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -72,4 +112,52 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
super.onViewStateRestored(savedInstanceState);
|
super.onViewStateRestored(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String formatBytes(final long bytes) {
|
||||||
|
if (bytes < 1024)
|
||||||
|
return getContext().getString(R.string.transfer_bytes, bytes);
|
||||||
|
else if (bytes < 1024*1024)
|
||||||
|
return getContext().getString(R.string.transfer_kibibytes, bytes/1024.0);
|
||||||
|
else if (bytes < 1024*1024*1024)
|
||||||
|
return getContext().getString(R.string.transfer_mibibytes, bytes/(1024.0*1024.0));
|
||||||
|
else if (bytes < 1024*1024*1024*1024)
|
||||||
|
return getContext().getString(R.string.transfer_gibibytes, bytes/(1024.0*1024.0*1024.0));
|
||||||
|
return getContext().getString(R.string.transfer_tibibytes, bytes/(1024.0*1024.0*1024.0)/1024.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStats() {
|
||||||
|
if (binding == null || !isResumed())
|
||||||
|
return;
|
||||||
|
final State state = binding.getTunnel().getState();
|
||||||
|
if (state != State.UP && lastState == state)
|
||||||
|
return;
|
||||||
|
lastState = state;
|
||||||
|
binding.getTunnel().getStatisticsAsync().whenComplete((statistics, throwable) -> {
|
||||||
|
if (throwable != null) {
|
||||||
|
for (int i = 0; i < binding.peersLayout.getChildCount(); ++i) {
|
||||||
|
final TunnelDetailPeerBinding peer = DataBindingUtil.getBinding(binding.peersLayout.getChildAt(i));
|
||||||
|
if (peer == null)
|
||||||
|
continue;
|
||||||
|
peer.transferLabel.setVisibility(View.GONE);
|
||||||
|
peer.transferText.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < binding.peersLayout.getChildCount(); ++i) {
|
||||||
|
final TunnelDetailPeerBinding peer = DataBindingUtil.getBinding(binding.peersLayout.getChildAt(i));
|
||||||
|
if (peer == null)
|
||||||
|
continue;
|
||||||
|
final Key publicKey = peer.getItem().getPublicKey();
|
||||||
|
final long rx = statistics.peerRx(publicKey);
|
||||||
|
final long tx = statistics.peerTx(publicKey);
|
||||||
|
if (rx == 0 && tx == 0) {
|
||||||
|
peer.transferLabel.setVisibility(View.GONE);
|
||||||
|
peer.transferText.setVisibility(View.GONE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
peer.transferText.setText(getContext().getString(R.string.transfer_rx_tx, formatBytes(rx), formatBytes(tx)));
|
||||||
|
peer.transferLabel.setVisibility(View.VISIBLE);
|
||||||
|
peer.transferText.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
package com.wireguard.android.model;
|
package com.wireguard.android.model;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
import androidx.databinding.BaseObservable;
|
import androidx.databinding.BaseObservable;
|
||||||
import androidx.databinding.Bindable;
|
import androidx.databinding.Bindable;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -12,8 +15,11 @@ import androidx.annotation.Nullable;
|
|||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
|
import com.wireguard.crypto.Key;
|
||||||
import com.wireguard.util.Keyed;
|
import com.wireguard.util.Keyed;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import java9.util.concurrent.CompletableFuture;
|
import java9.util.concurrent.CompletableFuture;
|
||||||
@ -85,15 +91,13 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
@Bindable
|
@Bindable
|
||||||
@Nullable
|
@Nullable
|
||||||
public Statistics getStatistics() {
|
public Statistics getStatistics() {
|
||||||
// FIXME: Check age of statistics.
|
if (statistics == null || statistics.isStale())
|
||||||
if (statistics == null)
|
|
||||||
TunnelManager.getTunnelStatistics(this).whenComplete(ExceptionLoggers.E);
|
TunnelManager.getTunnelStatistics(this).whenComplete(ExceptionLoggers.E);
|
||||||
return statistics;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletionStage<Statistics> getStatisticsAsync() {
|
public CompletionStage<Statistics> getStatisticsAsync() {
|
||||||
// FIXME: Check age of statistics.
|
if (statistics == null || statistics.isStale())
|
||||||
if (statistics == null)
|
|
||||||
return TunnelManager.getTunnelStatistics(this);
|
return TunnelManager.getTunnelStatistics(this);
|
||||||
return CompletableFuture.completedFuture(statistics);
|
return CompletableFuture.completedFuture(statistics);
|
||||||
}
|
}
|
||||||
@ -154,5 +158,48 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Statistics extends BaseObservable {
|
public static class Statistics extends BaseObservable {
|
||||||
|
private long lastTouched = SystemClock.elapsedRealtime();
|
||||||
|
private final Map<Key, Pair<Long, Long>> peerBytes = new HashMap<>();
|
||||||
|
|
||||||
|
public void add(final Key key, final long rx, final long tx) {
|
||||||
|
peerBytes.put(key, Pair.create(rx, tx));
|
||||||
|
lastTouched = SystemClock.elapsedRealtime();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStale() {
|
||||||
|
return SystemClock.elapsedRealtime() - lastTouched > 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key[] peers() {
|
||||||
|
return peerBytes.keySet().toArray(new Key[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long peerRx(final Key peer) {
|
||||||
|
if (!peerBytes.containsKey(peer))
|
||||||
|
return 0;
|
||||||
|
return peerBytes.get(peer).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long peerTx(final Key peer) {
|
||||||
|
if (!peerBytes.containsKey(peer))
|
||||||
|
return 0;
|
||||||
|
return peerBytes.get(peer).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long totalRx() {
|
||||||
|
long rx = 0;
|
||||||
|
for (final Pair<Long, Long> val : peerBytes.values()) {
|
||||||
|
rx += val.first;
|
||||||
|
}
|
||||||
|
return rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long totalTx() {
|
||||||
|
long tx = 0;
|
||||||
|
for (final Pair<Long, Long> val : peerBytes.values()) {
|
||||||
|
tx += val.second;
|
||||||
|
}
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ package com.wireguard.crypto;
|
|||||||
|
|
||||||
import com.wireguard.crypto.KeyFormatException.Type;
|
import com.wireguard.crypto.KeyFormatException.Type;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -247,6 +248,24 @@ public final class Key {
|
|||||||
return new String(output);
|
return new String(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int ret = 0;
|
||||||
|
for (int i = 0; i < key.length / 4; ++i)
|
||||||
|
ret ^= (key[i * 4 + 0] >> 0) + (key[i * 4 + 1] >> 8) + (key[i * 4 + 2] >> 16) + (key[i * 4 + 3] >> 24);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (obj == this)
|
||||||
|
return true;
|
||||||
|
if (obj == null || obj.getClass() != getClass())
|
||||||
|
return false;
|
||||||
|
final Key other = (Key) obj;
|
||||||
|
return MessageDigest.isEqual(key, other.key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The supported formats for encoding a WireGuard key.
|
* The supported formats for encoding a WireGuard key.
|
||||||
*/
|
*/
|
||||||
|
@ -125,6 +125,7 @@
|
|||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/peers_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
|
@ -89,6 +89,24 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/endpoint_label"
|
android:layout_below="@+id/endpoint_label"
|
||||||
android:text="@{item.endpoint}" />
|
android:text="@{item.endpoint}" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transfer_label"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/endpoint_text"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:labelFor="@+id/transfer_text"
|
||||||
|
android:text="@string/transfer"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/transfer_text"
|
||||||
|
style="?android:attr/textAppearanceMedium"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/transfer_label"
|
||||||
|
android:visibility="gone" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -144,6 +144,13 @@
|
|||||||
<string name="tools_installer_title">Install command line tools</string>
|
<string name="tools_installer_title">Install command line tools</string>
|
||||||
<string name="tools_installer_working">Installing wg and wg-quick</string>
|
<string name="tools_installer_working">Installing wg and wg-quick</string>
|
||||||
<string name="tools_unavailable_error">Required tools unavailable</string>
|
<string name="tools_unavailable_error">Required tools unavailable</string>
|
||||||
|
<string name="transfer">Transfer</string>
|
||||||
|
<string name="transfer_rx_tx">rx: %s, tx: %s</string>
|
||||||
|
<string name="transfer_bytes">%d B</string>
|
||||||
|
<string name="transfer_kibibytes">%.2f KiB</string>
|
||||||
|
<string name="transfer_mibibytes">%.2f MiB</string>
|
||||||
|
<string name="transfer_gibibytes">%.2f GiB</string>
|
||||||
|
<string name="transfer_tibibytes">%.2f TiB</string>
|
||||||
<string name="tun_create_error">Unable to create tun device</string>
|
<string name="tun_create_error">Unable to create tun device</string>
|
||||||
<string name="tunnel_config_error">Unable to configure tunnel (wg-quick returned %d)</string>
|
<string name="tunnel_config_error">Unable to configure tunnel (wg-quick returned %d)</string>
|
||||||
<string name="tunnel_create_error">Unable to create tunnel: %s</string>
|
<string name="tunnel_create_error">Unable to create tunnel: %s</string>
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/device"
|
"golang.zx2c4.com/wireguard/device"
|
||||||
"golang.zx2c4.com/wireguard/ipc"
|
"golang.zx2c4.com/wireguard/ipc"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
|
"bytes"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
@ -168,6 +169,22 @@ func wgGetSocketV6(tunnelHandle int32) int32 {
|
|||||||
return int32(fd)
|
return int32(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export wgGetConfig
|
||||||
|
func wgGetConfig(tunnelHandle int32) *C.char {
|
||||||
|
handle, ok := tunnelHandles[tunnelHandle]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
settings := new(bytes.Buffer)
|
||||||
|
writer := bufio.NewWriter(settings)
|
||||||
|
err := handle.device.IpcGetOperation(writer)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
writer.Flush()
|
||||||
|
return C.CString(settings.String())
|
||||||
|
}
|
||||||
|
|
||||||
//export wgVersion
|
//export wgVersion
|
||||||
func wgVersion() *C.char {
|
func wgVersion() *C.char {
|
||||||
return C.CString(device.WireGuardGoVersion)
|
return C.CString(device.WireGuardGoVersion)
|
||||||
|
@ -12,6 +12,7 @@ extern int wgTurnOn(struct go_string ifname, int tun_fd, struct go_string settin
|
|||||||
extern void wgTurnOff(int handle);
|
extern void wgTurnOff(int handle);
|
||||||
extern int wgGetSocketV4(int handle);
|
extern int wgGetSocketV4(int handle);
|
||||||
extern int wgGetSocketV6(int handle);
|
extern int wgGetSocketV6(int handle);
|
||||||
|
extern char *wgGetConfig(int handle);
|
||||||
extern char *wgVersion();
|
extern char *wgVersion();
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNIEnv *env, jclass c, jstring ifname, jint tun_fd, jstring settings)
|
JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNIEnv *env, jclass c, jstring ifname, jint tun_fd, jstring settings)
|
||||||
@ -47,6 +48,17 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgGetSocketV
|
|||||||
return wgGetSocketV6(handle);
|
return wgGetSocketV6(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jstring JNICALL Java_com_wireguard_android_backend_GoBackend_wgGetConfig(JNIEnv *env, jclass c, jint handle)
|
||||||
|
{
|
||||||
|
jstring ret;
|
||||||
|
char *config = wgGetConfig(handle);
|
||||||
|
if (!config)
|
||||||
|
return NULL;
|
||||||
|
ret = (*env)->NewStringUTF(env, config);
|
||||||
|
free(config);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_com_wireguard_android_backend_GoBackend_wgVersion(JNIEnv *env, jclass c)
|
JNIEXPORT jstring JNICALL Java_com_wireguard_android_backend_GoBackend_wgVersion(JNIEnv *env, jclass c)
|
||||||
{
|
{
|
||||||
jstring ret;
|
jstring ret;
|
||||||
|
@ -7,7 +7,7 @@ allprojects {
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
Loading…
Reference in New Issue
Block a user