add hop
This commit is contained in:
@ -28,153 +28,191 @@ func ParseChain(cfg *config.ChainConfig) (chain.Chainer, error) {
|
||||
"chain": cfg.Name,
|
||||
})
|
||||
|
||||
c := xchain.NewChain(cfg.Name)
|
||||
var md metadata.Metadata
|
||||
if cfg.Metadata != nil {
|
||||
c.WithMetadata(mdx.NewMetadata(cfg.Metadata))
|
||||
md = mdx.NewMetadata(cfg.Metadata)
|
||||
}
|
||||
|
||||
sel := parseNodeSelector(cfg.Selector)
|
||||
for _, hop := range cfg.Hops {
|
||||
var nodes []*chain.Node
|
||||
for _, v := range hop.Nodes {
|
||||
nodeLogger := chainLogger.WithFields(map[string]any{
|
||||
"kind": "node",
|
||||
"connector": v.Connector.Type,
|
||||
"dialer": v.Dialer.Type,
|
||||
"hop": hop.Name,
|
||||
"node": v.Name,
|
||||
})
|
||||
connectorLogger := nodeLogger.WithFields(map[string]any{
|
||||
"kind": "connector",
|
||||
})
|
||||
c := xchain.NewChain(cfg.Name,
|
||||
xchain.MetadataChainOption(md),
|
||||
xchain.LoggerChainOption(chainLogger),
|
||||
)
|
||||
|
||||
tlsCfg := v.Connector.TLS
|
||||
if tlsCfg == nil {
|
||||
tlsCfg = &config.TLSConfig{}
|
||||
}
|
||||
tlsConfig, err := tls_util.LoadClientConfig(
|
||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
||||
tlsCfg.Secure, tlsCfg.ServerName)
|
||||
if err != nil {
|
||||
chainLogger.Error(err)
|
||||
for _, ch := range cfg.Hops {
|
||||
var hop chain.Hop
|
||||
var err error
|
||||
|
||||
if len(ch.Nodes) > 0 {
|
||||
if hop, err = ParseHop(ch); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var nm metadata.Metadata
|
||||
if v.Metadata != nil {
|
||||
nm = mdx.NewMetadata(v.Metadata)
|
||||
}
|
||||
|
||||
var cr connector.Connector
|
||||
if rf := registry.ConnectorRegistry().Get(v.Connector.Type); rf != nil {
|
||||
cr = rf(
|
||||
connector.AuthOption(parseAuth(v.Connector.Auth)),
|
||||
connector.TLSConfigOption(tlsConfig),
|
||||
connector.LoggerOption(connectorLogger),
|
||||
)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unregistered connector: %s", v.Connector.Type)
|
||||
}
|
||||
|
||||
if v.Connector.Metadata == nil {
|
||||
v.Connector.Metadata = make(map[string]any)
|
||||
}
|
||||
if err := cr.Init(mdx.NewMetadata(v.Connector.Metadata)); err != nil {
|
||||
connectorLogger.Error("init: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dialerLogger := nodeLogger.WithFields(map[string]any{
|
||||
"kind": "dialer",
|
||||
})
|
||||
|
||||
tlsCfg = v.Dialer.TLS
|
||||
if tlsCfg == nil {
|
||||
tlsCfg = &config.TLSConfig{}
|
||||
}
|
||||
tlsConfig, err = tls_util.LoadClientConfig(
|
||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
||||
tlsCfg.Secure, tlsCfg.ServerName)
|
||||
if err != nil {
|
||||
chainLogger.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ppv int
|
||||
if nm != nil {
|
||||
ppv = mdutil.GetInt(nm, mdKeyProxyProtocol)
|
||||
}
|
||||
|
||||
var d dialer.Dialer
|
||||
if rf := registry.DialerRegistry().Get(v.Dialer.Type); rf != nil {
|
||||
d = rf(
|
||||
dialer.AuthOption(parseAuth(v.Dialer.Auth)),
|
||||
dialer.TLSConfigOption(tlsConfig),
|
||||
dialer.LoggerOption(dialerLogger),
|
||||
dialer.ProxyProtocolOption(ppv),
|
||||
)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unregistered dialer: %s", v.Dialer.Type)
|
||||
}
|
||||
|
||||
if v.Dialer.Metadata == nil {
|
||||
v.Dialer.Metadata = make(map[string]any)
|
||||
}
|
||||
if err := d.Init(mdx.NewMetadata(v.Dialer.Metadata)); err != nil {
|
||||
dialerLogger.Error("init: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v.Resolver == "" {
|
||||
v.Resolver = hop.Resolver
|
||||
}
|
||||
if v.Hosts == "" {
|
||||
v.Hosts = hop.Hosts
|
||||
}
|
||||
if v.Interface == "" {
|
||||
v.Interface = hop.Interface
|
||||
}
|
||||
if v.SockOpts == nil {
|
||||
v.SockOpts = hop.SockOpts
|
||||
}
|
||||
|
||||
var sockOpts *chain.SockOpts
|
||||
if v.SockOpts != nil {
|
||||
sockOpts = &chain.SockOpts{
|
||||
Mark: v.SockOpts.Mark,
|
||||
}
|
||||
}
|
||||
|
||||
tr := chain.NewTransport(d, cr,
|
||||
chain.AddrTransportOption(v.Addr),
|
||||
chain.InterfaceTransportOption(v.Interface),
|
||||
chain.SockOptsTransportOption(sockOpts),
|
||||
chain.TimeoutTransportOption(10*time.Second),
|
||||
)
|
||||
|
||||
node := chain.NewNode(v.Name, v.Addr,
|
||||
chain.TransportNodeOption(tr),
|
||||
chain.BypassNodeOption(bypass.BypassGroup(bypassList(v.Bypass, v.Bypasses...)...)),
|
||||
chain.ResoloverNodeOption(registry.ResolverRegistry().Get(v.Resolver)),
|
||||
chain.HostMapperNodeOption(registry.HostsRegistry().Get(v.Hosts)),
|
||||
chain.MetadataNodeOption(nm),
|
||||
)
|
||||
nodes = append(nodes, node)
|
||||
} else {
|
||||
hop = registry.HopRegistry().Get(ch.Name)
|
||||
}
|
||||
|
||||
sl := sel
|
||||
if s := parseNodeSelector(hop.Selector); s != nil {
|
||||
sl = s
|
||||
if hop != nil {
|
||||
c.AddHop(hop)
|
||||
}
|
||||
if sl == nil {
|
||||
sl = defaultNodeSelector()
|
||||
}
|
||||
|
||||
c.AddHop(xchain.NewChainHop(nodes,
|
||||
xchain.SelectorHopOption(sl),
|
||||
xchain.BypassHopOption(bypass.BypassGroup(bypassList(hop.Bypass, hop.Bypasses...)...))),
|
||||
)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func ParseHop(cfg *config.HopConfig) (chain.Hop, error) {
|
||||
if cfg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
hopLogger := logger.Default().WithFields(map[string]any{
|
||||
"kind": "hop",
|
||||
"hop": cfg.Name,
|
||||
})
|
||||
|
||||
var nodes []*chain.Node
|
||||
for _, v := range cfg.Nodes {
|
||||
if v == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if v.Connector == nil {
|
||||
v.Connector = &config.ConnectorConfig{
|
||||
Type: "http",
|
||||
}
|
||||
v.Dialer = &config.DialerConfig{
|
||||
Type: "tcp",
|
||||
}
|
||||
}
|
||||
|
||||
nodeLogger := hopLogger.WithFields(map[string]any{
|
||||
"kind": "node",
|
||||
"node": v.Name,
|
||||
"connector": v.Connector.Type,
|
||||
"dialer": v.Dialer.Type,
|
||||
})
|
||||
|
||||
tlsCfg := v.Connector.TLS
|
||||
if tlsCfg == nil {
|
||||
tlsCfg = &config.TLSConfig{}
|
||||
}
|
||||
tlsConfig, err := tls_util.LoadClientConfig(
|
||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
||||
tlsCfg.Secure, tlsCfg.ServerName)
|
||||
if err != nil {
|
||||
hopLogger.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var nm metadata.Metadata
|
||||
if v.Metadata != nil {
|
||||
nm = mdx.NewMetadata(v.Metadata)
|
||||
}
|
||||
|
||||
connectorLogger := nodeLogger.WithFields(map[string]any{
|
||||
"kind": "connector",
|
||||
})
|
||||
var cr connector.Connector
|
||||
if rf := registry.ConnectorRegistry().Get(v.Connector.Type); rf != nil {
|
||||
cr = rf(
|
||||
connector.AuthOption(parseAuth(v.Connector.Auth)),
|
||||
connector.TLSConfigOption(tlsConfig),
|
||||
connector.LoggerOption(connectorLogger),
|
||||
)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unregistered connector: %s", v.Connector.Type)
|
||||
}
|
||||
|
||||
if v.Connector.Metadata == nil {
|
||||
v.Connector.Metadata = make(map[string]any)
|
||||
}
|
||||
if err := cr.Init(mdx.NewMetadata(v.Connector.Metadata)); err != nil {
|
||||
connectorLogger.Error("init: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tlsCfg = v.Dialer.TLS
|
||||
if tlsCfg == nil {
|
||||
tlsCfg = &config.TLSConfig{}
|
||||
}
|
||||
tlsConfig, err = tls_util.LoadClientConfig(
|
||||
tlsCfg.CertFile, tlsCfg.KeyFile, tlsCfg.CAFile,
|
||||
tlsCfg.Secure, tlsCfg.ServerName)
|
||||
if err != nil {
|
||||
hopLogger.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ppv int
|
||||
if nm != nil {
|
||||
ppv = mdutil.GetInt(nm, mdKeyProxyProtocol)
|
||||
}
|
||||
|
||||
dialerLogger := nodeLogger.WithFields(map[string]any{
|
||||
"kind": "dialer",
|
||||
})
|
||||
|
||||
var d dialer.Dialer
|
||||
if rf := registry.DialerRegistry().Get(v.Dialer.Type); rf != nil {
|
||||
d = rf(
|
||||
dialer.AuthOption(parseAuth(v.Dialer.Auth)),
|
||||
dialer.TLSConfigOption(tlsConfig),
|
||||
dialer.LoggerOption(dialerLogger),
|
||||
dialer.ProxyProtocolOption(ppv),
|
||||
)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unregistered dialer: %s", v.Dialer.Type)
|
||||
}
|
||||
|
||||
if v.Dialer.Metadata == nil {
|
||||
v.Dialer.Metadata = make(map[string]any)
|
||||
}
|
||||
if err := d.Init(mdx.NewMetadata(v.Dialer.Metadata)); err != nil {
|
||||
dialerLogger.Error("init: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v.Resolver == "" {
|
||||
v.Resolver = cfg.Resolver
|
||||
}
|
||||
if v.Hosts == "" {
|
||||
v.Hosts = cfg.Hosts
|
||||
}
|
||||
if v.Interface == "" {
|
||||
v.Interface = cfg.Interface
|
||||
}
|
||||
if v.SockOpts == nil {
|
||||
v.SockOpts = cfg.SockOpts
|
||||
}
|
||||
|
||||
var sockOpts *chain.SockOpts
|
||||
if v.SockOpts != nil {
|
||||
sockOpts = &chain.SockOpts{
|
||||
Mark: v.SockOpts.Mark,
|
||||
}
|
||||
}
|
||||
|
||||
tr := chain.NewTransport(d, cr,
|
||||
chain.AddrTransportOption(v.Addr),
|
||||
chain.InterfaceTransportOption(v.Interface),
|
||||
chain.SockOptsTransportOption(sockOpts),
|
||||
chain.TimeoutTransportOption(10*time.Second),
|
||||
)
|
||||
|
||||
node := chain.NewNode(v.Name, v.Addr,
|
||||
chain.TransportNodeOption(tr),
|
||||
chain.BypassNodeOption(bypass.BypassGroup(bypassList(v.Bypass, v.Bypasses...)...)),
|
||||
chain.ResoloverNodeOption(registry.ResolverRegistry().Get(v.Resolver)),
|
||||
chain.HostMapperNodeOption(registry.HostsRegistry().Get(v.Hosts)),
|
||||
chain.MetadataNodeOption(nm),
|
||||
)
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
sel := parseNodeSelector(cfg.Selector)
|
||||
if sel == nil {
|
||||
sel = defaultNodeSelector()
|
||||
}
|
||||
return xchain.NewChainHop(nodes,
|
||||
xchain.SelectorHopOption(sel),
|
||||
xchain.BypassHopOption(bypass.BypassGroup(bypassList(cfg.Bypass, cfg.Bypasses...)...)),
|
||||
xchain.LoggerHopOption(hopLogger),
|
||||
), nil
|
||||
}
|
||||
|
@ -185,7 +185,11 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
||||
}
|
||||
|
||||
if forwarder, ok := h.(handler.Forwarder); ok {
|
||||
forwarder.Forward(parseForwarder(cfg.Forwarder))
|
||||
hop, err := parseForwarder(cfg.Forwarder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forwarder.Forward(hop)
|
||||
}
|
||||
|
||||
if cfg.Handler.Metadata == nil {
|
||||
@ -205,36 +209,45 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func parseForwarder(cfg *config.ForwarderConfig) chain.Hop {
|
||||
if cfg == nil ||
|
||||
(len(cfg.Targets) == 0 && len(cfg.Nodes) == 0) {
|
||||
return nil
|
||||
func parseForwarder(cfg *config.ForwarderConfig) (chain.Hop, error) {
|
||||
if cfg == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var nodes []*chain.Node
|
||||
hc := config.HopConfig{
|
||||
Name: cfg.Name,
|
||||
Selector: cfg.Selector,
|
||||
}
|
||||
if len(cfg.Nodes) > 0 {
|
||||
for _, node := range cfg.Nodes {
|
||||
if node != nil {
|
||||
nodes = append(nodes,
|
||||
chain.NewNode(node.Name, node.Addr,
|
||||
chain.BypassNodeOption(bypass.BypassGroup(bypassList(node.Bypass, node.Bypasses...)...)),
|
||||
),
|
||||
hc.Nodes = append(hc.Nodes,
|
||||
&config.NodeConfig{
|
||||
Name: node.Name,
|
||||
Addr: node.Addr,
|
||||
Bypass: node.Bypass,
|
||||
Bypasses: node.Bypasses,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, target := range cfg.Targets {
|
||||
if v := strings.TrimSpace(target); v != "" {
|
||||
nodes = append(nodes, chain.NewNode(target, target))
|
||||
hc.Nodes = append(hc.Nodes,
|
||||
&config.NodeConfig{
|
||||
Name: target,
|
||||
Addr: target,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sel := parseNodeSelector(cfg.Selector)
|
||||
if sel == nil {
|
||||
sel = defaultNodeSelector()
|
||||
if len(hc.Nodes) > 0 {
|
||||
return ParseHop(&hc)
|
||||
}
|
||||
return xchain.NewChainHop(nodes, xchain.SelectorHopOption(sel))
|
||||
return registry.HopRegistry().Get(hc.Name), nil
|
||||
}
|
||||
|
||||
func bypassList(name string, names ...string) []bypass.Bypass {
|
||||
|
@ -38,9 +38,9 @@ func BuildDefaultTLSConfig(cfg *config.TLSConfig) {
|
||||
tlsConfig = &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
log.Warn("load global TLS certificate files failed, use random generated certificate")
|
||||
log.Debug("load global TLS certificate files failed, use random generated certificate")
|
||||
} else {
|
||||
log.Info("load global TLS certificate files OK")
|
||||
log.Debug("load global TLS certificate files OK")
|
||||
}
|
||||
defaultTLSConfig = tlsConfig
|
||||
}
|
||||
|
Reference in New Issue
Block a user