Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WebUI Support for V2Ray #3284

Merged
merged 14 commits into from
Jan 17, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add support for web based grpc
xiaokangwang committed Jan 14, 2025
commit 8159959308538d5fed7f32911623055381c0a3cc
17 changes: 16 additions & 1 deletion app/commander/commander.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ package commander

import (
"context"
"github.com/v2fly/v2ray-core/v5/features"
"net"
"sync"

@@ -17,6 +18,12 @@ import (
"github.com/v2fly/v2ray-core/v5/infra/conf/v5cfg"
)

type CommanderIfce interface {
features.Feature

ExtractGrpcServer() *grpc.Server
}

// Commander is a V2Ray feature that provides gRPC methods to external clients.
type Commander struct {
sync.Mutex
@@ -57,7 +64,7 @@ func NewCommander(ctx context.Context, config *Config) (*Commander, error) {

// Type implements common.HasType.
func (c *Commander) Type() interface{} {
return (*Commander)(nil)
return (*CommanderIfce)(nil)
}

// Start implements common.Runnable.
@@ -103,6 +110,14 @@ func (c *Commander) Close() error {
return nil
}

// ExtractGrpcServer extracts the gRPC server from Commander.
// Private function for core code base.
func (c *Commander) ExtractGrpcServer() *grpc.Server {
c.Lock()
defer c.Unlock()
return c.server
}

func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
return NewCommander(ctx, cfg.(*Config))
92 changes: 23 additions & 69 deletions app/commander/config.pb.go
Original file line number Diff line number Diff line change
@@ -18,24 +18,21 @@ const (

// Config is the settings for Commander.
type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

state protoimpl.MessageState `protogen:"open.v1"`
// Tag of the outbound handler that handles grpc connections.
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
// Services that supported by this server. All services must implement Service
// interface.
Service []*anypb.Any `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
Service []*anypb.Any `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}

func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_app_commander_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_app_commander_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}

func (x *Config) String() string {
@@ -46,7 +43,7 @@ func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -77,18 +74,16 @@ func (x *Config) GetService() []*anypb.Any {

// ReflectionConfig is the placeholder config for ReflectionService.
type ReflectionConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}

func (x *ReflectionConfig) Reset() {
*x = ReflectionConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_app_commander_config_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_app_commander_config_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}

func (x *ReflectionConfig) String() string {
@@ -99,7 +94,7 @@ func (*ReflectionConfig) ProtoMessage() {}

func (x *ReflectionConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_config_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -115,21 +110,18 @@ func (*ReflectionConfig) Descriptor() ([]byte, []int) {
}

type SimplifiedConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Name []string `protobuf:"bytes,2,rep,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields

Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Name []string `protobuf:"bytes,2,rep,name=name,proto3" json:"name,omitempty"`
sizeCache protoimpl.SizeCache
}

func (x *SimplifiedConfig) Reset() {
*x = SimplifiedConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_app_commander_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_app_commander_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}

func (x *SimplifiedConfig) String() string {
@@ -140,7 +132,7 @@ func (*SimplifiedConfig) ProtoMessage() {}

func (x *SimplifiedConfig) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_config_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -215,7 +207,7 @@ func file_app_commander_config_proto_rawDescGZIP() []byte {
}

var file_app_commander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_app_commander_config_proto_goTypes = []interface{}{
var file_app_commander_config_proto_goTypes = []any{
(*Config)(nil), // 0: v2ray.core.app.commander.Config
(*ReflectionConfig)(nil), // 1: v2ray.core.app.commander.ReflectionConfig
(*SimplifiedConfig)(nil), // 2: v2ray.core.app.commander.SimplifiedConfig
@@ -235,44 +227,6 @@ func file_app_commander_config_proto_init() {
if File_app_commander_config_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_app_commander_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_commander_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReflectionConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_app_commander_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SimplifiedConfig); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
14 changes: 14 additions & 0 deletions app/commander/outbound.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,13 @@ import (
"github.com/v2fly/v2ray-core/v5/transport"
)

func NewOutboundListener() *OutboundListener {
return &OutboundListener{
buffer: make(chan net.Conn, 4),
done: done.New(),
}
}

// OutboundListener is a net.Listener for listening gRPC connections.
type OutboundListener struct {
buffer chan net.Conn
@@ -59,6 +66,13 @@ func (l *OutboundListener) Addr() net.Addr {
}
}

func NewOutbound(tag string, listener *OutboundListener) *Outbound {
return &Outbound{
tag: tag,
listener: listener,
}
}

// Outbound is a outbound.Handler that handles gRPC connections.
type Outbound struct {
tag string
135 changes: 135 additions & 0 deletions app/commander/webcommander/config.pb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package webcommander

import (
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)

const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type Config struct {
state protoimpl.MessageState `protogen:"open.v1"`
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}

func (x *Config) Reset() {
*x = Config{}
mi := &file_app_commander_webcommander_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}

func (x *Config) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_commander_webcommander_config_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_app_commander_webcommander_config_proto_rawDescGZIP(), []int{0}
}

func (x *Config) GetTag() string {
if x != nil {
return x.Tag
}
return ""
}

var File_app_commander_webcommander_config_proto protoreflect.FileDescriptor

var file_app_commander_webcommander_config_proto_rawDesc = []byte{
0x0a, 0x27, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f,
0x77, 0x65, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x76, 0x32, 0x72, 0x61, 0x79,
0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x65, 0x72, 0x2e, 0x77, 0x65, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72,
0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78,
0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0x37, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03,
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x3a, 0x1b,
0x82, 0xb5, 0x18, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0c, 0x77,
0x65, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x42, 0x90, 0x01, 0x0a, 0x29,
0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61,
0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2e, 0x77, 0x65, 0x62,
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32,
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x61, 0x70, 0x70, 0x2f,
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x77, 0x65, 0x62, 0x63, 0x6f, 0x6d,
0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x25, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43,
0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
0x72, 0x2e, 0x57, 0x65, 0x62, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
file_app_commander_webcommander_config_proto_rawDescOnce sync.Once
file_app_commander_webcommander_config_proto_rawDescData = file_app_commander_webcommander_config_proto_rawDesc
)

func file_app_commander_webcommander_config_proto_rawDescGZIP() []byte {
file_app_commander_webcommander_config_proto_rawDescOnce.Do(func() {
file_app_commander_webcommander_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_commander_webcommander_config_proto_rawDescData)
})
return file_app_commander_webcommander_config_proto_rawDescData
}

var file_app_commander_webcommander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_app_commander_webcommander_config_proto_goTypes = []any{
(*Config)(nil), // 0: v2ray.core.app.commander.webcommander.Config
}
var file_app_commander_webcommander_config_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}

func init() { file_app_commander_webcommander_config_proto_init() }
func file_app_commander_webcommander_config_proto_init() {
if File_app_commander_webcommander_config_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_commander_webcommander_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_app_commander_webcommander_config_proto_goTypes,
DependencyIndexes: file_app_commander_webcommander_config_proto_depIdxs,
MessageInfos: file_app_commander_webcommander_config_proto_msgTypes,
}.Build()
File_app_commander_webcommander_config_proto = out.File
file_app_commander_webcommander_config_proto_rawDesc = nil
file_app_commander_webcommander_config_proto_goTypes = nil
file_app_commander_webcommander_config_proto_depIdxs = nil
}
16 changes: 16 additions & 0 deletions app/commander/webcommander/config.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";

package v2ray.core.app.commander.webcommander;
option csharp_namespace = "V2Ray.Core.App.Commander.WebCommander";
option go_package = "github.com/v2fly/v2ray-core/v5/app/commander/webcommander";
option java_package = "com.v2ray.core.app.commander.webcommander";
option java_multiple_files = true;

import "common/protoext/extensions.proto";

message Config {
option (v2ray.core.common.protoext.message_opt).type = "service";
option (v2ray.core.common.protoext.message_opt).short_name = "webcommander";

string tag = 1;
}
Loading