Skip to content

Commit 69b0907

Browse files
authored
Add WebUI Support for V2Ray (#3284)
* Add support for web based grpc * Avoid panic in observatory command: incorrect tag * Add WebCommander app for web based client * Add WebCommander app for web based client * Add urlline subscription container format support * avoid panic when serving user request * refine subscription info api * fix start consistency issue in web commander * fix webcommander import style * fix urlline parsing * fix crash in subscription commander * add webroot file serving at webcommmander * fix crash when observatory is not found * add autogenerated subscriptionmgr err
1 parent 4adda58 commit 69b0907

31 files changed

+2101
-152
lines changed

app/commander/commander.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package commander
44

55
import (
66
"context"
7+
"github.com/v2fly/v2ray-core/v5/features"
78
"net"
89
"sync"
910

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

21+
type CommanderIfce interface {
22+
features.Feature
23+
24+
ExtractGrpcServer() *grpc.Server
25+
}
26+
2027
// Commander is a V2Ray feature that provides gRPC methods to external clients.
2128
type Commander struct {
2229
sync.Mutex
@@ -57,7 +64,7 @@ func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
5764

5865
// Type implements common.HasType.
5966
func (c *Commander) Type() interface{} {
60-
return (*Commander)(nil)
67+
return (*CommanderIfce)(nil)
6168
}
6269

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

113+
// ExtractGrpcServer extracts the gRPC server from Commander.
114+
// Private function for core code base.
115+
func (c *Commander) ExtractGrpcServer() *grpc.Server {
116+
c.Lock()
117+
defer c.Unlock()
118+
return c.server
119+
}
120+
106121
func init() {
107122
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
108123
return NewCommander(ctx, cfg.(*Config))

app/commander/config.pb.go

+23-69
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,21 @@ const (
1818

1919
// Config is the settings for Commander.
2020
type Config struct {
21-
state protoimpl.MessageState
22-
sizeCache protoimpl.SizeCache
23-
unknownFields protoimpl.UnknownFields
24-
21+
state protoimpl.MessageState `protogen:"open.v1"`
2522
// Tag of the outbound handler that handles grpc connections.
2623
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
2724
// Services that supported by this server. All services must implement Service
2825
// interface.
29-
Service []*anypb.Any `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
26+
Service []*anypb.Any `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
27+
unknownFields protoimpl.UnknownFields
28+
sizeCache protoimpl.SizeCache
3029
}
3130

3231
func (x *Config) Reset() {
3332
*x = Config{}
34-
if protoimpl.UnsafeEnabled {
35-
mi := &file_app_commander_config_proto_msgTypes[0]
36-
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
37-
ms.StoreMessageInfo(mi)
38-
}
33+
mi := &file_app_commander_config_proto_msgTypes[0]
34+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
35+
ms.StoreMessageInfo(mi)
3936
}
4037

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

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

7875
// ReflectionConfig is the placeholder config for ReflectionService.
7976
type ReflectionConfig struct {
80-
state protoimpl.MessageState
81-
sizeCache protoimpl.SizeCache
77+
state protoimpl.MessageState `protogen:"open.v1"`
8278
unknownFields protoimpl.UnknownFields
79+
sizeCache protoimpl.SizeCache
8380
}
8481

8582
func (x *ReflectionConfig) Reset() {
8683
*x = ReflectionConfig{}
87-
if protoimpl.UnsafeEnabled {
88-
mi := &file_app_commander_config_proto_msgTypes[1]
89-
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
90-
ms.StoreMessageInfo(mi)
91-
}
84+
mi := &file_app_commander_config_proto_msgTypes[1]
85+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
86+
ms.StoreMessageInfo(mi)
9287
}
9388

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

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

117112
type SimplifiedConfig struct {
118-
state protoimpl.MessageState
119-
sizeCache protoimpl.SizeCache
113+
state protoimpl.MessageState `protogen:"open.v1"`
114+
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
115+
Name []string `protobuf:"bytes,2,rep,name=name,proto3" json:"name,omitempty"`
120116
unknownFields protoimpl.UnknownFields
121-
122-
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
123-
Name []string `protobuf:"bytes,2,rep,name=name,proto3" json:"name,omitempty"`
117+
sizeCache protoimpl.SizeCache
124118
}
125119

126120
func (x *SimplifiedConfig) Reset() {
127121
*x = SimplifiedConfig{}
128-
if protoimpl.UnsafeEnabled {
129-
mi := &file_app_commander_config_proto_msgTypes[2]
130-
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
131-
ms.StoreMessageInfo(mi)
132-
}
122+
mi := &file_app_commander_config_proto_msgTypes[2]
123+
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
124+
ms.StoreMessageInfo(mi)
133125
}
134126

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

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

217209
var file_app_commander_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
218-
var file_app_commander_config_proto_goTypes = []interface{}{
210+
var file_app_commander_config_proto_goTypes = []any{
219211
(*Config)(nil), // 0: v2ray.core.app.commander.Config
220212
(*ReflectionConfig)(nil), // 1: v2ray.core.app.commander.ReflectionConfig
221213
(*SimplifiedConfig)(nil), // 2: v2ray.core.app.commander.SimplifiedConfig
@@ -235,44 +227,6 @@ func file_app_commander_config_proto_init() {
235227
if File_app_commander_config_proto != nil {
236228
return
237229
}
238-
if !protoimpl.UnsafeEnabled {
239-
file_app_commander_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
240-
switch v := v.(*Config); i {
241-
case 0:
242-
return &v.state
243-
case 1:
244-
return &v.sizeCache
245-
case 2:
246-
return &v.unknownFields
247-
default:
248-
return nil
249-
}
250-
}
251-
file_app_commander_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
252-
switch v := v.(*ReflectionConfig); i {
253-
case 0:
254-
return &v.state
255-
case 1:
256-
return &v.sizeCache
257-
case 2:
258-
return &v.unknownFields
259-
default:
260-
return nil
261-
}
262-
}
263-
file_app_commander_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
264-
switch v := v.(*SimplifiedConfig); i {
265-
case 0:
266-
return &v.state
267-
case 1:
268-
return &v.sizeCache
269-
case 2:
270-
return &v.unknownFields
271-
default:
272-
return nil
273-
}
274-
}
275-
}
276230
type x struct{}
277231
out := protoimpl.TypeBuilder{
278232
File: protoimpl.DescBuilder{

app/commander/outbound.go

+14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import (
1010
"github.com/v2fly/v2ray-core/v5/transport"
1111
)
1212

13+
func NewOutboundListener() *OutboundListener {
14+
return &OutboundListener{
15+
buffer: make(chan net.Conn, 4),
16+
done: done.New(),
17+
}
18+
}
19+
1320
// OutboundListener is a net.Listener for listening gRPC connections.
1421
type OutboundListener struct {
1522
buffer chan net.Conn
@@ -59,6 +66,13 @@ func (l *OutboundListener) Addr() net.Addr {
5966
}
6067
}
6168

69+
func NewOutbound(tag string, listener *OutboundListener) *Outbound {
70+
return &Outbound{
71+
tag: tag,
72+
listener: listener,
73+
}
74+
}
75+
6276
// Outbound is a outbound.Handler that handles gRPC connections.
6377
type Outbound struct {
6478
tag string

0 commit comments

Comments
 (0)