рабочий вариант, но скороть 10 МБит
This commit is contained in:
@@ -0,0 +1,400 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package go;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import go.Universe;
|
||||
|
||||
// Seq is a sequence of machine-dependent encoded values.
|
||||
// Used by automatically generated language bindings to talk to Go.
|
||||
public class Seq {
|
||||
private static Logger log = Logger.getLogger("GoSeq");
|
||||
|
||||
// also known to bind/seq/ref.go and bind/objc/seq_darwin.m
|
||||
private static final int NULL_REFNUM = 41;
|
||||
|
||||
// use single Ref for null Object
|
||||
public static final Ref nullRef = new Ref(NULL_REFNUM, null);
|
||||
|
||||
// The singleton GoRefQueue
|
||||
private static final GoRefQueue goRefQueue = new GoRefQueue();
|
||||
|
||||
static {
|
||||
System.loadLibrary("gojni");
|
||||
init();
|
||||
Universe.touch();
|
||||
}
|
||||
|
||||
// setContext sets the context in the go-library to be used in RunOnJvm.
|
||||
public static void setContext(Context context) {
|
||||
setContext((java.lang.Object)context);
|
||||
}
|
||||
|
||||
private static native void init();
|
||||
|
||||
// Empty method to run class initializer
|
||||
public static void touch() {}
|
||||
|
||||
private Seq() {
|
||||
}
|
||||
|
||||
// ctx is an android.context.Context.
|
||||
static native void setContext(java.lang.Object ctx);
|
||||
|
||||
public static void incRefnum(int refnum) {
|
||||
tracker.incRefnum(refnum);
|
||||
}
|
||||
|
||||
// incRef increments the reference count of Java objects.
|
||||
// For proxies for Go objects, it calls into the Proxy method
|
||||
// incRefnum() to make sure the Go reference count is positive
|
||||
// even if the Proxy is garbage collected and its Ref is finalized.
|
||||
public static int incRef(Object o) {
|
||||
return tracker.inc(o);
|
||||
}
|
||||
|
||||
public static int incGoObjectRef(GoObject o) {
|
||||
return o.incRefnum();
|
||||
}
|
||||
|
||||
// trackGoRef tracks a Go reference and decrements its refcount
|
||||
// when the given GoObject wrapper is garbage collected.
|
||||
//
|
||||
// TODO(crawshaw): We could cut down allocations for frequently
|
||||
// sent Go objects by maintaining a map to weak references. This
|
||||
// however, would require allocating two objects per reference
|
||||
// instead of one. It also introduces weak references, the bane
|
||||
// of any Java debugging session.
|
||||
//
|
||||
// When we have real code, examine the tradeoffs.
|
||||
public static void trackGoRef(int refnum, GoObject obj) {
|
||||
if (refnum > 0) {
|
||||
throw new RuntimeException("trackGoRef called with Java refnum " + refnum);
|
||||
}
|
||||
goRefQueue.track(refnum, obj);
|
||||
}
|
||||
|
||||
public static Ref getRef(int refnum) {
|
||||
return tracker.get(refnum);
|
||||
}
|
||||
|
||||
// Increment the Go reference count before sending over a refnum.
|
||||
// The ref parameter is only used to make sure the referenced
|
||||
// object is not garbage collected before Go increments the
|
||||
// count. It's the equivalent of Go's runtime.KeepAlive.
|
||||
public static native void incGoRef(int refnum, GoObject ref);
|
||||
|
||||
// Informs the Go ref tracker that Java is done with this refnum.
|
||||
static native void destroyRef(int refnum);
|
||||
|
||||
// decRef is called from seq.FinalizeRef
|
||||
static void decRef(int refnum) {
|
||||
tracker.dec(refnum);
|
||||
}
|
||||
|
||||
// A GoObject is a Java class implemented in Go. When a GoObject
|
||||
// is passed to Go, it is wrapped in a Go proxy, to make it behave
|
||||
// the same as passing a regular Java class.
|
||||
public interface GoObject {
|
||||
// Increment refcount and return the refnum of the proxy.
|
||||
//
|
||||
// The Go reference count need to be bumped while the
|
||||
// refnum is passed to Go, to avoid finalizing and
|
||||
// invalidating it before being translated on the Go side.
|
||||
int incRefnum();
|
||||
}
|
||||
// A Proxy is a Java object that proxies a Go object. Proxies, unlike
|
||||
// GoObjects, are unwrapped to their Go counterpart when deserialized
|
||||
// in Go.
|
||||
public interface Proxy extends GoObject {}
|
||||
|
||||
// A Ref represents an instance of a Java object passed back and forth
|
||||
// across the language boundary.
|
||||
public static final class Ref {
|
||||
public final int refnum;
|
||||
|
||||
private int refcnt; // Track how many times sent to Go.
|
||||
|
||||
public final Object obj; // The referenced Java obj.
|
||||
|
||||
Ref(int refnum, Object o) {
|
||||
if (refnum < 0) {
|
||||
throw new RuntimeException("Ref instantiated with a Go refnum " + refnum);
|
||||
}
|
||||
this.refnum = refnum;
|
||||
this.refcnt = 0;
|
||||
this.obj = o;
|
||||
}
|
||||
|
||||
void inc() {
|
||||
// Count how many times this ref's Java object is passed to Go.
|
||||
if (refcnt == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("refnum " + refnum + " overflow");
|
||||
}
|
||||
refcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
static final RefTracker tracker = new RefTracker();
|
||||
|
||||
static final class RefTracker {
|
||||
private static final int REF_OFFSET = 42;
|
||||
|
||||
// Next Java object reference number.
|
||||
//
|
||||
// Reference numbers are positive for Java objects,
|
||||
// and start, arbitrarily at a different offset to Go
|
||||
// to make debugging by reading Seq hex a little easier.
|
||||
private int next = REF_OFFSET; // next Java object ref
|
||||
|
||||
// Java objects that have been passed to Go. refnum -> Ref
|
||||
// The Ref obj field is non-null.
|
||||
// This map pins Java objects so they don't get GCed while the
|
||||
// only reference to them is held by Go code.
|
||||
private final RefMap javaObjs = new RefMap();
|
||||
|
||||
// Java objects to refnum
|
||||
private final IdentityHashMap<Object, Integer> javaRefs = new IdentityHashMap<>();
|
||||
|
||||
// inc increments the reference count of a Java object when it
|
||||
// is sent to Go. inc returns the refnum for the object.
|
||||
synchronized int inc(Object o) {
|
||||
if (o == null) {
|
||||
return NULL_REFNUM;
|
||||
}
|
||||
if (o instanceof Proxy) {
|
||||
return ((Proxy)o).incRefnum();
|
||||
}
|
||||
Integer refnumObj = javaRefs.get(o);
|
||||
if (refnumObj == null) {
|
||||
if (next == Integer.MAX_VALUE) {
|
||||
throw new RuntimeException("createRef overflow for " + o);
|
||||
}
|
||||
refnumObj = next++;
|
||||
javaRefs.put(o, refnumObj);
|
||||
}
|
||||
int refnum = refnumObj;
|
||||
Ref ref = javaObjs.get(refnum);
|
||||
if (ref == null) {
|
||||
ref = new Ref(refnum, o);
|
||||
javaObjs.put(refnum, ref);
|
||||
}
|
||||
ref.inc();
|
||||
return refnum;
|
||||
}
|
||||
|
||||
synchronized void incRefnum(int refnum) {
|
||||
Ref ref = javaObjs.get(refnum);
|
||||
if (ref == null) {
|
||||
throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
|
||||
}
|
||||
ref.inc();
|
||||
}
|
||||
|
||||
// dec decrements the reference count of a Java object when
|
||||
// Go signals a corresponding proxy object is finalized.
|
||||
// If the count reaches zero, the Java object is removed
|
||||
// from the javaObjs map.
|
||||
synchronized void dec(int refnum) {
|
||||
if (refnum <= 0) {
|
||||
// We don't keep track of the Go object.
|
||||
// This must not happen.
|
||||
log.severe("dec request for Go object "+ refnum);
|
||||
return;
|
||||
}
|
||||
if (refnum == Seq.nullRef.refnum) {
|
||||
return;
|
||||
}
|
||||
// Java objects are removed on request of Go.
|
||||
Ref obj = javaObjs.get(refnum);
|
||||
if (obj == null) {
|
||||
throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
|
||||
}
|
||||
obj.refcnt--;
|
||||
if (obj.refcnt <= 0) {
|
||||
javaObjs.remove(refnum);
|
||||
javaRefs.remove(obj.obj);
|
||||
}
|
||||
}
|
||||
|
||||
// get returns an existing Ref to a Java object.
|
||||
synchronized Ref get(int refnum) {
|
||||
if (refnum < 0) {
|
||||
throw new RuntimeException("ref called with Go refnum " + refnum);
|
||||
}
|
||||
if (refnum == NULL_REFNUM) {
|
||||
return nullRef;
|
||||
}
|
||||
Ref ref = javaObjs.get(refnum);
|
||||
if (ref == null) {
|
||||
throw new RuntimeException("unknown java Ref: "+refnum);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
// GoRefQueue is a queue of GoRefs that are no longer live. An internal thread
|
||||
// processes the queue and decrement the reference count on the Go side.
|
||||
static class GoRefQueue extends ReferenceQueue<GoObject> {
|
||||
// The set of tracked GoRefs. If we don't hold on to the GoRef instances, the Java GC
|
||||
// will not add them to the queue when their referents are reclaimed.
|
||||
private final Collection<GoRef> refs = Collections.synchronizedCollection(new HashSet<GoRef>());
|
||||
|
||||
void track(int refnum, GoObject obj) {
|
||||
refs.add(new GoRef(refnum, obj, this));
|
||||
}
|
||||
|
||||
GoRefQueue() {
|
||||
Thread daemon = new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
GoRef ref = (GoRef)remove();
|
||||
refs.remove(ref);
|
||||
destroyRef(ref.refnum);
|
||||
ref.clear();
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
daemon.setDaemon(true);
|
||||
daemon.setName("GoRefQueue Finalizer Thread");
|
||||
daemon.start();
|
||||
}
|
||||
}
|
||||
|
||||
// A GoRef is a PhantomReference to a Java proxy for a Go object.
|
||||
// GoRefs are enqueued to the singleton GoRefQueue when no longer live,
|
||||
// so the corresponding reference count can be decremented.
|
||||
static class GoRef extends PhantomReference<GoObject> {
|
||||
final int refnum;
|
||||
|
||||
GoRef(int refnum, GoObject obj, GoRefQueue q) {
|
||||
super(obj, q);
|
||||
if (refnum > 0) {
|
||||
throw new RuntimeException("GoRef instantiated with a Java refnum " + refnum);
|
||||
}
|
||||
this.refnum = refnum;
|
||||
}
|
||||
}
|
||||
|
||||
// RefMap is a mapping of integers to Ref objects.
|
||||
//
|
||||
// The integers can be sparse. In Go this would be a map[int]*Ref.
|
||||
static final class RefMap {
|
||||
private int next = 0;
|
||||
private int live = 0;
|
||||
private int[] keys = new int[16];
|
||||
private Ref[] objs = new Ref[16];
|
||||
|
||||
RefMap() {}
|
||||
|
||||
Ref get(int key) {
|
||||
int i = Arrays.binarySearch(keys, 0, next, key);
|
||||
if (i >= 0) {
|
||||
return objs[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void remove(int key) {
|
||||
int i = Arrays.binarySearch(keys, 0, next, key);
|
||||
if (i >= 0) {
|
||||
if (objs[i] != null) {
|
||||
objs[i] = null;
|
||||
live--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void put(int key, Ref obj) {
|
||||
if (obj == null) {
|
||||
throw new RuntimeException("put a null ref (with key "+key+")");
|
||||
}
|
||||
int i = Arrays.binarySearch(keys, 0, next, key);
|
||||
if (i >= 0) {
|
||||
if (objs[i] == null) {
|
||||
objs[i] = obj;
|
||||
live++;
|
||||
}
|
||||
if (objs[i] != obj) {
|
||||
throw new RuntimeException("replacing an existing ref (with key "+key+")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (next >= keys.length) {
|
||||
grow();
|
||||
i = Arrays.binarySearch(keys, 0, next, key);
|
||||
}
|
||||
i = ~i;
|
||||
if (i < next) {
|
||||
// Insert, shift everything afterwards down.
|
||||
System.arraycopy(keys, i, keys, i+1, next-i);
|
||||
System.arraycopy(objs, i, objs, i+1, next-i);
|
||||
}
|
||||
keys[i] = key;
|
||||
objs[i] = obj;
|
||||
live++;
|
||||
next++;
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
// Compact and (if necessary) grow backing store.
|
||||
int[] newKeys;
|
||||
Ref[] newObjs;
|
||||
int len = 2*roundPow2(live);
|
||||
if (len > keys.length) {
|
||||
newKeys = new int[keys.length*2];
|
||||
newObjs = new Ref[objs.length*2];
|
||||
} else {
|
||||
newKeys = keys;
|
||||
newObjs = objs;
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
if (objs[i] != null) {
|
||||
newKeys[j] = keys[i];
|
||||
newObjs[j] = objs[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for (int i = j; i < newKeys.length; i++) {
|
||||
newKeys[i] = 0;
|
||||
newObjs[i] = null;
|
||||
}
|
||||
|
||||
keys = newKeys;
|
||||
objs = newObjs;
|
||||
next = j;
|
||||
|
||||
if (live != next) {
|
||||
throw new RuntimeException("bad state: live="+live+", next="+next);
|
||||
}
|
||||
}
|
||||
|
||||
private static int roundPow2(int x) {
|
||||
int p = 1;
|
||||
while (p < x) {
|
||||
p *= 2;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// Java class go.Universe is a proxy for talking to a Go program.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric
|
||||
package go;
|
||||
|
||||
import go.Seq;
|
||||
|
||||
public abstract class Universe {
|
||||
static {
|
||||
Seq.touch(); // for loading the native library
|
||||
_init();
|
||||
}
|
||||
|
||||
private Universe() {} // uninstantiable
|
||||
|
||||
// touch is called from other bound packages to initialize this package
|
||||
public static void touch() {}
|
||||
|
||||
private static native void _init();
|
||||
|
||||
private static final class proxyerror extends Exception implements Seq.Proxy, error {
|
||||
private final int refnum;
|
||||
|
||||
@Override public final int incRefnum() {
|
||||
Seq.incGoRef(refnum, this);
|
||||
return refnum;
|
||||
}
|
||||
|
||||
proxyerror(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
|
||||
|
||||
@Override public String getMessage() { return error(); }
|
||||
|
||||
public native String error();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// Java class go.error is a proxy for talking to a Go program.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric
|
||||
package go;
|
||||
|
||||
import go.Seq;
|
||||
|
||||
public interface error {
|
||||
public String error();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// Java class su.cin.rapvpn.fabric.fabricvpn.Fabricvpn is a proxy for talking to a Go program.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric github.com/example/remote-access-platform/agents/rap-node-agent/mobile/fabricvpn
|
||||
package su.cin.rapvpn.fabric.fabricvpn;
|
||||
|
||||
import go.Seq;
|
||||
|
||||
public abstract class Fabricvpn {
|
||||
static {
|
||||
Seq.touch(); // for loading the native library
|
||||
_init();
|
||||
}
|
||||
|
||||
private Fabricvpn() {} // uninstantiable
|
||||
|
||||
// touch is called from other bound packages to initialize this package
|
||||
public static void touch() {}
|
||||
|
||||
private static native void _init();
|
||||
|
||||
private static final class proxySocketProtector implements Seq.Proxy, SocketProtector {
|
||||
private final int refnum;
|
||||
|
||||
@Override public final int incRefnum() {
|
||||
Seq.incGoRef(refnum, this);
|
||||
return refnum;
|
||||
}
|
||||
|
||||
proxySocketProtector(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
|
||||
|
||||
public native boolean protect(long fd);
|
||||
}
|
||||
|
||||
|
||||
public static native Manager newManager();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// Java class su.cin.rapvpn.fabric.fabricvpn.Manager is a proxy for talking to a Go program.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric github.com/example/remote-access-platform/agents/rap-node-agent/mobile/fabricvpn
|
||||
package su.cin.rapvpn.fabric.fabricvpn;
|
||||
|
||||
import go.Seq;
|
||||
|
||||
public final class Manager implements Seq.Proxy {
|
||||
static { Fabricvpn.touch(); }
|
||||
|
||||
private final int refnum;
|
||||
|
||||
@Override public final int incRefnum() {
|
||||
Seq.incGoRef(refnum, this);
|
||||
return refnum;
|
||||
}
|
||||
|
||||
public Manager() {
|
||||
this.refnum = __NewManager();
|
||||
Seq.trackGoRef(refnum, this);
|
||||
}
|
||||
|
||||
private static native int __NewManager();
|
||||
|
||||
Manager(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
|
||||
|
||||
public native String controlRequest(String payloadJSON) throws Exception;
|
||||
public native byte[] receivePacket(long timeoutMillis) throws Exception;
|
||||
public native byte[] receivePacketBatchPayload(long timeoutMillis) throws Exception;
|
||||
public native void reconnect() throws Exception;
|
||||
public native void sendPacket(byte[] packet) throws Exception;
|
||||
public native void sendPacketBatchPayload(byte[] payload) throws Exception;
|
||||
public native void setSocketProtector(SocketProtector protector);
|
||||
public native String snapshotJSON();
|
||||
public native void start(String configJSON) throws Exception;
|
||||
public native void stop();
|
||||
public native void updateRuntimeConfig(String configJSON) throws Exception;
|
||||
@Override public boolean equals(Object o) {
|
||||
if (o == null || !(o instanceof Manager)) {
|
||||
return false;
|
||||
}
|
||||
Manager that = (Manager)o;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return java.util.Arrays.hashCode(new Object[] {});
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append("Manager").append("{");
|
||||
return b.append("}").toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// Java class su.cin.rapvpn.fabric.fabricvpn.SocketProtector is a proxy for talking to a Go program.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric github.com/example/remote-access-platform/agents/rap-node-agent/mobile/fabricvpn
|
||||
package su.cin.rapvpn.fabric.fabricvpn;
|
||||
|
||||
import go.Seq;
|
||||
|
||||
public interface SocketProtector {
|
||||
public boolean protect(long fd);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// JNI functions for the Go <=> Java bridge.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric github.com/example/remote-access-platform/agents/rap-node-agent/mobile/fabricvpn
|
||||
|
||||
#include <android/log.h>
|
||||
#include <stdint.h>
|
||||
#include "seq.h"
|
||||
#include "_cgo_export.h"
|
||||
#include "fabricvpn.h"
|
||||
|
||||
jclass proxy_class_fabricvpn_SocketProtector;
|
||||
jmethodID proxy_class_fabricvpn_SocketProtector_cons;
|
||||
static jmethodID mid_SocketProtector_Protect;
|
||||
jclass proxy_class_fabricvpn_Manager;
|
||||
jmethodID proxy_class_fabricvpn_Manager_cons;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Fabricvpn__1init(JNIEnv *env, jclass _unused) {
|
||||
jclass clazz;
|
||||
clazz = (*env)->FindClass(env, "su/cin/rapvpn/fabric/fabricvpn/Manager");
|
||||
proxy_class_fabricvpn_Manager = (*env)->NewGlobalRef(env, clazz);
|
||||
proxy_class_fabricvpn_Manager_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
|
||||
clazz = (*env)->FindClass(env, "su/cin/rapvpn/fabric/fabricvpn/Fabricvpn$proxySocketProtector");
|
||||
proxy_class_fabricvpn_SocketProtector = (*env)->NewGlobalRef(env, clazz);
|
||||
proxy_class_fabricvpn_SocketProtector_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
|
||||
clazz = (*env)->FindClass(env, "su/cin/rapvpn/fabric/fabricvpn/SocketProtector");
|
||||
mid_SocketProtector_Protect = (*env)->GetMethodID(env, clazz, "protect", "(J)Z");
|
||||
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Fabricvpn_newManager(JNIEnv* env, jclass _clazz) {
|
||||
int32_t r0 = proxyfabricvpn__NewManager();
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_fabricvpn_Manager, proxy_class_fabricvpn_Manager_cons);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager__1_1NewManager(JNIEnv *env, jclass clazz) {
|
||||
int32_t refnum = proxyfabricvpn__NewManager();
|
||||
return refnum;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_controlRequest(JNIEnv* env, jobject __this__, jstring payloadJSON) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nstring _payloadJSON = go_seq_from_java_string(env, payloadJSON);
|
||||
struct proxyfabricvpn_Manager_ControlRequest_return res = proxyfabricvpn_Manager_ControlRequest(o, _payloadJSON);
|
||||
jstring _r0 = go_seq_to_java_string(env, res.r0);
|
||||
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r1);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_receivePacket(JNIEnv* env, jobject __this__, jlong timeoutMillis) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nint _timeoutMillis = (nint)timeoutMillis;
|
||||
struct proxyfabricvpn_Manager_ReceivePacket_return res = proxyfabricvpn_Manager_ReceivePacket(o, _timeoutMillis);
|
||||
jbyteArray _r0 = go_seq_to_java_bytearray(env, res.r0, 1);
|
||||
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r1);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_receivePacketBatchPayload(JNIEnv* env, jobject __this__, jlong timeoutMillis) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nint _timeoutMillis = (nint)timeoutMillis;
|
||||
struct proxyfabricvpn_Manager_ReceivePacketBatchPayload_return res = proxyfabricvpn_Manager_ReceivePacketBatchPayload(o, _timeoutMillis);
|
||||
jbyteArray _r0 = go_seq_to_java_bytearray(env, res.r0, 1);
|
||||
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r1);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_reconnect(JNIEnv* env, jobject __this__) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
int32_t r0 = proxyfabricvpn_Manager_Reconnect(o);
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r0);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_sendPacket(JNIEnv* env, jobject __this__, jbyteArray packet) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nbyteslice _packet = go_seq_from_java_bytearray(env, packet, 0);
|
||||
int32_t r0 = proxyfabricvpn_Manager_SendPacket(o, _packet);
|
||||
go_seq_release_byte_array(env, packet, _packet.ptr);
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r0);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_sendPacketBatchPayload(JNIEnv* env, jobject __this__, jbyteArray payload) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nbyteslice _payload = go_seq_from_java_bytearray(env, payload, 0);
|
||||
int32_t r0 = proxyfabricvpn_Manager_SendPacketBatchPayload(o, _payload);
|
||||
go_seq_release_byte_array(env, payload, _payload.ptr);
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r0);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_setSocketProtector(JNIEnv* env, jobject __this__, jobject protector) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
int32_t _protector = go_seq_to_refnum(env, protector);
|
||||
proxyfabricvpn_Manager_SetSocketProtector(o, _protector);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_snapshotJSON(JNIEnv* env, jobject __this__) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nstring r0 = proxyfabricvpn_Manager_SnapshotJSON(o);
|
||||
jstring _r0 = go_seq_to_java_string(env, r0);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_start(JNIEnv* env, jobject __this__, jstring configJSON) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nstring _configJSON = go_seq_from_java_string(env, configJSON);
|
||||
int32_t r0 = proxyfabricvpn_Manager_Start(o, _configJSON);
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r0);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_stop(JNIEnv* env, jobject __this__) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
proxyfabricvpn_Manager_Stop(o);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Manager_updateRuntimeConfig(JNIEnv* env, jobject __this__, jstring configJSON) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nstring _configJSON = go_seq_from_java_string(env, configJSON);
|
||||
int32_t r0 = proxyfabricvpn_Manager_UpdateRuntimeConfig(o, _configJSON);
|
||||
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
|
||||
go_seq_maybe_throw_exception(env, _r0);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_su_cin_rapvpn_fabric_fabricvpn_Fabricvpn_00024proxySocketProtector_protect(JNIEnv* env, jobject __this__, jlong fd) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
int64_t _fd = (int64_t)fd;
|
||||
char r0 = proxyfabricvpn_SocketProtector_Protect(o, _fd);
|
||||
jboolean _r0 = r0 ? JNI_TRUE : JNI_FALSE;
|
||||
return _r0;
|
||||
}
|
||||
|
||||
char cproxyfabricvpn_SocketProtector_Protect(int32_t refnum, int64_t fd) {
|
||||
JNIEnv *env = go_seq_push_local_frame(1);
|
||||
jobject o = go_seq_from_refnum(env, refnum, proxy_class_fabricvpn_SocketProtector, proxy_class_fabricvpn_SocketProtector_cons);
|
||||
jlong _fd = (jlong)fd;
|
||||
jboolean res = (*env)->CallBooleanMethod(env, o, mid_SocketProtector_Protect, _fd);
|
||||
char _res = (char)res;
|
||||
go_seq_pop_local_frame(env);
|
||||
return _res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// JNI function headers for the Go <=> Java bridge.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric github.com/example/remote-access-platform/agents/rap-node-agent/mobile/fabricvpn
|
||||
|
||||
#ifndef __Fabricvpn_H__
|
||||
#define __Fabricvpn_H__
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
extern jclass proxy_class_fabricvpn_SocketProtector;
|
||||
extern jmethodID proxy_class_fabricvpn_SocketProtector_cons;
|
||||
|
||||
char cproxyfabricvpn_SocketProtector_Protect(int32_t refnum, int64_t fd);
|
||||
|
||||
extern jclass proxy_class_fabricvpn_Manager;
|
||||
extern jmethodID proxy_class_fabricvpn_Manager_cons;
|
||||
#endif
|
||||
@@ -0,0 +1,401 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// C support functions for bindings. This file is copied into the
|
||||
// generated gomobile_bind package and compiled along with the
|
||||
// generated binding files.
|
||||
|
||||
#include <android/log.h>
|
||||
#include <errno.h>
|
||||
#include <jni.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include "seq.h"
|
||||
#include "_cgo_export.h"
|
||||
|
||||
#define NULL_REFNUM 41
|
||||
|
||||
// initClasses are only exported from Go if reverse bindings are used.
|
||||
// If they're not, weakly define a no-op function.
|
||||
__attribute__((weak)) void initClasses(void) { }
|
||||
|
||||
static JavaVM *jvm;
|
||||
// jnienvs holds the per-thread JNIEnv* for Go threads where we called AttachCurrentThread.
|
||||
// A pthread key destructor is supplied to call DetachCurrentThread on exit. This trick is
|
||||
// documented in http://developer.android.com/training/articles/perf-jni.html under "Threads".
|
||||
static pthread_key_t jnienvs;
|
||||
|
||||
static jclass seq_class;
|
||||
static jmethodID seq_getRef;
|
||||
static jmethodID seq_decRef;
|
||||
static jmethodID seq_incRef;
|
||||
static jmethodID seq_incGoObjectRef;
|
||||
static jmethodID seq_incRefnum;
|
||||
|
||||
static jfieldID ref_objField;
|
||||
|
||||
static jclass throwable_class;
|
||||
|
||||
// env_destructor is registered as a thread data key destructor to
|
||||
// clean up a Go thread that is attached to the JVM.
|
||||
static void env_destructor(void *env) {
|
||||
if ((*jvm)->DetachCurrentThread(jvm) != JNI_OK) {
|
||||
LOG_INFO("failed to detach current thread");
|
||||
}
|
||||
}
|
||||
|
||||
static JNIEnv *go_seq_get_thread_env(void) {
|
||||
JNIEnv *env;
|
||||
jint ret = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_6);
|
||||
if (ret != JNI_OK) {
|
||||
if (ret != JNI_EDETACHED) {
|
||||
LOG_FATAL("failed to get thread env");
|
||||
}
|
||||
if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) != JNI_OK) {
|
||||
LOG_FATAL("failed to attach current thread");
|
||||
}
|
||||
pthread_setspecific(jnienvs, env);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
void go_seq_maybe_throw_exception(JNIEnv *env, jobject exc) {
|
||||
if (exc != NULL) {
|
||||
(*env)->Throw(env, exc);
|
||||
}
|
||||
}
|
||||
|
||||
jobject go_seq_get_exception(JNIEnv *env) {
|
||||
jthrowable exc = (*env)->ExceptionOccurred(env);
|
||||
if (!exc) {
|
||||
return NULL;
|
||||
}
|
||||
(*env)->ExceptionClear(env);
|
||||
return exc;
|
||||
}
|
||||
|
||||
jbyteArray go_seq_to_java_bytearray(JNIEnv *env, nbyteslice s, int copy) {
|
||||
if (s.ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
jbyteArray res = (*env)->NewByteArray(env, s.len);
|
||||
if (res == NULL) {
|
||||
LOG_FATAL("NewByteArray failed");
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, res, 0, s.len, s.ptr);
|
||||
if (copy) {
|
||||
free(s.ptr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#define surr1 0xd800
|
||||
#define surr2 0xdc00
|
||||
#define surr3 0xe000
|
||||
|
||||
// Unicode replacement character
|
||||
#define replacementChar 0xFFFD
|
||||
|
||||
#define rune1Max ((1<<7) - 1)
|
||||
#define rune2Max ((1<<11) - 1)
|
||||
#define rune3Max ((1<<16) - 1)
|
||||
// Maximum valid Unicode code point.
|
||||
#define MaxRune 0x0010FFFF
|
||||
|
||||
#define surrogateMin 0xD800
|
||||
#define surrogateMax 0xDFFF
|
||||
// 0011 1111
|
||||
#define maskx 0x3F
|
||||
// 1000 0000
|
||||
#define tx 0x80
|
||||
// 1100 0000
|
||||
#define t2 0xC0
|
||||
// 1110 0000
|
||||
#define t3 0xE0
|
||||
// 1111 0000
|
||||
#define t4 0xF0
|
||||
|
||||
// encode_rune writes into p (which must be large enough) the UTF-8 encoding
|
||||
// of the rune. It returns the number of bytes written.
|
||||
static int encode_rune(uint8_t *p, uint32_t r) {
|
||||
if (r <= rune1Max) {
|
||||
p[0] = (uint8_t)r;
|
||||
return 1;
|
||||
} else if (r <= rune2Max) {
|
||||
p[0] = t2 | (uint8_t)(r>>6);
|
||||
p[1] = tx | (((uint8_t)(r))&maskx);
|
||||
return 2;
|
||||
} else {
|
||||
if (r > MaxRune || (surrogateMin <= r && r <= surrogateMax)) {
|
||||
r = replacementChar;
|
||||
}
|
||||
if (r <= rune3Max) {
|
||||
p[0] = t3 | (uint8_t)(r>>12);
|
||||
p[1] = tx | (((uint8_t)(r>>6))&maskx);
|
||||
p[2] = tx | (((uint8_t)(r))&maskx);
|
||||
return 3;
|
||||
} else {
|
||||
p[0] = t4 | (uint8_t)(r>>18);
|
||||
p[1] = tx | (((uint8_t)(r>>12))&maskx);
|
||||
p[2] = tx | (((uint8_t)(r>>6))&maskx);
|
||||
p[3] = tx | (((uint8_t)(r))&maskx);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// utf16_decode decodes an array of UTF16 characters to a UTF-8 encoded
|
||||
// nstring copy. The support functions and utf16_decode itself are heavily
|
||||
// based on the unicode/utf8 and unicode/utf16 Go packages.
|
||||
static nstring utf16_decode(jchar *chars, jsize len) {
|
||||
jsize worstCaseLen = 4*len;
|
||||
uint8_t *buf = malloc(worstCaseLen);
|
||||
if (buf == NULL) {
|
||||
LOG_FATAL("utf16Decode: malloc failed");
|
||||
}
|
||||
jsize nsrc = 0;
|
||||
jsize ndst = 0;
|
||||
while (nsrc < len) {
|
||||
uint32_t r = chars[nsrc];
|
||||
nsrc++;
|
||||
if (surr1 <= r && r < surr2 && nsrc < len) {
|
||||
uint32_t r2 = chars[nsrc];
|
||||
if (surr2 <= r2 && r2 < surr3) {
|
||||
nsrc++;
|
||||
r = (((r-surr1)<<10) | (r2 - surr2)) + 0x10000;
|
||||
}
|
||||
}
|
||||
if (ndst + 4 > worstCaseLen) {
|
||||
LOG_FATAL("utf16Decode: buffer overflow");
|
||||
}
|
||||
ndst += encode_rune(buf + ndst, r);
|
||||
}
|
||||
struct nstring res = {.chars = buf, .len = ndst};
|
||||
return res;
|
||||
}
|
||||
|
||||
nstring go_seq_from_java_string(JNIEnv *env, jstring str) {
|
||||
struct nstring res = {NULL, 0};
|
||||
if (str == NULL) {
|
||||
return res;
|
||||
}
|
||||
jsize nchars = (*env)->GetStringLength(env, str);
|
||||
if (nchars == 0) {
|
||||
return res;
|
||||
}
|
||||
jchar *chars = (jchar *)(*env)->GetStringChars(env, str, NULL);
|
||||
if (chars == NULL) {
|
||||
LOG_FATAL("GetStringChars failed");
|
||||
}
|
||||
nstring nstr = utf16_decode(chars, nchars);
|
||||
(*env)->ReleaseStringChars(env, str, chars);
|
||||
return nstr;
|
||||
}
|
||||
|
||||
nbyteslice go_seq_from_java_bytearray(JNIEnv *env, jbyteArray arr, int copy) {
|
||||
struct nbyteslice res = {NULL, 0};
|
||||
if (arr == NULL) {
|
||||
return res;
|
||||
}
|
||||
|
||||
jsize len = (*env)->GetArrayLength(env, arr);
|
||||
if (len == 0) {
|
||||
return res;
|
||||
}
|
||||
jbyte *ptr = (*env)->GetByteArrayElements(env, arr, NULL);
|
||||
if (ptr == NULL) {
|
||||
LOG_FATAL("GetByteArrayElements failed");
|
||||
}
|
||||
if (copy) {
|
||||
void *ptr_copy = (void *)malloc(len);
|
||||
if (ptr_copy == NULL) {
|
||||
LOG_FATAL("malloc failed");
|
||||
}
|
||||
memcpy(ptr_copy, ptr, len);
|
||||
(*env)->ReleaseByteArrayElements(env, arr, ptr, JNI_ABORT);
|
||||
ptr = (jbyte *)ptr_copy;
|
||||
}
|
||||
res.ptr = ptr;
|
||||
res.len = len;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t go_seq_to_refnum_go(JNIEnv *env, jobject o) {
|
||||
if (o == NULL) {
|
||||
return NULL_REFNUM;
|
||||
}
|
||||
return (int32_t)(*env)->CallStaticIntMethod(env, seq_class, seq_incGoObjectRef, o);
|
||||
}
|
||||
|
||||
int32_t go_seq_to_refnum(JNIEnv *env, jobject o) {
|
||||
if (o == NULL) {
|
||||
return NULL_REFNUM;
|
||||
}
|
||||
return (int32_t)(*env)->CallStaticIntMethod(env, seq_class, seq_incRef, o);
|
||||
}
|
||||
|
||||
int32_t go_seq_unwrap(jint refnum) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jobject jobj = go_seq_from_refnum(env, refnum, NULL, NULL);
|
||||
int32_t goref = go_seq_to_refnum_go(env, jobj);
|
||||
go_seq_pop_local_frame(env);
|
||||
return goref;
|
||||
}
|
||||
|
||||
jobject go_seq_from_refnum(JNIEnv *env, int32_t refnum, jclass proxy_class, jmethodID proxy_cons) {
|
||||
if (refnum == NULL_REFNUM) {
|
||||
return NULL;
|
||||
}
|
||||
if (refnum < 0) { // Go object
|
||||
// return new <Proxy>(refnum)
|
||||
return (*env)->NewObject(env, proxy_class, proxy_cons, refnum);
|
||||
}
|
||||
// Seq.Ref ref = Seq.getRef(refnum)
|
||||
jobject ref = (*env)->CallStaticObjectMethod(env, seq_class, seq_getRef, (jint)refnum);
|
||||
if (ref == NULL) {
|
||||
LOG_FATAL("Unknown reference: %d", refnum);
|
||||
}
|
||||
// Go incremented the reference count just before passing the refnum. Decrement it here.
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)refnum);
|
||||
// return ref.obj
|
||||
return (*env)->GetObjectField(env, ref, ref_objField);
|
||||
}
|
||||
|
||||
// go_seq_to_java_string converts a nstring to a jstring.
|
||||
jstring go_seq_to_java_string(JNIEnv *env, nstring str) {
|
||||
jstring s = (*env)->NewString(env, str.chars, str.len/2);
|
||||
if (str.chars != NULL) {
|
||||
free(str.chars);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// go_seq_push_local_frame retrieves or creates the JNIEnv* for the current thread
|
||||
// and pushes a JNI reference frame. Must be matched with call to go_seq_pop_local_frame.
|
||||
JNIEnv *go_seq_push_local_frame(jint nargs) {
|
||||
JNIEnv *env = go_seq_get_thread_env();
|
||||
// Given the number of function arguments, compute a conservative bound for the minimal frame size.
|
||||
// Assume two slots for each per parameter (Seq.Ref and Seq.Object) and add extra
|
||||
// extra space for the receiver, the return value, and exception (if any).
|
||||
jint frameSize = 2*nargs + 10;
|
||||
if ((*env)->PushLocalFrame(env, frameSize) < 0) {
|
||||
LOG_FATAL("PushLocalFrame failed");
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
// Pop the current local frame, freeing all JNI local references in it
|
||||
void go_seq_pop_local_frame(JNIEnv *env) {
|
||||
(*env)->PopLocalFrame(env, NULL);
|
||||
}
|
||||
|
||||
void go_seq_inc_ref(int32_t ref) {
|
||||
JNIEnv *env = go_seq_get_thread_env();
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_incRefnum, (jint)ref);
|
||||
}
|
||||
|
||||
void go_seq_dec_ref(int32_t ref) {
|
||||
JNIEnv *env = go_seq_get_thread_env();
|
||||
(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)ref);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_go_Seq_init(JNIEnv *env, jclass clazz) {
|
||||
if ((*env)->GetJavaVM(env, &jvm) != 0) {
|
||||
LOG_FATAL("failed to get JVM");
|
||||
}
|
||||
if (pthread_key_create(&jnienvs, env_destructor) != 0) {
|
||||
LOG_FATAL("failed to initialize jnienvs thread local storage");
|
||||
}
|
||||
|
||||
seq_class = (*env)->NewGlobalRef(env, clazz);
|
||||
seq_getRef = (*env)->GetStaticMethodID(env, seq_class, "getRef", "(I)Lgo/Seq$Ref;");
|
||||
if (seq_getRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.getRef");
|
||||
}
|
||||
seq_decRef = (*env)->GetStaticMethodID(env, seq_class, "decRef", "(I)V");
|
||||
if (seq_decRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.decRef");
|
||||
}
|
||||
seq_incRefnum = (*env)->GetStaticMethodID(env, seq_class, "incRefnum", "(I)V");
|
||||
if (seq_incRefnum == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incRefnum");
|
||||
}
|
||||
seq_incRef = (*env)->GetStaticMethodID(env, seq_class, "incRef", "(Ljava/lang/Object;)I");
|
||||
if (seq_incRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incRef");
|
||||
}
|
||||
seq_incGoObjectRef = (*env)->GetStaticMethodID(env, seq_class, "incGoObjectRef", "(Lgo/Seq$GoObject;)I");
|
||||
if (seq_incGoObjectRef == NULL) {
|
||||
LOG_FATAL("failed to find method Seq.incGoObjectRef");
|
||||
}
|
||||
jclass ref_class = (*env)->FindClass(env, "go/Seq$Ref");
|
||||
if (ref_class == NULL) {
|
||||
LOG_FATAL("failed to find the Seq.Ref class");
|
||||
}
|
||||
ref_objField = (*env)->GetFieldID(env, ref_class, "obj", "Ljava/lang/Object;");
|
||||
if (ref_objField == NULL) {
|
||||
LOG_FATAL("failed to find the Seq.Ref.obj field");
|
||||
}
|
||||
initClasses();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_go_Seq_destroyRef(JNIEnv *env, jclass clazz, jint refnum) {
|
||||
DestroyRef(refnum);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_go_Seq_incGoRef(JNIEnv *env, jclass clazz, jint refnum, jobject ref) {
|
||||
IncGoRef(refnum);
|
||||
}
|
||||
|
||||
jclass go_seq_find_class(const char *name) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jclass clazz = (*env)->FindClass(env, name);
|
||||
if (clazz == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
} else {
|
||||
clazz = (*env)->NewGlobalRef(env, clazz);
|
||||
}
|
||||
go_seq_pop_local_frame(env);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
jmethodID go_seq_get_static_method_id(jclass clazz, const char *name, const char *sig) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig);
|
||||
if (m == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
go_seq_pop_local_frame(env);
|
||||
return m;
|
||||
}
|
||||
|
||||
jmethodID go_seq_get_method_id(jclass clazz, const char *name, const char *sig) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
|
||||
if (m == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
go_seq_pop_local_frame(env);
|
||||
return m;
|
||||
}
|
||||
|
||||
void go_seq_release_byte_array(JNIEnv *env, jbyteArray arr, jbyte* ptr) {
|
||||
if (ptr != NULL) {
|
||||
(*env)->ReleaseByteArrayElements(env, arr, ptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int go_seq_isinstanceof(jint refnum, jclass clazz) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jobject obj = go_seq_from_refnum(env, refnum, NULL, NULL);
|
||||
jboolean isinst = (*env)->IsInstanceOf(env, obj, clazz);
|
||||
go_seq_pop_local_frame(env);
|
||||
return isinst;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// Go support functions for bindings. This file is copied into the
|
||||
// generated main package and compiled along with the generated binding
|
||||
// files.
|
||||
|
||||
//#cgo CFLAGS: -Werror
|
||||
//#cgo LDFLAGS: -llog
|
||||
//#include <jni.h>
|
||||
//#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include "seq_android.h"
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/mobile/bind/seq"
|
||||
)
|
||||
|
||||
// DestroyRef is called by Java to inform Go it is done with a reference.
|
||||
//export DestroyRef
|
||||
func DestroyRef(refnum C.int32_t) {
|
||||
seq.Delete(int32(refnum))
|
||||
}
|
||||
|
||||
// encodeString returns a copy of a Go string as a UTF16 encoded nstring.
|
||||
// The returned data is freed in go_seq_to_java_string.
|
||||
//
|
||||
// encodeString uses UTF16 as the intermediate format. Note that UTF8 is an obvious
|
||||
// alternative, but JNI only supports a C-safe variant of UTF8 (modified UTF8).
|
||||
func encodeString(s string) C.nstring {
|
||||
n := C.int(len(s))
|
||||
if n == 0 {
|
||||
return C.nstring{}
|
||||
}
|
||||
// Allocate enough for the worst case estimate, every character is a surrogate pair
|
||||
worstCaseLen := 4 * len(s)
|
||||
utf16buf := C.malloc(C.size_t(worstCaseLen))
|
||||
if utf16buf == nil {
|
||||
panic("encodeString: malloc failed")
|
||||
}
|
||||
chars := (*[1<<30 - 1]uint16)(unsafe.Pointer(utf16buf))[:worstCaseLen/2 : worstCaseLen/2]
|
||||
nchars := seq.UTF16Encode(s, chars)
|
||||
return C.nstring{chars: unsafe.Pointer(utf16buf), len: C.jsize(nchars*2)}
|
||||
}
|
||||
|
||||
// decodeString decodes a UTF8 encoded nstring to a Go string. The data
|
||||
// in str is freed after use.
|
||||
func decodeString(str C.nstring) string {
|
||||
if str.chars == nil {
|
||||
return ""
|
||||
}
|
||||
chars := (*[1<<31 - 1]byte)(str.chars)[:str.len]
|
||||
s := string(chars)
|
||||
C.free(str.chars)
|
||||
return s
|
||||
}
|
||||
|
||||
// fromSlice converts a slice to a jbyteArray cast as a nbyteslice. If cpy
|
||||
// is set, the returned slice is a copy to be free by go_seq_to_java_bytearray.
|
||||
func fromSlice(s []byte, cpy bool) C.nbyteslice {
|
||||
if s == nil || len(s) == 0 {
|
||||
return C.nbyteslice{}
|
||||
}
|
||||
var ptr *C.jbyte
|
||||
n := C.jsize(len(s))
|
||||
if cpy {
|
||||
ptr = (*C.jbyte)(C.malloc(C.size_t(n)))
|
||||
if ptr == nil {
|
||||
panic("fromSlice: malloc failed")
|
||||
}
|
||||
copy((*[1<<31 - 1]byte)(unsafe.Pointer(ptr))[:n], s)
|
||||
} else {
|
||||
ptr = (*C.jbyte)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
return C.nbyteslice{ptr: unsafe.Pointer(ptr), len: n}
|
||||
}
|
||||
|
||||
// toSlice takes a nbyteslice (jbyteArray) and returns a byte slice
|
||||
// with the data. If cpy is set, the slice contains a copy of the data and is
|
||||
// freed.
|
||||
func toSlice(s C.nbyteslice, cpy bool) []byte {
|
||||
if s.ptr == nil || s.len == 0 {
|
||||
return nil
|
||||
}
|
||||
var b []byte
|
||||
if cpy {
|
||||
b = C.GoBytes(s.ptr, C.int(s.len))
|
||||
C.free(s.ptr)
|
||||
} else {
|
||||
b = (*[1<<31 - 1]byte)(unsafe.Pointer(s.ptr))[:s.len:s.len]
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#ifndef __GO_SEQ_ANDROID_HDR__
|
||||
#define __GO_SEQ_ANDROID_HDR__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <android/log.h>
|
||||
// For abort()
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "go/Seq", __VA_ARGS__)
|
||||
#define LOG_FATAL(...) \
|
||||
{ \
|
||||
__android_log_print(ANDROID_LOG_FATAL, "go/Seq", __VA_ARGS__); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
// Platform specific types
|
||||
typedef struct nstring {
|
||||
// UTF16 or UTF8 Encoded string. When converting from Java string to Go
|
||||
// string, UTF16. When converting from Go to Java, UTF8.
|
||||
void *chars;
|
||||
// length in bytes, regardless of encoding
|
||||
jsize len;
|
||||
} nstring;
|
||||
typedef struct nbyteslice {
|
||||
void *ptr;
|
||||
jsize len;
|
||||
} nbyteslice;
|
||||
typedef jlong nint;
|
||||
|
||||
extern void go_seq_dec_ref(int32_t ref);
|
||||
extern void go_seq_inc_ref(int32_t ref);
|
||||
// go_seq_unwrap takes a reference number to a Java wrapper and returns
|
||||
// a reference number to its wrapped Go object.
|
||||
extern int32_t go_seq_unwrap(jint refnum);
|
||||
extern int32_t go_seq_to_refnum(JNIEnv *env, jobject o);
|
||||
extern int32_t go_seq_to_refnum_go(JNIEnv *env, jobject o);
|
||||
extern jobject go_seq_from_refnum(JNIEnv *env, int32_t refnum, jclass proxy_class, jmethodID proxy_cons);
|
||||
|
||||
extern void go_seq_maybe_throw_exception(JNIEnv *env, jobject msg);
|
||||
// go_seq_get_exception returns any pending exception and clears the exception status.
|
||||
extern jobject go_seq_get_exception(JNIEnv *env);
|
||||
|
||||
extern jbyteArray go_seq_to_java_bytearray(JNIEnv *env, nbyteslice s, int copy);
|
||||
extern nbyteslice go_seq_from_java_bytearray(JNIEnv *env, jbyteArray s, int copy);
|
||||
extern void go_seq_release_byte_array(JNIEnv *env, jbyteArray arr, jbyte* ptr);
|
||||
|
||||
extern jstring go_seq_to_java_string(JNIEnv *env, nstring str);
|
||||
extern nstring go_seq_from_java_string(JNIEnv *env, jstring s);
|
||||
|
||||
// push_local_frame retrieves or creates the JNIEnv* for the current thread
|
||||
// and pushes a JNI reference frame. Must be matched with call to pop_local_frame.
|
||||
extern JNIEnv *go_seq_push_local_frame(jint cap);
|
||||
// Pop the current local frame, releasing all JNI local references in it
|
||||
extern void go_seq_pop_local_frame(JNIEnv *env);
|
||||
|
||||
// Return a global reference to the given class. Return NULL and clear exception if not found.
|
||||
extern jclass go_seq_find_class(const char *name);
|
||||
extern jmethodID go_seq_get_static_method_id(jclass clazz, const char *name, const char *sig);
|
||||
extern jmethodID go_seq_get_method_id(jclass clazz, const char *name, const char *sig);
|
||||
extern int go_seq_isinstanceof(jint refnum, jclass clazz);
|
||||
|
||||
#endif // __GO_SEQ_ANDROID_HDR__
|
||||
@@ -0,0 +1,43 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// JNI functions for the Go <=> Java bridge.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric
|
||||
|
||||
#include <android/log.h>
|
||||
#include <stdint.h>
|
||||
#include "seq.h"
|
||||
#include "_cgo_export.h"
|
||||
#include "universe.h"
|
||||
|
||||
jclass proxy_class__error;
|
||||
jmethodID proxy_class__error_cons;
|
||||
static jmethodID mid_error_Error;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_go_Universe__1init(JNIEnv *env, jclass _unused) {
|
||||
jclass clazz;
|
||||
clazz = (*env)->FindClass(env, "go/Universe$proxyerror");
|
||||
proxy_class__error = (*env)->NewGlobalRef(env, clazz);
|
||||
proxy_class__error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
|
||||
clazz = (*env)->FindClass(env, "java/lang/Throwable");
|
||||
mid_error_Error = (*env)->GetMethodID(env, clazz, "getMessage", "()Ljava/lang/String;");
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_go_Universe_00024proxyerror_error(JNIEnv* env, jobject __this__) {
|
||||
int32_t o = go_seq_to_refnum_go(env, __this__);
|
||||
nstring r0 = proxy_error_Error(o);
|
||||
jstring _r0 = go_seq_to_java_string(env, r0);
|
||||
return _r0;
|
||||
}
|
||||
|
||||
nstring cproxy_error_Error(int32_t refnum) {
|
||||
JNIEnv *env = go_seq_push_local_frame(0);
|
||||
jobject o = go_seq_from_refnum(env, refnum, proxy_class__error, proxy_class__error_cons);
|
||||
jstring res = (*env)->CallObjectMethod(env, o, mid_error_Error);
|
||||
nstring _res = go_seq_from_java_string(env, res);
|
||||
go_seq_pop_local_frame(env);
|
||||
return _res;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Code generated by gobind. DO NOT EDIT.
|
||||
|
||||
// JNI function headers for the Go <=> Java bridge.
|
||||
//
|
||||
// autogenerated by gobind -lang=java -javapkg=su.cin.rapvpn.fabric
|
||||
|
||||
#ifndef __Universe_H__
|
||||
#define __Universe_H__
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
extern jclass proxy_class__error;
|
||||
extern jmethodID proxy_class__error_cons;
|
||||
|
||||
nstring cproxy_error_Error(int32_t refnum);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user