diff --git a/core/src/main/cpp/main.cpp b/core/src/main/cpp/main.cpp index ad0af54..0c8d83f 100644 --- a/core/src/main/cpp/main.cpp +++ b/core/src/main/cpp/main.cpp @@ -66,10 +66,10 @@ jobject Master::Context::newTraffic(long upload, long download) { return env->NewObject(master->cTraffic, master->cTrafficConstructor, upload, download); } -jobject Master::Context::newGeneral(std::string const &mode, int http, int socks, int redirect, +jobject Master::Context::newGeneral(char const *mode, int http, int socks, int redirect, int mixed) { return env->NewObject(master->cGeneral, master->cGeneralConstructor, - env->NewStringUTF(mode.c_str()), http, socks, redirect, mixed); + env->NewStringUTF(mode), http, socks, redirect, mixed); } jobject Master::Context::newCompletableFuture() { @@ -141,7 +141,7 @@ jobjectArray Master::Context::createProxyArray(int size, jobject elements[]) { return result; } -jobject Master::Context::createProxy(std::string const &name, proxy_type_t type, long delay) { +jobject Master::Context::createProxy(char const *name, proxy_type_t type, long delay) { jstring ts = nullptr; switch (type) { @@ -191,11 +191,11 @@ jobject Master::Context::createProxy(std::string const &name, proxy_type_t type, ts = master->sUnknown; } - return env->NewObject(master->cProxy, master->cProxyConstructor, env->NewStringUTF(name.c_str()), ts, delay); + return env->NewObject(master->cProxy, master->cProxyConstructor, env->NewStringUTF(name), ts, delay); } -jobject Master::Context::createProxyGroup(std::string const &name, proxy_type_t type, - std::string const ¤t, jobjectArray proxies) { +jobject Master::Context::createProxyGroup(char const *name, proxy_type_t type, + char const *current, jobjectArray proxies) { jstring ts = nullptr; switch (type) { @@ -221,7 +221,7 @@ jobject Master::Context::createProxyGroup(std::string const &name, proxy_type_t ts = master->sUnknown; } - return env->NewObject(master->cProxyGroup, master->cProxyGroupConstructor, env->NewStringUTF(name.c_str()), ts, env->NewStringUTF(current.c_str()), proxies); + return env->NewObject(master->cProxyGroup, master->cProxyGroupConstructor, env->NewStringUTF(name), ts, env->NewStringUTF(current), proxies); } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) { diff --git a/core/src/main/cpp/main.h b/core/src/main/cpp/main.h index 1cf1bd7..de7a73c 100644 --- a/core/src/main/cpp/main.h +++ b/core/src/main/cpp/main.h @@ -70,7 +70,7 @@ public: public: jthrowable newClashException(std::string const &message); jobject newTraffic(long upload, long download); - jobject newGeneral(std::string const &mode, int http, int socks, int redirect, int mixed); + jobject newGeneral(char const *mode, int http, int socks, int redirect, int mixed); jobject newCompletableFuture(); public: @@ -87,8 +87,8 @@ public: void tunCallbackStop(jobject callback); public: - jobject createProxy(std::string const &name, proxy_type_t type, long delay); - jobject createProxyGroup(std::string const &name, proxy_type_t type, std::string const ¤t, jobjectArray proxies); + jobject createProxy(char const *name, proxy_type_t type, long delay); + jobject createProxyGroup(char const *name, proxy_type_t type, char const *current, jobjectArray proxies); jobjectArray createProxyArray(int size, jobject elements[]); jobjectArray createProxyGroupArray(int size, jobject elements[]); const_buffer_t createConstBufferFromByteArray(jbyteArray array); diff --git a/core/src/main/cpp/query.cpp b/core/src/main/cpp/query.cpp index 2f9af8a..68c36a4 100644 --- a/core/src/main/cpp/query.cpp +++ b/core/src/main/cpp/query.cpp @@ -71,30 +71,29 @@ Java_com_github_kr328_clash_core_bridge_Bridge_queryProxyGroups(JNIEnv *env, jcl auto *jgroups = new jobject[list->size]; for (int group_index = 0 ; group_index < list->size ; group_index++ ) { - std::string now; + char const * now = ""; proxy_group_t *group = list->groups[group_index]; auto *jproxies = new jobject[group->proxies_size]; + const char *group_name = &list->string_pool[group->base.name_index]; for ( int proxy_index = 0 ; proxy_index < group->proxies_size ; proxy_index++ ) { proxy_t *proxy = &group->proxies[proxy_index]; + const char *name = &list->string_pool[proxy->name_index]; - jproxies[proxy_index] = context->createProxy(proxy->name, proxy->proxy_type, proxy->delay); + jproxies[proxy_index] = context->createProxy(name, proxy->proxy_type, proxy->delay); if ( proxy_index == group->now ) - now = proxy->name; - - free(proxy->name); + now = name; } jgroups[group_index] = context->createProxyGroup( - group->base.name, + group_name, group->base.proxy_type, now, context->createProxyArray(group->proxies_size, jproxies)); delete[] jproxies; - free(group->base.name); free(group); } @@ -102,6 +101,7 @@ Java_com_github_kr328_clash_core_bridge_Bridge_queryProxyGroups(JNIEnv *env, jcl delete[] jgroups; + free(list->string_pool); free(list); return result; diff --git a/core/src/main/golang/ccall.go b/core/src/main/golang/ccall.go index e618152..3cd39a2 100644 --- a/core/src/main/golang/ccall.go +++ b/core/src/main/golang/ccall.go @@ -9,7 +9,6 @@ import "C" import ( "runtime" "sync" - "sync/atomic" "unsafe" ) @@ -21,9 +20,10 @@ type ccallContext struct { argument unsafe.Pointer } -var ccallQueue chan *ccallContext +var ccallQueue = make(chan *ccallContext) var ccallMap sync.Map var currentIndex uint64 +var indexLock sync.Mutex func init() { C.initialize_ccall(C.int(runtime.NumCPU())) @@ -45,9 +45,12 @@ func callCcall(call nativeCcall, argument unsafe.Pointer) { func nextCcall(ccall *nativeCcall, argument *unsafe.Pointer, index *uint64) { ctx := <- ccallQueue - *index = atomic.AddUint64(¤tIndex, 1) + indexLock.Lock() + currentIndex++ + *index = currentIndex *ccall = ctx.call *argument = ctx.argument + indexLock.Unlock() ccallMap.Store(*index, ctx) } diff --git a/core/src/main/golang/proxies.go b/core/src/main/golang/proxies.go index d9f87c6..810af30 100644 --- a/core/src/main/golang/proxies.go +++ b/core/src/main/golang/proxies.go @@ -6,38 +6,13 @@ import ( "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel" + "unsafe" ) /* #cgo CFLAGS: -Werror #include "buffer.h" #include "proxies.h" - -#include - -static proxy_group_list_t *new_proxy_group_list_t(int size) { - proxy_group_list_t *result = (proxy_group_list_t *) malloc(sizeof(proxy_group_list_t) + size * sizeof(proxy_group_t*)); - - result->size = size; - - return result; -} - -static proxy_group_t *new_proxy_group_t(int proxies_size) { - proxy_group_t *result = (proxy_group_t *) malloc(sizeof(proxy_group_t) + proxies_size * sizeof(proxy_t)); - - result->proxies_size = proxies_size; - - return result; -} - -static proxy_t *proxy_group_get_proxy(proxy_group_t *group, int index) { - return &group->proxies[index]; -} - -static void proxy_group_list_set(proxy_group_list_t *list, int index, proxy_group_t *group) { - list->groups[index] = group; -} */ import "C" @@ -87,6 +62,7 @@ func setSelector(group C.const_string_t, selected C.const_string_t) C.int { //export queryProxyGroups func queryProxyGroups() *C.proxy_group_list_t { + stringPool := make([]byte, 0, 4096) proxies := tunnel.Proxies() groups := make([]outboundgroup.ProxyGroup, 0, len(proxies)) @@ -104,7 +80,7 @@ func queryProxyGroups() *C.proxy_group_list_t { groups = append(groups, adapter) } - result := C.new_proxy_group_list_t(C.int(len(groups))) + result := allocCProxyGroupList(len(groups)) groupIndex := 0 for _, group := range groups { ps := make([]constant.Proxy, 0) @@ -112,20 +88,26 @@ func queryProxyGroups() *C.proxy_group_list_t { ps = append(ps, provider.Proxies()...) } - g := C.new_proxy_group_t(C.int(len(proxies))) + g := allocCProxyGroup(len(proxies)) - g.base.name = C.CString(group.Name()) + g.base.name_index = C.long(len(stringPool)) g.base.proxy_type = typeToProxyTypeC(group.Type()) g.base.delay = 0 + stringPool = append(stringPool, group.Name()...) + stringPool = append(stringPool, 0) + proxyIndex := 0 for _, proxy := range proxies { - p := C.proxy_group_get_proxy(g, C.int(proxyIndex)) + p := indexCProxyGroupElement(g, proxyIndex) - p.name = C.CString(proxy.Name()) + p.name_index = C.long(len(stringPool)) p.proxy_type = typeToProxyTypeC(proxy.Type()) p.delay = C.long(proxy.LastDelay()) + stringPool = append(stringPool, proxy.Name()...) + stringPool = append(stringPool, 0) + if proxy.Name() == group.Now() { g.now = C.int(proxyIndex) } @@ -133,14 +115,18 @@ func queryProxyGroups() *C.proxy_group_list_t { proxyIndex++ } - C.proxy_group_list_set(result, C.int(groupIndex), g) + setCProxyGroupListElement(result, groupIndex, g) groupIndex++ } + result.string_pool = (*C.char)(C.CBytes(stringPool)) + return result } + + func typeToProxyTypeC(t constant.AdapterType) C.proxy_type_t { switch t { case constant.Direct: @@ -175,4 +161,30 @@ func typeToProxyTypeC(t constant.AdapterType) C.proxy_type_t { default: return C.Unknown } +} + +func allocCProxyGroup(proxiesSize int) *C.proxy_group_t { + return (*C.proxy_group_t)(C.malloc(C.sizeof_proxy_group_t + C.sizeof_proxy_t * C.size_t(proxiesSize))) +} + +func allocCProxyGroupList(groupSize int) *C.proxy_group_list_t { + return (*C.proxy_group_list_t)(C.malloc(C.sizeof_proxy_group_list_t + C.sizeof_long * C.size_t(groupSize))) +} + +//noinspection GoVetUnsafePointer +func setCProxyGroupListElement(list *C.proxy_group_list_t, index int, element *C.proxy_group_t) { + address := uintptr(unsafe.Pointer(list)) + + offset := address + uintptr(C.sizeof_proxy_group_list_t) + uintptr(index) * uintptr(C.sizeof_long) + + *(**C.proxy_group_t)(unsafe.Pointer(offset)) = element +} + +//noinspection GoVetUnsafePointer +func indexCProxyGroupElement(group *C.proxy_group_t, index int) *C.proxy_t { + address := uintptr(unsafe.Pointer(group)) + + offset := address + uintptr(C.sizeof_proxy_group_list_t) + uintptr(index) * uintptr(C.sizeof_proxy_t) + + return (*C.proxy_t)(unsafe.Pointer(offset)) } \ No newline at end of file diff --git a/core/src/main/golang/proxies.h b/core/src/main/golang/proxies.h index fa34ea8..53e41de 100644 --- a/core/src/main/golang/proxies.h +++ b/core/src/main/golang/proxies.h @@ -9,7 +9,7 @@ typedef enum proxy_type_t { } proxy_type_t; typedef struct proxy_t { - char *name; + long name_index; proxy_type_t proxy_type; long delay; } proxy_t; @@ -23,6 +23,7 @@ typedef struct proxy_group_t { typedef struct proxy_group_list_t { int size; + char *string_pool; proxy_group_t *groups[]; } proxy_group_list_t;