summaryrefslogtreecommitdiffhomepage
path: root/tunnel/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'tunnel/src/main')
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java32
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/LocalSocketAdapter.java325
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/UnixDomainSocketFactory.java59
-rw-r--r--tunnel/src/main/proto/libwg.proto27
4 files changed, 442 insertions, 1 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
index de7f2027..f074abc5 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -7,14 +7,22 @@ package com.wireguard.android.backend;
import android.content.Context;
import android.content.Intent;
+import android.net.LocalSocketAddress;
import android.net.ProxyInfo;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.system.OsConstants;
import android.util.Log;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Empty;
+
import com.wireguard.android.backend.BackendException.Reason;
import com.wireguard.android.backend.Tunnel.State;
+import com.wireguard.android.backend.gen.LibwgGrpc;
+import com.wireguard.android.backend.gen.VersionRequest;
+import com.wireguard.android.backend.gen.VersionResponse;
import com.wireguard.android.util.SharedLibraryLoader;
import com.wireguard.config.Config;
import com.wireguard.config.InetEndpoint;
@@ -24,6 +32,11 @@ import com.wireguard.crypto.Key;
import com.wireguard.crypto.KeyFormatException;
import com.wireguard.util.NonNullForAll;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.okhttp.OkHttpChannelBuilder;
+
+import java.io.File;
import java.net.InetAddress;
import java.net.URL;
import java.util.Collections;
@@ -34,6 +47,8 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import javax.net.SocketFactory;
+
import androidx.annotation.Nullable;
import androidx.collection.ArraySet;
@@ -51,6 +66,7 @@ public final class GoBackend implements Backend {
@Nullable private Config currentConfig;
@Nullable private Tunnel currentTunnel;
private int currentTunnelHandle = -1;
+ private ManagedChannel channel;
/**
* Public constructor for GoBackend.
@@ -60,6 +76,15 @@ public final class GoBackend implements Backend {
public GoBackend(final Context context) {
SharedLibraryLoader.loadSharedLibrary(context, "wg-go");
this.context = context;
+
+ File socketFile = new File(context.getCacheDir(), "libwg.sock");
+ String socketName = socketFile.getAbsolutePath();
+ Log.i(TAG, "wgStartGrpc: " + wgStartGrpc(socketName));
+ ManagedChannelBuilder<?> channelBuilder = ManagedChannelBuilder.forAddress("localhost", 10000).usePlaintext();
+ LocalSocketAddress address = new LocalSocketAddress(socketName, LocalSocketAddress.Namespace.FILESYSTEM);
+ SocketFactory socketFactory = new UnixDomainSocketFactory(address);
+ ((OkHttpChannelBuilder) channelBuilder).socketFactory(socketFactory);
+ channel = channelBuilder.build();
}
/**
@@ -84,6 +109,8 @@ public final class GoBackend implements Backend {
private static native String wgVersion();
+ private static native int wgStartGrpc(String sockName);
+
/**
* Method to get the names of running tunnels.
*
@@ -168,7 +195,10 @@ public final class GoBackend implements Backend {
*/
@Override
public String getVersion() {
- return wgVersion();
+ LibwgGrpc.LibwgBlockingStub stub = LibwgGrpc.newBlockingStub(channel);
+ VersionRequest request = VersionRequest.newBuilder().build();
+ VersionResponse resp = stub.version(request);
+ return resp.getVersion();
}
/**
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/LocalSocketAdapter.java b/tunnel/src/main/java/com/wireguard/android/backend/LocalSocketAdapter.java
new file mode 100644
index 00000000..bf027ae1
--- /dev/null
+++ b/tunnel/src/main/java/com/wireguard/android/backend/LocalSocketAdapter.java
@@ -0,0 +1,325 @@
+/*
+ */
+package com.wireguard.android.backend;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImplFactory;
+import java.net.SocketOptions;
+import java.nio.channels.SocketChannel;
+import java.util.Vector;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.util.Log;
+
+/**
+ * Adaptor allows using a LocalSocket as a Socket.
+ */
+final class LocalSocketAdapter extends Socket {
+ private final LocalSocketAddress address;
+ private final LocalSocket unix;
+ private final SocketAddress localAddress;
+ private InetSocketAddress inetSocketAddress;
+ private InputStream is;
+ private OutputStream os;
+
+ LocalSocketAdapter(LocalSocketAddress address) {
+ this.address = address;
+ this.localAddress = new InetSocketAddress(0);
+ unix = new LocalSocket();
+ }
+
+ LocalSocketAdapter(LocalSocketAddress address, InetSocketAddress inetAddress) {
+ this(address);
+ this.inetSocketAddress = inetAddress;
+ }
+
+ private void throwUnsupportedOperationException() {
+ Log.i("helloworld", "Unsupported: " + Log.getStackTraceString(new Exception()));
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void bind (SocketAddress bindpoint) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void close() throws IOException {
+ unix.close();
+ }
+
+ @Override public void connect(SocketAddress endpoint) throws IOException {
+ this.inetSocketAddress = (InetSocketAddress) endpoint;
+ try {
+ unix.connect(address);
+ } catch (IOException e) {
+ Log.i("helloworld", "Error: " + e.toString());
+ throw e;
+ }
+ }
+
+ @Override
+ public void connect(SocketAddress endpoint, int timeout) throws IOException {
+ this.inetSocketAddress = (InetSocketAddress) endpoint;
+ unix.connect(address, timeout);
+ }
+
+ @Override
+ public SocketChannel getChannel() {
+ throwUnsupportedOperationException();
+ return null;
+ }
+
+ @Override public InetAddress getInetAddress() {
+ return inetSocketAddress.getAddress();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ is = unix.getInputStream();
+ return is;
+ }
+
+ @Override
+ public boolean getKeepAlive() {
+ throwUnsupportedOperationException();
+ return false;
+ }
+
+ @Override
+ public InetAddress getLocalAddress() {
+ throwUnsupportedOperationException();
+ return null;
+ }
+
+ @Override
+ public int getLocalPort() {
+ throwUnsupportedOperationException();
+ return 0;
+ }
+
+ @Override
+ public SocketAddress getLocalSocketAddress() {
+ //throwUnsupportedOperationException();
+ return localAddress;
+ }
+
+ @Override
+ public boolean getOOBInline() {
+ throwUnsupportedOperationException();
+ return false;
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ if (os != null)
+ return os;
+
+ OutputStream unixOs = unix.getOutputStream();
+ os = new OutputStream() {
+ @Override
+ public void close() throws IOException {
+ // LocalSocket's default implementation closes the socket,
+ // which leaves readers of thes InputStream hanging.
+ // Instead shutdown input (and output) to release readers.
+ LocalSocketAdapter.this.shutdownInput();
+ LocalSocketAdapter.this.shutdownOutput();
+ }
+
+ @Override
+ public void write (byte[] b) throws IOException {
+ unixOs.write(b);
+ }
+
+ @Override
+ public void write (byte[] b, int off, int len) throws IOException {
+ unixOs.write(b, off, len);
+ }
+
+ @Override
+ public void write (int b) throws IOException {
+ unixOs.write(b);
+ }
+ };
+ return os;
+ }
+
+ @Override
+ public int getPort() {
+ return inetSocketAddress.getPort();
+ }
+
+ @Override
+ public int getReceiveBufferSize() throws SocketException {
+ try {
+ return unix.getReceiveBufferSize();
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public SocketAddress getRemoteSocketAddress() {
+ return inetSocketAddress;
+ }
+
+ @Override
+ public boolean getReuseAddress() {
+ throwUnsupportedOperationException();
+ return false;
+ }
+
+ @Override
+ public int getSendBufferSize() throws SocketException {
+ try {
+ return unix.getSendBufferSize();
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public int getSoLinger() {
+ throwUnsupportedOperationException();
+ return 0;
+ }
+
+ @Override
+ public int getSoTimeout() throws SocketException {
+ try {
+ return unix.getSoTimeout();
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean getTcpNoDelay() {
+ throwUnsupportedOperationException();
+ return false;
+ }
+
+ @Override
+ public int getTrafficClass() {
+ throwUnsupportedOperationException();
+ return 0;
+ }
+
+ @Override
+ public boolean isBound() {
+ return unix.isBound();
+ }
+
+ @Override
+ public boolean isClosed() {
+ return unix.isClosed();
+ }
+
+ @Override
+ public boolean isConnected() {
+ return unix.isConnected();
+ }
+
+ @Override
+ public boolean isInputShutdown() {
+ return unix.isInputShutdown();
+ }
+
+ @Override
+ public boolean isOutputShutdown() {
+ return unix.isOutputShutdown();
+ }
+
+ @Override
+ public void sendUrgentData (int data) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setKeepAlive (boolean on) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setOOBInline (boolean on) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setPerformancePreferences (int connectionTime,
+ int latency,
+ int bandwidth) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setReceiveBufferSize(int size) throws SocketException {
+ try {
+ unix.setReceiveBufferSize(size);
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void setReuseAddress (boolean on) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setSendBufferSize(int size) throws SocketException {
+ try {
+ unix.setSendBufferSize(size);
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void setSoLinger (boolean on,
+ int linger) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void setSoTimeout(int timeout) throws SocketException {
+ try {
+ unix.setSoTimeout(timeout);
+ } catch (IOException e) {
+ throw new SocketException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void setTcpNoDelay (boolean on) {
+ // Not relevant for local sockets.
+ }
+
+ @Override
+ public void setTrafficClass (int tc) {
+ throwUnsupportedOperationException();
+ }
+
+ @Override
+ public void shutdownInput() throws IOException {
+ unix.shutdownInput();
+ }
+
+ @Override
+ public void shutdownOutput() throws IOException {
+ unix.shutdownOutput();
+ }
+
+ @Override
+ public String toString() {
+ return unix.toString();
+ }
+}
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/UnixDomainSocketFactory.java b/tunnel/src/main/java/com/wireguard/android/backend/UnixDomainSocketFactory.java
new file mode 100644
index 00000000..427a19f1
--- /dev/null
+++ b/tunnel/src/main/java/com/wireguard/android/backend/UnixDomainSocketFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.wireguard.android.backend;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import javax.net.SocketFactory;
+import android.net.LocalSocketAddress;
+
+/** Impersonate TCP-style SocketFactory over UNIX domain sockets. */
+public final class UnixDomainSocketFactory extends SocketFactory {
+ private final LocalSocketAddress address;
+
+ public UnixDomainSocketFactory(LocalSocketAddress address) {
+ this.address = address;
+ }
+
+ @Override public Socket createSocket() throws IOException {
+ return new LocalSocketAdapter(address);
+ }
+
+ @Override public Socket createSocket(String host, int port) throws IOException {
+ Socket result = createSocket();
+ result.connect(new InetSocketAddress(host, port));
+ return result;
+ }
+
+ @Override public Socket createSocket(
+ String host, int port, InetAddress localHost, int localPort) throws IOException {
+ return createSocket(host, port);
+ }
+
+ @Override public Socket createSocket(InetAddress host, int port) throws IOException {
+ Socket result = createSocket();
+ result.connect(new InetSocketAddress(host, port));
+ return result;
+ }
+
+ @Override public Socket createSocket(
+ InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException {
+ return createSocket(host, port);
+ }
+}
diff --git a/tunnel/src/main/proto/libwg.proto b/tunnel/src/main/proto/libwg.proto
new file mode 100644
index 00000000..2d964897
--- /dev/null
+++ b/tunnel/src/main/proto/libwg.proto
@@ -0,0 +1,27 @@
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = 'com.wireguard.android.backend.gen';
+option java_outer_classname = "LibwgProto";
+option java_generic_services = true;
+option go_package = 'golang.zx2c4.com/wireguard/android/gen';
+
+package api;
+
+service Libwg {
+ rpc StopGrpc(StopGrpcRequest) returns (StopGrpcResponse);
+ rpc Version(VersionRequest) returns (VersionResponse);
+}
+
+message StopGrpcRequest {
+}
+
+message StopGrpcResponse {
+}
+
+message VersionRequest {
+}
+
+message VersionResponse {
+ string version = 1;
+}