forked from v2ray/v2ray-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
v2ray.go
executable file
·223 lines (190 loc) · 6.55 KB
/
v2ray.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
package core
import (
"context"
"sync"
"v2ray.com/core/common"
"v2ray.com/core/common/serial"
"v2ray.com/core/common/uuid"
)
// Server is an instance of V2Ray. At any time, there must be at most one Server instance running.
// Deprecated. Use Instance directly.
type Server interface {
common.Runnable
}
// Feature is the interface for V2Ray features. All features must implement this interface.
// All existing features have an implementation in app directory. These features can be replaced by third-party ones.
type Feature interface {
common.Runnable
}
// Instance combines all functionalities in V2Ray.
type Instance struct {
dnsClient syncDNSClient
policyManager syncPolicyManager
dispatcher syncDispatcher
router syncRouter
ihm syncInboundHandlerManager
ohm syncOutboundHandlerManager
stats syncStatManager
access sync.Mutex
features []Feature
id uuid.UUID
running bool
}
// New returns a new V2Ray instance based on given configuration.
// The instance is not started at this point.
// To ensure V2Ray instance works properly, the config must contain one Dispatcher, one InboundHandlerManager and one OutboundHandlerManager. Other features are optional.
func New(config *Config) (*Instance, error) {
var server = &Instance{
id: uuid.New(),
}
if config.Transport != nil {
PrintDeprecatedFeatureWarning("global tranport settings")
}
if err := config.Transport.Apply(); err != nil {
return nil, err
}
for _, appSettings := range config.App {
settings, err := appSettings.GetInstance()
if err != nil {
return nil, err
}
if _, err := CreateObject(server, settings); err != nil {
return nil, err
}
}
for _, inbound := range config.Inbound {
rawHandler, err := CreateObject(server, inbound)
if err != nil {
return nil, err
}
handler, ok := rawHandler.(InboundHandler)
if !ok {
return nil, newError("not an InboundHandler")
}
if err := server.InboundHandlerManager().AddHandler(context.Background(), handler); err != nil {
return nil, err
}
}
for _, outbound := range config.Outbound {
rawHandler, err := CreateObject(server, outbound)
if err != nil {
return nil, err
}
handler, ok := rawHandler.(OutboundHandler)
if !ok {
return nil, newError("not an OutboundHandler")
}
if err := server.OutboundHandlerManager().AddHandler(context.Background(), handler); err != nil {
return nil, err
}
}
return server, nil
}
// ID returns a unique ID for this V2Ray instance.
func (s *Instance) ID() uuid.UUID {
return s.id
}
// Close shutdown the V2Ray instance.
func (s *Instance) Close() error {
s.access.Lock()
defer s.access.Unlock()
s.running = false
var errors []interface{}
for _, f := range s.allFeatures() {
if err := f.Close(); err != nil {
errors = append(errors, err)
}
}
if len(errors) > 0 {
return newError("failed to close all features").Base(newError(serial.Concat(errors...)))
}
return nil
}
// Start starts the V2Ray instance, including all registered features. When Start returns error, the state of the instance is unknown.
// A V2Ray instance can be started only once. Upon closing, the instance is not guaranteed to start again.
func (s *Instance) Start() error {
s.access.Lock()
defer s.access.Unlock()
s.running = true
for _, f := range s.allFeatures() {
if err := f.Start(); err != nil {
return err
}
}
newError("V2Ray ", Version(), " started").AtWarning().WriteToLog()
return nil
}
// RegisterFeature registers the given feature into V2Ray.
// If feature is one of the following types, the corresponding feature in this Instance
// will be replaced: DNSClient, PolicyManager, Router, Dispatcher, InboundHandlerManager, OutboundHandlerManager.
func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error {
running := false
switch feature.(type) {
case DNSClient, *DNSClient:
s.dnsClient.Set(instance.(DNSClient))
case PolicyManager, *PolicyManager:
s.policyManager.Set(instance.(PolicyManager))
case Router, *Router:
s.router.Set(instance.(Router))
case Dispatcher, *Dispatcher:
s.dispatcher.Set(instance.(Dispatcher))
case InboundHandlerManager, *InboundHandlerManager:
s.ihm.Set(instance.(InboundHandlerManager))
case OutboundHandlerManager, *OutboundHandlerManager:
s.ohm.Set(instance.(OutboundHandlerManager))
case StatManager, *StatManager:
s.stats.Set(instance.(StatManager))
default:
s.access.Lock()
s.features = append(s.features, instance)
running = s.running
s.access.Unlock()
}
if running {
return instance.Start()
}
return nil
}
func (s *Instance) allFeatures() []Feature {
return append([]Feature{s.DNSClient(), s.PolicyManager(), s.Dispatcher(), s.Router(), s.InboundHandlerManager(), s.OutboundHandlerManager(), s.Stats()}, s.features...)
}
// GetFeature returns a feature that was registered in this Instance. Nil if not found.
// The returned Feature must implement common.HasType and whose type equals to the given feature type.
func (s *Instance) GetFeature(featureType interface{}) Feature {
for _, f := range s.features {
if hasType, ok := f.(common.HasType); ok {
if hasType.Type() == featureType {
return f
}
}
}
return nil
}
// DNSClient returns the DNSClient used by this Instance. The returned DNSClient is always functional.
func (s *Instance) DNSClient() DNSClient {
return &(s.dnsClient)
}
// PolicyManager returns the PolicyManager used by this Instance. The returned PolicyManager is always functional.
func (s *Instance) PolicyManager() PolicyManager {
return &(s.policyManager)
}
// Router returns the Router used by this Instance. The returned Router is always functional.
func (s *Instance) Router() Router {
return &(s.router)
}
// Dispatcher returns the Dispatcher used by this Instance. If Dispatcher was not registered before, the returned value doesn't work, although it is not nil.
func (s *Instance) Dispatcher() Dispatcher {
return &(s.dispatcher)
}
// InboundHandlerManager returns the InboundHandlerManager used by this Instance. If InboundHandlerManager was not registered before, the returned value doesn't work.
func (s *Instance) InboundHandlerManager() InboundHandlerManager {
return &(s.ihm)
}
// OutboundHandlerManager returns the OutboundHandlerManager used by this Instance. If OutboundHandlerManager was not registered before, the returned value doesn't work.
func (s *Instance) OutboundHandlerManager() OutboundHandlerManager {
return &(s.ohm)
}
// Stats returns the StatManager used by this Instance. If StatManager was not registered before, the returned value doesn't work.
func (s *Instance) Stats() StatManager {
return &(s.stats)
}