diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1711997..cd9614f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: branches: - main - dev - - android-fix-action-bug + - v3 paths-ignore: - '**.md' - 'docs/**' diff --git a/Makefile b/Makefile index 9877006..b9eb4d8 100644 --- a/Makefile +++ b/Makefile @@ -32,15 +32,15 @@ protos: lib_install: - go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.1 - go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.1 + go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.4 + go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.4 npm install headers: go build -buildmode=c-archive -o $(BINDIR)/$(LIBNAME).h ./custom android: lib_install - gomobile bind -v -androidapi=21 -javapkg=io.nekohasekai -libname=box -tags=$(TAGS) -trimpath -target=android -o $(BINDIR)/$(LIBNAME).aar github.com/sagernet/sing-box/experimental/libbox ./mobile + gomobile bind -v -androidapi=21 -javapkg=com.hiddify.core -libname=box -tags=$(TAGS) -trimpath -target=android -o $(BINDIR)/$(LIBNAME).aar github.com/sagernet/sing-box/experimental/libbox ./mobile ios-full: lib_install gomobile bind -v -target ios,iossimulator,tvos,tvossimulator,macos -libname=box -tags=$(TAGS),$(IOS_ADD_TAGS) -trimpath -ldflags="-w -s" -o $(BINDIR)/$(PRODUCT_NAME).xcframework github.com/sagernet/sing-box/experimental/libbox ./mobile diff --git a/cmd/cmd_run.go b/cmd/cmd_run.go index f714ccc..ae3bd79 100644 --- a/cmd/cmd_run.go +++ b/cmd/cmd_run.go @@ -2,6 +2,7 @@ package cmd import ( hcore "github.com/hiddify/hiddify-core/v2/hcore" + "github.com/spf13/cobra" ) @@ -22,6 +23,27 @@ func init() { } func runCommand(cmd *cobra.Command, args []string) { - hcore.Setup("./tmp", "./", "./tmp", 0, false) + hcore.Setup( + hcore.SetupParameters{ + BasePath: "./tmp", + WorkingDir: "./", + TempDir: "./tmp", + FlutterStatusPort: 0, + Debug: false, + Mode: hcore.GRPC_BOTH, + Listen: "127.0.0.1:17078", + }, + ) + // conn, err := grpc.Dial("127.0.0.1:17078", grpc.WithInsecure()) + // if err != nil { + // fmt.Printf("did not connect: %v", err) + // } + // defer conn.Close() + // c := hello.NewHelloClient(conn) + // ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + // defer cancel() + // res, err := c.SayHello(ctx, &hello.HelloRequest{Name: "test"}) + // fmt.Println(res, err) + // <-time.After(10 * time.Second) hcore.RunStandalone(hiddifySettingPath, configPath, defaultConfigs) } diff --git a/custom/custom.go b/custom/custom.go index 03d2304..9b74a97 100644 --- a/custom/custom.go +++ b/custom/custom.go @@ -13,7 +13,7 @@ import ( "github.com/hiddify/hiddify-core/bridge" "github.com/hiddify/hiddify-core/config" - pb "github.com/hiddify/hiddify-core/hiddifyrpc" + hcore "github.com/hiddify/hiddify-core/v2/hcore" "github.com/sagernet/sing-box/log" @@ -25,14 +25,24 @@ func setupOnce(api unsafe.Pointer) { } //export setup -func setup(baseDir *C.char, workingDir *C.char, tempDir *C.char, statusPort C.longlong, debug bool) (CErr *C.char) { - err := hcore.Setup(C.GoString(baseDir), C.GoString(workingDir), C.GoString(tempDir), int64(statusPort), debug) +func setup(baseDir *C.char, workingDir *C.char, tempDir *C.char, mode C.int, listen *C.char, secret *C.char, statusPort C.longlong, debug bool) (CErr *C.char) { + // err := hcore.Setup(C.GoString(baseDir), C.GoString(workingDir), C.GoString(tempDir), int64(statusPort), debug) + err := hcore.Setup(hcore.SetupParameters{ + BasePath: C.GoString(baseDir), + WorkingDir: C.GoString(workingDir), + TempDir: C.GoString(tempDir), + FlutterStatusPort: int64(statusPort), + Debug: debug, + Mode: hcore.SetupMode(mode), + Listen: C.GoString(listen), + Secret: C.GoString(secret), + }) return emptyOrErrorC(err) } //export parse func parse(path *C.char, tempPath *C.char, debug bool) (CErr *C.char) { - res, err := hcore.Parse(&pb.ParseRequest{ + res, err := hcore.Parse(&hcore.ParseRequest{ ConfigPath: C.GoString(path), TempPath: C.GoString(tempPath), }) @@ -47,7 +57,7 @@ func parse(path *C.char, tempPath *C.char, debug bool) (CErr *C.char) { //export changeHiddifyOptions func changeHiddifyOptions(HiddifyOptionsJson *C.char) (CErr *C.char) { - _, err := hcore.ChangeHiddifySettings(&pb.ChangeHiddifySettingsRequest{ + _, err := hcore.ChangeHiddifySettings(&hcore.ChangeHiddifySettingsRequest{ HiddifySettingsJson: C.GoString(HiddifyOptionsJson), }) return emptyOrErrorC(err) @@ -55,7 +65,7 @@ func changeHiddifyOptions(HiddifyOptionsJson *C.char) (CErr *C.char) { //export generateConfig func generateConfig(path *C.char) (res *C.char) { - conf, err := hcore.GenerateConfig(&pb.GenerateConfigRequest{ + conf, err := hcore.GenerateConfig(&hcore.GenerateConfigRequest{ Path: C.GoString(path), }) if err != nil { @@ -68,7 +78,7 @@ func generateConfig(path *C.char) (res *C.char) { //export start func start(configPath *C.char, disableMemoryLimit bool) (CErr *C.char) { - _, err := hcore.Start(&pb.StartRequest{ + _, err := hcore.Start(&hcore.StartRequest{ ConfigPath: C.GoString(configPath), EnableOldCommandServer: true, DisableMemoryLimit: disableMemoryLimit, @@ -84,7 +94,7 @@ func stop() (CErr *C.char) { //export restart func restart(configPath *C.char, disableMemoryLimit bool) (CErr *C.char) { - _, err := hcore.Restart(&pb.StartRequest{ + _, err := hcore.Restart(&hcore.StartRequest{ ConfigPath: C.GoString(configPath), EnableOldCommandServer: true, DisableMemoryLimit: disableMemoryLimit, @@ -106,7 +116,7 @@ func stopCommandClient(command C.int) *C.char { //export selectOutbound func selectOutbound(groupTag *C.char, outboundTag *C.char) (CErr *C.char) { - _, err := hcore.SelectOutbound(&pb.SelectOutboundRequest{ + _, err := hcore.SelectOutbound(&hcore.SelectOutboundRequest{ GroupTag: C.GoString(groupTag), OutboundTag: C.GoString(outboundTag), }) @@ -116,7 +126,7 @@ func selectOutbound(groupTag *C.char, outboundTag *C.char) (CErr *C.char) { //export urlTest func urlTest(groupTag *C.char) (CErr *C.char) { - _, err := hcore.UrlTest(&pb.UrlTestRequest{ + _, err := hcore.UrlTest(&hcore.UrlTestRequest{ GroupTag: C.GoString(groupTag), }) @@ -133,7 +143,7 @@ func emptyOrErrorC(err error) *C.char { //export generateWarpConfig func generateWarpConfig(licenseKey *C.char, accountId *C.char, accessToken *C.char) (CResp *C.char) { - res, err := hcore.GenerateWarpConfig(&pb.GenerateWarpConfigRequest{ + res, err := hcore.GenerateWarpConfig(&hcore.GenerateWarpConfigRequest{ LicenseKey: C.GoString(licenseKey), AccountId: C.GoString(accountId), AccessToken: C.GoString(accessToken), @@ -167,3 +177,18 @@ func generateWarpConfig(licenseKey *C.char, accountId *C.char, accessToken *C.ch } func main() {} + +//export GetServerPublicKey +func GetServerPublicKey() []byte { + return hcore.GetGrpcServerPublicKey() +} + +//export AddGrpcClientPublicKey +func AddGrpcClientPublicKey(clientPublicKey []byte) error { + return hcore.AddGrpcClientPublicKey(clientPublicKey) +} + +//export close +func close() { + hcore.Close() +} diff --git a/extension/server/run_server.go b/extension/server/run_server.go index fb85b5c..3bd757a 100644 --- a/extension/server/run_server.go +++ b/extension/server/run_server.go @@ -17,7 +17,19 @@ import ( ) func StartTestExtensionServer() { - hcore.Setup("./tmp", "./", "./tmp", 0, false) + hcore.Setup( + hcore.SetupParameters{ + BasePath: "./tmp", + WorkingDir: "./", + TempDir: "./tmp", + FlutterStatusPort: 0, + Listen: "", + Secret: "", + Debug: false, + Mode: hcore.OLD, + }, + ) + // "./tmp", "./", "./tmp", 0, false) StartExtensionServer() } diff --git a/go.mod b/go.mod index ad140b2..bf7eda0 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,159 @@ +// module github.com/hiddify/hiddify-core + +// go 1.22.0 + +// toolchain go1.22.3 + +// require ( +// github.com/bepass-org/warp-plus v1.2.4 +// github.com/google/uuid v1.6.0 +// github.com/hiddify/hiddify-app-demo-extension v0.0.0-20241001070003-26039f960ad6 +// github.com/hiddify/ray2sing v0.0.0-20240804185422-f340989b59a0 +// github.com/improbable-eng/grpc-web v0.15.0 +// github.com/jellydator/validation v1.1.0 +// github.com/kardianos/service v1.2.2 +// github.com/sagernet/gomobile v0.1.4 +// github.com/sagernet/sing v0.4.3 +// github.com/sagernet/sing-box v1.8.9 +// github.com/sagernet/sing-dns v0.2.3 +// github.com/spf13/cobra v1.8.0 +// github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca +// github.com/tendermint/tm-db v0.6.7 +// github.com/xmdhs/clash2singbox v0.0.2 +// golang.org/x/net v0.28.0 +// golang.org/x/sys v0.25.0 +// google.golang.org/grpc v1.67.0 +// google.golang.org/protobuf v1.35.1 +// gopkg.in/yaml.v3 v3.0.1 +// ) + +// require ( +// berty.tech/go-libtor v1.0.385 // indirect +// github.com/DataDog/zstd v1.4.1 // indirect +// github.com/ajg/form v1.5.1 // indirect +// github.com/andybalholm/brotli v1.1.0 // indirect +// github.com/caddyserver/certmagic v0.20.0 // indirect +// github.com/cenkalti/backoff/v4 v4.1.1 // indirect +// github.com/cespare/xxhash v1.1.0 // indirect +// github.com/cloudflare/circl v1.4.0 // indirect +// github.com/cosmos/gorocksdb v1.2.0 // indirect +// github.com/cretz/bine v0.2.0 // indirect +// github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect +// github.com/dgraph-io/badger/v2 v2.2007.2 // indirect +// github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de // indirect +// github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect +// github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect +// github.com/dustin/go-humanize v1.0.0 // indirect +// github.com/fatih/color v1.16.0 // indirect +// github.com/francoispqt/gojay v1.2.13 // indirect +// github.com/fsnotify/fsnotify v1.7.0 // indirect +// github.com/gaukas/godicttls v0.0.4 // indirect +// github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 // indirect +// github.com/go-chi/chi/v5 v5.0.12 // indirect +// github.com/go-chi/cors v1.2.1 // indirect +// github.com/go-chi/render v1.0.3 // indirect +// github.com/go-ole/go-ole v1.3.0 // indirect +// github.com/go-task/slim-sprig/v3 v3.0.0 // indirect +// github.com/gobwas/httphead v0.1.0 // indirect +// github.com/gobwas/pool v0.2.1 // indirect +// github.com/gofrs/uuid/v5 v5.2.0 // indirect +// github.com/golang/protobuf v1.5.4 // indirect +// github.com/golang/snappy v0.0.1 // indirect +// github.com/google/btree v1.1.2 // indirect +// github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect +// github.com/gorilla/websocket v1.5.3 // indirect +// github.com/hashicorp/yamux v0.1.1 // indirect +// github.com/imkira/go-observer/v2 v2.0.0-20230629064422-8e0b61f11f1b // indirect +// github.com/inconshreveable/mousetrap v1.1.0 // indirect +// github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect +// github.com/jmhodges/levigo v1.0.0 // indirect +// github.com/josharian/native v1.1.0 // indirect +// github.com/klauspost/compress v1.17.8 // indirect +// github.com/klauspost/cpuid/v2 v2.2.7 // indirect +// github.com/libdns/alidns v1.0.3 // indirect +// github.com/libdns/cloudflare v0.1.1 // indirect +// github.com/libdns/libdns v0.2.2 // indirect +// github.com/logrusorgru/aurora v2.0.3+incompatible // indirect +// github.com/mattn/go-colorable v0.1.13 // indirect +// github.com/mattn/go-isatty v0.0.20 // indirect +// github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect +// github.com/mholt/acmez v1.2.0 // indirect +// github.com/miekg/dns v1.1.62 // indirect +// github.com/modern-go/reflect2 v1.0.2 // indirect +// github.com/onsi/ginkgo/v2 v2.19.0 // indirect +// github.com/ooni/go-libtor v1.1.8 // indirect +// github.com/oschwald/maxminddb-golang v1.12.0 // indirect +// github.com/pelletier/go-toml v1.9.5 // indirect +// github.com/pierrec/lz4/v4 v4.1.14 // indirect +// github.com/pion/dtls/v2 v2.2.7 // indirect +// github.com/pion/logging v0.2.2 // indirect +// github.com/pion/randutil v0.1.0 // indirect +// github.com/pion/stun/v2 v2.0.0 // indirect +// github.com/pion/transport/v2 v2.2.3 // indirect +// github.com/pion/transport/v3 v3.0.1 // indirect +// github.com/pion/turn/v3 v3.0.1 // indirect +// github.com/pires/go-proxyproto v0.7.0 // indirect +// github.com/pkg/errors v0.9.1 // indirect +// github.com/quic-go/qpack v0.4.0 // indirect +// github.com/quic-go/qtls-go1-20 v0.4.1 // indirect +// github.com/quic-go/quic-go v0.46.0 // indirect +// github.com/refraction-networking/utls v1.6.7 // indirect +// github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect +// github.com/rs/cors v1.7.0 // indirect +// github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect +// github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect +// github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect +// github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect +// github.com/sagernet/quic-go v0.47.0-beta.2 // indirect +// github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect +// github.com/sagernet/sing-mux v0.2.0 // indirect +// github.com/sagernet/sing-quic v0.2.2 // indirect +// github.com/sagernet/sing-shadowsocks v0.2.7 // indirect +// github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect +// github.com/sagernet/sing-shadowtls v0.1.4 // indirect +// github.com/sagernet/sing-tun v0.3.3 // indirect +// github.com/sagernet/sing-vmess v0.1.12 // indirect +// github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect +// github.com/sagernet/utls v1.5.4 // indirect +// github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 // indirect +// github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 // indirect +// github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect +// github.com/spf13/pflag v1.0.5 // indirect +// github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect +// github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect +// github.com/vishvananda/netns v0.0.4 // indirect +// github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect +// github.com/xtls/xray-core v1.8.21 // indirect +// github.com/zeebo/blake3 v0.2.3 // indirect +// go.etcd.io/bbolt v1.3.6 // indirect +// go.uber.org/mock v0.4.0 // indirect +// go.uber.org/multierr v1.11.0 // indirect +// go.uber.org/zap v1.27.0 // indirect +// go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect +// golang.org/x/crypto v0.26.0 // indirect +// golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect +// golang.org/x/mod v0.18.0 // indirect +// golang.org/x/sync v0.8.0 // indirect +// golang.org/x/text v0.18.0 // indirect +// golang.org/x/time v0.5.0 // indirect +// golang.org/x/tools v0.22.0 // indirect +// google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect +// gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +// gopkg.in/yaml.v2 v2.4.0 // indirect +// lukechampine.com/blake3 v1.3.0 // indirect +// nhooyr.io/websocket v1.8.6 // indirect +// ) + +// replace github.com/sagernet/sing-box => github.com/hiddify/hiddify-sing-box v1.8.9-0.20241013222038-47abad60f848 + +// replace github.com/xtls/xray-core => github.com/hiddify/xray-core v0.0.0-20240902024714-0fcb0895bb4b + +// replace github.com/sagernet/wireguard-go => github.com/hiddify/wireguard-go v0.0.0-20240727191222-383c1da14ff1 + +// replace github.com/bepass-org/warp-plus => github.com/hiddify/warp-plus v0.0.0-20240717223357-4f3122e0d11d + +// replace github.com/hiddify/ray2sing => github.com/hiddify/ray2sing v0.0.0-20240928221833-190b549d5222 + module github.com/hiddify/hiddify-core go 1.22.0 @@ -6,6 +162,8 @@ toolchain go1.22.3 require ( github.com/bepass-org/warp-plus v1.2.4 + github.com/fatih/color v1.16.0 // indirect + github.com/hiddify/hiddify-app-demo-extension v0.0.0-20241001070003-26039f960ad6 github.com/improbable-eng/grpc-web v0.15.0 github.com/jellydator/validation v1.1.0 github.com/kardianos/service v1.2.2 @@ -16,14 +174,13 @@ require ( github.com/spf13/cobra v1.8.0 github.com/xmdhs/clash2singbox v0.0.2 golang.org/x/sys v0.25.0 - google.golang.org/grpc v1.67.0 + google.golang.org/grpc v1.66.0 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/google/uuid v1.6.0 - github.com/hiddify/hiddify-app-demo-extension v0.0.0-20241001070003-26039f960ad6 github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/tendermint/tm-db v0.6.7 ) @@ -38,14 +195,12 @@ require ( github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de // indirect github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect github.com/dustin/go-humanize v1.0.0 // indirect - github.com/fatih/color v1.16.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rs/cors v1.7.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect @@ -145,7 +300,7 @@ require ( golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.22.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 28961bf..732b9db 100644 --- a/go.sum +++ b/go.sum @@ -385,9 +385,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -893,8 +892,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -910,8 +909,8 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/hiddify-core.tar.gz b/hiddify-core.tar.gz deleted file mode 100644 index 7ca4eaa..0000000 Binary files a/hiddify-core.tar.gz and /dev/null differ diff --git a/mobile/mobile.go b/mobile/mobile.go index 5353d8e..0159a9d 100644 --- a/mobile/mobile.go +++ b/mobile/mobile.go @@ -1,63 +1,63 @@ package mobile import ( - "encoding/json" - "os" - "path/filepath" - - "github.com/hiddify/hiddify-core/config" hcore "github.com/hiddify/hiddify-core/v2/hcore" _ "github.com/sagernet/gomobile" - "github.com/sagernet/sing-box/option" + + "github.com/sagernet/sing-box/experimental/libbox" ) -func Setup(baseDir string, workingDir string, tempDir string, debug bool) error { - return hcore.Setup(baseDir, workingDir, tempDir, 0, debug) +func Setup(baseDir string, workingDir string, tempDir string, mode int, listen string, secret string, debug bool) error { + return hcore.Setup(hcore.SetupParameters{ + BasePath: baseDir, + WorkingDir: workingDir, + TempDir: tempDir, + FlutterStatusPort: 0, + Listen: listen, + Debug: debug, + Mode: hcore.SetupMode(mode), + Secret: secret, + }) + // return hcore.Start(17078) } -func Parse(path string, tempPath string, debug bool) error { - config, err := config.ParseConfig(tempPath, debug) - if err != nil { - return err - } - return os.WriteFile(path, config, 0o644) +func BuildConfig(configPath string) (string, error) { + return hcore.BuildConfigJson(&hcore.StartRequest{ + ConfigPath: configPath, + }) +} + +// func Start(configPath string, configContent string, platformInterface libbox.PlatformInterface) (*hcore.CoreInfoResponse, error) { +// state, err := hcore.StartWithPlatformInterface(&hcore.StartRequest{ +// ConfigContent: configContent, +// ConfigPath: configPath, +// }, platformInterface) +// return state, err +// } + +func Start(configPath string, platformInterface libbox.PlatformInterface) error { + _, err := hcore.StartWithPlatformInterface(&hcore.StartRequest{ + ConfigPath: configPath, + }, platformInterface) + return err +} + +func Stop() error { + _, err := hcore.Stop() + + return err +} + +func GetServerPublicKey() []byte { + return hcore.GetGrpcServerPublicKey() } -func BuildConfig(path string, HiddifyOptionsJson string) (string, error) { - os.Chdir(filepath.Dir(path)) - fileContent, err := os.ReadFile(path) - if err != nil { - return "", err - } - var options option.Options - err = options.UnmarshalJSON(fileContent) - if err != nil { - return "", err - } - HiddifyOptions := &config.HiddifyOptions{} - err = json.Unmarshal([]byte(HiddifyOptionsJson), HiddifyOptions) - if err != nil { - return "", nil - } - if HiddifyOptions.Warp.WireguardConfigStr != "" { - err := json.Unmarshal([]byte(HiddifyOptions.Warp.WireguardConfigStr), &HiddifyOptions.Warp.WireguardConfig) - if err != nil { - return "", err - } - } - - if HiddifyOptions.Warp2.WireguardConfigStr != "" { - err := json.Unmarshal([]byte(HiddifyOptions.Warp2.WireguardConfigStr), &HiddifyOptions.Warp2.WireguardConfig) - if err != nil { - return "", err - } - } - - return config.BuildConfigJson(*HiddifyOptions, options) +func AddGrpcClientPublicKey(clientPublicKey []byte) error { + return hcore.AddGrpcClientPublicKey(clientPublicKey) } -func GenerateWarpConfig(licenseKey string, accountId string, accessToken string) (string, error) { - return config.GenerateWarpAccount(licenseKey, accountId, accessToken) +func Close() { + hcore.Close() } diff --git a/v2/common/constants/constants.go b/v2/common/constants/constants.go new file mode 100644 index 0000000..19ab89b --- /dev/null +++ b/v2/common/constants/constants.go @@ -0,0 +1,6 @@ +package constants + +const ( + DEFAULT_GRPC_NORMAL_PORT = 24354 + DEFAULT_GRPC_PORXY_PORT = 24355 +) diff --git a/v2/common/utils/cert.go b/v2/common/utils/cert.go new file mode 100644 index 0000000..eef3be7 --- /dev/null +++ b/v2/common/utils/cert.go @@ -0,0 +1,61 @@ +package utils + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "time" +) + +// CertificatePair holds the certificate and private key +type CertificatePair struct { + Certificate []byte + PrivateKey []byte +} + +// GenerateCertificatePair generates a self-signed certificate and private key +func GenerateCertificatePair() (*CertificatePair, error) { + // Generate a new RSA private key + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return nil, fmt.Errorf("failed to generate private key: %v", err) + } + + // Create a template for the certificate + certTemplate := x509.Certificate{ + SerialNumber: big.NewInt(1), // A unique serial number for the certificate + Subject: pkix.Name{ + Organization: []string{"Hiddify, Inc."}, + CommonName: "Hiddify", + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(365 * 24 * time.Hour), // Valid for 1 year + + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + + BasicConstraintsValid: true, + IsCA: true, // This is a CA certificate (for testing purposes) + } + + // Self-sign the certificate + certBytes, err := x509.CreateCertificate(rand.Reader, &certTemplate, &certTemplate, &privateKey.PublicKey, privateKey) + if err != nil { + return nil, fmt.Errorf("failed to create certificate: %v", err) + } + + // Encode the certificate to PEM format + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) + + // Encode the private key to PEM format + keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) + + return &CertificatePair{ + Certificate: certPEM, + PrivateKey: keyPEM, + }, nil +} diff --git a/v2/extension/server/run_server.go b/v2/extension/server/run_server.go new file mode 100644 index 0000000..57f340a --- /dev/null +++ b/v2/extension/server/run_server.go @@ -0,0 +1,125 @@ +package server + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + "os/signal" + "sync" + "syscall" + + "github.com/hiddify/hiddify-core/utils" + hcore "github.com/hiddify/hiddify-core/v2/hcore" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "google.golang.org/grpc" +) + +func StartTestExtensionServer() { + hcore.Setup(hcore.SetupParameters{ + BasePath: "./tmp", + WorkingDir: "./", + TempDir: "./tmp", + FlutterStatusPort: 0, + Listen: "", + Secret: "", + Debug: false, + Mode: hcore.OLD, + }) + StartExtensionServer() +} + +func StartExtensionServer() { + grpc_server, _ := hcore.StartCoreGrpcServer("127.0.0.1:12345") + fmt.Printf("Waiting for CTRL+C to stop\n") + runWebserver(grpc_server) +} + +func allowCors(resp http.ResponseWriter, req *http.Request) { + resp.Header().Set("Access-Control-Allow-Origin", "*") + resp.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + resp.Header().Set("Access-Control-Allow-Headers", "Content-Type") + if req.Method == "OPTIONS" { + resp.WriteHeader(http.StatusOK) + return + } +} + +func runWebserver(grpcServer *grpc.Server) { + // Context for cancellation + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Channels to signal termination + grpcTerminated := make(chan struct{}) + grpcWebTerminated := make(chan struct{}) + + // Specify the directory to serve static files + dir := "./extension/html/" + + // Wrapping gRPC server with grpc-web + grpcWeb := grpcweb.WrapServer(grpcServer) + + // HTTP multiplexer + mux := http.NewServeMux() + mux.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) { + allowCors(resp, req) + if grpcWeb.IsGrpcWebRequest(req) || grpcWeb.IsAcceptableGrpcCorsRequest(req) { + grpcWeb.ServeHTTP(resp, req) + } else { + http.DefaultServeMux.ServeHTTP(resp, req) + } + }) + + // File server for static files + fs := http.FileServer(http.Dir(dir)) + http.Handle("/", http.StripPrefix("/", fs)) + + // HTTP server for grpc-web + rpcWebServer := &http.Server{ + Handler: mux, + Addr: ":12346", + } + log.Println("Serving grpc-web from https://localhost:12346/") + + // Add a goroutine for the grpc-web server + wg := sync.WaitGroup{} + wg.Add(1) + + go func() { + defer wg.Done() + utils.GenerateCertificate("cert/server-cert.pem", "cert/server-key.pem", true, true) + if err := rpcWebServer.ListenAndServeTLS("cert/server-cert.pem", "cert/server-key.pem"); err != nil && err != http.ErrServerClosed { + // if err := rpcWebServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + fmt.Printf("Web server (gRPC-web) shutdown with error: %s", err) + } + grpcServer.Stop() + close(grpcWebTerminated) // Server terminated + }() + + // Signal handling to gracefully shutdown + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + select { + case <-ctx.Done(): // Context canceled + log.Println("Context canceled, shutting down servers...") + case sig := <-sigChan: // OS signal received + log.Printf("Received signal: %s, shutting down servers...", sig) + case <-grpcTerminated: // Unexpected gRPC termination + log.Println("gRPC server terminated unexpectedly") + case <-grpcWebTerminated: // Unexpected gRPC-web termination + log.Println("gRPC-web server terminated unexpectedly") + } + + // Graceful shutdown of the servers + if err := rpcWebServer.Shutdown(ctx); err != nil { + log.Printf("gRPC-web server shutdown with error: %s", err) + } + <-grpcWebTerminated + + // Ensure all routines finish + wg.Wait() + log.Println("Server shutdown complete") +} diff --git a/v2/hcore/command_client.go b/v2/hcore/command_client.go index 8570ae2..0854076 100644 --- a/v2/hcore/command_client.go +++ b/v2/hcore/command_client.go @@ -27,7 +27,7 @@ func (cch *CommandClientHandler) WriteLog(message string) { } func (cch *CommandClientHandler) WriteStatus(message *libbox.StatusMessage) { - systemInfoObserver.Emit(SystemInfo{ + systemInfoObserver.Emit(&SystemInfo{ ConnectionsIn: message.ConnectionsIn, ConnectionsOut: message.ConnectionsOut, Uplink: message.Uplink, @@ -62,8 +62,8 @@ func (cch *CommandClientHandler) WriteGroups(message libbox.OutboundGroupIterato } groups.Items = append(groups.Items, &OutboundGroup{Tag: group.Tag, Type: group.Type, Selected: group.Selected, Items: groupItems}) } - outboundsInfoObserver.Emit(groups) - mainOutboundsInfoObserver.Emit(groups) + outboundsInfoObserver.Emit(&groups) + mainOutboundsInfoObserver.Emit(&groups) } func (cch *CommandClientHandler) InitializeClashMode(modeList libbox.StringIterator, currentMode string) { diff --git a/v2/hcore/commands.go b/v2/hcore/commands.go index 183e74b..efac538 100644 --- a/v2/hcore/commands.go +++ b/v2/hcore/commands.go @@ -10,9 +10,9 @@ import ( ) var ( - systemInfoObserver = NewObserver[SystemInfo](10) - outboundsInfoObserver = NewObserver[OutboundGroupList](10) - mainOutboundsInfoObserver = NewObserver[OutboundGroupList](10) + systemInfoObserver = NewObserver[*SystemInfo](10) + outboundsInfoObserver = NewObserver[*OutboundGroupList](10) + mainOutboundsInfoObserver = NewObserver[*OutboundGroupList](10) ) var ( @@ -47,7 +47,7 @@ func (s *CoreService) GetSystemInfo(req *common.Empty, stream grpc.ServerStreami case <-done: return nil case info := <-sub: - stream.Send(&info) + stream.Send(info) case <-time.After(1000 * time.Millisecond): } } @@ -79,7 +79,7 @@ func (s *CoreService) OutboundsInfo(req *common.Empty, stream grpc.ServerStreami case <-done: return nil case info := <-sub: - stream.Send(&info) + stream.Send(info) case <-time.After(500 * time.Millisecond): } } @@ -111,7 +111,7 @@ func (s *CoreService) MainOutboundsInfo(req *common.Empty, stream grpc.ServerStr case <-stopch: return nil case info := <-sub: - stream.Send(&info) + stream.Send(info) case <-time.After(500 * time.Millisecond): } } diff --git a/v2/hcore/coreinfo.go b/v2/hcore/coreinfo.go index ddc772e..014a47e 100644 --- a/v2/hcore/coreinfo.go +++ b/v2/hcore/coreinfo.go @@ -10,7 +10,7 @@ import ( ) var ( - coreInfoObserver = *NewObserver[*CoreInfoResponse](1) + coreInfoObserver = NewObserver[*CoreInfoResponse](1) CoreState = CoreStates_STOPPED ) diff --git a/v2/hcore/custom.go b/v2/hcore/custom.go index 24ce204..cdedca6 100644 --- a/v2/hcore/custom.go +++ b/v2/hcore/custom.go @@ -11,14 +11,16 @@ import ( "github.com/hiddify/hiddify-core/bridge" "github.com/hiddify/hiddify-core/config" common "github.com/hiddify/hiddify-core/v2/common" + "github.com/hiddify/hiddify-core/v2/db" "github.com/sagernet/sing-box/experimental/libbox" "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" ) var ( - Box *libbox.BoxService - HiddifyOptions *config.HiddifyOptions - activeConfigPath string + Box *libbox.BoxService + HiddifyOptions *config.HiddifyOptions + // activeConfigPath string coreLogFactory log.Factory useFlutterBridge bool = true ) @@ -72,13 +74,101 @@ func (s *CoreService) StartService(ctx context.Context, in *StartRequest) (*Core return StartService(in) } +func errorWrapper(state MessageType, err error) (*CoreInfoResponse, error) { + Log(LogLevel_FATAL, LogType_CORE, err.Error()) + StopAndAlert(MessageType_UNEXPECTED_ERROR, err.Error()) + return SetCoreStatus(CoreStates_STOPPED, state, err.Error()), err +} + +func StartWithPlatformInterface(in *StartRequest, platformInterface libbox.PlatformInterface) (coreResponse *CoreInfoResponse, err error) { + defer config.DeferPanicToError("start", func(recovered_err error) { + coreResponse, err = errorWrapper(MessageType_UNEXPECTED_ERROR, recovered_err) + <-time.After(5 * time.Second) + }) + + Log(LogLevel_DEBUG, LogType_CORE, "Starting Core Service") + json, err := BuildConfigJson(in) + if err != nil { + return errorWrapper(MessageType_ERROR_BUILDING_CONFIG, err) + } + Log(LogLevel_DEBUG, LogType_CORE, "Saving config") + // currentBuildConfigPath := filepath.Join(sWorkingPath, "current-config.json") + // config.SaveCurrentConfig(currentBuildConfigPath, *parsedContent) + // activeConfigPath = currentBuildConfigPath + + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("Starting Service json %++v, platformInterface %++v", json, platformInterface)) + instance, err := libbox.NewService(json, &HiddifyPlatformInterface{ + platform: platformInterface, + }) + if err != nil { + return errorWrapper(MessageType_CREATE_SERVICE, err) + } + + Log(LogLevel_DEBUG, LogType_CORE, "Stating Service with delay ?", in.DelayStart) + if in.DelayStart { + <-time.After(250 * time.Millisecond) + } + + err = instance.Start() + if err != nil { + return errorWrapper(MessageType_START_SERVICE, err) + } + Box = instance + if in.EnableOldCommandServer { + Log(LogLevel_DEBUG, LogType_CORE, "Starting Command Server") + if err := startCommandServer(); err != nil { + return errorWrapper(MessageType_START_COMMAND_SERVER, err) + } + oldCommandServer.SetService(Box) + } + + return SetCoreStatus(CoreStates_STARTED, MessageType_EMPTY, ""), nil +} + +func BuildConfigJson(in *StartRequest) (string, error) { + Log(LogLevel_DEBUG, LogType_CORE, "Stating Service ") + + parsedContent, err := BuildConfig(in) + if err != nil { + return "", err + } + return config.ToJson(*parsedContent) +} + +func BuildConfig(in *StartRequest) (*option.Options, error) { + content := in.ConfigContent + if content == "" { + fileContent, err := os.ReadFile(in.ConfigPath) + if err != nil { + return nil, err + } + content = string(fileContent) + } + + Log(LogLevel_DEBUG, LogType_CORE, "Parsing Config") + + parsedContent, err := readOptions(content) + Log(LogLevel_DEBUG, LogType_CORE, "Parsed") + + if err != nil { + return nil, err + } + + if !in.EnableRawConfig { + Log(LogLevel_DEBUG, LogType_CORE, "Building config "+fmt.Sprintf("%++v", HiddifyOptions)) + return config.BuildConfig(*HiddifyOptions, parsedContent) + + } + + return &parsedContent, nil +} + func StartService(in *StartRequest) (*CoreInfoResponse, error) { Log(LogLevel_DEBUG, LogType_CORE, "Starting Core Service") content := in.ConfigContent if content == "" { - activeConfigPath = in.ConfigPath - fileContent, err := os.ReadFile(activeConfigPath) + fileContent, err := os.ReadFile(in.ConfigPath) if err != nil { Log(LogLevel_FATAL, LogType_CORE, err.Error()) resp := SetCoreStatus(CoreStates_STOPPED, MessageType_ERROR_READING_CONFIG, err.Error()) @@ -112,9 +202,9 @@ func StartService(in *StartRequest) (*CoreInfoResponse, error) { Log(LogLevel_DEBUG, LogType_CORE, "Saving config") currentBuildConfigPath := filepath.Join(sWorkingPath, "current-config.json") config.SaveCurrentConfig(currentBuildConfigPath, parsedContent) - if activeConfigPath == "" { - activeConfigPath = currentBuildConfigPath - } + // if activeConfigPath == "" { + // activeConfigPath = currentBuildConfigPath + // } if in.EnableOldCommandServer { Log(LogLevel_DEBUG, LogType_CORE, "Starting Command Server") err = startCommandServer() @@ -205,6 +295,14 @@ func (s *CoreService) ChangeHiddifySettings(ctx context.Context, in *ChangeHiddi func ChangeHiddifySettings(in *ChangeHiddifySettingsRequest) (*CoreInfoResponse, error) { HiddifyOptions = config.DefaultHiddifyOptions() + if in.HiddifySettingsJson == "" { + return &CoreInfoResponse{}, nil + } + settings := db.GetTable[common.AppSettings]() + settings.UpdateInsert(&common.AppSettings{ + Id: "HiddifySettingsJson", + Value: in.HiddifySettingsJson, + }) err := json.Unmarshal([]byte(in.HiddifySettingsJson), HiddifyOptions) if err != nil { return nil, err @@ -299,7 +397,7 @@ func Stop() (*CoreInfoResponse, error) { CoreState: CoreState, MessageType: MessageType_UNEXPECTED_ERROR, Message: "Error while stopping the service.", - }, fmt.Errorf("Error while stopping the service.") + }, fmt.Errorf("error while stopping the service") } Box = nil if oldCommandServer != nil { @@ -309,7 +407,7 @@ func Stop() (*CoreInfoResponse, error) { CoreState: CoreState, MessageType: MessageType_UNEXPECTED_ERROR, Message: "Error while Closing the comand server.", - }, fmt.Errorf("error while Closing the comand server.") + }, fmt.Errorf("error while Closing the comand server") } oldCommandServer = nil } @@ -356,6 +454,21 @@ func Restart(in *StartRequest) (*CoreInfoResponse, error) { return resp, gErr } +func Close() error { + defer config.DeferPanicToError("close", func(err error) { + Log(LogLevel_FATAL, LogType_CORE, err.Error()) + StopAndAlert(MessageType_UNEXPECTED_ERROR, err.Error()) + }) + log.Debug("[Service] Closing") + + _, err := Stop() + CloseGrpcServer() + if err != nil { + return err + } + return nil +} + // func (s *CoreService) Status(ctx context.Context, empty *common.Empty) (*CoreInfoResponse, error) { // return Status() // } diff --git a/v2/hcore/grpc_server.go b/v2/hcore/grpc_server.go index d1f3835..df16d2c 100644 --- a/v2/hcore/grpc_server.go +++ b/v2/hcore/grpc_server.go @@ -5,10 +5,21 @@ package hcore */ import ( + "crypto/tls" + "crypto/x509" + "encoding/pem" + "fmt" "log" "net" + "github.com/hiddify/hiddify-core/v2/hello" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + "github.com/hiddify/hiddify-core/v2/common" + "github.com/hiddify/hiddify-core/v2/common/utils" + + "github.com/hiddify/hiddify-core/v2/db" ) type CoreService struct { @@ -23,9 +34,7 @@ func StartGrpcServer(listenAddressG string, service string) (*grpc.Server, error } s := grpc.NewServer() if service == "core" { - // Setup("./tmp/", "./tmp", "./tmp", 11111, false) - useFlutterBridge = false RegisterCoreServer(s, &CoreService{}) // pb.RegisterExtensionHostServiceServer(s, &extension.ExtensionHostService{}) @@ -52,3 +61,117 @@ func StartCoreGrpcServer(listenAddressG string) (*grpc.Server, error) { func StartHelloGrpcServer(listenAddressG string) (*grpc.Server, error) { return StartGrpcServer(listenAddressG, "hello") } + +var ( + certpair *utils.CertificatePair + grpcServer map[SetupMode]*grpc.Server = make(map[SetupMode]*grpc.Server) + caCertPool = x509.NewCertPool() +) + +// StartGrpcServerByMode starts a gRPC server on the specified address with mTLS. +func StartGrpcServerByMode(listenAddressG string, mode SetupMode) (*grpc.Server, error) { + // Fetch the server private key and public key from the database + if grpcServer[mode] != nil { + Log(LogLevel_WARNING, LogType_CORE, "grpcServer already started") + return grpcServer[mode], nil + } + table := db.GetTable[common.AppSettings]() + grpcServerPrivateKey, err := table.Get("grpc_server_private_key") + grpcServerPublicKey, err2 := table.Get("grpc_server_public_key") + if err != nil || err2 != nil { + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("failed to get grpc_server_private_key and grpc_server_public_key from database: %v %v\n", err, err2)) + certpair, err = utils.GenerateCertificatePair() + if err != nil { + Log(LogLevel_ERROR, LogType_CORE, fmt.Sprintf("failed to generate certificate pair: %v", err)) + + return nil, err + } + table.UpdateInsert( + &common.AppSettings{Id: "grpc_server_public_key", Value: certpair.Certificate}, + &common.AppSettings{Id: "grpc_server_private_key", Value: certpair.PrivateKey}, + ) + } else { + certpair = &utils.CertificatePair{ + Certificate: grpcServerPublicKey.Value.([]byte), + PrivateKey: grpcServerPrivateKey.Value.([]byte), + } + } + + // Load server certificate and private key + serverCert, err := tls.X509KeyPair(certpair.Certificate, certpair.PrivateKey) + if err != nil { + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("failed to load server certificate and key: %v\n", err)) + + return nil, err + } + + // Create TLS credentials for the gRPC server + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{serverCert}, + ClientAuth: tls.RequireAndVerifyClientCert, // Enforce mutual TLS (mTLS) + ClientCAs: caCertPool, // Client CAs to verify client certificates + } + + // Create a new gRPC server with TLS credentials + creds := credentials.NewTLS(tlsConfig) + if mode == GRPC_BACKGROUND_INSECURE || mode == GRPC_NORMAL_INSECURE { + grpcServer[mode] = grpc.NewServer() + } else { + grpcServer[mode] = grpc.NewServer(grpc.Creds(creds)) + } + // Register your gRPC service here + RegisterCoreServer(grpcServer[mode], &CoreService{}) + hello.RegisterHelloServer(grpcServer[mode], &hello.HelloService{}) + + // Listen on the provided address + lis, err := net.Listen("tcp", listenAddressG) + if err != nil { + Log(LogLevel_ERROR, LogType_CORE, fmt.Sprintf("failed to listen on %s: %v\n", listenAddressG, err)) + return nil, err + } + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("grpcServer started on %s\n", listenAddressG)) + log.Printf("Server listening on %s", listenAddressG) + + // Run the server in a goroutine + go func() { + if err := grpcServer[mode].Serve(lis); err != nil { + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("failed to serve: %v\n", err)) + } + Log(LogLevel_DEBUG, LogType_CORE, "Server stopped") + }() + + return grpcServer[mode], nil +} + +// GetGrpcServerPublicKey returns the gRPC server's public key. +func GetGrpcServerPublicKey() []byte { + return certpair.Certificate +} + +// AddGrpcClientPublicKey adds a client's public key to the CA pool for verification. +func AddGrpcClientPublicKey(clientPublicKey []byte) error { + block, _ := pem.Decode(clientPublicKey) + if block == nil || block.Type != "PUBLIC KEY" { + return fmt.Errorf("failed to decode client public key") + } + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + pubKey, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return fmt.Errorf("failed to parse client public key: %v", err) + } + cert = &x509.Certificate{ + PublicKey: pubKey, + } + } + caCertPool.AddCert(cert) + + return nil +} + +func CloseGrpcServer() { + for mode := range grpcServer { + grpcServer[mode].Stop() + grpcServer[mode] = nil + } +} diff --git a/v2/hcore/hcore.pb.go b/v2/hcore/hcore.pb.go index 4bfb736..67ddbe9 100644 --- a/v2/hcore/hcore.pb.go +++ b/v2/hcore/hcore.pb.go @@ -832,11 +832,11 @@ type WarpWireguardConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - PrivateKey string `protobuf:"bytes,1,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` - LocalAddressIpv4 string `protobuf:"bytes,2,opt,name=local_address_ipv4,json=localAddressIpv4,proto3" json:"local_address_ipv4,omitempty"` - LocalAddressIpv6 string `protobuf:"bytes,3,opt,name=local_address_ipv6,json=localAddressIpv6,proto3" json:"local_address_ipv6,omitempty"` - PeerPublicKey string `protobuf:"bytes,4,opt,name=peer_public_key,json=peerPublicKey,proto3" json:"peer_public_key,omitempty"` - ClientId string `protobuf:"bytes,5,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + PrivateKey string `protobuf:"bytes,1,opt,name=private_key,json=private-key,proto3" json:"private_key,omitempty"` + LocalAddressIpv4 string `protobuf:"bytes,2,opt,name=local_address_ipv4,json=local-address-ipv4,proto3" json:"local_address_ipv4,omitempty"` + LocalAddressIpv6 string `protobuf:"bytes,3,opt,name=local_address_ipv6,json=local-address-ipv6,proto3" json:"local_address_ipv6,omitempty"` + PeerPublicKey string `protobuf:"bytes,4,opt,name=peer_public_key,json=peer-public-key,proto3" json:"peer_public_key,omitempty"` + ClientId string `protobuf:"bytes,5,opt,name=client_id,json=client-id,proto3" json:"client_id,omitempty"` } func (x *WarpWireguardConfig) Reset() { @@ -1713,130 +1713,130 @@ var file_v2_hcore_hcore_proto_rawDesc = []byte{ 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xd7, 0x01, 0x0a, 0x13, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xdf, 0x01, 0x0a, 0x13, 0x57, 0x61, 0x72, 0x70, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x49, 0x70, - 0x76, 0x34, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, - 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x49, 0x70, 0x76, 0x36, - 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x16, 0x57, 0x61, 0x72, 0x70, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2c, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x61, 0x72, 0x70, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6c, 0x6f, 0x67, - 0x12, 0x32, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x57, 0x61, 0x72, 0x70, 0x57, 0x69, 0x72, - 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x22, 0x4b, 0x0a, 0x11, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x22, 0x7c, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1b, 0x0a, 0x09, - 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x74, 0x65, 0x6d, 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x62, - 0x75, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x22, - 0x7e, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x39, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x52, 0x0a, 0x1c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x32, 0x0a, 0x15, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, - 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, - 0x73, 0x6f, 0x6e, 0x22, 0x5e, 0x0a, 0x15, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, - 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x65, - 0x62, 0x75, 0x67, 0x22, 0x3f, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, - 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x22, 0x57, 0x0a, 0x15, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x22, 0x2d, 0x0a, - 0x0e, 0x55, 0x72, 0x6c, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x22, 0x7e, 0x0a, 0x19, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x57, 0x61, 0x72, 0x70, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, 0x0a, 0x1c, - 0x53, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x71, 0x0a, 0x0a, 0x4c, - 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, - 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0d, - 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x42, 0x0a, - 0x0a, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, - 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, - 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, - 0x03, 0x2a, 0xcd, 0x02, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x45, 0x4d, 0x50, 0x54, 0x59, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, - 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, - 0x12, 0x0a, 0x0e, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, - 0x45, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x53, 0x45, 0x52, - 0x56, 0x49, 0x43, 0x45, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x4e, 0x45, 0x58, 0x50, 0x45, - 0x43, 0x54, 0x45, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, - 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, - 0x06, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, 0x54, 0x4f, - 0x50, 0x50, 0x45, 0x44, 0x10, 0x07, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, - 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x08, 0x12, 0x18, - 0x0a, 0x14, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, - 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x09, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x53, 0x54, - 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, - 0x10, 0x0a, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x42, 0x55, 0x49, 0x4c, - 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x0b, 0x12, 0x18, 0x0a, - 0x14, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x50, 0x41, 0x52, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x43, - 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x0c, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x52, 0x45, 0x41, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, - 0x0d, 0x2a, 0x42, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, - 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, - 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, - 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, - 0x54, 0x41, 0x4c, 0x10, 0x04, 0x2a, 0x2c, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, - 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, - 0x47, 0x10, 0x02, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x2f, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, - 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x32, 0x2f, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x2d, 0x6b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x70, 0x76, 0x34, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x2d, 0x69, 0x70, 0x76, 0x34, 0x12, 0x2e, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x70, 0x76, 0x36, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x2d, 0x69, 0x70, 0x76, 0x36, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x70, 0x65, 0x65, 0x72, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x12, + 0x1c, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x64, 0x22, 0x8c, 0x01, + 0x0a, 0x16, 0x57, 0x61, 0x72, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x68, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x57, 0x61, 0x72, 0x70, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x07, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, + 0x2e, 0x57, 0x61, 0x72, 0x70, 0x57, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x4b, 0x0a, 0x11, + 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x7c, 0x0a, 0x0c, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x70, 0x61, 0x74, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x7e, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x52, 0x0a, 0x1c, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x48, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x69, 0x64, 0x64, 0x69, + 0x66, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x73, 0x6f, 0x6e, 0x22, 0x5e, 0x0a, 0x15, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x65, 0x6d, 0x70, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, + 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x3f, 0x0a, 0x16, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x57, 0x0a, 0x15, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x74, + 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x54, + 0x61, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, + 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x54, 0x61, 0x67, 0x22, 0x2d, 0x0a, 0x0e, 0x55, 0x72, 0x6c, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x5f, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x54, 0x61, 0x67, 0x22, 0x7e, 0x0a, 0x19, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x57, 0x61, 0x72, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, + 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, 0x0a, 0x1c, 0x53, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x22, 0x71, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x25, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x0f, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, + 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x42, 0x0a, 0x0a, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0b, + 0x0a, 0x07, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x53, + 0x54, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x2a, 0xcd, 0x02, 0x0a, 0x0b, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, + 0x54, 0x59, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x5f, 0x43, 0x4f, + 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x18, 0x0a, + 0x14, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x53, + 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x52, 0x45, 0x41, 0x54, + 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x53, + 0x54, 0x41, 0x52, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x04, 0x12, 0x14, + 0x0a, 0x10, 0x55, 0x4e, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, + 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x4c, 0x52, + 0x45, 0x41, 0x44, 0x59, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x07, 0x12, 0x16, + 0x0a, 0x12, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, + 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, + 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x09, + 0x12, 0x18, 0x0a, 0x14, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4e, 0x43, 0x45, 0x5f, 0x4e, 0x4f, 0x54, + 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x4f, 0x4e, + 0x46, 0x49, 0x47, 0x10, 0x0b, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x50, + 0x41, 0x52, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x0c, 0x12, + 0x18, 0x0a, 0x14, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x49, 0x4e, 0x47, + 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x0d, 0x2a, 0x42, 0x0a, 0x08, 0x4c, 0x6f, 0x67, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x00, + 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, + 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x04, 0x2a, 0x2c, 0x0a, + 0x07, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x45, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x01, 0x12, + 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x02, 0x42, 0x2a, 0x5a, 0x28, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, + 0x79, 0x2f, 0x68, 0x69, 0x64, 0x64, 0x69, 0x66, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, + 0x32, 0x2f, 0x68, 0x63, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/v2/hcore/hcore.proto b/v2/hcore/hcore.proto index 770dd85..ac19131 100644 --- a/v2/hcore/hcore.proto +++ b/v2/hcore/hcore.proto @@ -87,11 +87,11 @@ message WarpAccount { } message WarpWireguardConfig { - string private_key = 1; - string local_address_ipv4 = 2; - string local_address_ipv6 = 3; - string peer_public_key = 4; - string client_id=5; + string private_key = 1 [json_name = "private-key"]; + string local_address_ipv4 = 2 [json_name = "local-address-ipv4"]; + string local_address_ipv6 = 3 [json_name = "local-address-ipv6"]; + string peer_public_key = 4 [json_name = "peer-public-key"]; + string client_id=5 [json_name = "client-id"]; } message WarpGenerationResponse { diff --git a/v2/hcore/logproto.go b/v2/hcore/logproto.go index 83885f6..bd82e5f 100644 --- a/v2/hcore/logproto.go +++ b/v2/hcore/logproto.go @@ -2,7 +2,6 @@ package hcore import ( "fmt" - "time" common "github.com/hiddify/hiddify-core/v2/common" "github.com/sagernet/sing/common/observable" @@ -13,16 +12,16 @@ func NewObserver[T any](listenerBufferSize int) *observable.Observer[T] { return observable.NewObserver(observable.NewSubscriber[T](listenerBufferSize), listenerBufferSize) } -var logObserver = NewObserver[LogMessage](10) +var logObserver = NewObserver[*LogMessage](10) -func Log(level LogLevel, typ LogType, message string) { +func Log(level LogLevel, typ LogType, message ...any) { if level != LogLevel_DEBUG { fmt.Printf("%s %s %s\n", level, typ, message) } - logObserver.Emit(LogMessage{ + logObserver.Emit(&LogMessage{ Level: level, Type: typ, - Message: message, + Message: fmt.Sprint(message...), }) } @@ -37,8 +36,8 @@ func (s *CoreService) LogListener(req *common.Empty, stream grpc.ServerStreaming case <-stopch: return nil case info := <-logSub: - stream.Send(&info) - case <-time.After(500 * time.Millisecond): + stream.Send(info) + // case <-time.After(500 * time.Millisecond): } } } diff --git a/v2/hcore/old_command_server.go b/v2/hcore/old_command_server.go index 5202a11..ff0167b 100644 --- a/v2/hcore/old_command_server.go +++ b/v2/hcore/old_command_server.go @@ -23,7 +23,7 @@ func (csh *CommandServerHandler) ServiceReload() error { Box.Close() Box = nil } - _, err := StartService(&StartRequest{ + _, err := Start(&StartRequest{ EnableOldCommandServer: true, DelayStart: true, }) diff --git a/v2/hcore/platform_interface.go b/v2/hcore/platform_interface.go new file mode 100644 index 0000000..8294bc5 --- /dev/null +++ b/v2/hcore/platform_interface.go @@ -0,0 +1,129 @@ +package hcore + +import ( + "fmt" + + "github.com/sagernet/sing-box/experimental/libbox" +) + +var _ libbox.PlatformInterface = (*HiddifyPlatformInterface)(nil) + +type HiddifyPlatformInterface struct { + platform libbox.PlatformInterface +} + +func (h *HiddifyPlatformInterface) UsePlatformAutoDetectInterfaceControl() bool { + if h.platform == nil { + return true + } + return h.platform.UsePlatformAutoDetectInterfaceControl() +} + +func (h *HiddifyPlatformInterface) AutoDetectInterfaceControl(fd int32) error { + if h.platform == nil { + return nil + } + return h.platform.AutoDetectInterfaceControl(fd) +} + +func (h *HiddifyPlatformInterface) OpenTun(options libbox.TunOptions) (int32, error) { + if h.platform == nil { + return 0, fmt.Errorf("platform is nil") + } + return h.platform.OpenTun(options) +} + +func (h *HiddifyPlatformInterface) WriteLog(message string) { + Log(LogLevel_DEBUG, LogType_CORE, message) +} + +func (h *HiddifyPlatformInterface) UseProcFS() bool { + if h.platform == nil { + return false + } + return h.platform.UseProcFS() +} + +func (h *HiddifyPlatformInterface) FindConnectionOwner(ipProtocol int32, sourceAddress string, sourcePort int32, destinationAddress string, destinationPort int32) (int32, error) { + if h.platform == nil { + return 0, fmt.Errorf("platform is nil") + } + return h.platform.FindConnectionOwner(ipProtocol, sourceAddress, sourcePort, destinationAddress, destinationPort) +} + +func (h *HiddifyPlatformInterface) PackageNameByUid(uid int32) (string, error) { + if h.platform == nil { + return "", fmt.Errorf("platform is nil") + } + return h.platform.PackageNameByUid(uid) +} + +func (h *HiddifyPlatformInterface) UIDByPackageName(packageName string) (int32, error) { + if h.platform == nil { + return 0, fmt.Errorf("platform is nil") + } + return h.platform.UIDByPackageName(packageName) +} + +func (h *HiddifyPlatformInterface) UsePlatformDefaultInterfaceMonitor() bool { + if h.platform == nil { + return false + } + return h.platform.UsePlatformDefaultInterfaceMonitor() +} + +func (h *HiddifyPlatformInterface) StartDefaultInterfaceMonitor(listener libbox.InterfaceUpdateListener) error { + if h.platform == nil { + return fmt.Errorf("platform is nil") + } + return h.platform.StartDefaultInterfaceMonitor(listener) +} + +func (h *HiddifyPlatformInterface) CloseDefaultInterfaceMonitor(listener libbox.InterfaceUpdateListener) error { + if h.platform == nil { + return fmt.Errorf("platform is nil") + } + return h.platform.CloseDefaultInterfaceMonitor(listener) +} + +func (h *HiddifyPlatformInterface) UsePlatformInterfaceGetter() bool { + if h.platform == nil { + return false + } + return h.platform.UsePlatformInterfaceGetter() +} + +func (h *HiddifyPlatformInterface) GetInterfaces() (libbox.NetworkInterfaceIterator, error) { + if h.platform == nil { + return nil, fmt.Errorf("platform is nil") + } + return h.platform.GetInterfaces() +} + +func (h *HiddifyPlatformInterface) UnderNetworkExtension() bool { + if h.platform == nil { + return false + } + return h.platform.UnderNetworkExtension() +} + +func (h *HiddifyPlatformInterface) IncludeAllNetworks() bool { + if h.platform == nil { + return false + } + return h.platform.IncludeAllNetworks() +} + +func (h *HiddifyPlatformInterface) ReadWIFIState() *libbox.WIFIState { + if h.platform == nil { + return nil + } + return h.platform.ReadWIFIState() +} + +func (h *HiddifyPlatformInterface) ClearDNSCache() { + if h.platform == nil { + return + } + h.platform.ClearDNSCache() +} diff --git a/v2/hcore/service.go b/v2/hcore/service.go index 699ad0e..a7981cc 100644 --- a/v2/hcore/service.go +++ b/v2/hcore/service.go @@ -2,12 +2,16 @@ package hcore import ( "context" + "fmt" "io" "os" "runtime" runtimeDebug "runtime/debug" "time" + "github.com/hiddify/hiddify-core/config" + common "github.com/hiddify/hiddify-core/v2/common" + "github.com/hiddify/hiddify-core/v2/db" "github.com/hiddify/hiddify-core/v2/service_manager" B "github.com/sagernet/sing-box" @@ -33,18 +37,43 @@ func InitHiddifyService() error { return service_manager.StartServices() } -func Setup(basePath string, workingPath string, tempPath string, statusPort int64, debug bool) error { - statusPropagationPort = int64(statusPort) +type SetupMode int + +const ( + OLD SetupMode = 0 + GRPC_NORMAL SetupMode = 1 + GRPC_BACKGROUND SetupMode = 2 + GRPC_NORMAL_INSECURE SetupMode = 3 + GRPC_BACKGROUND_INSECURE SetupMode = 4 +) + +type SetupParameters struct { + BasePath string + WorkingDir string + TempDir string + FlutterStatusPort int64 + Listen string + Secret string + Debug bool + Mode SetupMode +} + +func Setup(params SetupParameters) error { + defer config.DeferPanicToError("setup", func(err error) { + Log(LogLevel_FATAL, LogType_CORE, err.Error()) + }) tcpConn := runtime.GOOS == "windows" // TODO add TVOS - libbox.Setup(basePath, workingPath, tempPath, tcpConn) - sWorkingPath = workingPath + libbox.Setup(params.BasePath, params.WorkingDir, params.TempDir, tcpConn) + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("libbox.Setup success %s %s %s %v", params.BasePath, params.WorkingDir, params.TempDir, tcpConn)) + + sWorkingPath = params.WorkingDir os.Chdir(sWorkingPath) - sTempPath = tempPath + sTempPath = params.TempDir sUserID = os.Getuid() sGroupID = os.Getgid() var defaultWriter io.Writer - if !debug { + if !params.Debug { defaultWriter = io.Discard } factory, err := log.New( @@ -63,6 +92,33 @@ func Setup(basePath string, workingPath string, tempPath string, statusPort int6 if err != nil { return E.Cause(err, "create logger") } + + Log(LogLevel_DEBUG, LogType_CORE, fmt.Sprintf("StartGrpcServerByMode %s %d\n", params.Listen, params.Mode)) + switch params.Mode { + case OLD: + statusPropagationPort = int64(params.FlutterStatusPort) + default: + _, err := StartGrpcServerByMode(params.Listen, params.Mode) + + useFlutterBridge = false + if err != nil { + return err + } + } + settings := db.GetTable[common.AppSettings]() + val, err := settings.Get("HiddifySettingsJson") + if val == nil || err != nil { + _, err := ChangeHiddifySettings(&ChangeHiddifySettingsRequest{HiddifySettingsJson: ""}) + if err != nil { + Log(LogLevel_DEBUG, LogType_CORE, E.Cause(err, "ChangeHiddifySettings").Error()) + } + } else { + _, err := ChangeHiddifySettings(&ChangeHiddifySettingsRequest{HiddifySettingsJson: val.Value.(string)}) + if err != nil { + Log(LogLevel_DEBUG, LogType_CORE, E.Cause(err, "ChangeHiddifySettings").Error()) + } + + } return InitHiddifyService() } diff --git a/v2/hcore/standalone.go b/v2/hcore/standalone.go index 645f6b5..2e6e81e 100644 --- a/v2/hcore/standalone.go +++ b/v2/hcore/standalone.go @@ -175,7 +175,14 @@ func buildConfig(configContent string, options config.HiddifyOptions) (string, e fmt.Printf("Open http://localhost:6756/ui/?secret=%s in your browser\n", finalconfig.Experimental.ClashAPI.Secret) - if err := Setup("./", "./", "./tmp", 0, false); err != nil { + if err := Setup( + SetupParameters{ + BasePath: "./", + WorkingDir: "./", + TempDir: "./tmp", + FlutterStatusPort: 0, + Debug: false, + }); err != nil { return "", fmt.Errorf("failed to set up global configuration: %w", err) } diff --git a/v2/profile/test/profile_test.go b/v2/profile/test/profile_test.go index aedf729..a5b5c8f 100644 --- a/v2/profile/test/profile_test.go +++ b/v2/profile/test/profile_test.go @@ -8,7 +8,7 @@ import ( ) func TestAddByContent(t *testing.T) { - entity, err := profile.AddByUrl("https://raw.githubusercontent.com/hiddify/hiddify-next/refs/heads/main/test.configs/warp", false) + entity, err := profile.AddByUrl("https://raw.githubusercontent.com/hiddify/hiddify-next/refs/heads/main/test.configs/warp", "", false) if err != nil { t.Fatalf("expected no error, but got: %v", err) }