我发现自己用go语言写了这个久,没有高级的语言应用,只会用基础的用法进行CRUD。v2ray是一个go语言项目,所以希望借这个项目,来提高自己的go语言编程能力。
Closable
Interruptible
Runnable 含(Closable)
HasType
type Feature interface {common.HasTypecommon.Runnable
}
type Closable interface {// Close release all resources used by this object, including goroutines.Close() error
}type Runnable interface {// Start starts the runnable object. Upon the method returning nil, the object begins to function properly.Start() errorClosable
}type Server interface {common.Runnable
}// Instance combines all functionalities in V2Ray.
type Instance struct {access sync.Mutex // 锁features []features.Feature // instance的功能featureResolutions []resolutionrunning bool // 运行状态ctx context.Context
}
// main/main.go
func main() {flag.Parse()printVersion()if *version {return}server, err := startV2Ray()if err != nil {fmt.Println(err)// Configuration error. Exit with a special value to prevent systemd from restarting.os.Exit(23)}if *test {fmt.Println("Configuration OK.")os.Exit(0)}if err := server.Start(); err != nil {fmt.Println("Failed to start", err)os.Exit(-1)}defer server.Close()// Explicitly triggering GC to remove garbage from config loading.runtime.GC(){osSignals := make(chan os.Signal, 1)signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM)<-osSignals}
}func startV2Ray() (core.Server, error) {configFiles, err := getConfigFilePath()if err != nil {return nil, err}config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)if err != nil {return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)}server, err := core.New(config)if err != nil {return nil, newError("failed to create server").Base(err)}return server, nil
}// v2ray.go
func New(config *Config) (*Instance, error) {var server = &Instance{ctx: context.Background()}err, done := initInstanceWithConfig(config, server)if done {return nil, err}return server, nil
}
config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)
serial.LoadJSONConfig(v)
这行,他首先会解析json配置到infra/conf/v2ray.go定义的结构体type Config struct {Port uint16 `json:"port"` // Port of this Point server. Deprecated.LogConfig *LogConfig `json:"log"`RouterConfig *RouterConfig `json:"routing"`DNSConfig *DnsConfig `json:"dns"`InboundConfigs []InboundDetourConfig `json:"inbounds"`OutboundConfigs []OutboundDetourConfig `json:"outbounds"`InboundConfig *InboundDetourConfig `json:"inbound"` // Deprecated.OutboundConfig *OutboundDetourConfig `json:"outbound"` // Deprecated.InboundDetours []InboundDetourConfig `json:"inboundDetour"` // Deprecated.OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` // Deprecated.Transport *TransportConfig `json:"transport"`Policy *PolicyConfig `json:"policy"`Api *ApiConfig `json:"api"`Stats *StatsConfig `json:"stats"`Reverse *ReverseConfig `json:"reverse"`
}
然后会调用jsonConfig.Build()
,转化为如下pb格式的结构体。
config.pb.go定义的配置,供V2Ray运行使用。
// Config is the master config of V2Ray. V2Ray takes this config as input and
// functions accordingly.
type Config struct {state protoimpl.MessageStatesizeCache protoimpl.SizeCacheunknownFields protoimpl.UnknownFields// Inbound handler configurations. Must have at least one item.Inbound []*InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbound,proto3" json:"inbound,omitempty"`// Outbound handler configurations. Must have at least one item. The first// item is used as default for routing.Outbound []*OutboundHandlerConfig `protobuf:"bytes,2,rep,name=outbound,proto3" json:"outbound,omitempty"`// App is for configurations of all features in V2Ray. A feature must// implement the Feature interface, and its config type must be registered// through common.RegisterConfig.App []*serial.TypedMessage `protobuf:"bytes,4,rep,name=app,proto3" json:"app,omitempty"`// Transport settings.// Deprecated. Each inbound and outbound should choose their own transport// config. Date to remove: 2020-01-13//// Deprecated: Do not use.Transport *transport.Config `protobuf:"bytes,5,opt,name=transport,proto3" json:"transport,omitempty"`// Configuration for extensions. The config may not work if corresponding// extension is not loaded into V2Ray. V2Ray will ignore such config during// initialization.Extension []*serial.TypedMessage `protobuf:"bytes,6,rep,name=extension,proto3" json:"extension,omitempty"`
}
func initInstanceWithConfig(config *Config, server *Instance) (error, bool) {...essentialFeatures := []struct {Type interface{}Instance features.Feature}{{dns.ClientType(), localdns.New()},{policy.ManagerType(), policy.DefaultManager{}},{routing.RouterType(), routing.DefaultRouter{}},{stats.ManagerType(), stats.NoopManager{}},}for _, f := range essentialFeatures {if server.GetFeature(f.Type) == nil {if err := server.AddFeature(f.Instance); err != nil {return err, true}}}...
}
func (s *Instance) Start() error {s.access.Lock()defer s.access.Unlock()s.running = truefor _, f := range s.features {if err := f.Start(); err != nil {return err}}newError("V2Ray ", Version(), " started").AtWarning().WriteToLog()return nil
}
type Handler interface {common.RunnableTag() string
}type Manager interface {features.FeatureGetHandler(ctx context.Context, tag string) (Handler, error)AddHandler(ctx context.Context, handler Handler) errorRemoveHandler(ctx context.Context, tag string) error
}func ManagerType() interface{} {return (*Manager)(nil)
}
type Handler interface {common.RunnableTag() stringDispatch(ctx context.Context, link *transport.Link)
}type HandlerSelector interface {Select([]string) []string
}type Manager interface {features.FeatureGetHandler(tag string) HandlerGetDefaultHandler() HandlerAddHandler(ctx context.Context, handler Handler) errorRemoveHandler(ctx context.Context, tag string) error
}func ManagerType() interface{} {return (*Manager)(nil)
}
// Manager is to manage all inbound handlers.
type Manager struct {access sync.RWMutexuntaggedHandler []inbound.HandlertaggedHandlers map[string]inbound.Handlerrunning bool
}...// Start implements common.Runnable.
func (m *Manager) Start() error {m.access.Lock()defer m.access.Unlock()m.running = truefor _, handler := range m.taggedHandlers {if err := handler.Start(); err != nil {return err}}for _, handler := range m.untaggedHandler {if err := handler.Start(); err != nil {return err}}return nil
}
type AlwaysOnInboundHandler struct {proxy proxy.Inboundworkers []workermux *mux.Servertag string
}// Start implements common.Runnable.
func (h *AlwaysOnInboundHandler) Start() error {for _, worker := range h.workers {if err := worker.Start(); err != nil {return err}}return nil
}
type worker interface {Start() errorClose() errorPort() net.PortProxy() proxy.Inbound
}
type tcpWorker struct {address net.Addressport net.Portproxy proxy.Inbound //表示采用的代理协议stream *internet.MemoryStreamConfigrecvOrigDest booltag stringdispatcher routing.DispatchersniffingConfig *proxyman.SniffingConfiguplinkCounter stats.CounterdownlinkCounter stats.Counterhub internet.Listenerctx context.Context
}
// An Inbound processes inbound connections.
type Inbound interface {// Network returns a list of networks that this inbound supports. Connections with not-supported networks will not be passed into Process().Network() []net.Network// Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound.Process(context.Context, net.Network, internet.Connection, routing.Dispatcher) error
}
// Error is an error object with underlying error.
type Error struct {pathObj interface{}prefix []interface{}message []interface{}inner errorseverity log.Severity
}// New returns a new error object with message formed from given arguments.
func New(msg ...interface{}) *Error {return &Error{message: msg,severity: log.Severity_Info, // 默认日志级别为info}
}
每个目录下,都有一个newError方法,和一个errPathObjHolder。
func newError(values ...interface{}) *errors.Error {return errors.New(values...).WithPathObj(errPathObjHolder{})
}