package main /* #include #include #include static jstring make_jstring(JNIEnv *env, const char *s) { return (*env)->NewStringUTF(env, s ? s : ""); } static const char* get_jstring(JNIEnv *env, jstring s, jboolean *isCopy) { return (*env)->GetStringUTFChars(env, s, isCopy); } static void release_jstring(JNIEnv *env, jstring s, const char *c) { (*env)->ReleaseStringUTFChars(env, s, c); } static jint register_natives(JNIEnv *env, jclass clazz, JNINativeMethod *methods, jint n) { return (*env)->RegisterNatives(env, clazz, methods, n); } static jclass find_class(JNIEnv *env, const char *name) { return (*env)->FindClass(env, name); } */ import "C" import ( "bytes" "context" "encoding/json" "fmt" "sync" "unsafe" core "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/infra/conf/serial" _ "github.com/xtls/xray-core/app/dispatcher" _ "github.com/xtls/xray-core/app/dns" _ "github.com/xtls/xray-core/app/proxyman/inbound" _ "github.com/xtls/xray-core/app/proxyman/outbound" _ "github.com/xtls/xray-core/proxy/vless/outbound" _ "github.com/xtls/xray-core/proxy/socks" _ "github.com/xtls/xray-core/transport/internet/reality" _ "github.com/xtls/xray-core/transport/internet/tcp" _ "github.com/xtls/xray-core/transport/internet/grpc" ) var ( mu sync.Mutex instance *core.Instance ) type VlessConfig struct { Address string `json:"address"` Port int `json:"port"` UUID string `json:"uuid"` PublicKey string `json:"publicKey"` ShortID string `json:"shortId"` Fingerprint string `json:"fingerprint"` ServerName string `json:"serverName"` LocalPort int `json:"localPort"` // Transport: "tcp" (default) or "grpc" Network string `json:"network"` ServiceName string `json:"serviceName"` } func buildConfig(cfg VlessConfig) ([]byte, error) { fp := cfg.Fingerprint if fp == "" { fp = "chrome" } sni := cfg.ServerName if sni == "" { sni = cfg.Address } lp := cfg.LocalPort if lp == 0 { lp = 10808 } network := cfg.Network if network == "" { network = "tcp" } // Build streamSettings based on transport var streamSettings string if network == "grpc" { streamSettings = fmt.Sprintf(`{ "network": "grpc", "security": "reality", "realitySettings": { "serverName": %q, "fingerprint": %q, "publicKey": %q, "shortId": %q, "spiderX": "/" }, "grpcSettings": { "serviceName": %q, "multiMode": false } }`, sni, fp, cfg.PublicKey, cfg.ShortID, cfg.ServiceName) } else { streamSettings = fmt.Sprintf(`{ "network": "tcp", "security": "reality", "realitySettings": { "serverName": %q, "fingerprint": %q, "publicKey": %q, "shortId": %q, "spiderX": "/" } }`, sni, fp, cfg.PublicKey, cfg.ShortID) } // flow only for tcp/vision, not grpc flow := "" if network != "grpc" { flow = `"xtls-rprx-vision"` } else { flow = `""` } raw := fmt.Sprintf(`{ "log": {"loglevel": "warning"}, "inbounds": [{ "listen": "127.0.0.1", "port": %d, "protocol": "socks", "settings": {"auth": "noauth", "udp": false} }], "outbounds": [{ "protocol": "vless", "settings": { "vnext": [{ "address": %q, "port": %d, "users": [{"id": %q, "encryption": "none", "flow": %s}] }] }, "streamSettings": %s }] }`, lp, cfg.Address, cfg.Port, cfg.UUID, flow, streamSettings) return []byte(raw), nil } func xrayStart(configJSON string) string { mu.Lock() defer mu.Unlock() if instance != nil { _ = instance.Close() instance = nil } var cfg VlessConfig if err := json.Unmarshal([]byte(configJSON), &cfg); err != nil { return "config parse error: " + err.Error() } xrayJSON, err := buildConfig(cfg) if err != nil { return "build config error: " + err.Error() } confObj, err := serial.DecodeJSONConfig(bytes.NewReader(xrayJSON)) if err != nil { return "decode config error: " + err.Error() + " | json: " + string(xrayJSON) } pbCfg, err := confObj.Build() if err != nil { return "load config error: " + err.Error() + " | json: " + string(xrayJSON) } inst, err := core.New(pbCfg) if err != nil { return "create error: " + err.Error() } if err := inst.Start(); err != nil { return "start error: " + err.Error() } instance = inst return "" } func xrayStop() string { mu.Lock() defer mu.Unlock() if instance == nil { return "" } err := instance.Close() instance = nil if err != nil { return err.Error() } return "" } func xrayRunning() string { mu.Lock() defer mu.Unlock() if instance != nil { return "true" } return "false" } //export Java_org_telegram_messenger_XrayController_StartXray func Java_org_telegram_messenger_XrayController_StartXray(env *C.JNIEnv, clazz C.jclass, cfg C.jstring) C.jstring { var isCopy C.jboolean cs := C.get_jstring(env, cfg, &isCopy) result := xrayStart(C.GoString(cs)) C.release_jstring(env, cfg, cs) cr := C.CString(result) defer C.free(unsafe.Pointer(cr)) return C.make_jstring(env, cr) } //export Java_org_telegram_messenger_XrayController_StopXray func Java_org_telegram_messenger_XrayController_StopXray(env *C.JNIEnv, clazz C.jclass) C.jstring { result := xrayStop() cr := C.CString(result) defer C.free(unsafe.Pointer(cr)) return C.make_jstring(env, cr) } //export Java_org_telegram_messenger_XrayController_IsRunning func Java_org_telegram_messenger_XrayController_IsRunning(env *C.JNIEnv, clazz C.jclass) C.jstring { result := xrayRunning() cr := C.CString(result) defer C.free(unsafe.Pointer(cr)) return C.make_jstring(env, cr) } //export Java_org_telegram_messenger_XrayController_initXrayBridge func Java_org_telegram_messenger_XrayController_initXrayBridge(env *C.JNIEnv, clazz C.jclass, dir C.jstring) { } //export Java_org_telegram_messenger_XrayController_GetLocalSocksPort func Java_org_telegram_messenger_XrayController_GetLocalSocksPort(env *C.JNIEnv, clazz C.jclass, cfg C.jstring) C.jstring { var isCopy C.jboolean cs := C.get_jstring(env, cfg, &isCopy) var v VlessConfig _ = json.Unmarshal([]byte(C.GoString(cs)), &v) C.release_jstring(env, cfg, cs) lp := v.LocalPort if lp == 0 { lp = 10808 } result := fmt.Sprintf("%d", lp) cr := C.CString(result) defer C.free(unsafe.Pointer(cr)) return C.make_jstring(env, cr) } var _ = context.Background func main() {}