рабочий вариант, но скороть 10 МБит
build / backend (push) Has been cancelled
build / node-agent (push) Has been cancelled
build / worker (push) Has been cancelled

This commit is contained in:
2026-05-22 21:46:49 +03:00
parent 469fa0e860
commit 20d361a886
280 changed files with 954890 additions and 18524 deletions
+400
View File
@@ -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